[CodeForces]914D Bash and a Tough Math Puzzle

做了昨天的维护区间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

我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9301347.html