bzoj 3223: Tyvj 1729 文艺平衡树
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
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 }