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;
}

相关文章:

  • 2021-12-23
  • 2021-07-03
  • 2021-06-17
  • 2021-07-21
  • 2021-10-01
  • 2021-10-08
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-06-15
  • 2022-12-23
  • 2021-06-29
  • 2021-10-09
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案