splay 区间翻转最简单的应用。
本来只要[1,n]的区间,建立树的时候要建立[0,n+1]的区间,因为对区间 [l,r] 翻转的时候需要先把 l-1 的节点旋转到根节点的位置, 然后在将 r+1 的节点旋转到 l-1 的 右儿子, 那么 [l, r] 这段区间就在 r + 1 的左子树上了, 我们只需要对左子树打一个翻转标记来减少翻转次数就好了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5 + 100; 18 int tot = 0, root; 19 int n, m; 20 struct Node{ 21 int son[2], pre; 22 int val, sz, is_swap; 23 void init(int x){ 24 val = x; sz = 1; 25 is_swap = pre = son[0] = son[1] = 0; 26 } 27 }tr[N]; 28 void Push_up(int x){ 29 if(!x) return; 30 tr[x].sz = tr[tr[x].son[1]].sz + tr[tr[x].son[0]].sz + 1; 31 } 32 void Push_down(int x){ 33 if(tr[x].is_swap){ 34 tr[x].is_swap = 0; 35 int &l = tr[x].son[0], &r = tr[x].son[1]; 36 tr[l].is_swap ^= 1; tr[r].is_swap ^= 1; 37 swap(l, r); 38 } 39 } 40 int build(int ll, int rr){ 41 if(ll > rr) return 0; 42 int x = ++tot; 43 int m = ll + rr >> 1; 44 int &l = tr[x].son[0], &r = tr[x].son[1]; 45 tr[x].init(m); 46 l = build(ll, m-1); 47 r = build(m+1, rr); 48 tr[l].pre = tr[r].pre = x; 49 Push_up(x); 50 return x; 51 } 52 void rotate(int x){ 53 int y = tr[x].pre; 54 int z = tr[y].pre; 55 int k = x == tr[y].son[1]; 56 tr[x].pre = z; 57 tr[z].son[y == tr[z].son[1]] = x; 58 tr[y].son[k] = tr[x].son[k^1]; 59 tr[tr[y].son[k]].pre = y; 60 tr[x].son[k^1] = y; 61 tr[y].pre = x; 62 Push_up(y); 63 } 64 void splay(int x, int goal){ 65 Push_down(x); 66 while(tr[x].pre != goal){ 67 int y = tr[x].pre; 68 int z = tr[y].pre; 69 if(z != goal){ 70 if((tr[y].son[0] == x) ^ (tr[z].son[0] == y)) rotate(x); ///x和y分别是y和z的同一段的儿子 71 else rotate(y); 72 } 73 rotate(x); 74 } 75 if(!goal) root = x; 76 Push_up(x); 77 } 78 void dfs(int x){ 79 Push_down(x); 80 if(tr[x].son[0]) dfs(tr[x].son[0]); 81 if(tr[x].val <= n && tr[x].val >= 1) 82 printf("%d ", tr[x].val); 83 if(tr[x].son[1]) dfs(tr[x].son[1]); 84 } 85 int Find(int x, int p){ 86 Push_down(p); 87 int &l = tr[p].son[0], &r = tr[p].son[1]; 88 if(x == tr[l].sz + 1) return p; 89 if(x <= tr[l].sz) return Find(x, l); 90 return Find(x- tr[l].sz - 1, r); 91 } 92 int main(){ 93 int l, r, pl, pr; 94 scanf("%d%d", &n, &m); 95 root = build(0, n+2); 96 while(m--){ 97 scanf("%d%d", &l, &r); 98 pl = Find(l, root); 99 pr = Find(r+2, root); 100 splay(pl, 0); 101 splay(pr, root); 102 tr[tr[pr].son[0]].is_swap ^= 1; 103 } 104 dfs(root); 105 return 0; 106 }