[Tree line] Luo Gu P5278 arithmetic genius ⑨ and arithmetic sequence

Title Description

  ⑨ really like math genius and arithmetic sequence play. One day, he gives you a sequence of length n, wherein the i-th of a [i]. He wanted to test you, every time he would be asked to give l, r, k, ask the interval [l, r] in the number of small to large order after can form arithmetic sequences tolerance k. Of course, he will continue to modify any of those activities. Not to be despised him, you have to be quickly and correctly answering all the questions. Note: Only the number of columns is a number of arithmetic sequence.

Input and output formats

Input formats:

  The first line contains two positive integers n, m (1 <= n , m <= 300000), and the length of the sequence number of operations, respectively. The second line contains n integers, respectively for each of a number of sequence I . Next m lines of the beginning of a number of op, if op = 1, then the next two integers x, y (1 <= x <= n, 0 <= y <= 10 ^ 9), represents the a [x] modified to y. If op = 2, then the next three integers l, r, k (1 < = l <= r <= n, 0 <= k <= 10 ^ 9), represents a challenge. In this problem, x, y, l, r , k is encrypted, required number of XOR Yes you prior to output to decrypt.

Output formats:

  Several output lines for each inquiry, if you can form arithmetic sequence, then the output Yes, otherwise the output No.

analysis:

  Query section number in the title section configured tolerance requirements whether the K arithmetic sequence. Due to poor maintenance arithmetic sequence itself, then we can find the number in the interval equivalent conditions can constitute arithmetic sequence, and then maintain these conditions can be.

  By looking at someone else's solution to a problem, we can get these conditions:

  1. These numbers are not the same. (nonsense)

  2. The maximum minus minimum value equal to (lr) k. (Direct set formula, was quite obvious)

  3. All gcd two adjacent difference numbers are k, i.e. are multiples of k. (????????)

  Arithmetic sequence certainly meet the above conditions, so we only need to pseudo- evidence about its sufficiency can be.

  首先,所有相邻两数的差都是k的倍数,那么我们可以知道任意两数的差都是k的倍数,因为 任意两数的差 都可以用几个 相邻两数的差 通过加减得到。

  所以,所有数与最小值的差都是k的倍数。这段区间最大值与最小值的差是(l-r)k,所以每个数与最小值做差得到的值不会超过(l-r)k那么这些差就只有0,k,2k,3k.....(l-r)k这(l-r+1)种情况。又因为这段区间有(l-r+1)个且互不相同的数,所以只有可能是把拿(l-r+1)种情况都占满了的,也就是等差数列。

  在伪证完了之后,我们来考虑如何维护这些性质。鉴于是区间查询,所以考虑线段树维护。最大值和最小值不用说,gcd只需要记录一个数和它下一个数的差,再与其它差求gcd,查询只需要查询(l,r-1)即可。至于如何确定这些数不同,我们需要用一个pre数组记录每个位置的 上一个与这个位置有相同值的位置的编号,查询时只需要查询最大的pre,只要它小于l就行。我们可以先将值离散,再把拥有相同值的位置的编号丢将进set里让它自动排序,就可以维护pre数组了。

  代码如下(自带常数大性质的我开了o2才水过,还不如去维护区间平方和和立方和碰碰运气

 

#include<set>
#include<map>
#include<cstdio>
#include<algorithm>
#define lch (id<<1)
#define rch ((id<<1)+1)
#define mid ((l+r)>>1)
#define maxn 300005
using namespace std;map<int,int >ma;
set<int>s[maxn<<1];set<int>::iterator nex,bef;
int n,m,ny,cnt,a[maxn],ori[maxn],pre[maxn];
int mxp[maxn<<3],minn[maxn<<3],maxx[maxn<<3],G[maxn<<3];
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int find(int num)
{
    int id;if(ma.count(num))return ma[num];
    id=ma[num]=++cnt;s[id].insert(0);s[id].insert(n+1);return id;
}
void fix(int l,int r,int id,int i)
{
    if(i<l||r<i)return;
    if(l==r){minn[id]=maxx[id]=a[i];mxp[id]=pre[i];G[id]=abs(a[i]-a[i+1]);return;}
    fix(l,mid,lch,i);fix(mid+1,r,rch,i);
    minn[id]=min(minn[lch],minn[rch]);
    maxx[id]=max(maxx[lch],maxx[rch]);
    mxp[id]=max(mxp[lch],mxp[rch]);G[id]=gcd(G[rch],G[lch]);
}
int q1(int l,int r,int id,int l1,int r1)
{
    if(r1<l||r<l1)return 0;
    if(l1<=l&&r<=r1)return maxx[id];
    return max(q1(l,mid,lch,l1,r1),q1(mid+1,r,rch,l1,r1));
}
int q2(int l,int r,int id,int l1,int r1)
{
    if(r1<l||r<l1)return 2000000000;
    if(l1<=l&&r<=r1)return minn[id];
    return min(q2(l,mid,lch,l1,r1),q2(mid+1,r,rch,l1,r1));
}
int ansgcd;
void q3(int l,int r,int id,int l1,int r1)
{
    if(r1<l||r<l1)return;
    if(l1<=l&&r<=r1)
    {
        if(ansgcd==-1)ansgcd=G[id];
        else ansgcd=gcd(ansgcd,G[id]);return;
    }
    q3(l,mid,lch,l1,r1);q3(mid+1,r,rch,l1,r1);
}
int q4(int l,int r,int id,int l1,int r1)
{
    if(r1<l||r<l1)return 0;
    if(l1<=l&&r<=r1)return mxp[id];
    return max(q4(l,mid,lch,l1,r1),q4(mid+1,r,rch,l1,r1));
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);s[ori[i]=find(a[i])].insert(i);
        bef=s[ori[i]].find(i);bef--;pre[i]=*bef;
        fix(1,n,1,i);if(i>1)fix(1,n,1,i-1);
    }
    for(int t=1,ord,x,l,r,k;t<=m;t++)
    {
        scanf("%d",&ord);
        if(ord==1)
        {
            scanf("%d%d",&x,&k);x^=ny;k^=ny;
            nex=s[ori[x]].find(x);nex++;
            if(*nex!=n+1){pre[*nex]=pre[x];fix(1,n,1,*nex);}
            s[ori[x]].erase(x);
            s[ori[x]=find(a[x]=k)].insert(x);
            nex=s[ori[x]].find(x);nex++;
            pre[x]=pre[*nex];
            if(*nex!=n+1){pre[*nex]=x;fix(1,n,1,*nex);}
            fix(1,n,1,x);
            if(x>1)fix(1,n,1,x-1);
        }
        if(ord==2)
        {
           scanf("%d%d%d",&l,&r,&k);l^=ny;r^=ny;k^=ny;
            if(l==r){printf("Yes\n"),ny++;continue;}
            int mx=q1(1,n,1,l,r),mn=q2(1,n,1,l,r),p=q4(1,n,1,l,r),g;
            ansgcd=-1;q3(1,n,1,l,r-1);g=ansgcd;
            if(k==0&&mx-mn==0){printf("Yes\n"),ny++;continue;}
            if(k==0&&mx-mn!=0){printf("No\n");continue;}
            if(g%k==0&&mx-mn==(r-l)*k&&p<l)printf("Yes\n"),ny++;
            else printf("No\n");
        }
    }
}

 

Guess you like

Origin www.cnblogs.com/firecrazy/p/11228581.html