Cod sursa(job #631083)

Utilizator darkseekerBoaca Cosmin darkseeker Data 6 noiembrie 2011 21:43:02
Problema Nums Scor 85
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.56 kb
#include <fstream>
#include <cstring>
#include <string>
using namespace std;

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

typedef struct Trie{
	unsigned short cnt;
	char cif;
	Trie *sons,*next;
	
	Trie(char cifra)
	{
		next = NULL;
		sons = NULL;
		cif = cifra;
		cnt = 0;
	}
};

Trie *numbers[LMAX];
int arb[LMAX],value;
int maxL,M,solCount = - 1,lungime;
char curent[LMAX],bytes[LMAX],sol[LMAX];
Trie* fii[10];
Trie *findAux,*pushAux,*existsAux,*insertAux,*queryAux;
ifstream fin(in);
ofstream fout(out);


//
//aib procedures
//

inline void update(int position)
{
	while(position < LMAX)
	{
		arb[position]++;
		position += (1<<bytes[position]);
	}
}

inline int query(int position)
{
	int ans = 0;
	while(position > 0)
	{
		ans += arb[position];
		position -= (1<<bytes[position]);
	}
	return ans;
}

inline int bsearch(int value)
{
	int left,right,center,sum;
	left = 1;
	right = LMAX;
	
	while(left <= right)
	{
		center = (left + right)>>1;
		sum = query(center);
		if(sum < value)
			left = center + 1;
		else
			right = center - 1;
	}
	
	center = (left + right)/2;
	sum = query(center);
	if(sum > value)
		center--;
	return center;
}

//
//end of aib procedures
//


//
//trie procedures
//

inline void push(char cif,Trie* node)
{
	pushAux = new Trie(cif);
	pushAux->next = node->sons;
	node->sons = pushAux;
}

inline Trie* find(char cif,Trie *node)
{
	findAux = node->sons;
	while(findAux)
	{
		if(findAux->cif == cif)
			return findAux;
		findAux = findAux->next;
	}
	return NULL;
}

void insert(Trie *node,char *s)
{
	node->cnt++;
	if(*s >= '0' && *s <= '9')
		{
			insertAux = find(*s,node);
			if(insertAux)
				insert(insertAux,s+1);
			else
				{
					push(*s,node);
					insert(node->sons,s+1);
				}
		}
}

bool exista(Trie *node,char *s)
{
	if(*s < '0' || *s >'9')
		return 1;
	else
	{
		if(*s >= '0' && *s <= '9')
		{
			existsAux = find(*s,node);
			if(existsAux)
				return 0 + exista(existsAux,s+1);
			else
				return 0;
		}
	}
}

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

//
//end of trie procedures
//

inline 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;
}

inline void solve1()
{
	int lg = strlen(curent);
	lg-=2;
	if(!exista(numbers[lg],curent+2))
		{
			update(lg);
			insert(numbers[lg],curent+2);
		}
}

inline void solve2(int key)
{
	
	int poz = bsearch(key);
	if(poz != 0)
		key -= query(poz);
	solCount = -1;
	lungime = poz+1;
	TrieQuery(numbers[poz+1],key);
	sol[++solCount] = '\0';
	fout<<sol<<'\n';
}

void compute()
{
	int i;
	bytes[1] = 0;
	for(i = 2; i < LMAX; i++)
		if(i % 2 == 0)
			bytes[i] = 1 + bytes[i>>1];
		else
			bytes[i] = 0;
}

int main()
{
	int N,i;
	
	compute();
	
	fin>>N;
	fin.get();
	
	char *s = NULL;
	
	for(i=1; i<LMAX; i++)
		numbers[i] = new Trie(0);
	
	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));break;
		}
	}
	
	fin.close();
	fout.close();
	
	return 0;
	
}