• 区间gcd


    http://codeforces.com/problemset/problem/914/D

    题意:给你n个数,两种操作:1、询问区间【l,r】在至多一次修改一个数的条件下区间gcd是否等于x。

    2、修改第i个数为x。

    解法:区间维护gcd,如果该区间gcd%x==0,则该区间算是正确区间,不需要继续递归其儿子。如果该区间gcd%x  != 0,递归其儿子。如果递归到叶子儿子说明该点必须改变。减枝:如果需改变的数超过1个则返回。

    疑惑:如果某区间gcd为16,问区间gcd是否为2,并存在一个数必须修改,为什么是yes?

    答:只需将必须修改的数改为2,区间gcd就变成了2,答案是yes。

    //#include <bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include <vector>
    #define ME(x , y) memset(x , y , sizeof(x))
    #define SF(n) scanf("%d" , &n)
    #define rep(i , n) for(int i = 0 ; i < n ; i ++)
    #define INF  0x3f3f3f3f
    #define mod 20191117
    #define PI acos(-1)
    #define gcd __gcd
    using namespace std;
    typedef long long ll ;
    int ans ;
    
    struct node
    {
        int l , r , val ;
    }tree[500000<<2];
    
    void build(int l , int r , int root)
    {
        tree[root].l = l , tree[root].r = r ;
        if(l == r)
        {
            scanf("%d" , &tree[root].val);
            return ;
        }
        int mid = (tree[root].l + tree[root].r) >> 1 ;
        build(l , mid , root*2);
        build(mid+1 , r , root*2+1);
        tree[root].val = gcd(tree[root*2].val , tree[root*2+1].val);
    }
    
    void update(int x , int val , int root)
    {
        if(tree[root].l == tree[root].r)
        {
            tree[root].val = val ;
            return ;
        }
        int mid = (tree[root].l + tree[root].r) >> 1 ;
        if(x <= mid)
            update(x , val , root*2);
        else{
            update(x , val , root*2+1);
        }
        tree[root].val = gcd(tree[root*2].val , tree[root*2+1].val);
    }
    
    void query(int l , int r , int val , int root)
    {
        if(tree[root].l == tree[root].r)//该点必修改
        {
            ans++;
            return ;
        }
        if(ans > 1) return ;
        int mid = (tree[root].l + tree[root].r) >> 1 ;
    
        if(l <= mid && tree[root*2].val % val != 0)//目标在左儿子区间存在,且左儿子gcd%val!=0,则递归该儿子
            query(l , r , val , root*2);
        if(r > mid && tree[root*2+1].val % val != 0)
            query(l , r , val , root*2+1);
    }
    
    
    int main()
    {
        int n;
        scanf("%d" , &n);
        build(1 , n , 1);
        int q ;
        scanf("%d" , &q);
        for(int i = 0 ; i < q ; i++)
        {
            int t ;
            scanf("%d" , &t);
            if(t == 2)
            {
                int x ,val;
                scanf("%d%d" , &x , &val);
                update(x , val , 1);
            }
            else{
                int l , r , val ;
                scanf("%d%d%d" , &l , &r , &val);
                ans = 0 ;
                query(l , r , val , 1);
                if(ans <= 1)
                    printf("YES
    ");
                else{
                    printf("NO
    ");
                }
            }
        }
    
        return 0;
    }
    
  • 相关阅读:
    SDWebImage 原理及使用问题
    iOS沙盒目录
    java基础知识积累总结
    切片原型[start:stop:step]
    select嵌套问题
    Numpy:字符串转为数值型、日期型;日期型转为数值型
    数据标准化处理(简单整理)
    Numpy:自定义复合数据类型
    Numpy:数组创建 numpy.arrray() , numpy.arange()、np.linspace ()、数组基本属性
    Numpy:使用索引、切片提取一维数组、多维数组内数据
  • 原文地址:https://www.cnblogs.com/nonames/p/11955588.html
Copyright © 2020-2023  润新知