[JSOI2008]火星人prefix splay+Hash
阿新 • • 發佈:2018-12-10
Description 給你一個字串,每次有加字元和改字元兩種操作,讓你求從l開始的字尾和從r開始的字尾的最長公共字首。
Sample Input madamimadam 7 Q 1 7 Q 4 8 Q 10 11 R 3 a Q 1 7 I 10 a Q 2 11
Sample Output 5 1 0 2 1
這題一眼題, 但碼程式碼碼了一上午。。。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ULL; const ULL P = 131; int _min(int x, int y) {return x < y ? x : y;} int read() { int s = 0, o = 1; char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') o = -1; ch = getchar();} while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar(); return s * o; } struct tnode { int son[2], f, c; ULL s, sum, lazy; } t[250010]; int cnt, root; char ss[110000]; ULL s[110000], o[250010]; int new_node(ULL s, int f) { int now = ++cnt; t[now].s = s; t[now].sum = s; t[now].c = 1; t[now].f = f; t[now].lazy = 1; return cnt; } void update(int now) { int lc = t[now].son[0], rc = t[now].son[1]; t[now].c = 1 + t[lc].c + t[rc].c; t[now].sum = t[now].s * o[t[lc].c] + t[lc].sum + t[rc].sum * o[t[lc].c + 1]; } void rotate(int x, int fx) { int f = t[x].f, ff = t[f].f; int r, R; r = t[x].son[fx], R = f; if(r != 0) t[r].f = R; t[R].son[1 ^ fx] = r; r = x; R = ff; t[r].f = R; if(t[R].son[0] == f) t[R].son[0] = r; else if(t[R].son[1] == f) t[R].son[1] = r; r = f, R = x; t[r].f = R; t[R].son[fx] = r; update(f); update(x); } void splay(int x, int rt) { while(t[x].f != rt) { int f = t[x].f, ff = t[f].f; if(ff == rt) { if(t[f].son[0] == x) rotate(x, 1); else rotate(x, 0); } else if(t[f].son[0] == x && t[ff].son[0] == f) rotate(f, 1), rotate(x, 1); else if(t[f].son[0] == x && t[ff].son[1] == f) rotate(x, 1), rotate(x, 0); else if(t[f].son[1] == x && t[ff].son[1] == f) rotate(f, 0), rotate(x, 0); else if(t[f].son[1] == x && t[ff].son[0] == f) rotate(x, 0), rotate(x, 1); } if(rt == 0) root = x; } int findip(int k) { int x = root; while(1) { if(k <= t[t[x].son[0]].c) x = t[x].son[0]; else if(t[t[x].son[0]].c + 1 == k) return x; else k -= t[t[x].son[0]].c + 1, x = t[x].son[1]; } return x; } void add(int x, int c) { x++; int h1 = findip(x), h2 = findip(x + 1); splay(h2, 0), splay(h1, h2); t[h1].son[1] = new_node(c, h1); update(h1), update(h2); } ULL query(int l, int r) { l++, r++; int x = findip(l - 1), y = findip(r + 1); splay(x, 0), splay(y, x); return t[t[y].son[0]].sum; } void change(int x, int c) { x++; int hh = findip(x); splay(hh, 0); t[hh].s = c; update(hh); } int build(int l, int r) { if(l > r) return 0; int mid = (l + r) / 2; int now = mid; t[now].c = 1; t[now].s = s[mid]; t[now].lazy = 1; t[now].son[0] = build(l, mid - 1); t[now].son[1] = build(mid + 1, r); if(t[now].son[0]) t[t[now].son[0]].f = now; if(t[now].son[1]) t[t[now].son[1]].f = now; update(now); return now; } int main() { scanf("%s", ss + 1); int n = strlen(ss + 1); int m = read(); o[0] = 1; for(int i = 1; i <= n + m; i++) o[i] = o[i - 1] * P; for(int i = 1; i <= n; i++) s[i + 1] = ss[i]; root = build(1, n + 2); cnt = n + 2; int N = n; for(int i = 1; i <= m; i++) { scanf("%s", ss + 1); if(ss[1] == 'Q') { int x = read(), y = read(); int l = 1, r = _min(N - x + 1, N - y + 1), ans = 0; while(l <= r) { int mid = (l + r) / 2; if(query(x, x + mid - 1) == query(y, y + mid - 1)) l = mid + 1, ans = mid; else r = mid - 1; } printf("%d\n", ans); } else if(ss[1] == 'R') { int x = read(); scanf("%s", ss + 1); change(x, ss[1]); } else { int x = read(); scanf("%s", ss + 1); add(x, ss[1]); N++; } } return 0; }