题意:一个长度为n的序列,T个询问,2种询问1 l r x问[l, r]区间内替换一个数能不能使得gcd[l, r] == x,输出yes和no,2 l x序列第l个数替换为x
题解:区间询问,单点需修改,线段树,算出区间有t个数不是x的倍数,t>1输出no
#include#define maxn 501000#define INF 0x3f3f3f3ftypedef long long ll;using namespace std;int gcd[maxn*4];void pushup(int x){ gcd[x] = __gcd(gcd[x<<1], gcd[x<<1|1]);}void build(int l,int r,int x){ if(l == r){ scanf("%d", &gcd[x]); return ; } int mid = (l+r)>>1; build(l, mid, x<<1); build(mid+1, r, x<<1|1); pushup(x);}void update(int l,int r,int x,int t, int c){ if(l == r){ gcd[x] = c; return ; } int mid = (l+r)>>1; if(t<=mid) update(l, mid, x<<1, t, c); else update(mid+1, r, x<<1|1, t, c); pushup(x);}int query(int l,int r,int x,int L,int R,int g){ if(l == r){ return gcd[x]%g?1:0; } if(L>=l && R<=r&&gcd[x]%g == 0) return 0; int mid = l+r>>1; if(mid < L) return query(mid+1, r, x<<1|1, L, R, g); else if(mid >= R) return query(l, mid, x<<1, L, R, g); else{ int b1 = query(l, mid, x<<1, L, mid, g); if(b1 >= 2) return 2; int b2 = query(mid+1, r, x<<1|1, mid+1, R, g); return b1+b2; }}int main(){ int n, t, a, l ,r, x; cin>>n; build(1, n, 1); scanf("%d", &t); while(t--){ scanf("%d", &a); if(a == 1){ scanf("%d%d%d", &l, &r, &x); if(query(1, n, 1, l, r, x) <= 1) printf("YES\n"); else printf("NO\n"); } else { scanf("%d%d", &l, &x); update(1, n, 1, l, x); } } return 0;}