3224: Tyvj 1728 普通平衡树(finger tree)
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 19122 Solved: 8359
[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]
分析
学了一个神奇的平衡树,叫:finger tree
贴一下模板。。
code
1 #include<cstdio> 2 #include<algorithm> 3 #define ls ch[cur][0] 4 #define rs ch[cur][1] 5 6 using namespace std; 7 8 const int N = 200100; 9 10 int siz[N],val[N],ch[N][2],q[N]; 11 int tot,cnt,Root; 12 13 int getid() { 14 return tot?q[tot--]:++cnt; 15 } 16 void pushup(int cur) { 17 if (!siz[ls]) return; // - 18 siz[cur] = siz[ls] + siz[rs]; 19 val[cur] = val[rs]; 20 } 21 int newNode(int v) { 22 int cur = getid(); 23 siz[cur] = 1;val[cur] = v; 24 ls = rs = 0; 25 return cur; 26 } 27 void copyNode(int x,int y) { 28 ch[x][0] = ch[y][0];ch[x][1] = ch[y][1]; 29 siz[x] = siz[y];val[x] = val[y]; 30 } 31 int Merge(int x,int y) { 32 int cur = getid(); 33 val[cur] = val[y];siz[cur] = siz[x]+siz[y]; //--- 34 ls = x;rs = y; 35 return cur; 36 } 37 void lturn(int cur) { 38 ls = Merge(ls,ch[rs][0]); 39 q[++tot] = rs; 40 rs = ch[rs][1]; 41 } 42 void rturn(int cur) { 43 rs = Merge(ch[ls][1],rs); 44 q[++tot] = ls; 45 ls = ch[ls][0]; 46 } 47 void Maintain(int cur) { 48 if (rs && siz[ls] > siz[rs] * 4) rturn(cur); 49 if (ls && siz[rs] > siz[ls] * 4) lturn(cur); 50 } 51 void Insert(int cur,int x) { 52 if (siz[cur]==1) { 53 ls = newNode(min(val[cur],x)); 54 rs = newNode(max(val[cur],x)); 55 pushup(cur); 56 return ; 57 } 58 if (x > val[ls]) Insert(rs,x); 59 else Insert(ls,x); 60 pushup(cur); 61 Maintain(cur); 62 } 63 void Delete(int cur,int fa,int x) { 64 if (siz[cur]==1) { 65 if (ch[fa][0] == cur) copyNode(fa,ch[fa][1]); //----- 66 else copyNode(fa,ch[fa][0]); 67 return; 68 } 69 fa = cur; 70 if (x > val[ls]) Delete(rs,cur,x); 71 else Delete(ls,cur,x); 72 pushup(cur); 73 Maintain(cur); 74 } 75 int getrnk(int cur,int x) { 76 if (siz[cur]==1) return 1; 77 //{ 78 // if (x > val[cur]) return 2; 79 // return 1; 80 //} 81 if (x > val[ls]) 82 return getrnk(rs,x) + siz[ls]; 83 else return getrnk(ls,x); 84 } 85 int getkth(int cur,int k) { 86 if (siz[cur]==k) return val[cur]; 87 if (k > siz[ls]) 88 return getkth(rs,k-siz[ls]); 89 else return getkth(ls,k); 90 } 91 int main () { 92 int T; 93 scanf("%d",&T); 94 Root = newNode(1e9); 95 while (T--) { 96 int opt,x; 97 scanf("%d%d",&opt,&x); 98 if (opt==1) Insert(Root,x); 99 else if (opt==2) Delete(Root,Root,x); 100 else if (opt==3) printf("%d\n",getrnk(Root,x)); 101 else if (opt==4) printf("%d\n",getkth(Root,x)); 102 else if (opt==5) printf("%d\n",getkth(Root,getrnk(Root,x)-1)); 103 else printf("%d\n",getkth(Root,getrnk(Root,x+1))); // --- 104 } 105 return 0; 106 }
模板的变迁史:
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int N = 200100; 7 8 int siz[N],val[N],ch[N][2]; 9 int q[N],tot; 10 int cnt; 11 int Root; 12 13 int getid() { 14 return tot?q[tot--]:++cnt; 15 } 16 void pushup(int x) { 17 if (!siz[ch[x][0]]) return; // - 18 siz[x] = siz[ch[x][0]] + siz[ch[x][1]]; 19 val[x] = val[ch[x][1]]; 20 } 21 int newNode(int v) { 22 int cur = getid(); 23 siz[cur] = 1;val[cur] = v; 24 ch[cur][0] = ch[cur][1] = 0; 25 return cur; 26 } 27 void copyNode(int x,int y) { 28 ch[x][0] = ch[y][0];ch[x][1] = ch[y][1]; 29 siz[x] = siz[y];val[x] = val[y]; 30 } 31 int merge(int x,int y) { 32 int cur = getid(); 33 val[cur] = val[y];siz[cur] = siz[x]+siz[y]; //--- 34 ch[cur][0] = x;ch[cur][1] = y; 35 return cur; 36 } 37 void lturn(int cur) { 38 ch[cur][0] = merge(ch[cur][0],ch[ch[cur][1]][0]); 39 q[++tot] = ch[cur][1]; 40 ch[cur][1] = ch[ch[cur][1]][1]; 41 } 42 void rturn(int cur) { 43 ch[cur][1] = merge(ch[ch[cur][0]][1],ch[cur][1]); 44 q[++tot] = ch[cur][0]; 45 ch[cur][0] = ch[ch[cur][0]][0]; 46 } 47 void maintain(int cur) { 48 if (ch[cur][1] && siz[ch[cur][0]] > siz[ch[cur][1]] * 4) rturn(cur); 49 if (ch[cur][0] && siz[ch[cur][1]] > siz[ch[cur][0]] * 4) lturn(cur); 50 } 51 void Insert(int cur,int x) { 52 if (siz[cur]==1) { 53 ch[cur][0] = newNode(min(val[cur],x)); 54 ch[cur][1] = newNode(max(val[cur],x)); 55 pushup(cur); 56 return ; 57 } 58 if (x > val[ch[cur][0]]) Insert(ch[cur][1],x); 59 else Insert(ch[cur][0],x); 60 pushup(cur); 61 maintain(cur); 62 } 63 void Delete(int cur,int fa,int x) { 64 if (siz[cur]==1) { 65 if (ch[fa][0] == cur) copyNode(fa,ch[fa][1]); //----- 66 else copyNode(fa,ch[fa][0]); 67 return; 68 } 69 fa = cur; 70 if (x > val[ch[cur][0]]) Delete(ch[cur][1],cur,x); 71 else Delete(ch[cur][0],cur,x); 72 pushup(cur); 73 maintain(cur); 74 } 75 int rnk(int cur,int x) { 76 if (siz[cur]==1) return 1; 77 //{ 78 // if (x > val[cur]) return 2; 79 // return 1; 80 //} 81 if (x > val[ch[cur][0]]) 82 return rnk(ch[cur][1],x) + siz[ch[cur][0]]; 83 else return rnk(ch[cur][0],x); 84 } 85 int kth(int cur,int k) { 86 if (siz[cur]==k) return val[cur]; 87 if (k > siz[ch[cur][0]]) 88 return kth(ch[cur][1],k-siz[ch[cur][0]]); 89 else return kth(ch[cur][0],k); 90 } 91 int main () { 92 int T; 93 scanf("%d",&T); 94 Root = newNode(1e9); 95 while (T--) { 96 int opt,x; 97 scanf("%d%d",&opt,&x); 98 if (opt==1) Insert(Root,x); 99 else if (opt==2) Delete(Root,Root,x); 100 else if (opt==3) printf("%d\n",rnk(Root,x)); 101 else if (opt==4) printf("%d\n",kth(Root,x)); 102 else if (opt==5) printf("%d\n",kth(Root,rnk(Root,x)-1)); 103 else printf("%d\n",kth(Root,rnk(Root,x+1))); // --- 104 } 105 return 0; 106 }
指针
1 // luogu-judger-enable-o2 2 #include<cstdio> 3 #include<iostream> 4 5 using namespace std; 6 7 const int MAXN = 400010; 8 9 struct Node { 10 int val,size; 11 Node *ls,*rs; 12 Node():val(0),size(0),ls(NULL),rs(NULL) { } 13 Node(int v,int s,Node *l,Node *r) { 14 val = v,size = s,ls = l,rs = r; 15 } 16 bool isleaf() { 17 return ls == NULL; 18 } 19 void pushup() { 20 if (!isleaf()) { 21 size = ls->size + rs->size; 22 val = max(ls->val,rs->val); 23 } 24 } 25 }pool[MAXN]; 26 27 Node *newNode(int val,int size,Node *ls,Node *rs) { 28 static int cnt = 0; 29 pool[cnt] = Node(val,size,ls,rs); 30 return &pool[cnt++]; 31 } 32 33 void insert(Node *&cur,int x) { 34 if (cur==NULL) cur = newNode(x,1,NULL,NULL); 35 else { 36 if (cur->isleaf()) { 37 cur->ls = newNode(min(x,cur->val),1,NULL,NULL); 38 cur->rs = newNode(max(x,cur->val),1,NULL,NULL); 39 } 40 else { 41 if (x > cur->ls->val) insert(cur->rs,x); 42 else insert(cur->ls,x); 43 } 44 cur -> pushup(); 45 } 46 } 47 void erase(Node *cur,Node *fa,int x) { 48 if (cur->isleaf()) { 49 if (fa->ls == cur) *fa = *fa->rs; 50 else *fa = *fa->ls; 51 } 52 else { 53 if (x > cur->ls->val) erase(cur->rs,cur,x); 54 else erase(cur->ls,cur,x); 55 cur -> pushup(); 56 } 57 } 58 int rnk(Node *cur,int x) { 59 if (cur->isleaf()) { 60 if (x > cur->val) return 2; 61 return 1; 62 } 63 else { 64 if (x > cur->ls->val) 65 return rnk(cur->rs,x)+cur->ls->size; 66 else return rnk(cur->ls,x); 67 } 68 } 69 int kth(Node *cur,int k) { 70 if (cur->isleaf()) return cur->val; 71 else { 72 if (k > cur->ls->size) 73 return kth(cur->rs,k - cur->ls->size); 74 else return kth(cur->ls,k); 75 } 76 } 77 int main () { 78 int T; 79 scanf("%d",&T); 80 Node *root = NULL; 81 while (T--) { 82 int opt,x; 83 scanf("%d%d",&opt,&x); 84 if (opt==1) insert(root,x); 85 else if (opt==2) erase(root,root,x); 86 else if (opt==3) printf("%d\n",rnk(root,x)); 87 else if (opt==4) printf("%d\n",kth(root,x)); 88 else if (opt==5) printf("%d\n",kth(root,rnk(root,x)-1)); 89 else printf("%d\n",kth(root,rnk(root,x+1))); 90 } 91 return 0; 92 }