bzoj 3223: Tyvj 1729 文艺平衡树 (splay)
链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3223
题面:
3223: Tyvj 1729 文艺平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 7451 Solved: 4657
[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
实现代码:
#include<bits/stdc++.h> using namespace std; const int M = 2e5+10; const int inf = 0x3f3f3f; int n,m,sz,rt; int c[M][2],fa[M],v[M],siz[M]; bool rev[M]; inline void up(int k){ int l = c[k][0],r = c[k][1]; siz[k] = siz[l] + siz[r] + 1; } void pushdown(int k){ int l = c[k][0],r = c[k][1]; if(rev[k]){ rev[k] = 0; rev[l]^=1; rev[r]^=1; swap(c[k][0],c[k][1]); } } void rotate(int x,int &k){ int y = fa[x],z = fa[y],l,r; if(c[y][0] == x) l = 0; else l = 1; r = l^1; if(y == k) k = x; else { if(c[z][0]==y) c[z][0]=x; else c[z][1] = x; } fa[x] = z;fa[y] = x;fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; up(y); up(x); } void splay(int x,int &k){ while(x != k){ int y = fa[x],z = fa[y]; if(y != k){ if(c[y][0]==x^c[z][0]==y)rotate(x,k); else rotate(y,k); } rotate(x,k); } } int find(int k,int rk){ if(rev[k]) pushdown(k); int l = c[k][0],r = c[k][1]; if(siz[l] + 1 == rk) return k; else if(siz[l] >= rk) return find(l,rk); else return find(r,rk-siz[l]-1); } inline void reve(int l,int r){ int x = find(rt,l),y = find(rt,r+2); splay(x,rt); splay(y,c[x][1]); int z = c[y][0]; rev[z] ^= 1; } inline void build(int l,int r,int f) { if(l>r)return; int now=l,last=f; if(l==r) { v[now]=l;siz[now]=1;fa[now]=last; if(l<f)c[last][0]=now; else c[last][1]=now; return; } int mid=(l+r)>>1;now=mid; build(l,mid-1,mid);build(mid+1,r,mid); v[now]=mid;fa[now]=last; if(mid<f)c[last][0]=now; else c[last][1]=now; up(now); } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int x,y; cin>>n>>m; build(1,n+2,0); rt = (n+3) >> 1; for(int i = 1;i <= m;i ++){ cin>>x>>y; reve(x,y); } for(int i = 1;i <= n;i ++){ cout<<find(rt,i+1)-1<<" "; } cout<<endl; }