1. 程式人生 > >bzoj4825 [Hnoi2017]單旋

bzoj4825 [Hnoi2017]單旋

max reg 開始 urn ace -- || namespace while

我寫的第一道HNOI2017的題。。。

記得去年(沒錯就是去年)不會splay,然後spaly GG現在看好water啊

參照已經AFO的QYP巨佬的手玩結論(orzorzorz):spaly操作雖然是\(O(n)\)的,但是只需修改幾條邊(So 你可以開個數組來維護splay)

Insert:

查出前驅和後繼,x會接在深度大的下面

以splay min為例:

一開始x(key最小的點)並沒有lson,只有father和rson;spaly之後,rson取代x的位置,x變成新的root,father沒有;x的rson變成了以前的root。只需修改幾個。

splay max就把l,r互換就可以了。

這很明顯用Link-Cut Tree來維護辣。然後我順便把BST也給維護了。(就幾個)
常數巨大。

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
#define il inline
#define rg register
#define vd void
#define sta static
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while
(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar(); while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } const int maxn=1e5+1; set<int>yyb; namespace LCT{ int rt=0,ch[maxn][2],fa[maxn],siz[maxn];bool rev[maxn]; int
f[maxn],c[maxn][2]; il bool isrt(const int&x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} il vd upd(const int&x){siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;} il vd down(const int&x){if(rev[x])rev[x]=0,swap(ch[x][0],ch[x][1]),rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;} il vd rotate(const int&x){ sta int y,z,o;y=fa[x],z=fa[y],o=x==ch[y][1]; if(!isrt(y))ch[z][y==ch[z][1]]=x;fa[x]=z; ch[y][o]=ch[x][!o];fa[ch[x][!o]]=y; ch[x][!o]=y,fa[y]=x;upd(y); } il vd splay(const int&x){ sta int stk[maxn],top;stk[top=1]=x; for(rg int i=x;!isrt(i);i=fa[i])stk[++top]=fa[i]; while(top)down(stk[top--]); for(rg int y=fa[x],z=fa[y];!isrt(x);rotate(x),y=fa[x],z=fa[y]) if(!isrt(y))rotate(((x==ch[y][0])^(y==ch[z][0]))?x:y); upd(x); } il vd access(int x){for(rg int y=0;x;x=fa[y=x])splay(x),ch[x][1]=y,upd(x);} il vd makeroot(const int&x){access(x),splay(x),rev[x]^=1;} il vd link(const int&x,const int&y){if(x&&y)makeroot(x),fa[x]=y;} il vd cut(const int&x,const int&y){if(x&&y)makeroot(x),access(y),splay(y),fa[x]=ch[y][0]=0;} il int depth(const int&x){makeroot(rt);access(x),splay(x);return siz[x];} il int Insert(const int&x){ sta set<int>::iterator it;it=yyb.insert(x).first; if(rt==0){rt=x;siz[rt]=1;return 1;} sta int pre,nxt;pre=nxt=0; if(it!=yyb.begin())--it,pre=*it,++it; ++it;if(it!=yyb.end())nxt=*it; if(!pre)link(x,nxt),c[nxt][0]=x,f[x]=nxt; else if(!nxt)link(x,pre),c[pre][1]=x,f[x]=pre; else if(depth(pre)>depth(nxt))link(x,pre),c[pre][1]=x,f[x]=pre; else link(x,nxt),c[nxt][0]=x,f[x]=nxt; return depth(x); } il int Spaly_Min(){ sta int x,ret; x=*yyb.begin(); if(rt==x)return 1; ret=depth(x),cut(x,f[x]),cut(x,c[x][1]),link(x,rt),link(f[x],c[x][1]); c[f[x]][0]=c[x][1];f[c[x][1]]=f[x]; f[x]=0;c[x][1]=rt;f[rt]=x;rt=x; return ret; } il int Spaly_Max(){ sta int x,ret; x=*--yyb.end(); if(rt==x)return 1; ret=depth(x),cut(x,f[x]),cut(x,c[x][0]),link(x,rt),link(f[x],c[x][0]); c[f[x]][1]=c[x][0];f[c[x][0]]=f[x]; f[x]=0;c[x][0]=rt;f[rt]=x;rt=x; return ret; } il vd Del_Root(){ yyb.erase(yyb.find(rt)); if(c[rt][0])cut(rt,c[rt][0]),rt=c[rt][0],f[rt]=0; else if(c[rt][1])cut(rt,c[rt][1]),rt=c[rt][1],f[rt]=0; else rt=0; } }using namespace LCT; int main(){ #ifdef xzz freopen("4825.in","r",stdin); freopen("4825.out","w",stdout); #endif int m=gi();sta int opt[maxn],x[maxn],y[maxn]; for(rg int i=1;i<=m;++i){opt[i]=gi();if(opt[i]==1)x[i]=gi(),y[++y[0]]=x[i];} sort(y+1,y+y[0]+1); for(rg int i=1;i<=m;++i)if(opt[i]==1)x[i]=lower_bound(y+1,y+y[0]+1,x[i])-y; for(rg int i=1;i<=m;++i){ if(opt[i]==1)printf("%d\n",Insert(x[i])); else if(opt[i]==2)printf("%d\n",Spaly_Min()); else if(opt[i]==3)printf("%d\n",Spaly_Max()); else if(opt[i]==4)printf("%d\n",Spaly_Min()),Del_Root(); else printf("%d\n",Spaly_Max()),Del_Root(); } return 0; }

bzoj4825 [Hnoi2017]單旋