还是一道很不错的题目,很容易想到用一棵线段树来维护区间gcd
注意用倍数来剪枝就好了,很是一到很好的题目的
#include<iostream>
#include<vector>
using namespace std;
const int N = 5e5+10;
int n,q;
struct Segment{
int l,r;
int d;
}tr[N<<2];
int w[N];
int res;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
void pushup(int u){
tr[u].d = gcd(tr[u<<1].d,tr[u<<1|1].d);
}
void build(int u,int l,int r){
tr[u] = {l,r};
if(l==r){tr[u].d = w[l];return;}
int mid = l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int x,int c){
if(tr[u].l==tr[u].r&&tr[u].l==x){
tr[u].d = c;return;
}
int mid = (tr[u].l+tr[u].r)>>1;
if(x<=mid)modify(u<<1,x,c);
else modify(u<<1|1,x,c);
pushup(u);
}
void query(int u,int l,int r,int x){
if(res>1)return;
if(l<=tr[u].l&&tr[u].r<=r){
if(tr[u].d%x==0)return;
}
if(tr[u].l==tr[u].r){
res+=(tr[u].d%x!=0);
return;
}
int mid = tr[u].l+tr[u].r>>1;
if(l<=mid)query(u<<1,l,r,x);
if(r>mid)query(u<<1|1,l,r,x);
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
cin>>q;
build(1,1,n);
while(q--){
int op;cin>>op;
if(op==1){
int l,r,x;cin>>l>>r>>x;
res = 0;
query(1,l,r,x);
if(res>1)cout<<"NO"<<"\n";
else cout<<"YES\n";
}else{
int x,c;cin>>x>>c;
modify(1,x,c);
}
}
}