並不對勁的bzoj4825:loj2018:p3721:[HNOI2017]單旋
阿新 • • 發佈:2019-02-18
lib 題目 數據結構 getch 最小值 turn clas 維護 ++
題目大意
spaly是一種數據結構,它是只有單旋的splay
有一個初始為空的spaly,\(m\)(\(m\leq10^5\))次操作,每個操作是以下5種中的一種:
1.向spaly中插入一個數(過程和treap的插入類似,只不過插入之後不會調整),並詢問這個數的深度
2.詢問最小值的深度,並將它splay到根
3.詢問最大值的深度,並將它splay到根
4.詢問最小值的深度,將它splay到根並把它刪掉
5.詢問最大值的深度,將它splay到根並把它刪掉
題解
直接維護spaly的話,spaly不一定平衡,“從一個根走到一個點”和“把一個點旋轉到根”的復雜度會很大
對於1操作,發現新插入的數的父親一定是它的前驅或者後繼中深度更大的那個,直接把它接過去,並把它的深度置為父親的深度+1就行
對於2,3,4,5操作,發現被splay的點只可能是最小或最大的點
在把最小值或最大值轉到根時,會發現只要把它的兒子接到它的父親、把原來的根接到它就可以
在這個過程中,要把它子樹外的點深度+1,如果還要刪掉它的話就把所有點深度-1
用splay維護前驅後繼、最大值最小值、區間加單點查詢
代碼
#include<algorithm> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> #include<iomanip>0 #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define rep(i,x,y) for(register int i=(x);i<=(y);++i) #define dwn(i,x,y) for(register int i=(x);i>=(y);--i) #define maxn 100010 #define inf 2147483647 #define ls son[u][0] #define rs son[u][1] using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)&&ch!=‘-‘)ch=getchar(); if(ch==‘-‘)f=-1,ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar(); return x*f; } void write(int x) { if(x==0){putchar(‘0‘),putchar(‘\n‘);return;} int f=0;char ch[20]; if(x<0)putchar(‘-‘),x=-x; while(x)ch[++f]=x%10+‘0‘,x/=10; while(f)putchar(ch[f--]); putchar(‘\n‘); return; } int dep[maxn],son[maxn][2],fa[maxn],key[maxn],mk[maxn],rt; int fakefa[maxn],fakeson[maxn][2],fakert,n,cnt; void mark(int u,int k){if(u)dep[u]+=k,mk[u]+=k;} void pd(int u){if(mk[u]&&u)mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;} int getso(int u){return son[fa[u]][0]!=u;} int newnd(int k,int f){int u=++cnt;ls=rs=0,key[u]=k,fa[u]=f;return u;} void rot(int u) { int fu=fa[u],ffu=fa[fu],l=getso(u),fl=getso(fu),r=l^1,rson=son[u][r]; fa[rson]=fu,fa[u]=ffu,fa[fu]=u,son[u][r]=fu,son[fu][l]=rson,son[ffu][fl]=u; } void splay(int u,int k) { pd(u);while(fa[u]!=k){if(mk[fa[u]])cout<<"nooo"<<endl;if(fa[fa[u]]!=k)rot(getso(u)^getso(fa[u])?u:fa[u]);rot(u);} if(!k)rt=u; } void fnd(int k) { int u=rt; while(key[u]!=k&&son[u][key[u]<k])pd(u),u=son[u][key[u]<k]; splay(u,0); } int nxt(int k,int f) { fnd(k);int u=rt; if((key[u]<k&&!f)||(key[u]>k&&f))return u; pd(u),u=son[u][f]; while(u&&son[u][f^1])pd(u),u=son[u][f^1]; return u; } void ins(int k) { int lk=nxt(k,0),rk=nxt(k,1),mxk=dep[lk]>dep[rk]?lk:rk; splay(lk,0),splay(rk,lk); son[rk][0]=newnd(k,rk),dep[cnt]=dep[mxk]+1; if(mxk<=2)fakert=cnt; else fakeson[mxk][key[mxk]<k?1:0]=cnt,fakefa[cnt]=mxk; } void del(int k) { int lk=nxt(k,0),rk=nxt(k,1); splay(lk,0),splay(rk,lk); son[rk][0]=0; } void add(int l,int r,int k) { int lk=nxt(l,0),rk=nxt(r,1); //cout<<"adl:"<<l<<" adr:"<<r<<" adk:"<<k<<endl; splay(lk,0),splay(rk,lk),mark(son[rk][0],k); } int spaly(int u,int f) { int res; res=dep[u],dep[u]=1,add(f?-inf+1:key[fakefa[u]],f?key[fakefa[u]]:inf-1,1); fakeson[fakefa[u]][f]=fakeson[u][f^1],fakefa[fakeson[u][f^1]]=fakefa[u]; fakefa[fakert]=u,fakeson[u][f^1]=fakert,fakert=u; return res; } int main() { rt=newnd(inf,0),son[rt][0]=newnd(-inf,rt); n=read(); while(n--) { int f=read(); if(f==1) { int k=read();ins(k); write(dep[cnt]); } else if(f==2) { int ans=0,u=nxt(-inf,1); if(fakert!=u)ans=spaly(u,0); else ans=1; write(ans); } else if(f==3) { int ans=0,u=nxt(inf,0); if(fakert!=u)ans=spaly(u,1); else ans=1; write(ans); } else if(f==4) { int ans=0,u=nxt(-inf,1); if(fakert!=u)ans=spaly(u,0); else ans=1; write(ans); fakert=fakeson[u][1],fakefa[fakert]=0,del(key[u]),add(-inf+1,inf-1,-1); } else if(f==5) { int ans=0,u=nxt(inf,0); if(fakert!=u)ans=spaly(u,1); else ans=1; write(ans); fakert=fakeson[u][0],fakefa[fakert]=0,del(key[u]),add(-inf+1,inf-1,-1); } } return 0; }
並不對勁的bzoj4825:loj2018:p3721:[HNOI2017]單旋