BZOJ 3223: Tyvj 1729 文艺平衡树
3223: Tyvj 1729 文艺平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3629 Solved: 2053
[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
Source
分析:
第一次写Splay维护区间翻转操作...
我们可以用线段树的lazy标记的思想,如果要翻转某个区间,就在子节点打上标记,然后每次访问到带标记的节点的时候就下放标记...
对于每一个节点,它的权值就是初始序列的序号,每一次翻转区间[l,r]的时候,我们先把排名为l-1的节点转到根节点,这样就保证了[l,+∞)都在根节点的右子树中,然后我们再找到排名为r-1节点,把它转到根节点的右儿子的位置,这样就保证了[l,r]都在r-1节点的左儿子,这样我们直接打标记就好...
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 using namespace std; 7 8 const int maxn=100000+5; 9 10 int n,m; 11 int tot,root,w[maxn],ls[maxn],rs[maxn],fa[maxn],siz[maxn],lazy[maxn]; 12 13 inline void zig(int x){ 14 int y=fa[x],tmp=siz[y]; 15 if(rs[x]) 16 ls[y]=rs[x],fa[rs[x]]=y,siz[y]=siz[y]-siz[x]+siz[rs[x]],siz[x]=tmp; 17 else 18 ls[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp; 19 fa[x]=fa[y]; 20 if(fa[x]){ 21 if(ls[fa[x]]==y) 22 ls[fa[x]]=x; 23 else 24 rs[fa[x]]=x; 25 } 26 fa[y]=x,rs[x]=y; 27 } 28 29 inline void zag(int x){ 30 int y=fa[x],tmp=siz[y]; 31 if(ls[x]) 32 rs[y]=ls[x],fa[ls[x]]=y,siz[y]=siz[y]-siz[x]+siz[ls[x]],siz[x]=tmp; 33 else 34 rs[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp; 35 fa[x]=fa[y]; 36 if(fa[x]){ 37 if(ls[fa[x]]==y) 38 ls[fa[x]]=x; 39 else 40 rs[fa[x]]=x; 41 } 42 fa[y]=x,ls[x]=y; 43 } 44 45 inline void splay(int x,int z){ 46 while(fa[x]!=z){ 47 int y=fa[x]; 48 if(fa[y]==z){ 49 if(ls[y]==x) 50 zig(x); 51 else 52 zag(x); 53 } 54 else{ 55 if(ls[fa[y]]==y){ 56 if(ls[y]==x) 57 zig(y),zig(x); 58 else 59 zag(x),zig(x); 60 } 61 else{ 62 if(rs[y]==x) 63 zag(y),zag(x); 64 else 65 zig(x),zag(x); 66 } 67 } 68 } 69 if(!z) 70 root=x; 71 } 72 73 inline void ins(int rt,int x){ 74 if(rt==0) 75 w[++tot]=x,siz[tot]=1,root=tot; 76 else if(x<w[rt]){ 77 if(ls[rt]==0) 78 w[++tot]=x,siz[tot]=1,fa[tot]=rt,siz[rt]++,ls[rt]=tot,splay(tot,0); 79 else 80 siz[rt]++,ins(ls[rt],x); 81 } 82 else{ 83 if(rs[rt]==0) 84 w[++tot]=x,siz[tot]=1,siz[rt]++,fa[tot]=rt,rs[rt]=tot,splay(tot,0); 85 else 86 siz[rt]++,ins(rs[rt],x); 87 } 88 } 89 90 inline void push_down(int x){ 91 lazy[x]=0;lazy[ls[x]]^=1,lazy[rs[x]]^=1; 92 swap(ls[x],rs[x]); 93 } 94 95 inline int find(int rt,int x){ 96 if(lazy[rt]) 97 push_down(rt); 98 if(siz[ls[rt]]+1==x){ 99 splay(rt,0);return rt; 100 } 101 else if(siz[ls[rt]]>=x) 102 return find(ls[rt],x); 103 else 104 return find(rs[rt],x-siz[ls[rt]]-1); 105 } 106 107 inline void dfs(int rt){ 108 if(lazy[rt]) 109 push_down(rt); 110 if(!rt) 111 return; 112 if(!ls[rt]) 113 printf("%d ",w[rt]),dfs(rs[rt]); 114 else 115 dfs(ls[rt]),printf("%d ",w[rt]),dfs(rs[rt]); 116 } 117 118 signed main(void){ 119 memset(ls,0,sizeof(ls)); 120 memset(rs,0,sizeof(rs)); 121 memset(fa,0,sizeof(fa)); 122 memset(siz,0,sizeof(siz)); 123 memset(lazy,0,sizeof(lazy)); 124 scanf("%d%d",&n,&m);root=tot=0; 125 for(int i=1;i<=n;i++) 126 ins(root,i); 127 for(int i=1,l,r;i<=m;i++){ 128 scanf("%d%d",&l,&r); 129 if(l==1&&r==tot) 130 lazy[root]^=1; 131 else if(l==1) 132 r=find(root,r+1),splay(r,0),lazy[ls[r]]^=1; 133 else if(r==tot) 134 l=find(root,l-1),splay(l,0),lazy[rs[l]]^=1; 135 else 136 l=find(root,l-1),r=find(root,r+1),splay(l,0),splay(r,l),lazy[ls[r]]^=1; 137 } 138 dfs(root);puts(""); 139 return 0; 140 }
by NeighThorn