2020ccpc威海 G Caesar Cipher(线段树+哈希)

如果没有取模,直接维护线段树哈希,原理跟普通哈希是相同的,就是维护一个哈希数组

本题有取模操作,其实有一个常见的套路就是我们发现取模的次数并不会太多,因此对最大值超过限制的区间直接暴力取模变成0,这样复杂度还是可以过关的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
const int base=131;
const int mod=1e9+7;
ll f[N];
struct node{
    int l,r;
    ll mx;
    ll lazy;
    ll h;
    ll base;
}tr[N<<2];
int a[N];
int n,q;
void init(){
    int i;
    f[0]=1;
    for(i=1;i<=n;i++){
        f[i]=f[i-1]*base%mod;
    }
}
void pushup(int u){
    tr[u].h=(tr[u<<1].h+tr[u<<1|1].h)%mod;
    tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx);
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r,a[l],0,a[l]*f[l]%mod,f[l]};
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        tr[u].base=(tr[u<<1].base+tr[u<<1|1].base)%mod;
        pushup(u);
    }
}
void pushdown(int u){
    ll x=tr[u].lazy;
    tr[u<<1].lazy+=x;
    tr[u<<1|1].lazy+=x;
    tr[u<<1].mx+=x;
    tr[u<<1|1].mx+=x;
    tr[u<<1].h=(tr[u<<1].h+tr[u<<1].base*x)%mod;
    tr[u<<1|1].h=(tr[u<<1|1].h+tr[u<<1|1].base*x)%mod;
    tr[u].lazy=0;
}
void modify(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].h=(tr[u].h+tr[u].base)%mod;
        tr[u].mx++;
        tr[u].lazy++;
        return ;
    }
    if(tr[u].lazy)
        pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,r);
    if(r>mid)
        modify(u<<1|1,l,r);
    pushup(u);
}
void modify_mod(int u){
    if(tr[u].mx<65536)
        return ;
    if(tr[u].l==tr[u].r){
        tr[u].mx=0;
        tr[u].h=0;
        return ;
    }
    if(tr[u].lazy)
        pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    modify_mod(u<<1);
    modify_mod(u<<1|1);
    pushup(u);
}
ll query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r){
        return tr[u].h;
    }
    if(tr[u].lazy)
        pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    ll ans=0;
    if(l<=mid)
        ans=query(u<<1,l,r);
    if(r>mid)
        ans=(ans+query(u<<1|1,l,r))%mod;
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>q;
    int i;
    init();
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    build(1,1,n);
    while(q--){
        int opt;
        cin>>opt;
        if(opt==1){
            int l,r;
            cin>>l>>r;
            modify(1,l,r);
            modify_mod(1);
        }
        else{
            int l,r,len;
            cin>>l>>r>>len;
            if(l>r)
                swap(l,r);
            if(query(1,l,l+len-1)*f[r-l]%mod==query(1,r,r+len-1))
                cout<<"yes"<<endl;
            else{
                cout<<"no"<<endl;
            }
        }
    }
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/13893472.html