• 【BZOJ4373】算术天才⑨与等差数列


    Description

    算术天才⑨很喜欢和等差数列玩耍。
    有一天,他给了你一个长度为n的序列,当中第i个数为a[i]。


    他想考考你,每次他会给出询问l,r,k。问区间[l,r]内的数从小到大排序后是否能形成公差为k的等差数列。
    当然,他还会不断改动当中的某一项。
    为了不被他歧视,你必需要高速并正确地回答全然部问题。
    注意:仅仅有一个数的数列也是等差数列。

    Input

    第一行包括两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
    第二行包括n个整数,依次表示序列中的每一个数ai
    接下来m行,每行一開始为一个数op,
    若op=1,则接下来两个整数x,y(1<=x<=n。0<=y<=10^9),表示把a[x]改动为y。
    若op=2。则接下来三个整数l,r,k(1<=l<=r<=n。0<=k<=10^9)。表示一个询问。
    在本题中,x,y,l,r,k都是经过加密的,都需要异或你之前输出的Yes的个数来进行解密。

    Output

    输出若干行,对于每一个询问。假设能够形成等差数列,那么输出Yes,否则输出No。

    Sample Input

    5 3

    1 3 2 5 6

    2 1 5 1

    1 5 4

    2 1 5 1
    Sample Output

    No

    Yes
    HINT

    Source

    假设l,r是公差为k的等差数列,一定满足两个条件:
    1.maxri=la[i]minri=l=(rl)k
    2.序列里相邻两个数的差的gcd为k
    这是蛮显然的(尽管根本没试过证明
    然后直接线段树
    题解发出5分钟后的UPD>
    必须满足区间里不可重…可是我懒得加了..加上代码就上3KB辣
    看题解的人懂就好_ (:зゝ∠)_

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define lchild rt<<1,l,mid
    #define rchild rt<<1|1,mid+1,r
    #define ln rt<<1
    #define rn rt<<1|1
    #define GET (ch>='0'&&ch<='9')
    #define MAXN 300010
    using namespace std;
    int n,m,cnt;
    int a[MAXN];
    void in(int &x)
    {
        char ch=getchar();x=0;
        while (!GET)    ch=getchar();
        while (GET) x=x*10+ch-'0',ch=getchar();
    }
    int gcd(int a,int b)    {return !b?a:gcd(b,a%b);}
    int Abs(int x)  {return x>0?x:-x;}
    struct seg
    {
        int l,r,maxn,minn,Gcd,lnum,rnum;
    }tree[MAXN<<2],empty;
    void push_up(int rt)
    {
        tree[rt].lnum=tree[ln].lnum;tree[rt].rnum=tree[rn].rnum;
        tree[rt].maxn=max(tree[ln].maxn,tree[rn].maxn);tree[rt].minn=min(tree[ln].minn,tree[rn].minn);
        tree[rt].Gcd=gcd(gcd(tree[ln].Gcd,tree[rn].Gcd),Abs(tree[ln].rnum-tree[rn].lnum));
    }
    void build(int rt=1,int l=1,int r=n)
    {
        tree[rt].l=l;tree[rt].r=r;
        if (l==r)   {tree[rt].maxn=tree[rt].minn=tree[rt].lnum=tree[rt].rnum=a[l];return;}
        int mid=(l+r)>>1;build(lchild);build(rchild);push_up(rt);
    }
    void modify(int rt,int x,int delta)
    {
        int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;
        if (L==R)   {tree[rt].maxn=tree[rt].minn=tree[rt].lnum=tree[rt].rnum=delta;return;}
        if (x<=mid) modify(ln,x,delta);
        else    modify(rn,x,delta);
        push_up(rt);
    }
    seg query(int rt,int l,int r)
    {
        int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;
        if (l<=L&&r>=R) return tree[rt];
        seg ret,ans1,ans2;ret=empty;
        bool _l=0,_r=0;
        if (l<=mid) _l=1,ans1=query(ln,l,r);
        if (r>mid)  _r=1,ans2=query(rn,l,r);
        if (_l)
        {
            if (_r) ret.lnum=ans1.lnum,ret.rnum=ans2.rnum,ret.maxn=max(ans1.maxn,ans2.maxn),ret.minn=min(ans1.minn,ans2.minn),ret.Gcd=gcd(gcd(ans1.Gcd,ans2.Gcd),Abs(ans1.rnum-ans2.lnum));
            else    ret=ans1;
        }
        else    ret=ans2;
        return ret;
    }
    int main()
    {
         in(n);in(m);int opt,l,r,k;
         for (int i=1;i<=n;i++) in(a[i]);
         build();
         while (m--)
         {
            in(opt);
            if (opt==1) in(l),in(r),l^=cnt,r^=cnt,modify(1,l,r);
            else
            {
                in(l);in(r);in(k);l^=cnt;r^=cnt;k^=cnt;if (l>r) swap(l,r);
                seg t=query(1,l,r);
                if ((l==r)||(t.Gcd==k&&t.maxn-t.minn==(r-l)*k)) puts("Yes"),cnt++;
                else    puts("No");
            }
         }
    }
  • 相关阅读:
    java中CyclicBarrier的使用
    java并发中CountDownLatch的使用
    java中Locks的使用
    java 中的fork join框架
    java中ThreadPool的介绍和使用
    java中的daemon thread
    java中interrupt,interrupted和isInterrupted的区别
    java中的Atomic类
    怎么在java中关闭一个thread
    java中join的使用
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7140603.html
Copyright © 2020-2023  润新知