2020CCPC威海站/gym102798 G-Caesar Cipher 线段树维护区间hash值

2020CCPC威海站/gym102798 G-Caesar Cipher

题意

给定一个长度为(n)的数组(a),有(q)次询问,每次询问为以下两种之一:

  • (1~l~r),将(a)(lle i le r)的数(a_i)变为((a_i+1)~ ext{mod}~65536)
  • (2~x~y~L),若区间([x,x+L-1])和区间([y,y+L-1])完全相等,输出"yes",否则输出"no"。

分析

找到一个质数(b),线段树维护这样一个数组(a_1 cdot b^1,a_2 cdot b^2,dots,a_n cdot b^n)的区间和,那么区间([l,r])(hash)值即为(frac {sum_{i=l}^{r}a_icdot b^i}{b^l}),同时维护区间(a_i)的最大值,对于区间加操作若当前区间的最大值大于等于(65535),就继续暴力递归到叶子结点去将大于等于(65535)的点修改一下,若区间的最大值小于(65535),就区间加上(sum_{i=l}^{r} b^i),并打上标记,这个区间(b)的幂次和是可以预处理的,对于每个(a_i)最多约有(frac{q}{65535})次暴力修改的操作,所以总时间复杂度为(O(frac{n^2}{65535}logn))

Code

#include <bits/stdc++.h>
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
using namespace std;
typedef long long ll;
const ll mod=1000173169;
const ll base=85531;
const int N=5e5+10;
ll h[N],pre[N];
int n,q;
ll a[N];
ll mx[N<<2],sum[N<<2],tag[N<<2];
ll inv[N];
void bd(int l,int r,int p){
    tag[p]=0;
    if(l==r){
        mx[p]=a[l];
        sum[p]=a[l]*h[l]%mod;
        return;
    }
    int mid=l+r>>1;
    bd(lson);bd(rson);
    mx[p]=max(mx[p<<1],mx[p<<1|1]);
    sum[p]=(sum[p<<1]+sum[p<<1|1])%mod;
}
void pd(int l,int r,int p,int k){
    mx[p]+=k;
    sum[p]=(sum[p]+(pre[r]-pre[l-1]+mod)%mod*k%mod)%mod;
    tag[p]+=k;
}
void up(int dl,int dr,int l,int r,int p){
    if(l==dl&&r==dr){
        if(mx[p]+1<65536){
            mx[p]++;
            sum[p]=(sum[p]+pre[r]-pre[l-1]+mod)%mod;
            tag[p]++;
            return;
        }else if(l==r){
            mx[p]=(mx[p]+1)%65536;
            sum[p]=mx[p]*h[l]%mod;
            return;
        }
    }
    int mid=l+r>>1;
    if(tag[p]) pd(lson,tag[p]),pd(rson,tag[p]);tag[p]=0;
    if(dr<=mid) up(dl,dr,lson);
    else if(dl>mid) up(dl,dr,rson);
    else up(dl,mid,lson),up(mid+1,dr,rson);
    mx[p]=max(mx[p<<1],mx[p<<1|1]);
    sum[p]=(sum[p<<1]+sum[p<<1|1])%mod;
}
ll qy(int dl,int dr,int l,int r,int p){
    if(dl>dr) return 0;
    if(l==dl&&r==dr) return sum[p];
    int mid=l+r>>1;
    if(tag[p]) pd(lson,tag[p]),pd(rson,tag[p]);tag[p]=0;
    if(dr<=mid) return qy(dl,dr,lson);
    else if(dl>mid) return qy(dl,dr,rson);
    else return (qy(dl,mid,lson)+qy(mid+1,dr,rson))%mod;
}
ll ksm(ll a,ll b){
    ll ret=1;
    while(b){
        if(b&1) ret=ret*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ret;
}
int main()
{
    h[0]=1;
    pre[0]=1;
    for(int i=1;i<N;i++){
        h[i]=h[i-1]*base%mod;
        pre[i]=(pre[i-1]+h[i])%mod;
        inv[i]=ksm(h[i],mod-2);
    }
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    bd(1,n,1);
    int op,l,r,x,y,L;
    while(q--){
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d",&l,&r);
            up(l,r,1,n,1);
        }else if(op==2){
            scanf("%d%d%d",&x,&y,&L);
            ll s1=qy(x,x+L-1,1,n,1)*inv[x]%mod;
            ll s2=qy(y,y+L-1,1,n,1)*inv[y]%mod;
            if(s1==s2) puts("yes");
            else puts("no");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xyq0220/p/13959381.html