首页 > 代码库 > UVA 11996 Jewel Magic —— splay、序列的分裂与合并、LCP的哈希算法

UVA 11996 Jewel Magic —— splay、序列的分裂与合并、LCP的哈希算法

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <vector>
  6 
  7 using namespace std;
  8 
  9 typedef unsigned long long ull;
 10 const int x = 123;
 11 const int maxn = 4e5 + 10;
 12 
 13 ull xp[maxn];
 14 int n, m;
 15 struct Node {
 16     Node* ch[2];
 17     int r, v, s;
 18     int val;
 19     ull Hush[2];
 20     int flip;
 21     Node(int v1, int v2): v(v1), val(v2) {
 22         r = rand();
 23         s = 1;
 24         ch[0] = ch[1] = NULL;
 25         flip = 0;
 26         Hush[0] = Hush[1] = val;
 27     }
 28     bool cmp(const int &x) const {
 29         if(x == v) return -1;
 30         return x < v ? 0 : 1;
 31     }
 32     void maintain() {
 33         s = 1;
 34         Hush[0] = Hush[1] = val;
 35         if(ch[0] != NULL) s += ch[0]->s, Hush[0] = ch[0]->Hush[ch[0]->flip] + val*xp[ch[0]->s];
 36         if(ch[1] != NULL) Hush[0] += (ch[1]->Hush[ch[1]->flip])*xp[s], s += ch[1]->s; 
 37         int s2 = 1;
 38         if(ch[1] != NULL) s2 += ch[1]->s, Hush[1] = ch[1]->Hush[(ch[1]->flip)^1] + val*xp[ch[1]->s];
 39         if(ch[0] != NULL) Hush[1] += (ch[0]->Hush[(ch[0]->flip)^1])*xp[s2];
 40     }
 41     void pushdown() {
 42         if(flip) {
 43             flip = 0;
 44             swap(ch[0], ch[1]);
 45             if(ch[0] != NULL) ch[0]->flip = !ch[0]->flip;
 46             if(ch[1] != NULL) ch[1]->flip = !ch[1]->flip;
 47         }
 48     }
 49 };
 50 
 51 void rotate(Node* &o, int d) {
 52     Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o;
 53     o->maintain(); k->maintain(); o = k;
 54 }
 55 
 56 void insert(Node* &o, int x, int val) {
 57     if(o == NULL) o = new Node(x, val);
 58     else {
 59         int d = o->cmp(x);
 60         insert(o->ch[d], x, val);
 61         if(o->ch[d]->r > o->r) rotate(o, d^1);
 62     }
 63     o->maintain();
 64 }
 65 void splay(Node* &o, int k) {
 66     o->pushdown();
 67     int s = o->ch[0] == NULL ? 0 : o->ch[0]->s;
 68     int d = k <= s ? 0 : (k == s+1? -1 : 1);
 69     if(d == 1) k -= s+1;
 70     if(d != -1) {
 71         splay(o->ch[d], k);
 72         rotate(o, d^1);
 73     }
 74 }
 75 
 76 Node * merge(Node* left, Node* right) {
 77     splay(left, left->s);
 78     left->ch[1] = right;
 79     left->maintain();
 80     return left;
 81 }
 82 void split(Node* o, int k , Node* &left, Node* &right) {
 83     splay(o, k);
 84     left = o;
 85     right = o->ch[1];
 86     o->ch[1] = NULL;
 87     left->maintain();
 88 }
 89 
 90 void oper1(Node* &o, int p, int c) {     
 91     Node* left, *right;
 92     Node* node = new Node(p+1, c);
 93     split(o, p+1, left, right);
 94     o = merge(merge(left, node), right);
 95 }
 96 void oper2(Node* &o, int p) {
 97     Node* left, *mid, *right;
 98     split(o, p, left, mid);
 99     split(mid, 1, mid, right);
100     o = merge(left, right);
101 }
102 void oper3(Node* &o, int p1, int p2) {
103     Node *left, *mid, *right;
104     split(o, p1, left, mid);
105     split(mid, p2-p1+1, mid, right);
106     mid->flip ^= 1;
107     o = merge(merge(left, mid), right);
108 }
109 ull Hush_val(Node* &o, int p, int L) {
110     Node *left, *mid, *right;
111     split(o, p, left, mid);
112     split(mid, L, mid, right);
113     ull ans =  mid->Hush[mid->flip];
114     o = merge(merge(left, mid), right);
115     return ans;
116 }
117 int oper4(Node* &o, int p1, int p2) {
118     int L = 0, R = min(n-p1+1, n-p2+1);
119     while(L < R) {
120         int M = R - (R-L)/2;
121         int l1 = Hush_val(o, p1, M), l2 =  Hush_val(o, p2, M);
122         if(l1 == l2) L = M;
123         else R = M-1;
124     }
125     return L;
126 }
127 char s[maxn];
128 int main() {
129     xp[0] = 1;
130     for(int i = 1; i < maxn; i++) xp[i] = xp[i-1]*x;
131     while(scanf("%d%d", &n, &m) == 2) {
132         scanf("%s", s);
133         Node* root = new Node(0, 0);
134         for(int i = 0; i < n; i++) {
135             int c = s[i] - 0; 
136             insert(root, i+1, c);    
137         }
138         for(int i = 0; i < m; i++) {
139             int id, p1, p2;
140             scanf("%d", &id);
141             if(id == 1) {
142                 scanf("%d%d", &p1, &p2);
143                 oper1(root, p1, p2);
144                 n++;
145             }
146             if(id == 2) {
147                 scanf("%d", &p1);
148                 oper2(root, p1);
149                 n--;
150             }
151             if(id == 3) {
152                 scanf("%d%d", &p1, &p2);
153                 oper3(root, p1, p2);    
154             }
155             if(id == 4) {
156                 scanf("%d%d", &p1, &p2);
157                 int ans = oper4(root, p1, p2);
158                 printf("%d\n", ans);
159             }
160         }
161     }
162     return 0;
163 }

 

UVA 11996 Jewel Magic —— splay、序列的分裂与合并、LCP的哈希算法