Cod sursa(job #630128)

Utilizator darkseekerBoaca Cosmin darkseeker Data 4 noiembrie 2011 19:14:50
Problema Nums Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.78 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 < 9; 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 bs(int key)
{
	int left = 1, right = LMAX, center,val = 0;
	
	start = 1;
	while(left <= right)
	{
		center = (left + right)/2;
		finish = center;
		ans = 0;
		query(1,LMAX,1);
		if(ans == key)
			{
				val = center;
				right = center - 1;
			}
		else
			if(ans > key)
				right = center - 1;
			else
				left = center + 1;
	}
	ans = 0;
	center = (left + right)/2;
	if(center == 0)
		center++;
	finish = center;
	query(1,LMAX,1);
	if(val != 0)
		return val-1;
	else
	if(ans > key)
		center--;
	return center;
}

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)
	if(position == 0)
		{
			for(i = 0; i < 10; i++)
				if(node->fii[i])
				{
					sol[++solCount] = i + '0';
					TrieQuery(node->fii[i],position);
					break;
				}
		}
	else
		for(i = 0; i < 10; i++)
			if(node->fii[i])
				if(node->fii[i]->cnt < position)
					position -= node->fii[i]->cnt;
				else
					if(node->fii[i]->cnt == position)
						{
							position -= node->fii[i]->cnt;
							sol[++solCount] = i + '0';
							TrieQuery(node->fii[i],position);
							break;
						}
					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 = bs(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();
	
	char *s = NULL;
	
	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;
	
}