1. 程式人生 > >csu1365 Play with Chain

csu1365 Play with Chain

set ring splay mes roo col uil d+ ont

很顯然的splay,第一次用splay操作區間...我實在佩服這個targan大佬,居然搞出這麽牛逼的平衡樹,調了大概5個小時終於搞定了。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<string>
#include<set>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<cmath>
#include
<cstring> #include<map> #include<stack> using namespace std; #define INF 0x3f3f3f3f #define maxn 300005 #define ull unsigned long long #define ll long long #define hashmod 99999839 #define mod 9997 struct tree{//splay樹 int sz[2];//以當前結點為根的左右子樹大小,不包括當前結點 int son[2];//當前結點的左右兒子
int fa;//當前結點的父親 int reverse;//翻轉標記 int v;//當前結點表示的權值 }a[maxn]; int root;//根節點 int len; int n,m,x,y,z; bool f; int isrson(int p,int f){ return a[f].son[1] == p; } void update(int p){//更新p結點的size if(a[p].son[0] != -1) a[p].sz[0] = a[a[p].son[0]].sz[0] + a[a[p].son[0]].sz[1] + 1;
else a[p].sz[0] = 0; if(a[p].son[1] != -1) a[p].sz[1] = a[a[p].son[1]].sz[0] + a[a[p].son[1]].sz[1] + 1; else a[p].sz[1] = 0; } void pushdown(int p){ swap(a[p].son[0],a[p].son[1]); update(p); a[p].reverse ^= 1; int ls = a[p].son[0],rs = a[p].son[1]; if(ls != -1) a[ls].reverse ^= 1; if(rs != -1) a[rs].reverse ^= 1; } void changeson(int p,int f,int v){//把p作為f的v兒子,p,f不一定存在 if(f != -1) a[f].son[v] = p; if(p != -1) a[p].fa = f; if(f == -1) root = p; } void rotate(int p){ int f = a[p].fa,g = a[f].fa; int u = isrson(p,f),v = isrson(f,g); changeson(a[p].son[u^1],f,u),changeson(f,p,u^1),changeson(p,g,v);//改變p,f,g的父子關系 update(f),update(p); } void splay(int p,int tar){ if(a[p].fa == tar) return; while(a[a[p].fa].fa != tar && a[p].fa != tar){ int f = a[p].fa,g = a[f].fa; int u = isrson(p,f),v = isrson(f,g); if(u ^ v) rotate(p),rotate(p); else rotate(f),rotate(p); } if(a[p].fa != tar) rotate(p); } int find(int x){ int p = root; for(;;){ if(a[p].reverse) pushdown(p); if(a[p].sz[0] >= x) p = a[p].son[0]; else if(a[p].sz[0] + 1 == x) return p; else x = x - a[p].sz[0] - 1,p = a[p].son[1]; } } void build(int l,int r){ len++; int p = len; int mid = (l + r) >> 1; a[p].v = mid,a[p].sz[0] = a[p].sz[1] = 0; a[p].son[0] = a[p].son[1] = -1; if(l == r) return; if(l <= mid - 1) changeson(len + 1,p,0),build(l,mid-1); if(mid + 1 <= r) changeson(len + 1,p,1),build(mid+1,r); update(p); } void flip(int x,int y){ int p = find(x - 1); splay(p,-1),p = find(y + 1),splay(p,root); p = a[a[root].son[1]].son[0]; a[p].reverse ^= 1; } void cut(int x,int y,int z){//cut [x,y] z 把區間x,y剪切到z位置後 //先得到區間[x,y],將其x-1rotate到根,將y+1rotate到根的兒子,則y+1結點的左兒子為根的樹即為該區間 int p = find(x - 1); splay(p,-1),p = find(y + 1),splay(p,root); p = a[a[root].son[1]].son[0]; a[a[p].fa].son[0] = -1; update(a[p].fa),update(root); int t = p; p = find(z); splay(p,-1),p = find(z + 1),splay(p,root); p = a[root].son[1],a[p].son[0] = t,a[t].fa = p; update(p),update(root); } void print(int p){ if(p == -1) return; if(a[p].reverse) pushdown(p),update(p); print(a[p].son[0]); if(a[p].v != 0 && a[p].v != n + 1) if(!f) printf("%d",a[p].v),f = true; else printf(" %d",a[p].v); print(a[p].son[1]); } int main(){ freopen("a.in","r",stdin); freopen("b.out","w",stdout); char op[10]; while(~scanf("%d%d",&n,&m)){ if(n < 0 && m < 0) break; len = 0,root = 1,f = false; build(0,n+1); a[root].fa = -1; for(int i = 1;i <= m;++i){ scanf("%s",op); if(op[0] == C){ scanf("%d%d%d",&x,&y,&z); ++x,++y,++z; cut(x,y,z); continue; } scanf("%d%d",&x,&y); ++x,++y; flip(x,y); } print(root),putchar(\n); } return 0; }

csu1365 Play with Chain