Splay

Splay的区间维护还是很机智的,不好写是真的。

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 #define REP(i, s, n) for(int i = s; i <= n; i ++)
  7 #define RAP(i, n, s) for(int i = n; i >= s; i --)
  8 using namespace std;
  9 const int maxn = 100000 + 10;
 10 char S[maxn]; int Q;
 11 inline void read(int &x){
 12     x = 0; int sig = 1; char ch = getchar();
 13     while(!isdigit(ch)) { if(ch == '-') sig = -1; ch = getchar(); }
 14     while(isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
 15     x *= sig; return ;
 16 }
 17 inline void write(int x){
 18     if(x < 0) putchar('-'), x = -x;
 19     int len = 0, buf[20];
 20     while(x) buf[++ len] = x % 10, x /= 10;
 21     RAP(i, len, 0) putchar(buf[i] + '0'); return ;
 22 }
 23 struct Node{
 24     int s, flip; char c;
 25     Node* ch[2];
 26     int cmp(int k){
 27         return k == ch[0] -> s + 1 ? -1 : k > ch[0] -> s;
 28     }
 29     void maintain(){
 30         s = ch[0] -> s + ch[1] -> s + 1; return ;
 31     }
 32     void pushdown(){
 33         if(flip) ch[0] -> flip ^= 1, ch[1] -> flip ^= 1, swap(ch[0], ch[1]), flip = 0; return ;
 34     }
 35 }* null = new Node(), nodes[maxn], * root, * _o, * _left, * _right, * _mid;
 36 int ms = 0;
 37 void rotate(Node* &o, int d){
 38     Node* k = o -> ch[d ^ 1]; o -> ch[d ^ 1] = k -> ch[d]; k -> ch[d] = o;
 39     o -> maintain(); k -> maintain(); o = k; return ; 
 40 }
 41 void splay(Node* &o, int k1){
 42     o -> pushdown(); int d1 = o -> cmp(k1);
 43     if(d1) k1 -= o -> ch[0] -> s + 1; if(d1 == -1) return ;
 44     Node* p = o -> ch[d1]; p -> pushdown();
 45     int d2 = p -> cmp(k1), k2 = d2 ? k1 - p -> ch[0] -> s - 1 : k1;
 46     if(d2 != -1){
 47         splay(p -> ch[d2], k2);
 48         if(d1 == d2) rotate(o, d1 ^ 1); else rotate(o -> ch[d1], d1);
 49     }
 50     rotate(o, d1 ^ 1); return ;
 51 }
 52 void print(Node* &o){
 53     if(o == null) return ;
 54     o -> pushdown();
 55     print(o -> ch[0]);
 56     putchar(o -> c);
 57     print(o -> ch[1]);
 58     return ;
 59 }
 60 void build(Node* &o, int L, int R){
 61     o = null; if(L > R) return ;
 62     int M = L + R >> 1; o = &nodes[ms ++];
 63     o -> c = S[M]; o -> flip = 0;
 64     build(o -> ch[0], L, M - 1); build(o -> ch[1], M + 1, R); //不包含M的两块
 65     o -> maintain(); return ; 
 66 }
 67 void merge(Node* &left, Node* &right){
 68     if(left == null) left = right;
 69     else splay(left, left -> s), left -> ch[1] = right, left -> maintain();//截掉右子树粘过去,别忘了重新维护一下 
 70     return ;
 71 }
 72 void split(Node* &o, Node* &left, Node* &right, int k){//前k小扔到left里 
 73     if(k <= 0) left = null, right = o;//直接搞好了o(* ̄3 ̄)o 
 74     else splay(o, k), left = o, right = left -> ch[1], left -> ch[1] = null, left -> maintain();//砍掉左子树的右孩子贴到右边去,别忘了维护值 
 75     return ;
 76 }
 77 void init(){
 78     scanf("%s", S); read(Q);
 79     build(root, 0, strlen(S) - 1);
 80     return ;
 81 }
 82 void work(){
 83     int L, R;
 84     while(Q --){
 85         read(L); read(R);
 86         split(root, _left, _o, L - 1); split(_o, _mid, _right, R - L + 1);//先拆root再拆 o (⊙ ▽ ⊙)
 87         _mid -> flip ^= 1;
 88         merge(_left, _mid); merge(_left, _right); root = _left;//哦哦一点点合并,merge又不是三元的 (⊙ ▽ ⊙),别忘了root要更新回来 
 89     }
 90     return ;
 91 }
 92 void print(){
 93     print(root);
 94     return ;
 95 }
 96 int main(){
 97     init();
 98     work();
 99     print();
100     return 0;
101 }
原文地址:https://www.cnblogs.com/chxer/p/4426226.html