判断区间是否构成等差数列:极差=k*(len-1),差分gcd=k,没有相同的值。(还有一种,似乎是判断最小值,和,平方和,可能简单点)
然后极差就是最小值跟最大值,跟差分gcd都比较容易维护。
但坑的是没有相同的值的判定。(似乎有人没写过了?excuse me?)
然后假装我们知道(维护)了一个值表示一个区间的数中上一个出现位置最晚的那个的位置(Mpre),就可以轻易用线段树轻松秒掉。
然后这个怎么维护:
对于每个权值开个set,值为位置(map搞标号)
每次修改值,除了set中的加减元素,还要对它的位置的Mpre,它原来权值后一个位置的Mpre,它改后值的后一个位置的Mpre修改。
然后就没了。。
#include <bits/stdc++.h>
#define gc getchar()
#define N 300009
#define inf 0x3f3f3f3f
#define ll long long
#define mid (l+r>>1)
#define root 1,1,n
#define lc cur<<1
#define rc lc|1
#define lson lc,l,mid
#define rson rc,mid+1,r
#define Now cur,l,r
#define NOW int cur,int l,int r
using namespace std;
int n,m,a[N],b[N],c[N],d[N],op,x,y,k;
int Max[N<<2],Min[N<<2],Gcd[N<<2],Mpre[N<<2],Ans,cnt;
map<int,int> mp;
set<int> T[N<<1];
set<int>::iterator pre,suc;
int read()
{
int x=1;
char ch;
while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
int s=ch-'0';
while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0';
return s*x;
}
int gcd(int x,int y)
{
if (y==0) return x;
else return gcd(y,x%y);
}
void up(NOW)
{
Min[cur]=min(Min[lc],Min[rc]);
Max[cur]=max(Max[lc],Max[rc]);
Mpre[cur]=max(Mpre[lc],Mpre[rc]);
Gcd[cur]=gcd(Gcd[lc],Gcd[rc]);
}
void build(NOW)
{
if (l==r)
{
Max[cur]=Min[cur]=a[l];
Gcd[cur]=b[l],Mpre[cur]=c[l];
return;
}
build(lson);
build(rson);
up(Now);
}
void ins(NOW,int x,int y)
{
if (l==r)
{
Min[cur]=Max[cur]=y;
return;
}
if (x<=mid) ins(lson,x,y);
else ins(rson,x,y);
up(Now);
}
int qry_Max(NOW,int L,int R)
{
if (L<=l&&R>=r) return Max[cur];
int ans=0;
if (L<=mid) ans=max(ans,qry_Max(lson,L,R));
if (R>mid) ans=max(ans,qry_Max(rson,L,R));
return ans;
}
int qry_Min(NOW,int L,int R)
{
if (L<=l&&R>=r) return Min[cur];
int ans=inf;
if (L<=mid) ans=min(ans,qry_Min(lson,L,R));
if (R>mid) ans=min(ans,qry_Min(rson,L,R));
return ans;
}
int qry_Gcd(NOW,int L,int R)
{
if (L<=l&&R>=r) return Gcd[cur];
int ans=0;
if (L<=mid) ans=gcd(ans,qry_Gcd(lson,L,R));
if (R>mid) ans=gcd(ans,qry_Gcd(rson,L,R));
return ans;
}
bool pd(NOW,int L,int R)
{
if (L<=l&&R>=r) return Mpre[cur]>=L;
bool ans=1;
if (L<=mid) ans&=pd(lson,L,R);
if (R>mid) ans&=pd(rson,L,R);
return ans;
}
void change(NOW,int x,int y)
{
if (l==r)
{
Mpre[cur]=y;
return;
}
if (x<=mid) change(lson,x,y);
else change(rson,x,y);
up(Now);
}
void mdy(NOW,int x,int y)
{
if (l==r)
{
Gcd[cur]=y;
return;
}
if (x<=mid) mdy(lson,x,y);
else mdy(rson,x,y);
up(Now);
}
int main()
{
n=read(),m=read();
for (int i=1;i<=n;i++)
{
a[i]=read(),b[i]=abs(a[i]-a[i-1]);
if (!mp.count(a[i]))
{
d[i]=mp[a[i]]=++cnt;
T[cnt].insert(0),T[cnt].insert(n+1);
}
else d[i]=mp[a[i]];
T[d[i]].insert(i);
pre=T[d[i]].find(i);
c[i]=*(--pre);
}
build(root);
for (int i=1;i<=m;i++)
{
op=read(),x=read()^Ans,y=read()^Ans;
if (op==1)
{
ins(root,x,y);
pre=suc=T[d[x]].find(x);
pre--,suc++;
if (*suc<=n) change(root,*suc,*pre);
T[d[x]].erase(x);
if (!mp.count(a[x]=y))
{
d[x]=mp[y]=++cnt;
T[cnt].insert(0),T[cnt].insert(n+1);
}
else d[x]=mp[y];
T[d[x]].insert(x);
pre=suc=T[d[x]].find(x);
pre--,suc++;
if (*suc<=n) change(root,*suc,x);
change(root,x,*pre);
mdy(root,x,a[x]-a[x-1]);
if (x<n) mdy(root,x+1,a[x+1]-a[x]);
}
else
{
k=read()^Ans;
if (x==y)
{
Ans++;
puts("Yes");
continue;
}
if ((ll)qry_Max(root,x,y)-qry_Min(root,x,y)!=(ll)(y-x)*k)
{
puts("No");
continue;
}
if (k==0)
{
Ans++;
puts("Yes");
continue;
}
if (qry_Gcd(root,x+1,y)%k)
{
puts("No");
continue;
}
if (pd(root,x,y)) puts("No");
else Ans++,puts("Yes");
}
}
return 0;
}