zoukankan      html  css  js  c++  java
  • bzoj4373 算术天才⑨与等差数列——线段树+set

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4373

    一个区间有以 k 为公差的数列,有3个条件:

    1.区间 mx - mn = (r-l) * k;

    2.差分数组的 gcd 是 k 的倍数;

    3.没有重复出现的数;

    其中1,2都可以用线段树维护,3用 set 维护每个数上一个出现的位置即可;

    模仿TJ写的:https://blog.csdn.net/neither_nor/article/details/52461940

    对 set 更熟悉了,细节还蛮多的。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<set>
    #include<map>
    using namespace std;
    int const maxn=3e5+5;
    int n,m,a[maxn],key,tot,pre[maxn];
    map<int,int>h;
    set<int>s[maxn<<1];
    int gcd(int a,int b){return b?gcd(b,a%b):a;}
    int ab(int x){return x>0?x:-x;}
    struct N{
        int mx,mn,fro,g;
        friend N operator + (N x,N y)
        {
            N ret;
            ret.mx=max(x.mx,y.mx);
            ret.mn=min(x.mn,y.mn);
            ret.fro=max(x.fro,y.fro);
            ret.g=gcd(x.g,y.g);
            return ret;//!
        }
    }t[maxn<<2];
    void build(int x,int l,int r)
    {
        if(l==r)
        {
            t[x].mn=t[x].mx=a[l]; t[x].g=ab(a[l+1]-a[l]);
            t[x].fro=pre[l]; return;
        }
        int mid=((l+r)>>1);
        build(x<<1,l,mid); build(x<<1|1,mid+1,r);
        t[x]=t[x<<1]+t[x<<1|1];
    }
    void update(int x,int l,int r,int p)
    {
        if(l==r)
        {
            t[x].mn=t[x].mx=a[l]; t[x].g=ab(a[l+1]-a[l]);
            t[x].fro=pre[l]; return;
        }
        int mid=((l+r)>>1);
        if(p<=mid)update(x<<1,l,mid,p);
        else update(x<<1|1,mid+1,r,p);
        t[x]=t[x<<1]+t[x<<1|1];
    }
    N query(int x,int l,int r,int L,int R)
    {
        if(l>=L&&r<=R)return t[x];
        int mid=((l+r)>>1);
        if(mid<L)return query(x<<1|1,mid+1,r,L,R);
        else if(mid>=R)return query(x<<1,l,mid,L,R);
        else return query(x<<1,l,mid,L,R)+query(x<<1|1,mid+1,r,L,R);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(!h[a[i]])
            {
                h[a[i]]=++tot;
                s[tot].insert(0);
                s[tot].insert(n+1);
            }
            int tmp=h[a[i]];
            s[tmp].insert(i);
            pre[i]=*--(s[tmp].insert(i).first);//
        }
        a[n+1]=a[n];//!
        build(1,1,n);
        for(int i=1,op,x,y,l,r,k;i<=m;i++)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&x,&y);
                x^=key; y^=key;
                int tmp,nxt,pr;
                tmp=h[a[x]];
                nxt=*s[tmp].upper_bound(x);
                if(nxt!=n+1)
                {
                    pre[nxt]=pre[x];
                    update(1,1,n,nxt);
                }
                s[tmp].erase(x);
                
                if(!h[y])//
                {
                    h[y]=++tot;
                    s[tot].insert(0);
                    s[tot].insert(n+1);
                }
                tmp=h[y];
                s[tmp].insert(x);
                nxt=*s[tmp].upper_bound(x);
                pre[x]=*--s[tmp].lower_bound(x);
                if(nxt!=n+1)
                {
                    pre[nxt]=x;
                    update(1,1,n,nxt);
                }
                a[x]=y;
                update(1,1,n,x);
                if(x!=1)update(1,1,n,x-1);//
            }
            if(op==2)
            {
                scanf("%d%d%d",&l,&r,&k);
                l^=key; r^=key; k^=key;
                if(l==r){key++; printf("Yes
    "); continue;}
                N tmpp=query(1,1,n,l,r-1);//
                N tmp=tmpp+query(1,1,n,r,r);//
                if(k==0)
                {
                    if(tmp.mx==tmp.mn)key++,printf("Yes
    ");
                    else printf("No
    ");
                    continue;
                }
                if(tmp.fro<l && tmp.mx==k*(r-l)+tmp.mn && tmpp.g%k==0)//tmpp!
                    key++,printf("Yes
    ");
                else printf("No
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    java高级程序设计(第十周)
    java高级程序设计(第五周)
    java高级程序设计(第四周)
    期末设计(第十四周)
    期末设计(第十三周)
    期末设计(计划进度表)
    Java学习笔记(六)
    Java学习笔记(六)
    Java学习笔记(五)
    Java学习笔记(四)
  • 原文地址:https://www.cnblogs.com/Zinn/p/9296713.html
Copyright © 2011-2022 走看看