bzoj 3223 文艺平衡树 splay 区间翻转

bzoj-3223

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 }
View Code

 

posted @ 2018-07-30 08:53  Schenker  阅读(236)  评论(0编辑  收藏  举报