给出
n
≤
1
e
5
n\leq1e5
n≤1e5的字符串,支持单点修改,判断区间是否为回文串。
基本上是哈希的模板题吧。用线段树维护正反两个哈希,然后直接修改和查询。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=1e5+7;
const int b=133;
char opt[20];
ull p[N];
ull hs1[N<<2],hs2[N<<2];
char str[N];
void pushup(int rt,int l,int mid,int r) {
hs1[rt]=hs1[rt<<1]*p[r-mid]+hs1[rt<<1|1];
hs2[rt]=hs2[rt<<1|1]*p[mid-l+1]+hs2[rt<<1];
}
void build(int rt,int l,int r) {
if(l==r) {
hs1[rt]=hs2[rt]=str[l];
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt,l,mid,r);
}
void modify(int rt,int l,int r,int x,int val) {
if(l==r) {
hs1[rt]=hs2[rt]=val;
return;
}
int mid=(l+r)>>1;
if(x<=mid) modify(rt<<1,l,mid,x,val);
else modify(rt<<1|1,mid+1,r,x,val);
pushup(rt,l,mid,r);
}
ull query1(int rt,int l,int r,int L,int R) {
if(L>r||R<l) return 0;
if(L<=l&&r<=R) return hs1[rt]*p[R-r];
int mid=(l+r)>>1;
return query1(rt<<1,l,mid,L,R)+query1(rt<<1|1,mid+1,r,L,R);
}
ull query2(int rt,int l,int r,int L,int R) {
if(L>r||R<l) return 0;
if(L<=l&&r<=R) return hs2[rt]*p[l-L];
int mid=(l+r)>>1;
return query2(rt<<1,l,mid,L,R)+query2(rt<<1|1,mid+1,r,L,R);
}
int main() {
int n,q;
scanf("%s",str+1);
n=strlen(str+1);
p[0]=1;
for(int i=1;i<=n;i++)
p[i]=p[i-1]*b;
build(1,1,n);
scanf("%d",&q);
while(q--) {
scanf("%s",opt);
if(opt[0]=='p') {
int l,r;
scanf("%d%d",&l,&r);
ull x=query1(1,1,n,l,r);
ull y=query2(1,1,n,l,r);
if(x==y) puts("Yes");
else puts("No");
}
else {
int x;
char val[2];
scanf("%d%s",&x,&val);
modify(1,1,n,x,val[0]);
}
}
return 0;
}