BZOJ 3224 普通平衡树 treap or vector
2016-01-01 13:05
435 查看
很明显这是一道treap的题,但看了黄学长的博客后,也让我大开了眼界,没想到vector也能用那么短的编码量把这道题AC,着实令我敬佩。这也提醒了我 STL 的重要性。 的确, 对于C++ 选手来说,如果能灵活地使用 STL, 的确受益匪浅(虽然速度可能比其他的慢一点,但正确性和编程复杂度都比其他的好,如果时间复杂度允许,在紧张的编程时间内,STL或许会是不错的选择)。
这是STL(vector)的代码, 用到了 insert, lowerr_bound, erase 等函数, 加油。(1700多毫秒)
接下来肯定是treap 的代码了,orz 黄学长。从他那里,着实学了不少好东西。(300多毫秒,比上面快多了吧!这个时间差距主要是因为查如何删除造成的)。
Submit: 5783 Solved: 2381
[Submit][Status][Discuss]
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
84185
492737
2.每个数的数据范围:[-1e7,1e7]
这是STL(vector)的代码, 用到了 insert, lowerr_bound, erase 等函数, 加油。(1700多毫秒)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<set> #include<vector> #include<algorithm> #define inf 1000000000 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int 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() { n=read(); a.reserve(200000); int f,x; for(int i=1;i<=n;i++) { f=read();x=read(); switch(f) { 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; }
接下来肯定是treap 的代码了,orz 黄学长。从他那里,着实学了不少好东西。(300多毫秒,比上面快多了吧!这个时间差距主要是因为查如何删除造成的)。
#include<cstdio> #include<iostream> #include<cstdlib> #define rep(i,j,k) for(int i = j; i <= k; i++) using namespace std; struct node{ int c[2], w, s, v, rnd; } tr[100005]; int n, ans, root, size; int read() { int s = 0, t = 1; char c= getchar(); while( !isdigit(c) ){ if( c == '-' ) t = -1; c = getchar(); } while( isdigit(c) ){ s = s * 10 + c - '0'; c = getchar(); } return s * t; } void update(int k) { tr[k].s = tr[tr[k].c[0]].s + tr[tr[k].c[1]].s + tr[k].w; } void rorate(int&k,int d) { int y = tr[k].c[d^1]; tr[k].c[d^1] = tr[y].c[d]; tr[y].c[d] = k; update(k), update(y), k = y; } void insert(int&k,int x) { if( k == 0 ){ ++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(); return; } tr[k].s++; if( x == tr[k].v ) tr[k].w++; else if( x < tr[k].v) { insert(tr[k].c[0],x); if( tr[tr[k].c[0]].rnd > tr[k].rnd )rorate(k,1); } else { insert(tr[k].c[1],x); if( tr[tr[k].c[1]].rnd > tr[k].rnd ) rorate(k,0); } } void delt(int&k,int x) { if( !k ) return; if( tr[k].v == x ){ if( tr[k].w > 1 ) { tr[k].w--, tr[k].s--; return; } else { if( tr[k].c[0] * tr[k].c[1] == 0 ) k = tr[k].c[0] + tr[k].c[1]; else { if( tr[tr[k].c[0]].rnd > tr[tr[k].c[1]].rnd ) { rorate(k,1); delt(k,x); } else { rorate(k,0); delt(k,x); } } } } else { tr[k].s--; if( x < tr[k].v ) delt(tr[k].c[0],x); else delt(tr[k].c[1],x); } } int query_rank(int k,int x) { if( !k ) return 0; if( tr[k].v == x ) return tr[tr[k].c[0]].s + 1; else if( tr[k].v < x ) return tr[tr[k].c[0]].s + tr[k].w + query_rank(tr[k].c[1],x); else return query_rank(tr[k].c[0],x); } int query_num(int k,int num) { if( !k ) return 0; if( tr[tr[k].c[0]].s >= num ) return query_num(tr[k].c[0],num); 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); else return tr[k].v; } void query_pre(int k,int x) { if( !k ) return; if( tr[k].v < x ){ ans = k, query_pre(tr[k].c[1],x); } else query_pre(tr[k].c[0],x); } void query_suc(int k,int x) { if( !k ) return; if( tr[k].v > x ){ ans = k, query_suc(tr[k].c[0],x); } else query_suc(tr[k].c[1],x); } int main() { scanf("%d",&n); int opt,x; for(int i=1;i<=n;i++) { scanf("%d%d",&opt,&x); switch(opt) { case 1:insert(root,x);break; case 2:delt(root,x);break; case 3:printf("%d\n",query_rank(root,x));break; case 4:printf("%d\n",query_num(root,x));break; case 5:ans=0;query_pre(root,x);printf("%d\n",tr[ans].v);break; case 6:ans=0;query_suc(root,x);printf("%d\n",tr[ans].v);break; } } return 0; }
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
101 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
10646584185
492737
HINT
1.n的数据范围:n<=1000002.每个数的数据范围:[-1e7,1e7]
Source
平衡树相关文章推荐
- OP01-delete_kernel
- 2015年度总结--android开发
- 代码之美
- 将viewController放进NavigationController的几种方式
- Java回调机制解析
- T-SQL触发器,限制一次只能删除一条数据
- viewDidLoad()注意事项
- css中背景图片路径问题
- 3n+1问题
- 建立序列
- IKVM.NET
- Linux命令后台执行技巧小结
- 设计模式之门面模式
- ROS下AR.Drone 2.0相机标定
- Android开发之玩转SwitchButton
- 使用AppCompat_v7 21.0.0d的几个兼容问题
- LeetCode - Search a 2D Matrix
- <LeetCode><Medium>15 ThreeNums
- python类:描述器Descriptors和元类MetaClasses
- MySQL安装详细步骤