hdu3487 伸展树(区间搬移 区间旋转)
对于区间旋转使用lazy思想就能解决。然后对于区间搬移,先把a-1结点做根,b+1作为它的右孩子,这样ch[ch[root][1]][0]就是区间[a,b],现将他取出。
然后在将当前的树伸展,把c结点转到根,c+1作为它的右孩子,这样c+1结点的左孩子就是空的,直接将上次取出的作为c+1结点的做孩子即可。
#include<queue> #include<stack> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 99999999 #define ll __int64 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define key_value ch[ch[root][1]][0] using namespace std; const int MAXN = 3*100010; int pre[MAXN],ch[MAXN][2],siz[MAXN],key[MAXN],rev[MAXN],root,tot1; int n; void Treavel(int x) { if(x) { Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d key=%2d\n",x,ch[x][0],ch[x][1],pre[x],siz[x],key[x]); Treavel(ch[x][1]); } } void debug() { printf("root:%d\n",root); Treavel(root); } void Newnode(int &rt,int pa,int k) { rt = ++tot1; pre[rt] = pa; siz[rt] = 1; rev[rt] = 0; key[rt] = k; ch[rt][0] = ch[rt][1] = 0; } void pushup(int rt) { siz[rt] = siz[ch[rt][0]] + siz[ch[rt][1]] + 1; } void pushdown(int rt) { if(rev[rt]){ rev[ch[rt][0]] ^= 1; rev[ch[rt][1]] ^= 1; swap(ch[rt][0],ch[rt][1]); rev[rt] = 0; } } void build(int &rt,int l,int r,int pa) { if(l > r) return ; int m = (l+r)/2; Newnode(rt,pa,m); build(ch[rt][0],l,m-1,rt); build(ch[rt][1],m+1,r,rt); pushup(rt); } void Init() { tot1 = root = 0; pre[root] = siz[root] = key[root] = rev[root] = 0; ch[root][0] = ch[root][1] = 0; Newnode(root,0,-1); Newnode(ch[root][1],root,-1); build(key_value,1,n,ch[root][1]); pushup(ch[root][1]); pushup(root); } void Rotate(int rt,int kind) { int y = pre[rt]; pushdown(y); pushdown(rt); ch[y][!kind] = ch[rt][kind]; pre[ch[rt][kind]] = y; if(pre[y]){ ch[pre[y]][ch[pre[y]][1]==y] = rt; } pre[rt] = pre[y]; ch[rt][kind] = y; pre[y] = rt; pushup(y); } void splay(int rt,int goal) { pushdown(rt); while(pre[rt] != goal) { if(pre[pre[rt]] == goal){ pushdown(pre[rt]); pushdown(rt); Rotate(rt,ch[pre[rt]][0]==rt); } else { pushdown(pre[pre[rt]]); pushdown(pre[rt]); pushdown(rt); int y = pre[rt]; int kind = ch[pre[y]][0]==y; if(ch[y][kind] == rt){ Rotate(rt,!kind); Rotate(rt,kind); } else { Rotate(y,kind); Rotate(rt,kind); } } } if(goal == 0) root = rt; pushup(rt); } int Get_kth(int rt,int k) { pushdown(rt); int t = siz[ch[rt][0]] + 1; if(t == k) return rt; else if(t > k){ return Get_kth(ch[rt][0],k); } else { return Get_kth(ch[rt][1],k-t); } pushup(rt); } void cut(int x,int y,int z) { splay(Get_kth(root,x),0); splay(Get_kth(root,y+2),root); //debug(); int tmp = key_value; key_value = 0; pushup(ch[root][1]); pushup(root); splay(Get_kth(root,z+1),0); splay(Get_kth(root,z+2),root); //debug(); key_value = tmp; pre[tmp] = ch[root][1]; pushup(ch[root][1]); pushup(root); //debug(); } int flag; void display(int rt) { if(rt == 0) return ; pushdown(rt); display(ch[rt][0]); if(!flag && rt !=1 && rt != 2){ flag = 1; printf("%d",key[rt]); } else if(rt !=1 && rt != 2){ printf(" %d",key[rt]); } display(ch[rt][1]); } int main() { int i,j,m; while(~scanf("%d%d",&n,&m),n!=-1&&m!=-1) { Init(); char work[10]; while(m--) { scanf("%s",work); if(work[0] == 'F'){ int x,y; scanf("%d%d",&x,&y); splay(Get_kth(root,x),0); splay(Get_kth(root,y+2),root); rev[key_value] ^= 1; //debug(); } else { int x,y,z; scanf("%d%d%d",&x,&y,&z); cut(x,y,z); } } //debug(); flag = 0; display(root); cout<<endl; } }