SPlay 板子
阿新 • • 發佈:2018-11-11
#include<stdio.h> #include<string.h> #include<vector> using namespace std; typedef long long ll; const int maxn=1e6+7; const int N=120005,INF=0x3f3f3f3f; struct Splay_Tree { struct Node { int val,Max,add,Size,son[2]; bool rev; void init(int _val) { val=Max=_val,Size=1; add=rev=son[0]=son[1]=0; } } T[N]; int fa[N],root,tot; /*void pushDown(int x)///下放標記(序列操作) { if(x==0)return ; if(T[x].add) { if(T[x].son[0]) { T[T[x].son[0]].val+=T[x].add; T[T[x].son[0]].Max+=T[x].add; T[T[x].son[0]].add+=T[x].add; } if(T[x].son[1]) { T[T[x].son[1]].val+=T[x].add; T[T[x].son[1]].Max+=T[x].add; T[T[x].son[1]].add+=T[x].add; } T[x].add=0; } if(T[x].rev) { if(T[x].son[0])T[T[x].son[0]].rev^=1; if(T[x].son[1])T[T[x].son[1]].rev^=1; swap(T[x].son[0],T[x].son[1]); T[x].rev=0; } }*/ /*void pushUp(int x)///更新節點(序列操作) { T[x].Max=T[x].val,T[x].Size=1; if(T[x].son[0]) { T[x].Max=max(T[x].Max,T[T[x].son[0]].Max); T[x].Size+=T[T[x].son[0]].Size; } if(T[x].son[1]) { T[x].Max=max(T[x].Max,T[T[x].son[1]].Max); T[x].Size+=T[T[x].son[1]].Size; } }*/ inline void up(int x)///更新節點(普通平衡樹操作) { T[x].Size=1; if(T[x].son[0]) T[x].Size+=T[T[x].son[0]].Size; if(T[x].son[1]) T[x].Size+=T[T[x].son[1]].Size; } void Rotate(int x,int kind)///旋轉,有左旋右旋(反正配合splay用就好了233) { int y=fa[x],z=fa[y]; T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y; T[x].son[kind]=y,fa[y]=x; T[z].son[T[z].son[1]==y]=x,fa[x]=z; up(y); } void Splay(int x,int goal)///把下標為x的元素旋轉到目標的兒子節點 { if(x==goal)return ; while(fa[x]!=goal) { int y=fa[x],z=fa[y]; //pushDown(z),pushDown(y),pushDown(x); int rx=T[y].son[0]==x,ry=T[z].son[0]==y; if(z==goal)Rotate(x,rx); else { if(rx==ry)Rotate(y,ry); else Rotate(x,rx); Rotate(x,ry); } } up(x); if(goal==0)root=x; } int Select(int pos)///查詢第k小元素 { int u=root; //pushDown(u); while(T[T[u].son[0]].Size!=pos) { if(pos<T[T[u].son[0]].Size)u=T[u].son[0]; else { pos-=T[T[u].son[0]].Size+1; u=T[u].son[1]; } //pushDown(u); } Splay(u,root); return u; } void update(int L,int R,int val)///序列操作的區間更新 { int u=Select(L-1),v=Select(R+1); Splay(u,0); Splay(v,u); T[T[v].son[0]].Max+=val; T[T[v].son[0]].val+=val; T[T[v].son[0]].add+=val; } void Reverse(int L,int R)///序列操作的區間翻轉 { int u=Select(L-1),v=Select(R+1); Splay(u,0); Splay(v,u); T[T[v].son[0]].rev^=1; } int query(int L,int R)///區間操作的區間詢問 { int u=Select(L-1),v=Select(R+1); Splay(u,0); Splay(v,u); return T[T[v].son[0]].Max; } int build(int L,int R)///區間操作建樹 { if(L>R)return 0; if(L==R)return L; int mid=(L+R)>>1,sL,sR; T[mid].son[0]=sL=build(L,mid-1); T[mid].son[1]=sR=build(mid+1,R); fa[sL]=fa[sR]=mid; up(mid); return mid; } void init(int n)///區間操作,輸入n個元素建樹 { T[0].init(-INF); for(int i=1,x;i<=n;i++) { scanf("%d",&x); T[i].init(x); } root=build(1,n),fa[root]=0; fa[0]=0,T[0].son[1]=root,T[0].Size=0; } void Insert(int &t,int val,int par=0)///普通平衡樹,往某個地方的下面插入元素,一般是插入根節點 { if(t==0) { t=++tot; T[t].init(val); fa[t]=par; Splay(tot,0); } else { int cur=t; if(val<T[t].val)Insert(T[t].son[0],val,cur); //else if(val==T[t].val)return ; else Insert(T[t].son[1],val,cur); up(cur); } } int find(int t,int v)///普通平衡樹查詢值為v的元素 { if(t==0)return 0; else if(T[t].val==v) { Splay(t,0); return t; } else if(v<T[t].val)return find(T[t].son[0],v); else return find(T[t].son[1],v); } ///刪除根節點元素 void Delete() { if(!T[root].son[0]) { fa[T[root].son[1]]=0; root=T[root].son[1]; } else { int cur=T[root].son[0]; while(T[cur].son[1])cur=T[cur].son[1]; Splay(cur,root); T[cur].son[1]=T[root].son[1]; root=cur,fa[cur]=0,fa[T[root].son[1]]=root; up(root); } } int size() { return T[root].Size; } ///從t開始找值為v的前驅,返回值 int pred(int t,int v) { if(t==0)return v; else { if(v<=T[t].val)return pred(T[t].son[0],v); else { int ans=pred(T[t].son[1],v); if(ans==v) ans=T[t].val,Splay(t,0); return ans; } } } ///查詢下標t節點的前驅返回下標 int pred(int t) { Splay(t,0); int u=T[t].son[0]; if(u==0)return fa[t]; while(T[u].son[1])u=T[u].son[1]; return u; } ///從t開始找值為v的後繼,返回值 int succ(int t,int v) { if(t==0)return v; else { if(v>=T[t].val)return succ(T[t].son[1],v); else { int ans=succ(T[t].son[0],v); if(ans==v) ans=T[t].val,Splay(t,0); return ans; } } } ///查詢下標t節點的後繼返回下標 int succ(int t) { Splay(t,0); int u=T[t].son[1]; if(u==0)return fa[t]; while(T[u].son[0])u=T[u].son[0]; return u; } void Preorder( int t ){///輸出成序列順便檢查是否有邏輯錯誤 if( !t ) return; Preorder( T[t].son[0] ); if(T[t].son[0]&&fa[T[t].son[0]]!=t) printf("!"); printf("%d " , T[t].val ); Preorder( T[t].son[1] ); } void init()///普通平衡樹初始化 { T[1].init(-INF); tot=root=1; } void update(int x)///更新下標為x的節點。。手動操作後呼叫 { while(x!=0) up(x),x=fa[x]; } };