P4036 [JSOI2008]火星人
作者:互联网
每次询问区间中的两个点 \(l,r\) 为起点的字符串的 LCP,支持单点修改和插入。
如果没有后面两个操作,直接 二分 + Hash 维护即可。
在有后面操作的情况下,我们需要一个支持 单点修改 和 插入 的数据结构,显然平衡树可以。
至于 Hash 值,简单 push_up 一下就好了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned long long ULL;
const int N = 100010;
const ULL P = 13331;
int n, m, root, tot;
char s[N];
ULL p[N];
struct Tree{int fa, v, sz, ch[2]; ULL hash;} tr[N];
int read(){
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' && c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
void push_up(int x){
int l = tr[x].ch[0], r = tr[x].ch[1];
tr[x].sz = tr[l].sz + tr[r].sz + 1;
tr[x].hash = tr[l].hash + p[tr[l].sz] * (ULL) tr[x].v + tr[r].hash * p[tr[l].sz + 1];
}
int findfa(int x) {return tr[tr[x].fa].ch[0] == x ? 0 : 1;}
void connect(int x, int fa, int son){
tr[x].fa = fa;
tr[fa].ch[son] = x;
}
int build(int l, int r){
if(l > r) return 0;
int mid = (l + r) >> 1;
connect(build(l, mid - 1), mid, 0);
connect(build(mid + 1, r), mid, 1);
push_up(mid);
return mid;
}
void rotate(int x){
int Y = tr[x].fa, R = tr[Y].fa;
if(Y == root)
root = x;
int Yson = findfa(x), Rson = findfa(Y);
int B = tr[x].ch[Yson ^ 1];
connect(B, Y, Yson);
connect(Y, x, Yson ^ 1);
connect(x, R, Rson);
push_up(Y), push_up(x);
}
void splay(int x, int to){
while(tr[x].fa != to){
int y = tr[x].fa;
if(tr[y].fa == to)
rotate(x);
else if(findfa(x) == findfa(y))
rotate(y), rotate(x);
else
rotate(x), rotate(x);
}
}
int find(int x){
int now = root;
while(true){
if(x == tr[tr[now].ch[0]].sz + 1) return now;
if(x < tr[tr[now].ch[0]].sz + 1) now = tr[now].ch[0];
else x -= tr[tr[now].ch[0]].sz + 1, now = tr[now].ch[1];
}
}
ULL Get_Hash(int l, int r){
int x = find(l), y = find(r + 2);
splay(x, 0), splay(y, x);
return tr[tr[y].ch[0]].hash;
}
int main(){
p[0] = 1;
for(int i = 1; i <= 100000; i ++) p[i] = p[i - 1] * P;
scanf("%s", s + 1); n = strlen(s + 1);
for(int i = 2; i <= n + 1; i ++)
tr[i].v = tr[i].hash = s[i - 1] - 'a' + 1;
root = build(1, n + 2);
tot = n + 2;
m = read(); char opt[3], c[3];
while(m --){
scanf("%s", opt);
if(opt[0] == 'Q'){
int x = read(), y = read();
if(x > y) swap(x, y);
int l = 0, r = tot - y - 1;
while(l < r){
int mid = (l + r + 1) >> 1;
if(Get_Hash(x, x + mid - 1) == Get_Hash(y, y + mid - 1))
l = mid;
else
r = mid - 1;
}
printf("%d\n", l);
}
else if(opt[0] == 'R'){
int x = read(); scanf("%s", c);
splay(find(x + 1), 0);
tr[root].v = c[0] - 'a' + 1;
push_up(root);
}
else{
int x = read(); scanf("%s", c);
int u = find(x + 1), v = find(x + 2);
splay(u, 0), splay(v, u);
connect(++ tot, tr[root].ch[1], 0);
tr[tot].hash = tr[tot].v = c[0] - 'a' + 1;
tr[tot].sz = 1;
splay(tot, 0);
}
}
return 0;
}
标签:火星人,P4036,int,JSOI2008,tr,mid,splay,ch,now 来源: https://www.cnblogs.com/lpf-666/p/14598881.html