还是一道很不错的题目,很容易想到用一棵线段树来维护区间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);}}
}