D. Bash and a Tough Math Puzzle

题目链接:Problem - 914D - Codeforces

题目大意:给你长度为n的数组, 然后q次查询,有两种选择

1 lrx ( 1 ≤ l ≤ r ≤ n , 1 ≤ x ≤ 109 ).

2 iy . (1 ≤ i ≤ n , 1 ≤ y ≤ 109) .

第一种判断 区间[l, r] 是否满足猜测, 在[l ,r] 区间最多 可以修改一个值 (可以不改),让区间的gcd == x

第二种将位置 i 上的数改为 y

输入:第一行包含一个整数 n ( 1 ≤ n ≤ 5·1e5 );- 数组的大小。( 1 ≤ n ≤ 5·1e5 ) - 数组的大小。

第二行包含 n 个整数 a 1, a 2, ..., a n ( 1 ≤ a i ≤ 1e9 - 数组的元素。

第三行包含一个整数 q ( 1 ≤ q ≤ 4·1e5 ) - 查询次数。

接下来的 q 行对查询进行了描述,可能有以下几种形式:

  • 1 lrx ( 1 ≤ l ≤ r ≤ n , 1 ≤ x ≤ 1e9 ).
  • 2 iy . (1 ≤ i ≤ n , 1 ≤ y ≤ 1e9) .

保证至少有一个第一种类型的查询。

输出:满足 YES, 否则 NO

算法: 线段树, 数论

  1. 首先手玩一组样例 12 8 18 24 , 此时 假设查询 x = 4, 明显可以的。 x=2, 也是可以的, 只需要将其中的任意一个数改为2即可。x = 3 or 6, 也是可以的 将8 改为3 即可。 但如果是x=12,就不行了 就要修改两个数字 8 18 才可以了 。

  2. 结论:要想满足基本gcd的猜想,

  3. 就要让[l, r]区间(总数:r-l+1)里的 r - l 个数, 都可以整除x。

  4. 或本来 r-l+1个数就可以整除 x , 也是可以的(修改一个数为x即可)。

3.两者都只需要改一个数即可, 其他的情况都是NO

  1. 做法: 采用线段树维护 gcd, 加单点修改。 进行查询时, 判断左子树是否可以整除x, 以及右子树是否可以整除x, 不能整除, 向下查询, 当到达叶子节点时,说明该数据需要修改,然后统计一下。 注意 当tot > 1 直接return, 防止卡时间。
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
using i128 = __int128;
using ui64 = unsigned long long;

const int N = 5e5+2;
int a[N];

struct Node{
    int l, r;
    int g;
    Node(){
        this->l = this->r = 0;
        this->g = 0;
    }
}tr[N<<2];

void up(int id){// 线段树维护gcd
    tr[id].g = gcd(tr[id<<1].g, tr[id<<1|1].g);
}

void build(int id, int l, int r ){
    tr[id].l = l;
    tr[id].r = r;
    if(l==r) {
        tr[id].g = a[r];
        return;
    }
    
    int mid = (l+r)>>1;
    build(id<<1, l, mid);
    build(id<<1|1, mid+1, r);
    up(id);
}

void updata(int id, int jobt, int jobv){// 单点修改
    if(tr[id].l == tr[id].r) {
        tr[id].g = jobv;
        return;
    }
    int mid = (tr[id].l + tr[id].r) >> 1;
    if(jobt <= mid) {
        updata(id<<1, jobt, jobv);
    }else{
        updata(id<<1|1, jobt, jobv);
    }
    up(id);
}

int tot;

void query(int id, int jobl, int jobr, int jobv){
    if(tr[id].l == tr[id].r) {
        tot++;
        return;
    }
    if(tot>1)return;
    int mid = (tr[id].l + tr[id].r) >> 1;

    if(jobl <= mid && tr[id<<1].g % jobv != 0) {//左子树
        query(id<<1, jobl, jobr, jobv);
    }
    if(jobr > mid && tr[id<<1|1].g % jobv != 0) {//右子树
        query(id<<1|1, jobl, jobr,jobv);
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    int n;
    cin >> n;
    for(int i=1; i<=n; i++) {
        cin >> a[i];
    }
    build(1, 1, n);
    int quy;
    cin >>  quy;
    while(quy--) {
        int op;
        cin >> op;
        if(op == 1) {
            tot = 0; // 归0
            int jobl, jobr, jobx;
            cin >> jobl >> jobr >> jobx;
            query(1, jobl, jobr,jobx);
            if(tot<=1){
                cout << "YES\n";
            }else{
                cout << "NO\n";
            }
        }else{
            int jobt, jobv;
            cin >> jobt >> jobv;
            updata(1, jobt, jobv);
        }
    }
    return 0;
}

感谢收看与点赞, 欢迎大佬指正。

相关推荐
Codingwiz_Joy6 分钟前
Day09 -实例:拿到加密密文进行解密
算法·安全·安全性测试
float_六七35 分钟前
双指针算法
算法
BingLin-Liu1 小时前
图论之cruskal算法(克鲁斯卡尔)
数据结构·算法·图论
进取星辰1 小时前
PyTorch 深度学习实战(15):Twin Delayed DDPG (TD3) 算法
pytorch·深度学习·算法
strive-debug1 小时前
C语言之 条件编译和预处理指令
算法
Sacuki2 小时前
BP神经网络公式推导与代码实现
算法
山登绝顶我为峰 3(^v^)32 小时前
VSCode + CMake
ide·vscode·算法·计算机·编辑器
勇敢滴勇2 小时前
【C++】二叉搜索树(二叉查找树、二叉排序树)详解
开发语言·c++·算法·霍夫曼树
f狐0狸x2 小时前
【蓝桥杯每日一题】3.16
c++·算法·蓝桥杯
周Echo周3 小时前
8、STL中的map和pair使用方法
开发语言·数据结构·c++·考研·算法·leetcode·pat考试