3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 18119 Solved: 7981
[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]
Source
分析:splay模板题,只是需要注意可能有多个相同的数,需要记录值为x的数有多少个.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 200010; int n,m,sizee[maxn],pos[maxn],tot,root,a[maxn]; struct node { int fa,left,right,v,cnt; }e[maxn]; void update(int x) { sizee[x] = e[x].cnt; if (e[x].left != -1) sizee[x] += sizee[e[x].left]; if (e[x].right != -1) sizee[x] += sizee[e[x].right]; } int getsize(int x) { if (x == -1) return 0; return sizee[x]; } void turnr(int x) { int y = e[x].fa; int z = e[y].fa; e[y].left = e[x].right; if (e[x].right != -1) e[e[x].right].fa = y; e[x].fa = z; if (z != -1) { if (e[z].left == y) e[z].left = x; else e[z].right = x; } e[x].right = y; e[y].fa = x; update(y); update(x); } void turnl(int x) { int y = e[x].fa; int z = e[y].fa; e[y].right = e[x].left; if (e[x].left != -1) e[e[x].left].fa = y; e[x].fa = z; if (z != -1) { if (e[z].left == y) e[z].left = x; else e[z].right = x; } e[x].left = y; e[y].fa = x; update(y); update(x); } void splay(int x) { while (e[x].fa != -1) { int y = e[x].fa; int z = e[y].fa; if (z == -1) { if (x == e[y].left) turnr(x); else turnl(x); } else { if (e[z].left == y && e[y].left == x) { turnr(y); turnr(x); } else { if (e[z].right == y && e[y].right == x) { turnl(y); turnl(x); } else { if (e[z].left == y && e[y].right == x) { turnl(x); turnr(x); } else { turnr(x); turnl(x); } } } } } root = x; } int find(int x) { int p = root; while (p != -1) { if (e[p].v == x) return p; if (x < e[p].v) p = e[p].left; else p = e[p].right; } return p; } void del(int x) { int p = find(x); splay(p); if (e[p].cnt > 1) { e[p].cnt--; update(p); return; } if (e[p].left == -1 && e[p].right == -1) { root = -1; return; } if (e[p].left == -1) { root = e[p].right; e[e[p].right].fa = -1; return; } if (e[p].right == -1) { root = e[p].left; e[e[p].left].fa = -1; return; } int j = e[p].left; while (e[j].right != -1) j = e[j].right; splay(j); e[j].right = e[p].right; e[e[p].right].fa = j; update(j); } void insert(int x,int y) { if (e[y].v == x) { e[y].cnt++; splay(y); update(y); return; } if (x < e[y].v) { if (e[y].left == -1) { e[y].left = ++tot; e[tot].left = e[tot].right = -1; e[tot].v = x; e[tot].fa = y; e[tot].cnt = 1; sizee[tot] = 1; return; } else insert(x,e[y].left); } else { if (e[y].right == -1) { e[y].right = ++tot; e[tot].left = e[tot].right = -1; e[tot].v = x; e[tot].fa = y; e[tot].cnt = 1; sizee[tot] = 1; return; } insert(x,e[y].right); } update(y); } int query(int x) { int p = root,res = 0; while (p != -1) { if (x < e[p].v) p = e[p].left; else { res += getsize(e[p].left); if (x == e[p].v) return res + 1; res += e[p].cnt; p = e[p].right; } } return res; } int query2(int x) { int p = root; while (p != -1) { if (e[p].left && x <= sizee[e[p].left]) p = e[p].left; else { int temp = getsize(e[p].left) + e[p].cnt; if (x <= temp) return e[p].v; x -= temp; p = e[p].right; } } return p; } int findl(int x) { int p = root,maxx = 0x7fffffff,cur = x; while (p != -1) { if (e[p].v < x && x - e[p].v < maxx) { maxx = x - e[p].v; cur = e[p].v; } if (x <= e[p].v) p = e[p].left; else p = e[p].right; } return cur; } int findr(int x) { int p = root,maxx = 0x7fffffff,cur = x; while (p != -1) { if(e[p].v > x && e[p].v - x < maxx) { maxx = e[p].v - x; cur = e[p].v; } if (x >= e[p].v) p = e[p].right; else p = e[p].left; } return cur; } int main() { scanf("%d",&n); root = -1; for (int i = 1; i <= n; i++) { int opt,x; scanf("%d%d",&opt,&x); if (opt == 1) { if (root == -1) { root = ++tot; e[tot].left = e[tot].right = e[tot].fa = -1; e[tot].cnt = 1; e[tot].v = x; sizee[tot] = 1; } else insert(x,root); splay(tot); update(tot); } if (opt == 2) del(x); if (opt == 3) printf("%d ",query(x)); if (opt == 4) printf("%d ",query2(x)); if (opt == 5) printf("%d ",findl(x)); if (opt == 6) printf("%d ",findr(x)); } return 0; }