Cod sursa(job #630182)

Utilizator darkseekerBoaca Cosmin darkseeker Data 4 noiembrie 2011 20:40:55
Problema Nums Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
#include <fstream>
#include <cstring>
using namespace std;

#define DIM 8+(1<<17)
#define in "nums.in"
#define out "nums.out"
#define LMAX 100010

struct Trie{
	Trie *fii[10];
	int cnt;
	
	Trie()
	{
		for(int i = 0; i < 10; i++)
			fii[i] = NULL;
		cnt = 0;
	}
};

Trie *numbers[LMAX];
int arb[DIM],start,finish,position,value,ans;
int maxL,M,solCount = - 1,lungime;
char sol[LMAX],curent[LMAX];

ifstream fin(in);
ofstream fout(out);

void query(int left,int right,int node)
{
	if(start <= left && right <= finish)
	{
		ans += arb[node];
		return;
	}
	
	int center = (left + right)/2;
	if(start <= center)
		query(left,center,2*node);
	if(center < finish)
		query(center+1,right,2*node+1);
}

void update(int left,int right,int node)
{
	if(left == right)
	{
		arb[node]++;
		return;
	}
	
	int center = (left + right)/2;
	if(position <= center)
		update(left,center,2*node);
	else
		update(center+1,right,2*node+1);
	arb[node] = arb[2*node] + arb[2*node+1];
}

int find(int key)
{
	int i,poz = 0;
	
	start = 1;
	
	for(i=1; i < LMAX; i++)
	{
		ans = 0;
		finish = i;
		query(1,LMAX,1);
		if(ans < key)
			poz = i;
		else
			i = LMAX;
	}
	
	return poz;
}

void insert(Trie *node,char *s)
{
	node->cnt++;
	if(*s >= '0' && *s <= '9')
		if(node->fii[*s-'0'])
			insert(node->fii[*s-'0'],s+1);
		else
			{
				node->fii[*s-'0'] = new Trie();
				insert(node->fii[*s-'0'],s+1);
			}
}

bool exists(Trie *node,char *s)
{
	if(*s < '0' || *s >'9')
		return 1;
	else
	{
		if(*s >= '0' && *s <= '9')
			if(node->fii[*s-'0'])
				return 0 + exists(node->fii[*s-'0'],s+1);
			else
				return 0;
	}
}

inline bool hasSons(Trie *node)
{
	for(int i = 0; i < 10; i++)
		if(node->fii[i])
			return 1;
	return 0;
}

int stringToNumber(char *S)
{
	int lg = strlen(S), i = 0,ans = 0;
	for(i = 0; i < lg; i++)
		ans = ans * 10 + S[i] - '0';
	return ans;
}

void TrieQuery(Trie *node,int position)
{
	int i;
	if(solCount < lungime-1)
		for(i = 0; i < 10; i++)
			if(node->fii[i])
				if(node->fii[i]->cnt < position)
					position -= node->fii[i]->cnt;
				else
				{
					sol[++solCount] = i + '0';
					TrieQuery(node->fii[i],position);
					break;
				}
}

void solve1()
{
	int lg = strlen(curent);
	lg-=2;
	position = lg;
	if(!exists(numbers[lg],curent+2))
		{
			update(1,LMAX,1);
			insert(numbers[lg],curent+2);
		}
}

void solve2(int key)
{
	int poz = find(key);
	start = 1;
	finish = poz;
	ans = 0;
	if(finish != 0)
		query(1,LMAX,1);
	key -= ans;
	solCount = -1;
	lungime = poz+1;
	TrieQuery(numbers[poz+1],key);
	for(poz = 0; poz<=solCount; poz++)
		fout<<sol[poz];
	fout<<'\n';
}

int main()
{
	int N,i;
		
	fin>>N;
	fin.get();
	
	for(i=1; i<=LMAX; i++)
		numbers[i] = new Trie();
	
	for(i=1; i<=N; i++)
	{
		strcpy(curent," ");
		fin.get(curent,LMAX,'\n');
		fin.get();
		switch(curent[0])
		{
			case '1': solve1(); break;
			case '0': solve2(stringToNumber(curent+2));
		}
	}
	
	fin.close();
	fout.close();
	
	return 0;
	
}