zoukankan      html  css  js  c++  java
  • [2020CCPC威海G] Caesar Cipher

    Description

    给定一个长度为 (n) 的序列,有 (q) 次操作,每次给定一个 ([l,r])(a_l,...,a_r) 每个元素 (+1),或者给定 (x,y,l) 询问 (a[x..x+l-1])(a[y..y+l-1]) 是否完全相同。所有元素在任意时刻对 (65536) 取模。

    Solution

    暴力用 hash 维护,模数自取,如果没有溢出的情况则正常处理即可。

    现在考虑如何处理溢出的情况,对于每个区间记录一个最大值,如果这个最大值 (ge 65536) 则暴力递归下去找到这个最大值并且把它修改掉。

    溢出的次数保证了复杂度。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    const int mod = 998244353;
    const int bas = 137;
    
    int n,q,t1,t2,t3,t4,a[N];
    
    int power[N];
    int mask[N];
    
    struct SegmentTree 
    {
        struct Node 
        {
            int len;
            int val;
            int tag;
            int mx;
    
            Node operator + (const Node &x) 
            {
                return {len+x.len, (val*power[x.len]+x.val)%mod, 0, max(mx,x.mx)};
            }
        } node[N*4];
    
        void maintain(int p)
        {
            node[p].val%=mod;
            node[p].tag%=mod;
        }
    
        void change(int p,int v)
        {
            node[p].val+=v*mask[node[p].len];
            node[p].tag+=v;
            node[p].mx+=v;
            maintain(p);
        }
    
        void pushdown(int p,int l,int r)
        {
            if(node[p].tag!=0)
            {
                int t=node[p].tag;
                node[p].tag=0;
                change(p*2,t);
                change(p*2+1,t);
            }
        }
    
        void build(int p,int l,int r,int *src)
        {
            if(l==r)
            {
                node[p]={1,a[l],0,a[l]};
            }
            else
            {
                build(p*2,l,(l+r)/2,src);
                build(p*2+1,(l+r)/2+1,r,src);
                node[p]=node[p*2]+node[p*2+1];
            }
        }
    
        void modify(int p,int l,int r,int ql,int qr)
        {
            if(l>qr || r<ql) return;
            if(l>=ql && r<=qr)
            {
                change(p,1);
            }
            else
            {
                pushdown(p,l,r);
                modify(p*2,l,(l+r)/2,ql,qr);
                modify(p*2+1,(l+r)/2+1,r,ql,qr);
                node[p]=node[p*2]+node[p*2+1];
            }
        }
    
        void reduce(int p,int l,int r,int pos)
        {
            if(l==r)
            {
                node[p]={1,0,0,0};
            }
            else
            {
                pushdown(p,l,r);
                if(pos<=(l+r)/2) reduce(p*2,l,(l+r)/2,pos);
                else reduce(p*2+1,(l+r)/2+1,r,pos);
                node[p]=node[p*2]+node[p*2+1];
            }
        }
    
        void eliminate(int p,int l,int r)
        {
            if(node[p].mx<65536) return;
            if(l==r) 
            {
                reduce(1,1,n,l);
            }
            else
            {
                pushdown(p,l,r);
                eliminate(p*2,l,(l+r)/2);
                eliminate(p*2+1,(l+r)/2+1,r);
            }
        }
    
        Node query(int p,int l,int r,int ql,int qr)
        {
            if(l>qr || r<ql) return {0,0,0,0};
            if(l>=ql && r<=qr) 
            {
                return node[p];
            }
            else
            {
                pushdown(p,l,r);
                return query(p*2,l,(l+r)/2,ql,qr) + query(p*2+1,(l+r)/2+1,r,ql,qr);
            }
        }
    
        int query(int ql,int qr)
        {
            return query(1,1,n,ql,qr).val;
        }
    } segtree;
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>q;
    
        power[0]=1;
        for(int i=1;i<=n;i++)
        {
            power[i]=power[i-1]*bas%mod;
            mask[i]=(mask[i-1]+power[i-1])%mod;
        }
    
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
    
        segtree.build(1,1,n,a);
    
        for(int i=1;i<=q;i++)
        {
            int op;
            cin>>op;
            if(op==1)
            {
                int l,r;
                cin>>l>>r;
                segtree.modify(1,1,n,l,r);
                segtree.eliminate(1,1,n);
            }
            else
            {
                int x,y,l;
                cin>>x>>y>>l;
                int l1=x,r1=x+l-1,l2=y,r2=y+l-1;
                int b1=segtree.query(l1,r1);
                int b2=segtree.query(l2,r2);
                if(b1==b2) puts("yes");
                else puts("no");
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    Android6.0-运行时权限处理
    Notification的基本用法以及使用RemoteView实现自定义布局
    Android Apk的反编译和加密
    SurfaceView的基本使用
    Java8部分新特性的学习
    Android的UI调优
    Builder模式详解及其在Android开发中的应用
    hex(x) 将整数x转换为16进制字符串
    oct(x) 将一个数字转化为8进制
    sum(iterable[, start]) 对集合求和
  • 原文地址:https://www.cnblogs.com/mollnn/p/13904038.html
Copyright © 2011-2022 走看看