点操作:
splay树可以一个一个的插入结点,这样的splay树是有序树,结点权值大于左儿子小于右儿子
这样就是点操作
区间操作:
还有就是可以自己建树,这样的splay树就不是按权值的有序树,它不满足结点权值大于左儿子小于右儿子,,
但是它也是有顺序的,无论怎么伸展,把它的结点中序遍历结果就是原来的数组顺序。
因此自己建树可以操作区间!
点操作模板
// File Name: ACM/bzoj/1208.cpp // Author: Zlbing // Created Time: 2013年08月08日 星期四 16时33分53秒 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=8e4+100; const int mod=1000000; struct SplayTree { int sz[MAXN]; int ch[MAXN][2]; int pre[MAXN]; int rt,top; inline void up(int x){ sz[x] = cnt[x] + sz[ ch[x][0] ] + sz[ ch[x][1] ]; } inline void Rotate(int x,int f){ int y=pre[x]; ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x; ch[x][f] = y; pre[y] = x; up(y); } inline void Splay(int x,int goal){//将x旋转到goal的下面 while(pre[x] != goal){ if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x); else { int y=pre[x],z=pre[y]; int f = (ch[z][0]==y); if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f); else Rotate(y,f),Rotate(x,f); } } up(x); if(goal==0) rt=x; } inline void RTO(int k,int goal){//将第k位数旋转到goal的下面 int x=rt; while(sz[ ch[x][0] ] != k-1) { if(k < sz[ ch[x][0] ]+1) x=ch[x][0]; else { k-=(sz[ ch[x][0] ]+1); x = ch[x][1]; } } Splay(x,goal); } inline void vist(int x){ if(x){ printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d sz=%d ",x,ch[x][0],ch[x][1],val[x],sz[x]); vist(ch[x][0]); vist(ch[x][1]); } } inline void Newnode(int &x,int c){ x=++top; ch[x][0] = ch[x][1] = pre[x] = 0; sz[x]=1; cnt[x]=1; val[x] = c; } inline void init(){ ans=0;type=-1; ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; rt=top=0; cnt[0]=0; Newnode(rt,-INF); Newnode(ch[rt][1],INF); pre[top]=rt; sz[rt]=2; } inline void Insert(int &x,int key,int f){ if(!x) { Newnode(x,key); pre[x]=f; Splay(x,0); return ; } if(key==val[x]){ cnt[x]++; sz[x]++; return ; }else if(key<val[x]) { Insert(ch[x][0],key,x); } else { Insert(ch[x][1],key,x); } up(x); } void Del(){ //删除根结点 int t=rt; if(ch[rt][1]) { rt=ch[rt][1]; RTO(1,0); ch[rt][0]=ch[t][0]; if(ch[rt][0]) pre[ch[rt][0]]=rt; } else rt=ch[rt][0]; pre[rt]=0; up(rt); } void findpre(int x,int key,int &ans){ //找key前趋 if(!x) return ; if(val[x] <= key){ ans=x; findpre(ch[x][1],key,ans); } else findpre(ch[x][0],key,ans); } void findsucc(int x,int key,int &ans){ //找key后继 if(!x) return ; if(val[x]>=key) { ans=x; findsucc(ch[x][0],key,ans); } else findsucc(ch[x][1],key,ans); }
//找第K大数 inline int find_kth(int x,int k){ if(k<sz[ch[x][0]]+1) { return find_kth(ch[x][0],k); }else if(k > sz[ ch[x][0] ] + cnt[x] ) return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x]); else{ Splay(x,0); return val[x]; } }
int cnt[MAXN]; int val[MAXN]; int type; int ans; }spt; int main() { int n; while(~scanf("%d",&n)) { spt.init(); int a,b; int ans=0; int type=-1; REP(i,1,n) { scanf("%d%d",&a,&b); if(a==type||spt.sz[spt.rt]==2) { spt.Insert(spt.rt,b,0); type=a; //spt.vist(spt.rt); } else { int x,y; if(spt.sz[spt.rt]==2)continue; spt.findpre(spt.rt,b,x); spt.findsucc(spt.rt,b,y); if(abs(spt.val[x]-b)<=abs(spt.val[y]-b)) { ans+=abs(spt.val[x]-b); ans%=mod; spt.Splay(x,0); //spt.vist(spt.rt); spt.Del(); } else{ ans+=abs(spt.val[y]-b); ans%=mod; spt.Splay(y,0); //spt.vist(spt.rt); spt.Del(); } } } printf("%d ",ans); } return 0; }
区间操作模板
// File Name: ACM/HDU/3487.cpp // Author: Zlbing // Created Time: 2013年08月10日 星期六 21时35分28秒 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) #define L ch[x][0] #define R ch[x][1] #define KT (ch[ ch[rt][1] ][0]) const int MAXN = 3e5+100; struct SplayTree { int sz[MAXN]; int ch[MAXN][2]; int pre[MAXN]; int rt,top; inline void down(int x){ if(flip[x]) { flip[ L ] ^= 1; flip[ R ] ^= 1; swap(L,R); flip[x]=0; } } inline void up(int x){ sz[x]=1+sz[ L ] + sz[ R ]; } inline void Rotate(int x,int f){ int y=pre[x]; down(y); down(x); ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x; ch[x][f] = y; pre[y] = x; up(y); } inline void Splay(int x,int goal){//将x旋转到goal的下面 down(x);////防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了 while(pre[x] != goal){ down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变 if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x); else { int y=pre[x],z=pre[y]; int f = (ch[z][0]==y); if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f); else Rotate(y,f),Rotate(x,f); } } up(x); if(goal==0) rt=x; } inline void RTO(int k,int goal){//将第k位数旋转到goal的下面 int x=rt; down(x); while(sz[ L ]+1 != k) { if(k < sz[ L ] + 1 ) x=L; else { k-=(sz[ L ]+1); x = R; } down(x); } Splay(x,goal); } void vist(int x){ if(x){ printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d flip:%d ",x,L,R,val[x],flip[x]); vist(L); vist(R); } } void Newnode(int &x,int c,int f){ x=++top;flip[x]=0; L = R = 0; pre[x] = f; sz[x]=1; val[x]=c; } inline void build(int &x,int l,int r,int f){ if(l>r) return ; int m=(l+r)>>1; Newnode(x,m,f); build(L , l , m-1 , x); build(R , m+1 , r , x); pre[x]=f; up(x); } inline void init(int n){ ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; rt=top=0; flip[0]=0; val[0]=0; Newnode(rt,-1,0); Newnode(ch[rt][1],-1,rt); sz[rt]=2; build(KT,1,n,ch[rt][1]); } //删除根结点 void Del(){ int t=rt; if(ch[rt][1]) { rt=ch[rt][1]; RTO(1,0); ch[rt][0]=ch[t][0]; if(ch[rt][0]) pre[ch[rt][0]]=rt; } else rt=ch[rt][0]; pre[rt]=0; up(rt); } //把[a,b]放在c的后面 void solve1(int a,int b,int c) { RTO(a,0); RTO(b+2,rt); int tmp=KT; KT=0; up(ch[rt][1]); up(rt); RTO(c+1,0); RTO(c+2,rt); KT=tmp; pre[tmp]=ch[rt][1]; up(ch[rt][1]); up(rt); } //翻转[a,b] void solve2(int a,int b) { RTO(a,0); RTO(b+2,rt); flip[KT]^=1; } void print(int x) { if(x) { down(x); print(L); if(val[x]!=-1) { if(flag)printf(" "); flag=1; printf("%d",val[x]); } print(R); } } void out() { flag=0; print(rt); printf(" "); } int flip[MAXN]; int val[MAXN]; int flag; }spt; int main() { int n,m; while(~scanf("%d%d",&n,&m)) { if(n==-1)break; char op[5]; int a,b,c; spt.init(n); REP(i,1,m) { scanf("%s",op); if(op[0]=='C') { scanf("%d%d%d",&a,&b,&c); spt.solve1(a,b,c); } else { scanf("%d%d",&a,&b); spt.solve2(a,b); } } spt.out(); } return 0; }