zoukankan      html  css  js  c++  java
  • 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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    linux学习笔记
    HDMI之CEC DDC学习笔记(可能有误)
    MAP按照value排序
    Map遍历四种方法
    Java native方法
    [PAT] 1143 Lowest Common Ancestor (30 分)Java
    [PAT] 1148 Werewolf
    [PAT] 1096 Consecutive Factors (20 分)Java
    [PAT] 1092 To Buy or Not to Buy (20 分)Java
    [PAT] 1088 Rational Arithmetic (20 分)Java
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13893472.html
Copyright © 2011-2022 走看看