线段树维护gcd,分左右子区间查询。
#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
#define ll long long
#define CLR(a) memset(a, 0, sizeof(a))
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define MID(a,b) (a+((b-a)>>1))
const int maxn=5e5+10;
int w[maxn];
int gcd(int x,int y){
return y==0?x:gcd(y,x%y);
}
struct node{
int l,r;
int mid(){return MID(l,r);}
int val;
};
int a[maxn];
struct Segtree{
node tree[maxn<<2];
void push_up(int rt){
tree[rt].val=gcd(tree[ls].val,tree[rs].val);
}
void build(int l,int r,int rt){
tree[rt].l=l;tree[rt].r=r;
if(l==r) tree[rt].val=a[l];
else{
int mid=tree[rt].mid();
build(l,mid,ls);
build(mid+1,r,rs);
push_up(rt);
}
}
void update(int rt,int pos,int val){
int l=tree[rt].l,r=tree[rt].r;
if(l==r) tree[rt].val=val;
else{
int mid=tree[rt].mid();
if(pos<=mid) update(ls,pos,val);
else update(rs,pos,val);
push_up(rt);
}
}
int query(int rt,int st,int ed){
int l=tree[rt].l,r=tree[rt].r;
int ans=0;
if(st<=l&&r<=ed) return tree[rt].val;
else{
int mid=tree[rt].mid();
int ans=0;
if(st<=mid) ans=gcd(query(ls,st,ed),ans);
if(mid<ed) ans=gcd(query(rs,st,ed),ans);
return ans;
}
}
int check(int rt,int l,int r,int x){
if(l==r) return 1;
int ansl=x,ansr=x;
int mid=tree[rt].mid();
if(mid>=l) ansl=query(ls,l,mid);
if(r>mid) ansr=query(rs,mid+1,r);
ansl=gcd(ansl,x);
ansr=gcd(ansr,x);
if(ansl!=x&&ansr!=x) return -1;
else if(ansl==x&&ansr==x) return 1;
else if(ansl==x) return check(rs,mid+1,r,x);
else return check(ls,l,mid,x);
}
}seg;
int n;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
seg.build(1,n,1);
int q;
scanf("%d",&q);
while(q--){
int op,a,b,x;
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&a,&b,&x);
if(seg.check(1,a,b,x)==1) printf("YES\n");
else printf("NO\n");
}else{
scanf("%d%d",&a,&b);
seg.update(1,a,b);
}
}
return 0;
}