P3391 【模板】文艺平衡树(Splay)新板子
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次变换后的结果
输入输出样例
说明
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],data[MAXN]; 8 int Root,tn,n; 9 10 inline char nc() { 11 static char buf[100000],*p1 = buf,*p2 = buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++; 13 } 14 inline int read() { 15 int x = 0,f = 1;char ch = nc(); 16 for (; ch<'0'||ch>'9'; ch = nc()) 17 if (ch=='-') f = -1; 18 for (; ch>='0'&&ch<='9'; ch = nc()) 19 x = x*10+ch-'0'; 20 return x * f; 21 } 22 inline int son(int x) { 23 return x == ch[fa[x]][1]; 24 } 25 inline void pushup(int x) { 26 siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1; 27 } 28 inline void pushdown(int x) { 29 if (tag[x]) { 30 tag[ch[x][0]] ^= 1; 31 tag[ch[x][1]] ^= 1; 32 swap(ch[x][0],ch[x][1]); 33 tag[x] = 0; 34 } 35 } 36 inline void rotate(int x) { 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 ch[x][!b] = y;fa[y] = x; 40 ch[y][b] = a;if (a) fa[a] = y; 41 pushup(y);pushup(x); 42 } 43 inline void splay(int x,int rt) { 44 while (fa[x] != rt) { 45 int y = fa[x],z = fa[y]; 46 if (z==rt) rotate(x); 47 else { 48 if (son(x)==son(y)) rotate(y),rotate(x); 49 else rotate(x),rotate(x); 50 } 51 } 52 } 53 inline int getkth(int k) { 54 int p = Root; 55 while (true) { 56 pushdown(p); 57 if (k == siz[ch[p][0]] + 1) return p; 58 if (ch[p][0] && k<=siz[ch[p][0]]) p = ch[p][0]; 59 else { 60 k -= ((ch[p][0] ? siz[ch[p][0]] : 0) + 1); 61 p = ch[p][1]; 62 } 63 } 64 } 65 void Reverse(int l,int r) { 66 int L = getkth(l),R = getkth(r+2); 67 splay(L,0);splay(R,L); 68 tag[ch[R][0]] ^= 1; 69 } 70 int build(int l,int r) { 71 if (l > r) return 0; 72 int mid = (l + r) >> 1; 73 int t = build(l,mid-1); 74 ch[mid][0] = t;fa[t] = mid; 75 t = build(mid+1,r); 76 ch[mid][1] = t;fa[t] = mid; 77 pushup(mid); 78 return mid; 79 } 80 void Print(int x) { 81 if (!x) return; 82 pushdown(x); 83 Print(ch[x][0]); 84 if (x > 1 && x < n+2) printf("%d ",x-1); 85 Print(ch[x][1]); 86 } 87 int main() { 88 n = read(); 89 Root = build(1,n+2); 90 /*for(int i=1;i<=n+2;i++) { 91 siz[i] = n+3-i; 92 fa[i] = i-1; 93 ch[i][1] = i+1; 94 } 95 ch[n+2][1]=0,Root=1;*/ 96 int m = read(); 97 while (m--) { 98 int a = read(),b = read(); 99 Reverse(a,b); 100 } 101 Print(Root); 102 return 0; 103 }