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