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+1];
int len;
struct node{
    ll suml,sumr;
}tree[maxn<<2];//区间保存从左到右和从右到左的hash值
inline void pushup(int rt){
    tree[rt].suml=tree[rt<<1].suml+tree[rt<<1|1].suml;
    tree[rt].sumr=tree[rt<<1].sumr+tree[rt<<1|1].sumr;
}
void build(int l,int r,int rt){
    if(l==r){
        tree[rt].suml=F[l-1]*(s[l-1]-'a');
        tree[rt].sumr=F[len-l]*(s[l-1]-'a');
        return;
    }
    int m=l+r>>1;
    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-1]*val;
        tree[rt].sumr=F[len-l]*val;
        return;
    }
    int m=l+r>>1;
    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>>1;
    if(x<=m) query(x,y,lson);
    if(y>m) query(x,y,rson);
}
int main(){
    F[0]=1;
    for(int i=1;i<=maxn;i++)
        F[i]=F[i-1]*27;//打表处理
    int q;
    while(scanf("%s",s)!=EOF){
        scanf("%d",&q);
        len=strlen(s);
        build(1,len,1);
        char op[20];
        int x,y;
        while(q--){
            scanf("%s",op);
            if(op[0]=='p'){//查询
                scanf("%d%d",&x,&y);
                suml=sumr=0;
                query(x,y,1,len,1);
                int k1=x-1;//左到右的长度
                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[2];
                scanf("%d%s",&x,tmp);
                update(x,tmp[0]-'a',1,len,1);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zsben991126/p/9905959.html