Cod sursa(job #306779)

Utilizator andrei-alphaAndrei-Bogdan Antonescu andrei-alpha Data 21 aprilie 2009 22:27:21
Problema Nums Scor Ascuns
Compilator cpp Status done
Runda Marime 4.03 kb
// (c) Mircea Dima

#include <cstdio>
#include <vector>
#define oo 0x3f3f3f3f

using namespace std;


struct nod
{
    int nr;
    bool end;
    nod *next[10];

};

struct nodtreap
{
    int v, p;

    int nr;
    nodtreap *l,*r;

    nod *T;
};


typedef nodtreap* treap;

treap R, nil;


inline void init()
{
    nil=new nodtreap;
    nil->l=nil->r=0;
    nil->p=nil->v=-0x3f3f3f3f;
    nil->T=0;
    nil->nr=0;
    R=nil;
}

inline void getnr(treap &n)
{
    if(n == nil) return;

    
    n->nr=n->l->nr + n->r->nr + n->T->nr;
}

inline void rotleft(treap &n)
{
    treap t=n->l;
    n->l=t->r;
    t->r=n;
    getnr(n); getnr(t);
    n=t;
}

inline void rotright(treap &n)
{
    treap t=n->r;
    n->r=t->l;
    t->l=n;
    getnr(n); getnr(t);
    n=t;
}

inline void insert(treap &n, nod *&T, int len)
// inserarea in treap
{
    if(n == nil)
    {
	n=new nodtreap;
	n->l=n->r=nil;
	n->v=len;
	n->T=T;
	n->p=rand();//*rand();
	n->nr=T->nr;
	
	return;

    }

    if(len < n->v) 
    {
	insert(n->l, T, len);
	if(n->l->p > n->p) rotleft(n);
    }

    if(len > n->v)
    {
	insert(n->r, T, len);
	if(n->r->p > n->p) rotright(n);
    }

    getnr(n);
}

inline void update(treap &n, int len)
{
    if(n == nil) return;
    if(len < n->v) update(n->l, len);
    if(len > n->v) update(n->r, len);

    n->nr++;
}

inline nod* find(treap n, int len)
// cautare in treap
{
    if(n == nil) return (nod*) 0;
    if(len < n->v) return find(n->l, len);
    if(len > n->v) return find(n->r, len);
    return n->T;
}

char a[100024];

inline int findk(treap n, int k)
// pe treap
{
    if(n == nil) return  0;
    if(n->l->nr + n->T->nr >= k && n->l->nr < k) return n->v;
    if(n->l->nr + n->T->nr  < k) return findk(n->r, k-(n->l->nr + n->T->nr));
    if(n->l->nr  >= k) return findk(n->l, k);
    return 0;
}

inline void afis(nod *T, int k, int poz)
{
    int pz=-1,s=0;

    for(int i=0; i < 10 ; ++i)
	 if(T->next[i])
	    {
		pz=i;
		++s;
	    }
   
    if(s == 0) 
    {	
        printf("%s\n", a);
	return;
    }	
    if(s == 1)
    {
	a[poz]=pz+'0';
	a[poz+1]=0;

	afis(T->next[pz], k, poz+1);
	return;


    }


    s=0;

    for(int i=0; i < 10; ++i)
    {
	if(T->next[i] == 0) continue;

	if(s + T->next[i]->nr >= k)
	{
	    a[poz]=i+'0';
	    a[poz+1]=0;

	    afis(T->next[i], k-s, poz+1);
	    break;
	}
	
	s += T->next[i]->nr;

    }
}


inline void findkth(treap n, int k)
// pe treap
{
    if(n == nil) return ;
    if(n->l->nr + n->T->nr >= k && n->l->nr < k) { afis(n->T, k - n->l->nr,0);return;}
    if(n->l->nr + n->T->nr < k)  findkth(n->r, k-(n->l->nr + n->T->nr));
    if(n->l->nr >= k)  findkth(n->l, k);

    return ;
}
int OK;
int n;

inline void insrt(nod *T, char a[], int i)
{
    if(i == n) {T->nr=1; T->end=1;return;}

    
    if(T->next[a[i]] == 0)
    {
	T->next[a[i]]=new nod;
	T->next[a[i]]->end=0;
	memset(T->next[a[i]]->next, 0,sizeof(T->next));
	T->next[a[i]]->nr=0;
    }

    insrt(T->next[a[i]], a, i+1);

     ++T->nr;    
       
}

void afis(nod *T, int k)
{
    for(int i=0; i < 10; ++i)
	if(T->next[i])
	{
	    a[k]=i+'0';
	    a[k+1]=0;
	    afis(T->next[i],k+1);
	    if(T->next[i]->end) printf("%s\n", a);
	}

}
inline void insert(char a[], int n)
{
    int i;
    for(i=0; i < n; ++i) a[i] -= '0';

    nod *t=find(R, n);

    
    if(t == 0)
    {
	t=new nod;
	memset(t->next, 0, sizeof(t->next));
	t->nr=0;
	insrt(t, a,0);
	
	insert(R, t, n);

    }
    else
    {
	insrt(t, a,0);

	update(R, n);
    }


}


void ino(treap n)
{
    if(n == nil) return;
    ino(n->l);

    afis(n->T, 0);

    ino(n->r);

}

int N;
int main()
{

    init();
    int i;

    freopen("nums.in","r",stdin);
    freopen("nums.out","w",stdout);
    scanf("%d\n", &N);
   
    int type,k;
    while(N--)
    {
	scanf("%d ", &type);

	if(type == 1)
	{
	    scanf("%s\n", &a);
	    n=strlen(a);
	
	    insert(a, n);
	    memset(a, 0, sizeof(char)*(n+1));
	}
	
	if(type == 0)
	{
	    scanf("%d\n", &k);
	    findkth(R, k);

	}
    }

    //for(i=1; i <= 3000; ++i) findkth(R, i);

    //printf("herr\n");

    //findk(R,0);
  // printf("ok"); 
    //printf("\n");
   // ino(R);
    return 0;
}