[CODEVS1343][HNOI]蚱蜢(平衡树splay)
2016-03-23 23:23
399 查看
题目描述
传送门题解
在线段树即将写吐之际改了平衡树,没想到吃屎程度不减反增。调了一晚上,想不出哪里出错了,最终的原因是一个小地方。
思路是按照位置存储,每一次找位置(find) ,维护maxn。求区间的时候将区间的前驱和后继splay到根和根的右儿子,添加的时候把要插在两个结点中间的两个结点splay到根和根的右儿子,删除的时候把结点的前驱和后继splay到根和根的右儿子,这样我们就可以对根的右儿子的左儿子进行操作来达到目的。
要注意的是,蚱蜢跳啊跳时insert和del的顺序,这个很重要,因为在平衡树中是按照位置存储的,每一次需要find到它的位置,del之后位置就不存在了。
代码
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=2e5+5; const int INF=2e9; int n,m,st,cnt; int a[max_n]; int root,sz; int ch[max_n][2],f[max_n],size[max_n],maxn[max_n],key[max_n]; inline bool get(int x){ return ch[ f[x] ][1]==x; } inline void update(int x){ if (x){ size[x]=1; maxn[x]=key[x]; if (ch[x][0]){ size[x]+=size[ ch[x][0] ]; maxn[x]=max(maxn[x],maxn[ ch[x][0] ]); } if (ch[x][1]){ size[x]+=size[ ch[x][1] ]; maxn[x]=max(maxn[x],maxn[ ch[x][1] ]); } } } inline void rotate(int x){ int old=f[x],oldf=f[old],which=get(x); ch[old][which]=ch[x][which^1]; f[ ch[old][which] ]=old; ch[x][which^1]=old; f[old]=x; f[x]=oldf; if (oldf) ch[oldf][ ch[oldf][1]==old ]=x; update(old); update(x); } inline void splay(int x,int tar){ for (int fa;(fa=f[x])!=tar;rotate(x)) if (f[fa]!=tar) rotate( (get(x)==get(fa)) ?fa:x ); if (!tar) root=x; } inline int build(int l,int r,int fa){ if (l>r) return 0; int mid=(l+r)>>1; int now=++sz; key[now]=a[mid]; maxn[now]=a[mid]; size[now]=1; f[now]=fa; int lch=build(l,mid-1,now); int rch=build(mid+1,r,now); ch[now][0]=lch; ch[now][1]=rch; update(now); return now; } //Find the xth number inline int find(int x){ int now=root; while (1){ if (ch[now][0]&&x<=size[ ch[now][0] ]) now=ch[now][0]; else{ int temp=1; if (ch[now][0]) temp+=size[ ch[now][0] ]; if (x<=temp) return now; x-=temp; now=ch[now][1]; } } } //Find the xth number's val inline int findval(int x){ int now=root; while (1){ if (ch[now][0]&&x<=size[ ch[now][0] ]) now=ch[now][0]; else{ int temp=1; if (ch[now][0]) temp+=size[ ch[now][0] ]; if (x<=temp) return key[now]; x-=temp; now=ch[now][1]; } } } inline void Query(int L,int R){ //L-1 R+1 int aa=find(L); int bb=find(R+2); splay(aa,0); splay(bb,aa); int ans=maxn[ ch[ ch[root][1] ][0] ]; printf("%d\n",ans); update(ch[root][1]); update(root); } //Insert val to x inline void Insert(int x,int val){ //x-1 x int aa=find(x); int bb=find(x+1); splay(aa,0); splay(bb,aa); ch[ ch[root][1] ][0]=++sz; f[sz]=ch[root][1]; ch[sz][0]=ch[sz][1]=0; size[sz]=1; key[sz]=val; maxn[sz]=val; update(f[sz]); update(root); } inline void del(int x){ //x-1 x+1 int aa=find(x); int bb=find(x+2); splay(aa,0); splay(bb,aa); ch[ ch[root][1] ][0]=0; update(ch[root][1]); update(root); } int main(){ scanf("%d%d",&n,&m); a[1]=-INF; a[n+2]=INF; for (int i=1;i<=n;++i) scanf("%d",&a[i+1]); root=build(1,n+2,0); for (int i=1;i<=m;++i){ scanf("%d",&st); char c=getchar(); while (c!='L'&&c!='D') c=getchar(); scanf("%d",&cnt); if (c=='L'){ //query int L=st-cnt; int R=st-1; Query(L,R); //change int val=findval(st+1);//st del(st); Insert(L,val); } else{ //query int L=st+1; int R=st+cnt; Query(L,R); //change int val=findval(st+1);//st del(st); Insert(R,val); } } }
总结
①添加和删除一定要想好。②平衡树还是要继续熟悉。
相关文章推荐
- mapreduce工作原理
- unity Game Center iOS 认证失败social.authenticate
- 【数据结构与算法】十二 字符串搜索
- 【c++】字符串最后一个单词的长度
- lintcode:Topological Sorting
- 20160317第一题
- 【c++】字符串最后一个单词的长度
- ubuntu下eclipse无法启动问题
- Android ScrollView 去掉 scrollbar 和 阴影
- Hadoop自定义 inputformat 和outputformat 实现图像的读写
- C/C++ 服务端性能评测和检测优化工具
- java中传参
- IOS开发之OC学习笔记(中)
- 扑克牌大小
- synchronized和ReentrantLock的区别
- 括号配对
- Hibernate 简介
- 塔防游戏中iTweenPath路点插件的使用
- 二代旅游网站程序管理系统V1.0正式发布
- 盒子嵌套问题 (二分图||费用流)