bzoj 3224 Tyvj 1728 普通平衡树 Treap

Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 17187  Solved: 7501
[Submit][Status][Discuss]

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

HINT

 

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]
 
 
题解:是用treap去维护,当然c++的STL也可以过(不知道为什么),
这些都是treap的基本操作,复杂度是O(n log n)的。
 
  1 #include<cstring>
  2 #include<cmath>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cstdio>
  6 
  7 #define ls tr[p].l
  8 #define rs tr[p].r
  9 #define N 100007
 10 #define inf 2000000010
 11 using namespace std;
 12 inline int read()
 13 {
 14     int x=0,f=1;char ch=getchar();
 15     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
 16     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 17     return x*f;
 18 }
 19 
 20 int n,sz,rt,ans;
 21 struct Node
 22 {
 23     int l,r,val,siz,rnd,ct;//记录左儿子,右儿子,点值,该子树大小,随机的值,该点值出现的次数。 
 24 }tr[N];//最多多少个节点,就开多少空间 
 25 
 26 inline int rand(){
 27     static int seed = 2333;
 28     return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007);
 29 }
 30 inline void update(int p)
 31 {
 32     tr[p].siz=tr[ls].siz+tr[rs].siz+tr[p].ct;
 33 }
 34 void lturn(int &p)
 35 {
 36     int t=tr[p].r;tr[p].r=tr[t].l;tr[t].l=p;
 37     tr[t].siz=tr[p].siz;update(p);p=t;
 38 }
 39 void rturn(int &p)
 40 {
 41     int t=tr[p].l;tr[p].l=tr[t].r;tr[t].r=p;
 42     tr[t].siz=tr[p].siz;update(p);p=t;
 43 }
 44 void ins(int &p,int x)
 45 {
 46     if (p==0)
 47     {
 48         p=++sz;
 49         tr[p].siz=tr[p].ct=1,tr[p].val=x,tr[p].rnd=rand();
 50         return;
 51     }
 52     tr[p].siz++;
 53     if (tr[p].val==x) tr[p].ct++;
 54     else if (x>tr[p].val)
 55     {
 56         ins(tr[p].r,x);
 57         if (tr[rs].rnd<tr[p].rnd) lturn(p);
 58     }else
 59     {
 60         ins(tr[p].l,x);
 61         if (tr[ls].rnd<tr[p].rnd) rturn(p);
 62     }
 63 }
 64 void del(int &p,int x)
 65 {
 66     if (p==0) return;
 67     if (tr[p].val==x)
 68     {
 69         if (tr[p].ct>1) tr[p].ct--,tr[p].siz--;//如果有多个直接减一即可。
 70         else
 71         {
 72             if (ls==0||rs==0) p=ls+rs;//单节点或者空的话直接儿子移上来或者删去即可。
 73             else if (tr[ls].rnd<tr[rs].rnd) rturn(p),del(p,x);
 74             else lturn(p),del(p,x); 
 75         }
 76     }
 77     else if (x>tr[p].val) tr[p].siz--,del(rs,x);
 78     else tr[p].siz--,del(ls,x);
 79 }
 80 int find_pm(int p,int x)
 81 {
 82     if (p==0) return 0;
 83     if (tr[p].val==x) return tr[ls].siz+1;
 84     if (x>tr[p].val) return tr[ls].siz+tr[p].ct+find_pm(rs,x);
 85     else return find_pm(ls,x);
 86 }
 87 int find_sz(int p,int x)
 88 {
 89     if (p==0) return 0;
 90     if (x<=tr[ls].siz) return find_sz(ls,x);
 91     x-=tr[ls].siz;
 92     if (x<=tr[p].ct) return tr[p].val;
 93     x-=tr[p].ct;
 94     return find_sz(rs,x);
 95 }
 96 int find_qq(int p,int x)
 97 {
 98     if (p==0) return -inf;
 99     if (tr[p].val<x) return max(tr[p].val,find_qq(rs,x));
100     else if (tr[p].val>=x) return find_qq(ls,x);
101 }
102 int find_hj(int p,int x)
103 {
104     if (p==0) return inf;
105     if (tr[p].val<=x) return find_hj(rs,x);
106     else return min(tr[p].val,find_hj(ls,x));
107 }
108 int main()
109 {
110     n=read();
111     for (int i=1;i<=n;i++)
112     {
113         int flag=read(),x=read();
114         if (flag==1) ins(rt,x);
115         if (flag==2) del(rt,x);
116         if (flag==3) printf("%d\n",find_pm(rt,x));//寻找x的排名
117         if (flag==4) printf("%d\n",find_sz(rt,x));//寻找排名为x的数字 
118         if (flag==5) printf("%d\n",find_qq(rt,x));
119         if (flag==6) printf("%d\n",find_hj(rt,x));
120     }
121 }

 

posted @ 2017-12-06 19:25  Kaiser-  阅读(181)  评论(0编辑  收藏  举报