做了昨天的维护区间GCD的题这道题就不难了
有一个性质就是一个区间内如果有>=两个数不能被x整除,即输出NO
那么就可以用线段树维护区间的GCD是否是X的倍数,如果发现有两个区间不是,那么就GG了。
用return 2表示有1个,还可以挽救,return 1表示很完美,return 0表示已经GG。
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int N=5e5+5;
struct Segtree{
int gcd,l,r;
}t[N<<2];
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int n,a[N],opt;
void pushup(int cur) {t[cur].gcd=gcd(t[cur<<1].gcd,t[cur<<1|1].gcd);}
void build(int cur,int l,int r) {
t[cur].l=l,t[cur].r=r;
if(l==r) {t[cur].gcd=a[l];return;}
int mid=l+r>>1;
build(cur<<1,l,mid);
build(cur<<1|1,mid+1,r);
pushup(cur);
}
void update(int node,int c,int cur) {
if(t[cur].l==t[cur].r) {t[cur].gcd=c;return;}
int mid=t[cur].l+t[cur].r>>1;
if(node<=mid) update(node,c,cur<<1);
else update(node,c,cur<<1|1);
pushup(cur);
}
int query(int l,int r,int cur,int x) {
if(t[cur].gcd%x==0) return 1;
if(t[cur].r==t[cur].l) return 2;
int mid=t[cur].l+t[cur].r>>1;
if(l<=mid) {
int ans=query(l,r,cur<<1,x);
if(!ans) return 0;
if(ans==1) return r>mid?query(l,r,cur<<1|1,x):1;
return r>mid?(query(l,r,cur<<1|1,x)==1?2:0):2;
}
if(r>mid) return query(l,r,cur<<1|1,x);
return 0;
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int q,l,r,x,y;scanf("%d",&q);
build(1,1,n);
while(q--) {
scanf("%d",&opt);
if(opt==1) {
scanf("%d%d%d",&l,&r,&x);
if(!query(l,r,1,x)) puts("NO");
else puts("YES");
}
if(opt==2) scanf("%d%d",&x,&y),update(x,y,1);
}
}
嵩哥发新歌了,开心.jpg