【bzoj 3595】: [Scoi2014]方伯伯的Oj
2018-07-30 16:23
363 查看
传送门&& 原题解
蒟蒻终于做到一道方伯伯的题了……
调了一个上午一直TLE(发现自己打了好久的splay板子竟然是错的这种丢人事情我就不说了)
很明显,要建两棵树,$T1$维护排名,$T2$维护编号,$T2$表示编号为$x$的点在$T1$中的节点编号
操作一:在$T2$中找到编号,到$T1$算排名,然后更新$T2$
其他操作类似
然后重点讲一下分点操作
因为只有$10^5$个操作,但却有$10^8$个点,所以不可能对每一个点都建树
于是我们考虑一下,让splay的每一个节点代表的不是点,而是一个区间。当需要用到点时,再把这个点从区间中分裂出来
这样可以保证不需要用到的节点不会影响复杂度
关于分点操作具体如何实现,可以参考代码
蒟蒻终于做到一道方伯伯的题了……
调了一个上午一直TLE(发现自己打了好久的splay板子竟然是错的这种丢人事情我就不说了)
很明显,要建两棵树,$T1$维护排名,$T2$维护编号,$T2$表示编号为$x$的点在$T1$中的节点编号
操作一:在$T2$中找到编号,到$T1$算排名,然后更新$T2$
其他操作类似
然后重点讲一下分点操作
因为只有$10^5$个操作,但却有$10^8$个点,所以不可能对每一个点都建树
于是我们考虑一下,让splay的每一个节点代表的不是点,而是一个区间。当需要用到点时,再把这个点从区间中分裂出来
这样可以保证不需要用到的节点不会影响复杂度
关于分点操作具体如何实现,可以参考代码
//minamoto #include<bits/stdc++.h> using namespace std; const int N=330005,INF=0x3f3f3f3f; #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<15,stdin),p1==p2)?EOF:*p1++) char buf[1<<15],*p1=buf,*p2=buf; inline int read(){ #define num ch-'0' char ch;bool flag=0;int res; while(!isdigit(ch=getc())) (ch=='-')&&(flag=true); for(res=num;isdigit(ch=getc());res=res*10+num); (flag)&&(res=-res); #undef num return res; } char obuf[1<<24],*o=obuf; void print(int x){ if(x>9) print(x/10); *o++=x%10+48; } map<int,int> f;int n,m,ans; struct node{ int fa,ch[2]; int sz,l,r; } e ; int cnt,root; void pushup(int x){ e[x].sz=e[e[x].ch[0]].sz+e[e[x].ch[1]].sz+e[x].r-e[x].l+1; } void rotate(int x){ int y=e[x].fa,z=e[y].fa; int op= e[y].ch[1]==x; e[x].fa=z; if(z) e[z].ch[e[z].ch[1]==y]=x; e[y].ch[op]=e[x].ch[op^1],e[e[x].ch[op^1]].fa=y; e[y].fa=x;e[x].ch[op^1]=y; pushup(x),pushup(y); } void splay(int x,int goal){ while(e[x].fa!=goal){ int y=e[x].fa,z=e[y].fa; if(z!=goal) ((e[z].ch[0]==y)^(e[y].ch[0]==x))?rotate(x):rotate(y); rotate(x); } pushup(x); if(goal==0) root=x; } int query(int x){ splay(x,0); return e[x].sz-e[e[x].ch[1]].sz; } void pop(int x){ int lower=e[x].ch[0]; int upper=e[x].ch[1]; while(e[lower].ch[1]) lower=e[lower].ch[1]; while(e[upper].ch[0]) upper=e[upper].ch[0]; if(!lower&&!upper) {root=0;return;} if(!lower){ splay(upper,0); e[x].fa=e[upper].ch[0]=0; e[x].sz=1,pushup(upper); } else if(!upper){ splay(lower,0); e[x].fa=e[lower].ch[1]=0; e[x].sz=1,pushup(lower); } else{ splay(lower,0),splay(upper,lower); e[upper].ch[0]=e[x].fa=0; e[x].sz=1; pushup(upper),pushup(lower); } } int getKth(int x){ int now=root; while(true){ int sum=e[e[now].ch[0]].sz+e[now].r-e[now].l+1; if(e[e[now].ch[0]].sz>=x) now=e[now].ch[0]; else if(sum>=x){x-=e[e[now].ch[0]].sz;break;} else x-=sum,now=e[now].ch[1]; } return e[now].l+x-1; } void push_front(int x){ if(!root){root=x;return;} int fa=root; while(e[fa].ch[0]) e[fa].sz++,fa=e[fa].ch[0]; e[fa].sz++; e[fa].ch[0]=x,e[x].fa=fa; splay(x,0); } void push_back(int x){ if(!root){root=x;return;} int fa=root; while(e[fa].ch[1]) e[fa].sz++,fa=e[fa].ch[1]; e[fa].sz++; e[fa].ch[1]=x,e[x].fa=fa; splay(x,0); } void split(int x,int id){ int l=e[x].l,r=e[x].r,ls,rs; if(l==r) return; if(l==id){ rs=++cnt; f[r]=rs,f[id]=x; e[rs].ch[1]=e[x].ch[1]; e[e[rs].ch[1]].fa=rs; e[x].ch[1]=rs,e[rs].fa=x; e[rs].l=l+1,e[rs].r=r; e[x].r=l; pushup(rs),pushup(x); } else if(r==id){ ls=++cnt; f[r-1]=ls,f[id]=x; e[ls].ch[0]=e[x].ch[0]; e[e[ls].ch[0]].fa=ls; e[x].ch[0]=ls,e[ls].fa=x; e[ls].l=l,e[ls].r=r-1; e[x].l=r; pushup(ls),pushup(x); } else{ ls=++cnt,rs=++cnt; f[id]=x,f[id-1]=ls,f[r]=rs; e[ls].ch[0]=e[x].ch[0],e[rs].ch[1]=e[x].ch[1]; e[e[ls].ch[0]].fa=ls,e[e[rs].ch[1]].fa=rs; e[x].ch[0]=ls,e[x].ch[1]=rs,e[ls].fa=x,e[rs].fa=x; e[x].l=e[x].r=id; e[ls].l=l,e[ls].r=id-1; e[rs].l=id+1,e[rs].r=r; pushup(ls),pushup(rs),pushup(x); } splay(x,0); } void init(){ root=cnt=1; e[1].l=1,e[1].r=n,e[1].sz=n; f =1; } int main(){ //freopen("testdata.in","r",stdin); n=read(),m=read(); init(); while(m--){ int opt=read(); switch(opt){ case 1:{ int oid=read()-ans,nid=read()-ans; int x=f.lower_bound(oid)->second; split(x,oid); ans=query(x); e[x].l=e[x].r=nid,f[nid]=x; print(ans),*o++='\n'; break; } case 2:{ int id=read()-ans; int x=f.lower_bound(id)->second; split(x,id); ans=query(x); pop(x); push_front(x); print(ans),*o++='\n'; break; } case 3:{ int id=read()-ans; int x=f.lower_bound(id)->second; split(x,id); ans=query(x); pop(x); push_back(x); print(ans),*o++='\n'; break; } case 4:{ int k=read()-ans; ans=getKth(k); print(ans),*o++='\n'; break; } } } fwrite(obuf,o-obuf,1,stdout); return 0; }
相关文章推荐
- 【bzoj 3595】: [Scoi2014]方伯伯的Oj
- [BZOJ3595][SCOI2014]方伯伯的OJ(平衡树)
- 【Treap】[Scoi2014] bzoj3595 方伯伯的Oj
- 【双Treap】[Scoi2014] bzoj3595 方伯伯的Oj
- BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap
- [BZOJ]3594 [SCOI2014] 方伯伯的玉米田 二维树状数组 + dp
- 【bzoj3594[Scoi2014]方伯伯的玉米田】动规+二维树状数组
- bzoj 3594: [Scoi2014]方伯伯的玉米田
- bzoj3594: [Scoi2014]方伯伯的玉米田【动态规划+二维树状数组优化】
- BZOJ 3594 [SCOI 2014] 方伯伯的玉米田 (DP,树状数组优化)
- 【BZOJ3598】【SCOI2014】方伯伯的商场之旅
- BZOJ 3597 [Scoi2014]方伯伯运椰子
- [BZOJ]3597: [Scoi2014]方伯伯运椰子 01分数规划+spfa
- SCOI2014 方伯伯的OJ onlinejudge
- BZOJ3594 [Scoi2014]方伯伯的玉米田 【树状数组优化dp】
- BZOJ-3595 方伯伯的OJ 双Treap
- BZOJ 3594: [Scoi2014]方伯伯的玉米田
- 【bzoj3594】【SCOI2014】【方伯伯的玉米田】【dp+二维树状数组】
- 【bzoj3598】: [Scoi2014]方伯伯的商场之旅
- BZOJ3598 [Scoi2014]方伯伯的商场之旅