bzoj 3223: Tyvj 1729 文艺平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2853  Solved: 1602
[Submit][Status][Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 

Input

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n 

Output

输出一行n个数字,表示原始序列经过m次变换后的结果 

Sample Input

5 3
1 3
1 3
1 4

Sample Output

4 3 2 1 5

HINT

N,M<=100000

题解:

  给定一个序列要求区间翻转,可以用splay来维护,只要让左区间的前驱旋到根,右区间的后继选到根的右孩子,那么根的右孩子的左孩子所在子树就是需要翻转的区间,打上标记维护一下就行了。其实可以发现,这并不是严格的平衡树,因为对于x节点,它的左孩子的权值未必比右孩子小。最后只要按照中序遍历输出一下就好了。

  1 /**************************************************************
  2     Problem: 3223
  3     User: __abcdef__
  4     Language: C++
  5     Result: Accepted
  6     Time:3124 ms
  7     Memory:4020 kb
  8 ****************************************************************/
  9  
 10 #include<iostream>
 11 #include<cstdio>
 12 #include<cstdlib>
 13 #include<cstring>
 14 #include<cmath>
 15 #include<algorithm>
 16 #include<queue>
 17 #include<vector>
 18 #include<ctime>
 19 using namespace std;
 20 typedef long long LL;
 21 const int inf=1e9;
 22 const int maxn=100005;
 23 int N,M,tot,root;
 24 int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
 25 int rev[maxn];
 26 int ans[maxn],cnt;
 27 inline void update(int x){
 28     siz[x]=siz[lc[x]]+siz[rc[x]]+1;
 29 }
 30 inline void pushdown(int x){
 31     if(rev[x]){
 32         swap(lc[x],rc[x]);
 33         rev[lc[x]]^=1; rev[rc[x]]^=1;
 34         rev[x]=0;
 35     }
 36 }
 37 inline void r_rotate(int x){
 38     int y=fa[x];
 39     lc[y]=rc[x];
 40     if(rc[x]) fa[rc[x]]=y;
 41     fa[x]=fa[y];
 42     if(y==lc[fa[y]]) lc[fa[y]]=x;
 43     else rc[fa[y]]=x;
 44     fa[y]=x; rc[x]=y;
 45     update(y); update(x); 
 46 }
 47 inline void l_rotate(int x){
 48     int y=fa[x];
 49     rc[y]=lc[x];
 50     if(lc[x]) fa[lc[x]]=y;
 51     fa[x]=fa[y];
 52     if(y==lc[fa[y]]) lc[fa[y]]=x;
 53     else rc[fa[y]]=x;
 54     fa[y]=x;  lc[x]=y;
 55     update(y); update(x);
 56 }
 57 inline void splay(int x,int s){
 58     int p;
 59     while(fa[x]!=s){
 60         int p=fa[x];
 61         if(fa[p]==s){
 62             if(x==lc[p]) r_rotate(x);
 63             else l_rotate(x);
 64             break;
 65         }
 66         else if (x==lc[p]){
 67             if(p==lc[fa[p]]) r_rotate(x),r_rotate(x);
 68             else r_rotate(x),l_rotate(x);
 69         }
 70         else if(x==rc[p]){
 71             if(p==rc[fa[p]]) l_rotate(x),l_rotate(x);
 72             else l_rotate(x),r_rotate(x);
 73         }
 74     }
 75     if(s==0) root=x;
 76 }
 77 inline void insert(int v){
 78     if(root==0){
 79         root=++tot;
 80         rc[0]=tot; key[root]=v; siz[root]=1;
 81         return ;
 82     }
 83     int p,x=root;
 84     while(x!=0){
 85         p=x;
 86         if(v<=key[x]) siz[x]++,x=lc[x];
 87         else siz[x]++,x=rc[x];
 88     }
 89     if(v<=key[p]){
 90         lc[p]=++tot; 
 91         key[tot]=v; fa[tot]=p; siz[tot]=1;
 92     }
 93     else{
 94         rc[p]=++tot;
 95         key[tot]=v; fa[tot]=p; siz[tot]=1;
 96     }
 97     splay(tot,0);
 98 }
 99 inline int findkth(int x,int k){
100     pushdown(x);
101     if(siz[lc[x]]+1==k) return x;
102     else if(siz[lc[x]]+1>k) return findkth(lc[x],k);
103     else return findkth(rc[x],k-siz[lc[x]]-1);
104 }
105 inline void rever(int L,int R){
106     int x=findkth(root,L),y=findkth(root,R+2);
107     splay(x,0); 
108     splay(y,x);
109     rev[lc[rc[root]]]^=1;
110 }
111 inline void print(int x){
112     pushdown(x);
113     if(lc[x]!=0) print(lc[x]);
114     ans[++cnt]=key[x];
115     if(rc[x]!=0) print(rc[x]);
116 }
117 int main(){
118     scanf("%d%d",&N,&M);
119     insert(-inf); insert(inf);
120     for(int i=1;i<=N;i++) insert(i);
121     while(M--){
122         int L,R;
123         scanf("%d%d",&L,&R);
124         rever(L,R);
125     }
126     print(root);
127     for(int i=2;i<=cnt-1;i++) printf("%d ",ans[i]);
128     return 0;
129 }

 

 

 

posted @ 2016-04-06 22:12  CXCXCXC  阅读(209)  评论(0编辑  收藏  举报