3223: Tyvj 1729 文艺平衡树
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上打标记,
然后翻转就好了。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 100000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 int n,m,sz,rt; 30 int fa[maxn],c[maxn][2],id[maxn]; 31 int s[maxn]; 32 bool rev[maxn]; 33 void pushup(int x){ 34 int l=c[x][0],r=c[x][1]; 35 s[x]=s[l]+s[r]+1; 36 } 37 void pushdown(int x){ 38 int l=c[x][0],r=c[x][1]; 39 if(!rev[x])return; 40 swap(c[x][1],c[x][0]); 41 rev[l]^=1;rev[r]^=1; 42 rev[x]=0; 43 } 44 void rotate(int x,int &k){ 45 int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1; 46 if(y==k)k=x; 47 else if(c[z][0]==y)c[z][0]=x; 48 else c[z][1]=x; 49 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 50 c[y][l]=c[x][r];c[x][r]=y; 51 pushup(y);pushup(x); 52 } 53 void splay(int x,int &k){ 54 while(x!=k){ 55 int y=fa[x],z=fa[y]; 56 if(y!=k){ 57 if(c[y][0]==x^c[z][0]==y)rotate(x,k); 58 else rotate(x,k); 59 } 60 else rotate(x,k); 61 } 62 } 63 int find(int k,int rk){ 64 pushdown(k); 65 int l=c[k][0],r=c[k][1]; 66 if(s[l]+1==rk)return k; 67 else if(s[l]>=rk)return find(l,rk); 68 else return find(r,rk-s[l]-1); 69 } 70 void rever(int l,int r){ 71 int x=find(rt,l),y=find(rt,r+2); 72 splay(x,rt);splay(y,c[x][1]); 73 int z=c[y][0]; 74 rev[z]^=1; 75 } 76 void build(int l,int r,int f){ 77 if(l>r)return ; 78 int now=id[l],last=id[f]; 79 if(l==r){ 80 fa[now]=last;s[now]=1; 81 if(l<f)c[last][0]=now; 82 else c[last][1]=now; 83 return ; 84 } 85 int mid=(l+r)>>1;now=id[mid]; 86 build(l,mid-1,mid);build(mid+1,r,mid); 87 fa[now]=last;pushup(mid); 88 if(mid<=f)c[last][0]=now; 89 else c[last][1]=now; 90 } 91 int main(){ 92 //freopen("input.txt","r",stdin); 93 //freopen("output.txt","w",stdout); 94 n=read();m=read(); 95 for1(i,n+2) 96 id[i]=++sz; 97 build(1,n+2,0);rt=(n+3)>>1; 98 for1(i,m){ 99 int l=read(),r=read(); 100 rever(l,r); 101 } 102 for(int i=2;i<=n+1;i++) 103 printf("%d ",find(rt,i)-1); 104 return 0; 105 }