BZOJ 3224 普通平衡树 treap or vector

    很明显这是一道treap的题,但看了黄学长的博客后,也让我大开了眼界,没想到vector也能用那么短的编码量把这道题AC,着实令我敬佩。这也提醒了我 STL 的重要性。 的确, 对于C++ 选手来说,如果能灵活地使用 STL, 的确受益匪浅(虽然速度可能比其他的慢一点,但正确性和编程复杂度都比其他的好,如果时间复杂度允许,在紧张的编程时间内,STL或许会是不错的选择)。 

这是STL(vector)的代码, 用到了 insert, lowerr_bound, erase 等函数, 加油。(1700多毫秒)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<set>
 6 #include<vector>
 7 #include<algorithm>
 8 #define inf 1000000000
 9 using namespace std;
10 
11 inline int read()
12 {
13     int x=0,f=1;char ch=getchar();
14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 int n;
19 vector<int> a;
20 
21 void insert(int x)
22 {
23     a.insert(upper_bound(a.begin(),a.end(),x),x);
24     return;
25 }
26 
27 void del(int x)
28 {
29     a.erase(lower_bound(a.begin(),a.end(),x));
30     return;
31 }
32 int find(int x)
33 {
34     return lower_bound(a.begin(),a.end(),x)-a.begin()+1;
35 }
36 int main()
37 {
38     n=read();
39     a.reserve(200000);
40     int f,x;
41     for(int i=1;i<=n;i++)
42     {
43         f=read();x=read();
44         switch(f)
45         {
46         case 1:insert(x);break;
47         case 2:del(x);break;
48         case 3:printf("%d\n",find(x));break;
49         case 4:printf("%d\n",a[x-1]);break;
50         case 5:printf("%d\n",*--lower_bound(a.begin(),a.end(),x));break;
51         case 6:printf("%d\n",*upper_bound(a.begin(),a.end(),x));break;
52         }
53     }
54     return 0;
55 }

 

接下来肯定是treap 的代码了,orz 黄学长。从他那里,着实学了不少好东西。(300多毫秒,比上面快多了吧!这个时间差距主要是因为查如何删除造成的)。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #define rep(i,j,k) for(int i = j; i <= k; i++)
  5 using namespace std;
  6 
  7 struct node{
  8 int c[2], w, s, v, rnd;
  9 } tr[100005];
 10 
 11 int n, ans, root, size;
 12 
 13 int read()
 14 {
 15     int s = 0, t = 1; char c= getchar();
 16     while( !isdigit(c) ){
 17         if( c == '-' ) t = -1; c = getchar();
 18     }
 19     while( isdigit(c) ){
 20         s = s * 10 + c - '0'; c = getchar();
 21     }
 22     return s * t;
 23 }
 24 
 25 void update(int k)
 26 {
 27     tr[k].s = tr[tr[k].c[0]].s + tr[tr[k].c[1]].s + tr[k].w;
 28 }
 29 
 30 void rorate(int&k,int d)
 31 {
 32     int y = tr[k].c[d^1]; tr[k].c[d^1] = tr[y].c[d];
 33     tr[y].c[d] = k; update(k), update(y), k = y;
 34 }
 35 
 36 void insert(int&k,int x)
 37 {
 38     if( k == 0 ){
 39         ++size; k = size; tr[k].c[0] = tr[k].c[1] = 0, tr[k].s = tr[k].w = 1, tr[k].v = x, tr[k].rnd = rand();
 40         return;
 41     }
 42     tr[k].s++;
 43     if( x == tr[k].v ) tr[k].w++;
 44     else if( x < tr[k].v) {
 45         insert(tr[k].c[0],x); 
 46         if( tr[tr[k].c[0]].rnd > tr[k].rnd )rorate(k,1);
 47     }
 48     else {
 49         insert(tr[k].c[1],x);
 50         if( tr[tr[k].c[1]].rnd > tr[k].rnd ) rorate(k,0);
 51     }
 52 }
 53 
 54 void delt(int&k,int x)
 55 {
 56     if( !k ) return;
 57     if( tr[k].v == x ){
 58         if( tr[k].w > 1 ) {
 59             tr[k].w--, tr[k].s--;  return;
 60         }
 61         else {
 62             if( tr[k].c[0] * tr[k].c[1] == 0 ) k = tr[k].c[0] + tr[k].c[1];
 63             else {
 64                 if( tr[tr[k].c[0]].rnd > tr[tr[k].c[1]].rnd ) {
 65                     rorate(k,1); delt(k,x);
 66                 }
 67                 else {
 68                     rorate(k,0); delt(k,x);
 69                 }
 70             }
 71         }
 72     }
 73     else {
 74         tr[k].s--;
 75         if( x < tr[k].v ) delt(tr[k].c[0],x);
 76         else delt(tr[k].c[1],x);
 77     }
 78 }
 79 
 80 int query_rank(int k,int x)
 81 {
 82     if( !k ) return 0;
 83     if( tr[k].v == x ) return tr[tr[k].c[0]].s + 1;
 84     else if( tr[k].v < x ) return tr[tr[k].c[0]].s + tr[k].w + query_rank(tr[k].c[1],x);
 85     else return query_rank(tr[k].c[0],x);
 86 }
 87 
 88 int query_num(int k,int num)
 89 {
 90     if( !k ) return 0;
 91     if( tr[tr[k].c[0]].s >= num ) return query_num(tr[k].c[0],num);
 92     else if( tr[tr[k].c[0]].s + tr[k].w < num ) return query_num(tr[k].c[1],num-tr[tr[k].c[0]].s - tr[k].w);
 93     else return tr[k].v;
 94 }
 95 
 96 void query_pre(int k,int x)
 97 {
 98     if( !k ) return;
 99     if( tr[k].v < x ){
100         ans = k, query_pre(tr[k].c[1],x);
101     }
102     else  query_pre(tr[k].c[0],x);
103 }
104 
105 void query_suc(int k,int x)
106 {
107     if( !k ) return;
108     if( tr[k].v > x ){
109         ans = k, query_suc(tr[k].c[0],x);
110     }
111     else  query_suc(tr[k].c[1],x);
112 }
113 
114 int main()
115 {
116     scanf("%d",&n);
117     int opt,x;
118     for(int i=1;i<=n;i++)
119     {
120         scanf("%d%d",&opt,&x);
121         switch(opt)
122         {
123         case 1:insert(root,x);break;
124         case 2:delt(root,x);break;
125         case 3:printf("%d\n",query_rank(root,x));break;
126         case 4:printf("%d\n",query_num(root,x));break;
127         case 5:ans=0;query_pre(root,x);printf("%d\n",tr[ans].v);break;
128         case 6:ans=0;query_suc(root,x);printf("%d\n",tr[ans].v);break;
129         }
130     }
131     return 0;
132 }

 

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 5783  Solved: 2381
[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.每个数的数据范围:[-1e7,1e7]

 

Source

posted on 2016-01-01 13:05  83131  阅读(181)  评论(0编辑  收藏  举报

导航