zoukankan      html  css  js  c++  java
  • codeforces 914 D 线段树+数学

    题意

    给出一个长度为(n)的数列(a),两种询问,第一种给出三个数(l,r,x),区间([l,r])(gcd)值是否和(x)相似,若最多改变区间([l,r])中的一个数使区间([l,r])(gcd)值等于(x),则相似,第二种给出两个数(i,y),将(a[i])变为(y)

    分析

    建一个线段树维护区间(gcd),这个线段树非常好写,因为是单点修改,所以不需要tag数组和pushdown,查询的时候用一个变量(cnt),记录区间([l,r])中有多少个数不是(x)的倍数,(cnt>1)时直接跳出。

    Code

        #include<bits/stdc++.h>
        #define fi first
        #define se second
        using namespace std;
        typedef long long ll;
        const double PI=acos(-1.0);
        const double eps=1e-6;
        const int inf=1e9;
        const int mod=1e9+7;
        const int maxn=5e5+10;
        int n,a[maxn];
        int ans[maxn*5];
        int gcd(int a,int b){
            return b==0?a:gcd(b,a%b);
        }
        void pushup(int p){
            ans[p]=gcd(ans[p<<1],ans[p<<1|1]);
        }
        void build(int l,int r,int p){
            if(l==r){
                ans[p]=a[l];
                return;
            }
            int mid=l+r>>1;
            build(l,mid,p<<1);
            build(mid+1,r,p<<1|1);
            pushup(p);
        }
        void update(int dl,int dr,int l,int r,int p,int k){
            if(l>=dl&&r<=dr){
                ans[p]=k;
                return;
            }
            int mid=l+r>>1;
            if(dl<=mid) update(dl,dr,l,mid,p<<1,k);
            if(dr>mid) update(dl,dr,mid+1,r,p<<1|1,k);
            pushup(p);
        }
        int cnt;
        bool query(int dl,int dr,int l,int r,int p,int x){
            if(l>=dl&&r<=dr){
                if(ans[p]%x==0) {//这个区间的gcd是x的倍数时直接返回true,否则继续向下查询
                    return true;
                }
                if(l==r){//这个数不是x的倍数,cnt++
                    cnt++;
                    if(cnt>1) return false;
                    return true;
                }
            }
            int mid=l+r>>1;
            if(dl<=mid) if(!query(dl,dr,l,mid,p<<1,x)) return false;
            if(dr>mid) if(!query(dl,dr,mid+1,r,p<<1|1,x)) return false;
            return true;
        }
        int main(){
            //ios::sync_with_stdio(false);
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            build(1,n,1);
            int q;
            scanf("%d",&q);
            while(q--){
                int op,l,r,x,i,y;
                scanf("%d",&op);
                if(op==1){
                    scanf("%d%d%d",&l,&r,&x);
                    cnt=0;
                    if(query(l,r,1,n,1,x)){
                        puts("YES");
                    }else{
                        puts("NO");
                    }
                }else{
                    scanf("%d%d",&i,&y);
                    update(i,i,1,n,1,y);
                }
            }
            return 0;
        }
    
  • 相关阅读:
    找零问题-完全背包
    可同时在nodejs和浏览器端使用的websocket
    C++ vector 比较大小
    npm ERR! Unexpected token in JSON at position 0 while parsing near '<HTML> 解决办法
    C/C++宏定义中#与##区别
    解析日志工具。
    3
    2
    dssfsfsfs
    android获取USB设备的名称
  • 原文地址:https://www.cnblogs.com/xyq0220/p/10764654.html
Copyright © 2011-2022 走看看