zoukankan      html  css  js  c++  java
  • gym102798 Caesar Cipher (2020 China Collegiate Programming Contest, Weihai Site) 线段树

    题意

    有一个一个长度为n的数组a和两种操作(1代表对区间([l,r])加1,2代表询问区间([x,x+L-1])和区间([y,y+L-1])是否相同),其中操作1对65536取模。

    思路

    容易想到可以用哈希判断是否相等。然后题目中的数组是对65536取模的,就会想到hash的模数取65536,即用unsigned short自然溢出取模,但是这个模数被出题人卡掉了。

    另外,做字符串哈希时,哈希的模数一般会选用大指数。因为当base和mod互质时,这个hash函数在([0,mod))上每个值概率相等,此时单次比较的错误率为(frac1{mod})

    对于65536取模的情况,与codeforces438D相同,除了区间和外再加一个区间最大值,对于大于等于65536的区间暴力修改。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    const ll base=1e8+7;
    const int maxn=5e5+5;
    
    struct Tree{
        ll max,sum,tag;
    }tree[maxn*4];
    ll a[maxn],p[maxn],pre[maxn];
    int n,q;
    
    
    ll M(ll val){
        return val>=mod?val-mod:val<0?val+mod:val;
    }
    
    void push_up(int i)
    {
        tree[i].max=max(tree[i<<1].max,tree[i<<1|1].max);
        tree[i].sum=M(tree[i<<1].sum+tree[i<<1|1].sum);
    }
    
    void push_down(int i,int L,int R)
    {
        if(tree[i].tag)
        {
            tree[i<<1].max+=tree[i].tag;
            tree[i<<1|1].max+=tree[i].tag;
            int mid=L+R>>1;
            if(L!=mid)
                tree[i<<1].tag+=tree[i].tag;
            if(mid+1!=R)
                tree[i<<1|1].tag+=tree[i].tag;
            tree[i<<1].sum=M(tree[i<<1].sum+M(pre[mid]-pre[L-1])*tree[i].tag%mod);
            tree[i<<1|1].sum=M(tree[i<<1|1].sum+M(pre[R]-pre[mid])*tree[i].tag%mod);
            tree[i].tag=0;
        }
    }
    
    void build(int i,int l,int r)
    {
        if(l==r)
        {
            tree[i].max=a[l];
            tree[i].sum=a[l]*p[l]%mod;
            tree[i].tag=0;
            return;
        }
        int mid=l+r>>1;
        build(i<<1,l,mid);
        build(i<<1|1,mid+1,r);
        push_up(i);
    }
    
    void add(int i,int l,int r,int L,int R)
    {
        push_down(i,L,R);
        if(l==L && r==R)
        {
            if(l==r)
            {
                tree[i].max++;
                if(tree[i].max==65536)tree[i].max=0;
                tree[i].sum=tree[i].max*p[l]%mod;
                return;
            }
            else if(tree[i].max<65535)
            {            
                tree[i].max++;
                tree[i].tag++;
                tree[i].sum=M(tree[i].sum+M(pre[R]-pre[L-1]));
                return;
            }
        }
        int mid=L+R>>1;
        if(r<=mid)
            add(i<<1,l,r,L,mid);
        else if(l>mid)
            add(i<<1|1,l,r,mid+1,R);
        else
        {
            add(i<<1,l,mid,L,mid);
            add(i<<1|1,mid+1,r,mid+1,R);
        }
        push_up(i);
    }
    
    ll cal(int i,int l,int r,int L,int R)
    {
        push_down(i,L,R);
        int mid=L+R>>1;
        if(l==L && r==R)return tree[i].sum;
        if(r<=mid)
            return cal(i<<1,l,r,L,mid);
        else if(l>mid)
            return cal(i<<1|1,l,r,mid+1,R);
        else
            return M(cal(i<<1,l,mid,L,mid)+cal(i<<1|1,mid+1,r,mid+1,R));
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>q;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        p[0]=1;
        pre[0]=1;
        for(int i=1;i<=n;i++)
        {
            p[i]=p[i-1]*base%mod;
            pre[i]=M(pre[i-1]+p[i]);
        }
    
        build(1,1,n);
        int op,l,r,x,y,L;
        while(q--)
        {
            cin>>op;
            if(op==1)
            {
                cin>>l>>r;
                add(1,l,r,1,n);
            }
            else
            {
                cin>>x>>y>>L;
                if(x>y)swap(x,y);
                ll res1=cal(1,x,x+L-1,1,n),res2=cal(1,y,y+L-1,1,n);
                if(res1*p[y-x]%mod==res2)
                    cout<<"yes
    ";
                else
                    cout<<"no
    ";
            }
            
        }
    
        return 0;
    }
    
  • 相关阅读:
    多任务顺序执行解决方案
    数码摄影学习总结
    ASP.NET Core与RESTful API 开发实战(二)
    通过三点求圆心程序(二维和三维两种方式),代码为ABB机器人程序,其他语言也适用
    ABB机器人选项611-1 Path Recovery使用记录
    C#刷新chart控件方法及task的启停功能记录
    ABB机器人输送链跟踪问题记录
    有关C#跨线程操作控件的委托方法
    c#get、set属性及类的继承
    正则表达式学习记录
  • 原文地址:https://www.cnblogs.com/intmian/p/14015085.html
Copyright © 2011-2022 走看看