[Bzoj1014][JSOI2008]火星人prefix(无旋Treap&hash)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1014
因为涉及到增加和修改,所以后缀数组就被pass掉了,想到的就是平衡树维护hash值,查询的时候就是二分相同的长度来比较,修改就是删除再增加。
这里使用的是无旋Treap
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int ull; 5 const int maxn = 200010; 6 int Siz[maxn], ls[maxn], rs[maxn], pos[maxn], val[maxn], root, cnt; 7 ull Hash[maxn], w[maxn]; 8 inline void up(int x) { 9 Siz[x] = Siz[ls[x]] + Siz[rs[x]] + 1; 10 w[x] = w[ls[x]] * Hash[Siz[rs[x]] + 1] + Hash[Siz[rs[x]]] * val[x] + w[rs[x]]; 11 } 12 inline void split_size(int x, int siz, int &A, int &B) { 13 if (x == 0)return (void)(A = B = 0); 14 if (siz <= Siz[ls[x]]) 15 B = x, split_size(ls[x], siz, A, ls[x]); 16 else 17 A = x, split_size(rs[x], siz - Siz[ls[x]] - 1, rs[x], B); 18 up(x); 19 } 20 inline int Merge(int A, int B) { 21 if (A == 0 || B == 0)return A | B; 22 int ans; 23 if (pos[A] > pos[B])ans = A, rs[A] = Merge(rs[A], B); 24 else ans = B, ls[B] = Merge(A, ls[B]); 25 up(ans); 26 return ans; 27 } 28 inline void insert(int x, char v) { 29 int A, B; 30 split_size(root, x, A, B); 31 cnt++; 32 w[cnt] = val[cnt] = v - 'a' + 1; 33 Siz[cnt] = 1; 34 pos[cnt] = rand(); 35 root = Merge(Merge(A, cnt), B); 36 } 37 inline void Delete(int x) { 38 int A, B, C, D; 39 split_size(root, x, A, B); 40 split_size(A, x - 1, C, D); 41 D = Merge(ls[D], rs[D]); 42 root = Merge(Merge(C, D), B); 43 } 44 inline ull query(int l, int r) { 45 int A, B, C, D; 46 ull ans; 47 split_size(root, l - 1, A, B); 48 split_size(B, r - l + 1, C, D); 49 ans = w[C]; 50 root = Merge(A, Merge(C, D)); 51 return ans; 52 } 53 inline bool check(int x, int y, int len) { 54 return query(x, x + len - 1) == query(y, y + len - 1); 55 } 56 inline int read() { 57 int x = 0, f = 1; char c = getchar(); 58 for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; 59 for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f; 60 } 61 inline char cread() { 62 char c = getchar(); 63 for (; !isalpha(c); c = getchar()); return c; 64 } 65 inline void reads(string& s) { 66 char c = getchar(); 67 for (; !isalpha(c); c = getchar()); s = " "; 68 for (; isalpha(c); c = getchar()) s += c; 69 } 70 string s; 71 int main() { 72 reads(s); 73 int n = s.size() - 1, m; 74 m = read(); 75 Hash[0] = 1; 76 for (int i = 1; i < maxn; i++) 77 Hash[i] = Hash[i - 1] * 131; 78 for (int i = 1; i <= n; i++) 79 insert(i, s[i]); 80 while (m--) { 81 char opt; 82 int x, y; 83 opt = cread(); 84 if (opt == 'Q') { 85 x = read(), y = read(); 86 int l = 0, r = min(n - x, n - y) + 1, ans; 87 while (l <= r) { 88 int mid = l + r >> 1; 89 if (check(x, y, mid)) { 90 ans = mid; 91 l = mid + 1; 92 } 93 else 94 r = mid - 1; 95 } 96 printf("%d\n", ans); 97 } 98 else if (opt == 'R') { 99 x = read(), opt = cread(); 100 Delete(x); 101 insert(x - 1, opt); 102 } 103 else { 104 x = read(), opt = cread(); 105 n++; 106 insert(x, opt); 107 } 108 } 109 return 0; 110 }