这道题显然是一道区间信息维护的题目,所以我们考虑使用线段树。如果没有修改一个点的限制,那么我们只需要开一个记录gcd的线段树即可。对于修改一个点的限制,我们这么考虑:如果(一串区间的gcd值 mod 题目给出的v) !=0,那么这个区间里至少有一个数不含v这个因数,所以我们一直用线段树二分查找这个区间,最终肯定会找出一些不含因数v的点。如果这个点只有一个,那我们修改这个点即可;如果有两个,那就不可能完成,输出NO。
using namespace std;
int read (){
char c;int x ;while (c=getchar(),c<'0' ||c>'9' );x =c-'0' ;
while (c=getchar(),c>='0' &&c<='9' ) x =x *10 +c-'0' ;return x ;
}
int n,q ,res,a[MAXN],sum[MAXN<<2 ];
int gcd(int x ,int y ){return !y ?x :gcd(y ,x %y );}
void up(int node){sum[node]=gcd(sum[node<<1 ],sum[node<<1 |1 ]);}
void build(int node,int l,int r){
if (l==r){
sum[node]=a[l];
return ;
}
int mid=(l+r)>>1 ;
build(node<<1 ,l,mid);
build(node<<1 |1 ,mid+1 ,r);
up(node);
}
void update(int p,int node,int l,int r,int c){
if (l==r){
sum[node]=c;
return ;
}
int mid=(l+r)>>1 ;
if (p<=mid) update(p,node<<1 ,l,mid,c);
else update(p,node<<1 |1 ,mid+1 ,r,c);
up(node);
}
void query(int lc ,int rc,int node,int l,int r,int v){
if (res>1 ) return ;
if (l==r){
res++;return ;
}
int mid=(l+r)>>1 ;
if (lc <=mid&&sum[node<<1 ]%v !=0 ) query(lc ,rc,node<<1 ,l,mid,v);
if (rc>mid&&sum[node<<1 |1 ]%v !=0 ) query(lc ,rc,node<<1 |1 ,mid+1 ,r,v);
}
int main()
{
n=read ();
for (int i=1 ;i<=n;i++) a[i]=read ();
build(1 ,1 ,n);
q =read ();
while (q --){
int x =read ();
if (x ==1 ){
res=0 ;
int y =read (),z=read (),v=read ();
query(y ,z,1 ,1 ,n,v);
if (res>1 ) puts("NO" );
else puts("YES" );
}
if (x ==2 ){
int y =read (),z=read ();
update(y ,1 ,1 ,n,z);
}
}
return 0 ;
}