您的位置:首页 > 其它

spoj 3273 Treap

2015-08-02 14:59 363 查看
算是一道比较全面的模板题了吧,需要注意的是:查找比x小的元素个数时x不一定在Treap中,解决办法是插入x,查询,再删除x。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;

struct Node
{
Node * ch[2];
int v, r, size;
int cmp( int x )
{
if ( x == v ) return -1;
return x < v ? 0 : 1;
}
void maintain()
{
size = 1;
if ( ch[0] != NULL ) size += ch[0]->size;
if ( ch[1] != NULL ) size += ch[1]->size;
}
};

void rotate( Node * & o, int d )
{
Node * k = o->ch[d ^ 1];
o->ch[d ^ 1] = k->ch[d];
k->ch[d] = o;
o->maintain();
k->maintain();
o = k;
}

void insert( Node * & o, int x )
{
if ( o == NULL )
{
o = new Node();
o->ch[0] = o->ch[1] = NULL;
o->v = x;
o->r = rand();
o->size = 1;
}
else
{
int d = o->cmp(x);
insert( o->ch[d], x );
if ( o->ch[d]->r > o->r )
{
rotate( o, d ^ 1 );
}
else
{
o->maintain();
}
}
}

void remove( Node * & o, int x )
{
int d = o->cmp(x);
if ( d == -1 )
{
if ( o->ch[0] != NULL && o->ch[1] != NULL )
{
int dd = ( o->ch[0]->r > o->ch[1]->r ? 1 : 0 );
rotate( o, dd );
remove( o->ch[dd], x );
}
else
{
Node * u = o;
if ( o->ch[0] == NULL ) o = o->ch[1];
else o = o->ch[0];
delete u;
}
}
else
{
remove( o->ch[d], x );
}
if ( o != NULL ) o->maintain();
}

int ranker( Node * o, int x, int sum )
{
int d = o->cmp(x);
if ( d == -1 )
{
return sum + ( o->ch[0] == NULL ? 0 : o->ch[0]->size );
}
else if ( d == 0 )
{
return ranker( o->ch[0], x, sum );
}
else
{
int tmp = ( o->ch[0] == NULL ? 0 : o->ch[0]->size );
return ranker( o->ch[1], x, sum + tmp + 1 );
}
}

int kth( Node * o, int k )
{
int tmp = ( o->ch[0] == NULL ? 0 : o->ch[0]->size );
if ( k == tmp + 1 ) return o->v;
else if ( k < tmp + 1 ) return kth( o->ch[0], k );
else return kth( o->ch[1], k - tmp - 1 );
}

int find( Node * o, int x )
{
if ( o == NULL ) return 0;
int d = o->cmp(x);
if ( d == -1 ) return 1;
return find( o->ch[d], x );
}

int main ()
{
Node * root = NULL;
char op[2];
int q, num;
scanf("%d", &q);
while ( q-- )
{
scanf("%s%d", op, &num);
if ( op[0] == 'I' )
{
if ( !find( root, num ) )
{
insert( root, num );
}
}
else if ( op[0] == 'D' )
{
if ( find( root, num ) )
{
remove( root, num );
}
}
else if ( op[0] == 'K' )
{
int s = ( root == NULL ? 0 : root->size );
if ( num > s )
{
printf("invalid\n");
}
else
{
printf("%d\n", kth( root, num ));
}
}
else
{
if ( find( root, num ) )
{
printf("%d\n", ranker( root, num, 0 ));
}
else
{
insert( root, num );
printf("%d\n", ranker( root, num, 0 ));
remove( root, num );
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: