P3391 【模板】文艺平衡树(Splay)
题目背景
这是一道经典的Splay模板题——文艺平衡树。
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
输入输出格式
输入格式:
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,⋯n−1,n) m表示翻转操作次数
接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n1≤l≤r≤n
输出格式:
输出一行n个数字,表示原始序列经过m次变换后的结果
输入输出样例
输入样例#1:
5 3 1 3 1 3 1 4
输出样例#1:
4 3 2 1 5
说明
n, m \leq 100000n,m≤100000
code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int MAXN = 100100; 7 int fa[MAXN],ch[MAXN][2],tag[MAXN],siz[MAXN],id[MAXN]; 8 int n,m,root,sz; 9 10 int read() 11 { 12 int x = 0;char ch = getchar(); 13 while (ch<'0'||ch>'9') ch = getchar(); 14 while (ch>='0'&&ch<='9') x = x*10+ch-'0',ch = getchar(); 15 return x; 16 } 17 void pushup(int x) 18 { 19 siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1; 20 } 21 void pushdown(int x) 22 { 23 if (tag[x]) 24 { 25 tag[ch[x][0]] ^= 1; 26 tag[ch[x][1]] ^= 1; 27 swap(ch[x][0],ch[x][1]); 28 tag[x] = 0; 29 } 30 } 31 int son(int x) 32 { 33 return ch[fa[x]][1]==x; 34 } 35 void rotate(int x) 36 { 37 int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b]; 38 if (z) ch[z][c] = x;else root = x;fa[x] = z; 39 if (a) fa[a] = y;ch[y][b] = a; 40 ch[x][!b] = y;fa[y] = x; 41 pushup(y); 42 } 43 void splay(int &x,int rt) 44 { 45 while (fa[x]!=rt) 46 { 47 int y = fa[x],z = fa[y]; 48 if (z==rt) rotate(x); 49 else 50 { 51 if (son(x)==son(y)) rotate(y),rotate(x); 52 else rotate(x), rotate(x); 53 } 54 } 55 pushup(x); 56 } 57 int getkth(int rt,int k) 58 { 59 pushdown(rt); 60 int l = ch[rt][0],r = ch[rt][1]; 61 if (k==siz[l]+1) return rt; 62 else if (k<siz[l]+1) return getkth(l,k); 63 else return getkth(r,k-siz[l]-1); 64 } 65 void reverse(int l,int r) 66 { 67 int tl = getkth(root,l),tr = getkth(root,r+2); 68 splay(tl,0);splay(tr,tl); 69 tag[ch[tr][0]] ^= 1; 70 } 71 void build(int l,int r,int f) 72 { 73 if (l>r) return ; 74 int now = id[l],last = id[f]; 75 if (l==r) 76 { 77 fa[now] = last; 78 siz[now] = 1; 79 if (l<f) ch[last][0] = now; 80 else ch[last][1] = now; 81 return ; 82 } 83 int mid = (l+r)>>1; 84 now = id[mid]; 85 build(l,mid-1,mid); 86 build(mid+1,r,mid); 87 fa[now] = last; 88 pushup(mid); 89 if (mid<f) ch[last][0] = now; 90 else ch[last][1] = now; 91 } 92 int main() 93 { 94 n = read();m = read(); 95 for (int i=1; i<=n+2; ++i) id[i] = ++sz; 96 build(1,n+2,0);root = (n+3)>>1; 97 while (m--) 98 { 99 int x = read(),y = read(); 100 reverse(x,y); 101 } 102 for (int i=2; i<=n+1; ++i) 103 printf("%d ",getkth(root,i)-1); 104 return 0; 105 }