(趁还是最优解,题解区也没有\(zkw\)跑来写一篇\(zkw\)的题解\(QWQ\))
题面
分析
Solution 1
根据题意,我们可以发现直接搞肯定不现实
那么我们考虑维护对于一个整段区间的信息,来代替每一个点的信息
所以很容易想到哈希的做法
那么这里我们可以考虑维护区间的平方和 (为什么呢,别问,问就是lxl说的)
因为我们可以发现,直接搞一个确定性做法的算法比较不好想,
所以我们就直接弄成这种正确性比较高的做法
就是一个序列是等差数列,我们可以直接改写它的平方和的形式(就是神鱼鱼的那个/kel)
然后带值进去比较两个值相不相等就行了/fad
这里我们线段树要维护的有两个值:
\(1.\)区间最小值
\(2.\)区间平方和
因为是单点修改,写起来也特别简单,这里采用常数小的\(zkw\)线段树实现
Solution 2
(复述一下\(lxl\)的正解)
这是一个确定性做法。(lxl给出的正解)
可以考虑维护区间最小值和最大值
然后把整个区间差分,维护差分数组的区间\(gcd\),而这个\(gcd\)必须等于\(k\),
易证其他情况都不满足这个区间是个等差数列。
接下来考虑重复的情况,我们可以维护一个前驱的最大值(这个前驱的值定义为数\(x\)前驱所在的位置)
(还有一种做法是一维数点,但是这样做有点慢,多一个\(log\))
那么最后判断一下就行了
Code
这里只给出第一种解法的代码 (因为第二种不会
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define int long long
const int N=1e6+5,p=998244353;
int n,m,las;
int sum[N<<2],minn[N<<2],mi,base,sqr1;
#define sqr(x) (x*x%p)
#define inc(x,y) (x+y>=p?x+y-p:x+y)
#define min(x,y) (x<y?x:y)
#define max(x,y) (x>y?x:y)
inline void modify(int x,int k){
minn[base+x]=k;
sum[base+x]=sqr(k);
for(int i=(base+x)>>1;i;i>>=1){
minn[i]=min(minn[i<<1],minn[i<<1|1]);
sum[i]=inc(sum[i<<1],sum[i<<1|1]);
}
return ;
}
inline int query1(int x,int y){
int res=0x3f3f3f3f;
for(int s=base+x-1,t=base+y+1;t-s>1;t>>=1,s>>=1){
if(~s&1) res=min(res,minn[s^1]);
if(t&1) res=min(res,minn[t^1]);
}
return res;
}
inline int query2(int x,int y){
int res=0;
for(int s=base+x-1,t=base+y+1;t-s>1;t>>=1,s>>=1){
if(~s&1) res=inc(res,sum[s^1]);
if(t&1) res=inc(res,sum[t^1]);
}
return res;
}
int QuickPow(int x){
int res=1,y=p-2;
while(y){
if(y&1) res=(res*x)%p;
x=(x*x)%p;
y>>=1;
}
return res;
}
int de;
signed main(){
read(n),read(m);de=QuickPow(6);
base=(1<<(int)(ceil(log(n+1)/log(2))));
for(int i=base+1;i<=base+n;i++) read(minn[i]),sum[i]=sqr(minn[i]);
for(int i=base-1;i>=1;i--) sum[i]=inc(sum[i<<1],sum[i<<1|1]),minn[i]=min(minn[i<<1],minn[i<<1|1]);
while(m--){
int op,x,y,k;
read(op),read(x),read(y);
x^=las,y^=las;
if(op==1) modify(x,y);
else{
read(k);
k^=las;int len=y-x+1;
mi=query1(x,y)%p,sqr1=query2(x,y)%p;
if(inc(inc(len*sqr(mi)%p,k*mi%p*len%p*(len-1)%p),sqr(k)*de%p*(len-1)%p*len%p*((len<<1)-1)%p)==sqr1){
las++;
puts("Yes");
}
else puts("No");
}
}
return 0;
}