CF914D Bash and a Tough Math Puzzle(线段树)

这题其实求的是x的倍数个数是否大于1,大于1肯定不行,否则可以

另外一点,如果区间gcd不能整除x,那么必有至少一个数不是x的倍数,不然gcd会更大

因此我们只要暴力维护并且在发现不止一个的时候及时退出,这样复杂度就可以

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e6+10;
const int mod=1e9+7;
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
struct node{
    int l,r;
    int d;
}tr[N<<2];
int a[N];
int cnt;
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){
    if(l==r){
        tr[u]={l,r,a[l]};
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushup(u);
    }
}
void modify(int u,int l,int x){
    if(tr[u].l==tr[u].r){
        tr[u].d=x;
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,x);
    else
        modify(u<<1|1,l,x);
    pushup(u);
}
void query(int u,int l,int r,int x){
    if(cnt>1)
        return ;
    if(tr[u].l==tr[u].r){
        cnt++;
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid&&(tr[u<<1].d%x))
        query(u<<1,l,r,x);
    if(r>mid&&(tr[u<<1|1].d%x))
        query(u<<1|1,l,r,x);
}
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int i;
    for(i=1;i<=n;i++)
        cin>>a[i];
    build(1,1,n);
    int q;
    cin>>q;
    while(q--){
        int opt;
        cin>>opt;
        if(opt==1){
            int l,r,x;
            cin>>l>>r>>x;
            cnt=0;
            query(1,l,r,x);
            if(cnt>1){
                cout<<"NO"<<endl;
            }
            else{
                cout<<"YES"<<endl;
            }
        }
        else{
            int l,x;
            cin>>l>>x;
            modify(1,l,x);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/14097651.html