bzoj 3224: Tyvj 1728 普通平衡树
来源:互联网 发布:淘宝客推广宣传海报 编辑:程序博客网 时间:2024/06/08 17:25
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 15580 Solved: 6786
[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
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
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
这个题是维护所有数是有序的, 每个rt其实就是这个数的大小所在位置,每个rt左面都比他小, 右面都比他大, 有相同的,他会缩到一个节点, cnt代表这个值的个数。
#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <cmath>using namespace std;typedef long long ll;const int maxn = 2e5 + 7;const int INF = 1e9;int n, m;int ch[maxn][2]; //0做孩子, 1右孩子int f[maxn]; //每个节点的父亲int sz[maxn]; //每个节点为根子树的大小int val[maxn]; //这个节点所表示的值int cnt[maxn]; //这个节点所表示值的数量int mi[maxn]; //这个节点子树的最小值int rev[maxn]; //反转标记int lazy[maxn]; //延迟标记int root; // splay的根int tot; //树所有的节点数量void newnode(int rt, int v, int fa){ f[rt] = fa; val[rt] = v; sz[rt] = cnt[rt] = 1; ch[rt][0] = ch[rt][1] = 0;}void delnode(int &rt) //删除之后, 把相关信息抹掉{ f[rt] = val[rt] = sz[rt] = cnt[rt] = 0; ch[rt][0] = ch[rt][1] = rt = 0;}void pushup(int x){ if(x) sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x]; //计算这个节点为根子树的节点个数}//void pushdown(int x)//{////}void Rotate(int x, int k) // k = 0左旋, k = 1右旋{ int y = f[x];int z = f[y];// pushdown(y); pushdown(x); ch[y][!k] = ch[x][k]; if(ch[x][k]) f[ch[x][k]] = y; f[x] = z; if(z) ch[z][ch[z][1]==y] = x; f[y] = x; ch[x][k] = y; pushup(y), pushup(x);}void splay(int x, int goal){// pushdown(x); while(f[x] != goal) { int y = f[x]; //在这里下传翻转标记,在rotate里下传标记可能会使树形改变导致旋转出错// pushdown(z); pushdown(y); pushdown(x); if(f[y] == goal) Rotate(x, ch[y][0] == x); else { int p = ch[f[y]][0] == y; if(ch[y][p] == x) Rotate(x, !p), Rotate(x, p); else Rotate(y, p), Rotate(x, p); } } pushup(x); if(goal == 0) root = x;}//以x为根的子树 的极值点 0 极小 1 极大int extreme(int x,int k){ while(ch[x][k]) x = ch[x][k]; splay(x, 0); return x;}//以x为根的子树 第k个数的位置int kth(int x, int k){// pushdown(x); if(sz[ch[x][0]]+1 <= k && k <= sz[ch[x][0]]+cnt[x]) return x; else if(sz[ch[x][0]] >= k) return kth(ch[x][0], k); else return kth(ch[x][1], k-sz[ch[x][0]]-cnt[x]);}//查找int Search(int rt, int x){// cout << rt << endl; if(ch[rt][0] && val[rt] > x) return Search(ch[rt][0], x); else if(ch[rt][1] && val[rt] < x) return Search(ch[rt][1], x); return rt;}//前驱:小于x的最大的数int prec(int x){ int k = Search(root, x); splay(k, 0); if(val[k] < x) return k; return extreme(ch[k][0], 1);}//后继:大于x的最小的数int sufc(int x){ int k = Search(root, x); splay(k, 0); if(val[k] > x) return k; return extreme(ch[k][1], 0);}//int Rank(int x){ int k = Search(root, x); splay(k, 0); return sz[ch[root][0]]+1;}//按照二叉树性质插入xvoid Insert(int x){ int y = Search(root, x), k = -1; if(val[y] == x) { cnt[y]++; sz[y]++; for(int yy = y; yy; yy = f[yy]) pushup(yy); } else { int p = prec(x), s = sufc(x); splay(p, 0); splay(s, p); newnode(++tot, x, ch[root][1]); ch[ch[root][1]][0] = tot; for(int z = ch[root][1]; z; z = f[z]) pushup(z); } splay(y, 0);}void Delete(int x) //删除值为x的数{// cout << 1 <<endl; int y = Search(root, x); if(val[y] != x) return ; if(cnt[y] > 1) //因为一个一个删 { cnt[y]--; sz[y]--; for(int yy = y; yy; yy = f[yy]) pushup(yy); } else if(ch[y][0] == 0 || ch[y][1] == 0) { int z = f[y]; ch[z][ch[z][1]==y] = ch[y][ch[y][0]==0]; f[ch[y][ch[y][0]==0]] = z; delnode(y); for(int yy = z; yy; yy = f[yy]) pushup(yy); } else { int p = prec(x), s = sufc(x); splay(p, 0); splay(s, p); ch[ch[root][1]][0] = 0; delnode(ch[ch[root][1]][0]); for(int yy = s; yy; yy = f[yy]) pushup(yy); }}void init(){ root = 1; tot = 0; newnode(++tot, -INF, 0); newnode(++tot, INF, root); ch[root][1] = tot;}int main(){ while(~scanf("%d", &n)) { init(); for(int op, x ; n--;) { scanf("%d", &op); scanf("%d", &x); if(op == 1) Insert(x); else if(op == 2) Delete(x); else if(op == 3) printf("%d\n", Rank(x)-1); else if(op == 4) printf("%d\n", val[kth(root, x+1)]); else if(op == 5) printf("%d\n", val[prec(x)]); else printf("%d\n", val[sufc(x)]); } } return 0;}
阅读全文
0 0
- BZOJ 3224: Tyvj 1728 普通平衡树
- BZOJ 3224 Tyvj 1728 普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树
- 【BZOJ 3224】 Tyvj 1728 普通平衡树
- bzoj 3224/Tyvj 1728 普通平衡树
- bzoj 3224,tyvj 1728普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树
- BZOJ 3224 Tyvj 1728 普通平衡树
- BZOJ 3224 TYVJ 1728 普通平衡树
- BZOJ 3224:Tyvj 1728 普通平衡树
- 【bzoj 3224】【Tyvj 1728】 普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树
- [BZOJ]3224: Tyvj 1728 普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树
- 【bzoj 3224】Tyvj 1728 普通平衡树
- BZOJ 3224: Tyvj 1728 普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树
- bzoj 3224: Tyvj 1728 普通平衡树
- NodeMCU与贝壳物联通信实现远程控制
- JAVA学习中收藏的大神的博客
- 框架模式和设计模式
- zookeeper集群服务搭建
- 为树莓派添加自动运行
- bzoj 3224: Tyvj 1728 普通平衡树
- 第二周总结(一)
- sublime text3 中无法输入中文的问题
- HDOJ HDU 1035 Robot Motion
- CAS单点登录-简介(一)
- MySQL存储引擎学习
- 图解RNN、RNN变体、Seq2Seq、Attention机制
- 矩阵、向量求导法则
- Struts初学小笔记1《2017-09-08》