Description
算术天才⑨非常喜欢和等差数列玩耍。
有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。
他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k的等差数列。
当然,他还会不断修改其中的某一项。
为了不被他鄙视,你必须要快速并正确地回答完所有问题。
注意:只有一个数的数列也是等差数列。
Input
第一行包含两个正整数n,m(1<=n,m<=300000),分别表示序列的长度和操作的次数。
第二行包含n个整数,依次表示序列中的每个数a[i](0<=a[i]<=10^9)。
接下来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
1 3 2 5 6
2 1 5 1
1 5 4
2 1 5 1
Sample Output
No
Yes
Yes
好久没写代码了。
这题询问区间能否构成等差数列,直接维护每一个数肯定是不好维护的。
所以我们考虑维护公差。
对于区间[l,r]。如果能构成公差为k的等差数列。记区间最大和最小的数分别为ma和mi
则满足k*(r-l)=ma-mi
且相邻的差的gcd=k
知道了这点就好维护了。
维护区间差的gcd和区间最大最小值,最后比较一下就可以了。
* l==r的情况需要注意一下
#include<cstdio>
#include<algorithm>
using namespace std;
struct tree
{
int l,r;
int s;
int ll,rr;
int ma,mi;
}tr[2400001];
int a[300001];
inline int gcd(int x,int y)
{
if(x==0)
return y;
else if(y==0)
return x;
int m=x%y;
while(m!=0)
{
x=y;
y=m;
m=x%y;
}
return y;
}
inline int absx(int x)
{
if(x<0)
x=-x;
return x;
}
inline void up(int p)
{
tr[p].ll=tr[p*2].ll;
tr[p].rr=tr[p*2+1].rr;
int xx=absx(tr[p*2].rr-tr[p*2+1].ll);
tr[p].s=gcd(gcd(tr[p*2].s,tr[p*2+1].s),xx);
tr[p].ma=max(tr[p*2].ma,tr[p*2+1].ma);
tr[p].mi=min(tr[p*2].mi,tr[p*2+1].mi);
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
}
else
{
tr[p].ll=a[l];
tr[p].rr=a[l];
tr[p].ma=a[l];
tr[p].mi=a[l];
}
}
inline void change(int p,int l,int r,int x)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
tr[p].ll=x;
tr[p].rr=x;
tr[p].ma=x;
tr[p].mi=x;
}
else
{
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
change(p*2,l,r,x);
if(r>mid)
change(p*2+1,l,r,x);
up(p);
}
}
tree nx;
inline tree ask(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p];
else
{
int mid=(tr[p].l+tr[p].r)/2;
tree ans=nx;
tree ans1,ans2;
bool flag1=false,flag2=false;
if(l<=mid)
{
flag1=true;
ans1=ask(p*2,l,r);
}
if(r>mid)
{
flag2=true;
ans2=ask(p*2+1,l,r);
}
if(flag1)
{
if(flag2)
{
int xx=absx(ans1.rr-ans2.ll);
ans.s=gcd(gcd(ans1.s,ans2.s),xx);
ans.ma=max(ans1.ma,ans2.ma);
ans.mi=min(ans1.mi,ans2.mi);
ans.ll=ans1.ll;
ans.rr=ans2.rr;
}
else
ans=ans1;
}
else
ans=ans2;
return ans;
}
}
int main()
{
// freopen("yyn.in","r",stdin);
// freopen("yyn.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
int i;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
int xx;
int l,r,k;
int sx=0;
for(i=1;i<=m;i++)
{
scanf("%d",&xx);
if(xx==1)
{
scanf("%d%d",&l,&r);
l=l^sx;
r=r^sx;
change(1,l,l,r);
}
else
{
scanf("%d%d%d",&l,&r,&k);
l=l^sx;
r=r^sx;
k=k^sx;
tree xt=ask(1,l,r);
if(xt.s==k&&(xt.ma-xt.mi)==k*(r-l)||l==r)
{
printf("Yes\n");
sx++;
}
else
printf("No\n");
}
}
return 0;
}