[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

猜你喜欢

转载自www.cnblogs.com/sdfzhsz/p/9301347.html