bzoj3224 普通平衡树(splay 模板)
Posted 安
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3224 普通平衡树(splay 模板)相关的知识,希望对你有一定的参考价值。
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 11427 Solved: 4878
[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.每个数的数据范围:[-1e7,1e7]
数据如下http://pan.baidu.com/s/1jHMJwO2
Source
#include <cstdio> #define Maxn 1000000 using namespace std; int f[Maxn];//father int ch[Maxn][2];//child ; 0 for left ; 1 for right int key[Maxn];//key int cnt[Maxn];//value int siz[Maxn];//size of subtree int sz,root;//size of tree and root //clear the ndoe void clear(int x) { ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0; } //rightson return 1;left son return 0 int getson(int x) { return ch[f[x]][1]==x; } //update the size void update(int x) { siz[x]=cnt[x]; if (ch[x][0]) siz[x]+=siz[ch[x][0]]; if (ch[x][1]) siz[x]+=siz[ch[x][1]]; } //retation int rotate(int x) { int fa=f[x],fafa=f[fa],k=getson(x); ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa; ch[x][k^1]=fa;f[fa]=x; f[x]=fafa; if (fafa) ch[fafa][ch[fafa][1]==fa]=x; update(fa);update(x); } //rotate until x is the root void splay(int x) { for (int fa;fa=f[x];rotate(x)) if (f[fa]) rotate(getson(x)==getson(fa) ? fa : x); root=x; } int pre() { int now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; return now; } int nex() { int now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; return now; } //find x‘s pos int findpos(int v) { int now=root,ans=0; while(1) { if (v<key[now]) now=ch[now][0]; else { ans+=ch[now][0]?siz[ch[now][0]]:0; if (v==key[now]) { splay(now); return ans+1; } ans+=cnt[now]; now=ch[now][1]; } } } //find pos‘s x int findx(int x) { int now=root; while(1) { if (ch[now][0] && x<=siz[ch[now][0]]) now=ch[now][0]; else { int temp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now]; if (x<=temp) return key[now]; x-=temp; now=ch[now][1]; } } } //ceate a new splay node void create(int v) { sz++; ch[sz][0]=ch[sz][1]=f[sz]=0; key[sz]=v; cnt[sz]=1; siz[sz]=1; //root=sz; } //insert a node void insert(int v) { if (!root) create(v),root=sz; else { int now=root,fa=0; while(1) { if (key[now]==v) { cnt[now]++; update(now);update(fa); splay(now); break; } fa=now; now=ch[fa][v>key[fa]]; if (!now) { create(v); f[sz]=fa; ch[fa][v>key[fa]]=sz; update(fa); splay(sz); break; } } } } void del(int x) { int t=findpos(x); if (cnt[root]>1) { cnt[root]--; update(root); return; } //none if (!ch[root][0] && !ch[root][1]) { clear(root); root=0; return; } //one if (!ch[root][1]) { int temp=root; root=ch[root][0]; f[root]=0; clear(temp); return; } else if (!ch[root][0]) { int temp=root; root=ch[root][1]; f[root]=0; clear(temp); return; } //two int pre1=pre(),temp=root; splay(pre1); f[ch[temp][1]]=root; ch[root][1]=ch[temp][1]; clear(temp); update(root); } int main() { int n,opt,x; scanf("%d",&n); for (int i=1;i<=n;++i) { scanf("%d%d",&opt,&x); switch(opt) { case 1: insert(x); break; case 2: del(x); break; case 3: printf("%d\n",findpos(x)); break; case 4: printf("%d\n",findx(x)); break; case 5: insert(x); printf("%d\n",key[pre()]); del(x); break; case 6: insert(x); printf("%d\n",key[nex()]); del(x); break; } } }
以上是关于bzoj3224 普通平衡树(splay 模板)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 3224: Tyvj 1728 普通平衡树 && loj 104 普通平衡树 (splay树)
BZOJ 3224 普通平衡树 平衡树的两种姿势:SBT,splay
bzoj3224: Tyvj 1728 普通平衡树(打个splay暖暖手)