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;
}

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

相关推荐
肖筱小瀟24 分钟前
2025-3-14 leetcode刷题情况(贪心算法)
算法·leetcode·贪心算法
alphaTao28 分钟前
LeetCode 每日一题 2025/3/10-2025/3/16
算法·leetcode
I AM_SUN41 分钟前
蓝桥杯:山
算法·职场和发展·蓝桥杯
weixin_399264291 小时前
c++ 封装、继承、重写、重载、多态性
开发语言·c++·算法
进取星辰1 小时前
PyTorch 深度学习实战(14):Deep Deterministic Policy Gradient (DDPG) 算法
pytorch·深度学习·算法
Doopny@1 小时前
分解质因数(信息学奥赛一本通-2032)
数据结构·算法
IT猿手1 小时前
基于雪雁算法(Snow Geese Algorithm,SGA)的多个无人机协同路径规划(可以自定义无人机数量及起始点),MATLAB代码
开发语言·人工智能·算法·机器学习·matlab·无人机
一只码代码的章鱼1 小时前
数据结构与算法-图论-欧拉路径和欧拉回路(有向图和无向图,骑马修栅栏,单词游戏 play on words)详细代码注解
算法·图论
2301_804774492 小时前
算法题练习
java·开发语言·算法
Doopny@2 小时前
矩阵转置(信息学奥赛一本通-1126)
算法