[bzoj4373]算术天才⑨与等差数列

[bzoj4373]算术天才⑨与等差数列


写的伪正解,应该会被卡
具体方法:维护区间max,min,区间和,区间平方和以及区间相邻两个数之差的gcd值,然后依次判断

  • 代码
#include<bits/stdc++.h>

using namespace std;
const int N=3e5+4;
typedef long long ll;
int n,m;
ll gcd(int x,int y){
    if(x==0)return y;
    if(y==0)return x;
    return gcd(y,x%y);
}
int a[N];
const int INF=0x3f3f3f3f,mod1=19260817,mod2=1e9+7;
int MX,MN,G;
long long S,HS1,HS2;

struct segtree{
    int mx[N*4],mn[N*4],g[N*4];
    long long s[N*4],hs1[N*4],hs2[N*4];
    inline void pushup(int x){
        mx[x]=max(mx[x<<1],mx[x<<1|1]),mn[x]=min(mn[x<<1],mn[x<<1|1]);
        s[x]=s[x<<1]+s[x<<1|1];
        hs1[x]=(hs1[x<<1]+hs1[x<<1|1])%mod1;
        hs2[x]=(hs2[x<<1]+hs2[x<<1|1])%mod2;
    }
    inline void build(int x,int l,int r){
        int mid=(l+r)>>1;
        if(l==r){
            mx[x]=mn[x]=s[x]=a[l],g[x]=abs(a[l]-a[l+1]);
            hs1[x]=1ll*a[l]%mod1*a[l]%mod1;hs2[x]=1ll*a[l]%mod2*a[l]%mod2;
            return;
        }
        build(x<<1,l,mid);build(x<<1|1,mid+1,r);
        pushup(x);
        g[x]=gcd(g[x<<1],g[x<<1|1]);
    }
    inline void chgcd(int x,int l,int r,int p){
        if(l==r){
            g[x]=abs(a[l]-a[l+1]);return ;
        }
        int mid=(l+r)>>1;
        if(p>mid)chgcd(x<<1|1,mid+1,r,p);
        if(p<=mid)chgcd(x<<1,l,mid,p);
        g[x]=gcd(g[x<<1|1],g[x<<1]);
    }
    inline void chany(int x,int l,int r,int p){
        if(l==r){
            s[x]=mx[x]=mn[x]=a[p];
            hs1[x]=1ll*a[l]%mod1*a[l]%mod1,hs2[x]=1ll*a[l]%mod2*a[l]%mod2;
            return ;
        }
        int mid=(l+r)>>1;
        if(p>mid)chany(x<<1|1,mid+1,r,p);
        if(p<=mid)chany(x<<1,l,mid,p);
        pushup(x);
    }
    inline void qrygcd(int x,int l,int r,int lx,int rx)
    {
        if (l==lx && r==rx){
            G=gcd(G,g[x]);return;
        }
        int mid=(l+r)>>1;
        if (rx<=mid) qrygcd(x<<1,l,mid,lx,rx);
        else if (lx>mid) qrygcd(x<<1|1,mid+1,r,lx,rx);
        else qrygcd(x<<1,l,mid,lx,mid), qrygcd(x<<1|1,mid+1,r,mid+1,rx);
    }
    inline void qry(int x,int l,int r,int lx,int rx){
        if(l==lx&&r==rx){
            MX=max(mx[x],MX),MN=min(mn[x],MN);S+=s[x];
            HS1=(HS1+hs1[x])%mod1;HS2=(HS2+hs2[x])%mod2;
            return;
        }
        int mid=(l+r)>>1;
        if(rx<=mid) qry(x<<1,l,mid,lx,rx);
        else if(lx>mid) qry(x<<1|1,mid+1,r,lx,rx);
        else qry(x<<1,l,mid,lx,mid), qry(x<<1|1,mid+1,r,mid+1,rx);
    }
    inline int chk(int l,int r,ll d){
        if(l==r)return true;
        MX=0,MN=INF,HS1=0,HS2=0,S=0,G=0;
        qrygcd(1,1,n,l,r-1);
        qry(1,1,n,l,r);
        ll k=(r-l);
        if(MX!=MN+d*(r-l))return false;
        if(d==0)return true;
        ll ss=1ll*(MN+MX)*(r-l+1)/2;
        if(ss!=S)return false;
        if(G!=d)return false;
        ll p2=k*(k+1)/2*(k*2+1)/3,p=k*(k+1)/2;
        ll ans1=1ll*MN%mod1*MN%mod1*(k+1)%mod1+p*2%mod1*MN%mod1*d%mod1+p2%mod1*d%mod1*d%mod1;
        ll ans2=1ll*MN%mod2*MN%mod2*(k+1)%mod2+p*2%mod2*MN%mod2*d%mod2+p2%mod2*d%mod2*d%mod2;//平方和
        ans1%=mod1;ans2%=mod2;
        if(ans1!=HS1||ans2!=HS2)return false;
        return true;
    }
    inline void change(int p,int x){
        a[p]=x;
        if(p>1)chgcd(1,1,n,p-1);
        chgcd(1,1,n,p);
        chany(1,1,n,p);
    }
}T;
int las=0;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    T.build(1,1,n);
    for(int op,i=1;i<=m;i++){
        scanf("%d",&op);
        int x,y,d;
        if(op==1){
            scanf("%d%d",&x,&y);
            x^=las,y^=las;
            if(x>=1&&x<=n)T.change(x,y);
        }
        else{
            scanf("%d%d%d",&x,&y,&d);   
            x^=las,y^=las,d^=las;
            if(x>y)swap(x,y);
            int result=T.chk(x,y,d);
            if(result)las++,printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/82730122