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

 

posted @ 2019-07-03 14:52  祈梦生  阅读(133)  评论(0编辑  收藏  举报