题目链接
- 题意:
给一个字符串(长度不超过1e5),m次操作(m不超过1e5),每次操作:1、查询[l, r]是否是回文串2、改动p位置的值为v - 分析:
这个题目涉及到回文串的一个处理方式:推断正向和反向是否同样。比較简单的方式是採用Hash判别。之后的问题就是点更新和查询区间,线段树解决
const int MAXN = 410000;
const int SEED = 13331;
ULL f[MAXN];
char ipt[MAXN], t[110];
#define lson rt << 1
#define rson rt << 1 | 1
struct Node
{
int l, r, m;
ULL vl, vr;
} nd[MAXN << 2], tt;
void merge(Node& ret, Node& l, Node& r, int L, int M, int R)
{
ret.vl = r.vl * f[M - L + 1] + l.vl;
ret.vr = l.vr * f[R - M] + r.vr;
}
void pushup(int rt)
{
merge(nd[rt], nd[lson], nd[rson], nd[rt].l, nd[rt].m, nd[rt].r);
}
void build(int l, int r, int rt)
{
nd[rt].l = l; nd[rt].r = r; nd[rt].m = (r + l) >> 1;
if (l == r)
{
nd[rt].vl = nd[rt].vr = ipt[l - 1];
}
else
{
build(l, nd[rt].m, lson);
build(nd[rt].m + 1, r, rson);
pushup(rt);
}
}
void update(int p, int v, int rt)
{
if (nd[rt].l == nd[rt].r)
{
nd[rt].vl = nd[rt].vr = v;
}
else
{
if (p <= nd[rt].m)
update(p, v, lson);
else
update(p, v, rson);
pushup(rt);
}
}
Node query(int L, int R, int rt)
{
if (L <= nd[rt].l && nd[rt].r <= R)
return nd[rt];
if (R <= nd[rt].m)
return query(L, R, lson);
else if (L > nd[rt].m)
return query(L, R, rson);
Node tl = query(L, R, lson);
Node tr = query(L, R, rson);
Node ret;
merge(ret, tl, tr, max(L, nd[rt].l), nd[rt].m, min(R, nd[rt].r));
return ret;
}
int main()
{
f[0] = 1;
FF(i, 1, MAXN)
f[i] = f[i - 1] * SEED;
int n;
while (~RS(ipt))
{
build(1, strlen(ipt), 1);
RI(n);
REP(i, n)
{
RS(t);
if (t[0] == 'p')
{
int a, b;
RII(a, b);
tt = query(a, b, 1);
printf("%s
", tt.vl == tt.vr ? "Yes" : "No");
}
else
{
int p; char v;
scanf("%d %c", &p, &v);
update(p, v, 1);
}
}
}
return 0;
}