传送门
Description
给定一个长度为 n 的序列,其中第 i 个数为 ai。
有 m 次操作,每次要么修改其中的某一项,要么给出询问l; r; k,问区间 [l; r] 内的数从小到大排序后能否形成公差为 k 的等差数列。
Input
第一行包含两个正整数
n,m(1<=n,m<=300000)
,分别表示序列的长度和操作的次数。
第二行包含
n
个整数,依次表示序列中的每个数
接下来
m
行,每行一开始为一个数
若
op=1
,则接下来两个整数
x,y(1<=x<=n,0<=y<=109)
,表示把
ax
修改为
y
。
若
在本题中,
x,y,l,r,k
都是经过加密的,都需要异或你之前输出的
Yes
的个数来进行解密。
Output
输出若干行,对于每个询问,如果可以形成等差数列,那么输出
Yes
,否则输出
No
。
Sample Input
5
1
2
Sample Output
No
Yes
条件一:这一区间的最大值与最小值的差满足等差数列的公式(
ai−aj=d∗(i−j)
)。
条件二:这一区间的所有数模
k
的值相同。
条件二相对于条件一麻烦得多,于是考虑相邻的两个数的差。如果差
这样就可以用线段树水过辣。
简单滴解释一下下面线段树中的标记含义。
maxv:区间最大值。minv:区间最小值。
l:左端点的值。r:右端点的值。
k:区间关于
k
成等差数列。
可能在写的过程中
注意
gcd(a,b)
中不能模
0
<script type="math/tex" id="MathJax-Element-44">0</script>。
据说可以用等差数列的和、各项平方的和水过 2333
#include <iostream>
#include <cstdio>
#include <algorithm>
#define MAXN 300005
using namespace std;
int n, m, num[MAXN];
inline int id(int x,int y){return (x+y)|(x!=y);}
int gcd(int a,int b)
{
if(!a)return b;
if(!b)return a;
return gcd(b,a%b);
}
struct node
{
int maxv, minv, l, r, k;
};
struct SGE
{
node t[MAXN<<1];
inline void up(node &a,node &b,node &c)
{
a.maxv=max(b.maxv,c.maxv), a.minv=min(b.minv,c.minv);
a.l=b.l, a.r=c.r;
a.k=gcd(gcd(b.k,c.k),abs(c.l-b.r));
}
void build(int code,int l,int r)
{
if(l==r)
{
t[code].maxv=t[code].minv=t[code].l=t[code].r=num[l];
return;
}
int mid=(l+r)>>1;
int lc=id(l,mid), rc=id(mid+1,r);
build(lc,l,mid), build(rc,mid+1,r);
up(t[code],t[lc],t[rc]);
}
node query(int code,int l,int r,int ql,int qr)
{
if(l==ql&&r==qr)return t[code];
int mid=(l+r)>>1;
if(qr<=mid)return query(id(l,mid),l,mid,ql,qr);
if(mid<ql)return query(id(mid+1,qr),mid+1,r,ql,qr);
int lc=id(l,mid), rc=id(mid+1,r);
node ans, ans1, ans2;
ans1=query(lc,l,mid,ql,mid), ans2=query(rc,mid+1,r,mid+1,qr);
up(ans,ans1,ans2);
return ans;
}
void change(int code,int l,int r,int pos,int d)
{
if(l==r)
{
t[code].maxv=t[code].minv=t[code].l=t[code].r=d;
return;
}
int mid=(l+r)>>1;
int lc=id(l,mid), rc=id(mid+1,r);
if(pos<=mid)change(lc,l,mid,pos,d);
else change(rc,mid+1,r,pos,d);
up(t[code],t[lc],t[rc]);
}
}sge;
bool solve(int l,int r,int k)
{
if(l==r)return 1;
node ans=sge.query(id(1,n),1,n,l,r);
if(ans.k==k&&ans.maxv-ans.minv==k*(r-l))return 1;
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&num[i]);
sge.build(id(1,n),1,n);
int key=0, f, l, r, x;
while(m--)
{
scanf("%d%d%d",&f,&l,&r);
l^=key, r^=key;
if(f==1)
sge.change(id(1,n),1,n,l,r);
else
{
scanf("%d",&x);
x^=key;
if(solve(l,r,x))
{
++key;
puts("Yes");
}
else puts("No");
}
}
return 0;
}