ural1989 单点更新+字符串hash

时间:2023-03-09 02:06:46
ural1989 单点更新+字符串hash

正解是双哈希,不过一次哈希也能解决。。

然后某个数字就对应一个字符串,虽然有些不同串对应同一个数字,但是概率非常小,可以忽略不计。从左到右、从右到左进行两次hash,如果是回文串,那么对应的整数必定存在某种关系(可以理解成相等),对于更新操作,就是单点更新。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#include<algorithm>
#define ll unsigned long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100005
char s[maxn];
ll F[maxn+];
int len;
struct node{
ll suml,sumr;
}tree[maxn<<];//区间保存从左到右和从右到左的hash值
inline void pushup(int rt){
tree[rt].suml=tree[rt<<].suml+tree[rt<<|].suml;
tree[rt].sumr=tree[rt<<].sumr+tree[rt<<|].sumr;
}
void build(int l,int r,int rt){
if(l==r){
tree[rt].suml=F[l-]*(s[l-]-'a');
tree[rt].sumr=F[len-l]*(s[l-]-'a');
return;
}
int m=l+r>>;
build(lson);
build(rson);
pushup(rt);
}
void update(int pos,int val,int l,int r,int rt){//单点更新
if(l==r){
tree[rt].suml=F[l-]*val;
tree[rt].sumr=F[len-l]*val;
return;
}
int m=l+r>>;
if(pos<=m) update(pos,val,lson);
else update(pos,val,rson);
pushup(rt);
}
ll suml,sumr;
void query(int x,int y,int l,int r,int rt){
if(x<=l && y>=r){
suml+=tree[rt].suml;
sumr+=tree[rt].sumr;
return;
}
int m=l+r>>;
if(x<=m) query(x,y,lson);
if(y>m) query(x,y,rson);
}
int main(){
F[]=;
for(int i=;i<=maxn;i++)
F[i]=F[i-]*;//打表处理
int q;
while(scanf("%s",s)!=EOF){
scanf("%d",&q);
len=strlen(s);
build(,len,);
char op[];
int x,y;
while(q--){
scanf("%s",op);
if(op[]=='p'){//查询
scanf("%d%d",&x,&y);
suml=sumr=;
query(x,y,,len,);
int k1=x-;//左到右的长度
int k2=len-y;//右到左的区间长度
if(k1>k2) sumr*=F[k1-k2];
else suml*=F[k2-k1];
cout<<suml<<" "<<sumr<<endl;
if(suml==sumr) puts("YES");
else puts("NO");
}
else {//单点修改
int x;
char tmp[];
scanf("%d%s",&x,tmp);
update(x,tmp[]-'a',,len,);
}
}
}
return ;
}