BZOJ 3224 TREAP 解题报告

来源:互联网 发布:零件设计软件手机 编辑:程序博客网 时间:2024/05/17 13:41

3224: Tyvj 1728 普通平衡树

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

【解题报告】
好多方法都可以做。。。

vector版:

#include<cstdio>#include<cstring>#include<set>#include<vector>#include<algorithm>using namespace std;#define inf 1000000000int n;vector<int> a;void insert(int x){a.insert(upper_bound(a.begin(),a.end(),x),x);return;}void del(int x){a.erase(lower_bound(a.begin(),a.end(),x));return;}int find(int x){return lower_bound(a.begin(),a.end(),x)-a.begin()+1;}int main(){    scanf("%d",&n);    a.reserve(200000);    int opt,x;    for(int i=1;i<=n;++i)    {        scanf("%d%d",&opt,&x);        switch(opt)        {            case 1:insert(x);break;            case 2:del(x);break;            case 3:printf("%d\n",find(x));break;            case 4:printf("%d\n",a[x-1]);break;            case 5:printf("%d\n",*--lower_bound(a.begin(),a.end(),x));break;            case 6:printf("%d\n",*upper_bound(a.begin(),a.end(),x));break;        }    }    return 0;}

reap版:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define inf 0x7fffffffinline int q_rand(){    static int seed=10007;     return seed=int(seed*48271LL%2147483647);}struct Treap {    struct node     {        node *son[2];        int key,siz,wei,cnt;        node(int _key,node *f)         {            son[0]=son[1]=f;            key=_key;siz=cnt=1;wei=q_rand();        }        void pushup()         {            siz=son[0]->siz+son[1]->siz+cnt;        }    }*null,*root;    Treap()     {        null=new node(0,0);        null->siz=null->siz=0;        null->wei=inf;root=null;    }    void rot(node* &rt,bool d)     {        node* c=rt->son[!d];        rt->son[!d]=c->son[d];        c->son[d]=rt;        rt->pushup();        c->pushup();        rt=c;    }    void insert(const int &key,node* &rt) //插入一个数     {        if(rt==null)         {            rt=new node(key,null);return;        }        if(key==rt->key)         {            rt->cnt++;rt->siz++;return;        }        bool d=key>rt->key;        insert(key,rt->son[d]);        if (rt->wei>rt->son[d]->wei) rot(rt,!d);        rt->pushup();    }    void remove(const int &key,node* &rt) //删除一个数    {        if(rt==null) return;        bool d=key>rt->key;        if(key==rt->key)         {            if(rt->cnt>1)             {                rt->cnt--;rt->siz--;return;            }            d=rt->son[0]->wei>rt->son[1]->wei;            if (rt->son[d]==null)             {                delete rt;rt=null;return;            }            rot(rt,!d);            remove(key,rt->son[!d]);        }         else remove(key,rt->son[d]);        rt->pushup();    }    node* select(int k,node* rt) //查询第k名     {        int s=rt->son[0]->siz+rt->cnt;        if(k>=rt->son[0]->siz+1&&k<=s) return rt;        if(s>k) return select(k,rt->son[0]);        else return select(k-s,rt->son[1]);    }    int rank(const int &key,node* rt) //查询排名     {        if(rt==null) return 0;        int s=rt->son[0]->siz+rt->cnt;        if(key==rt->key) return rt->son[0]->siz+1;        if(key<rt->key) return rank(key,rt->son[0]);        else return s+rank(key,rt->son[1]);    }    int pre(const int &k) //前驱     {        node* t=root;        int ret=0;        while(t!=null)        if(t->key<k) ret=t->key,t=t->son[1];        else t=t->son[0];        return ret;    }    int sub(const int &k) //后驱     {        node* t=root;        int ret=0;        while(t!=null)        if(t->key>k) ret=t->key,t=t->son[0];        else t=t->son[1];        return ret;    }};int main(){    int n;    Treap tree;    scanf("%d", &n);    int opt,x;    while(n--)    {        scanf("%d%d",&opt,&x);        switch(opt)        {            case 1:tree.insert(x,tree.root);break;//插入一个数             case 2:tree.remove(x,tree.root);break;//删除一个数             case 3:printf("%d\n",tree.rank(x,tree.root));break;//查询排名             case 4:printf("%d\n",tree.select(x,tree.root)->key);break;//查询第x名             case 5:printf("%d\n",tree.pre(x));break;//前驱             case 6:printf("%d\n",tree.sub(x));break;//后驱         }    }    return 0;}

让我看到你们的双手

原创粉丝点击