• 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;
    }
    
  • 相关阅读:
    codeforce 896A
    CQH分治与整体二分
    [CQOI2011]动态逆序对
    codeforce Hello 2018 913F sol
    A*算法[k短路([SDOI2010]魔法猪学院)]
    bzoj3524 [POI2014]Couriers
    整体二分
    bzoj5016 [SNOI2017]一个简单的询问
    CF176E Archaeology
    bzoj4551 [TJOI2016&HEOI2016]树
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13959381.html
Copyright © 2020-2023  润新知