CodeForces914D——线段树

英文题面,题目大意:Bash喜欢对数列进行操作。第一种操作是询问l~r区间内的gcd值是否几乎为x,几乎为表示能否至多修改一个数达到。第二种操作是将ai修改为x。总共Q个询问,N个数。
这道题显然是一道区间信息维护的题目,所以我们考虑使用线段树。如果没有修改一个点的限制,那么我们只需要开一个记录gcd的线段树即可。对于修改一个点的限制,我们这么考虑:如果(一串区间的gcd值 mod 题目给出的v) !=0,那么这个区间里至少有一个数不含v这个因数,所以我们一直用线段树二分查找这个区间,最终肯定会找出一些不含因数v的点。如果这个点只有一个,那我们修改这个点即可;如果有两个,那就不可能完成,输出NO。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<string.h>
#define MAXN 500005
using namespace std;
int read(){
    char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,q,res,a[MAXN],sum[MAXN<<2];
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
void up(int node){sum[node]=gcd(sum[node<<1],sum[node<<1|1]);}
void build(int node,int l,int r){
    if(l==r){
        sum[node]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(node<<1,l,mid);
    build(node<<1|1,mid+1,r);
    up(node);
}
void update(int p,int node,int l,int r,int c){
    if(l==r){
        sum[node]=c;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) update(p,node<<1,l,mid,c);
    else update(p,node<<1|1,mid+1,r,c);
    up(node);
}
void query(int lc,int rc,int node,int l,int r,int v){
    if(res>1) return;
    if(l==r){
        res++;return;
    }
    int mid=(l+r)>>1;
    if(lc<=mid&&sum[node<<1]%v!=0) query(lc,rc,node<<1,l,mid,v);
    if(rc>mid&&sum[node<<1|1]%v!=0) query(lc,rc,node<<1|1,mid+1,r,v);
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    build(1,1,n);
    q=read();
    while(q--){
        int x=read();
        if(x==1){
            res=0;
            int y=read(),z=read(),v=read();
            query(y,z,1,1,n,v);
            if(res>1) puts("NO");
            else puts("YES");
        }
        if(x==2){
            int y=read(),z=read();
            update(y,1,1,n,z);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值