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

2020CCPC威海站/gym102798 G-Caesar Cipher

题意

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

  • \(1~l~r\),将\(a\)\(l\le i \le r\)的数\(a_i\)变为\((a_i+1)~\text{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_i\cdot 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;
}
posted @ 2020-11-11 16:33  xyq0220  阅读(206)  评论(0编辑  收藏  举报