Codeforces Round #705 (Div. 2) D. GCD of an Array

这篇博客讨论了如何解决一个涉及数组和多次操作的最大公约数(GCD)问题。作者提出了两种方法:一是离线处理并计算每个素数对结果的贡献,二是动态开点线段树。这两种方法都避免了内存不足的问题,通过优化数据结构有效地解决了问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门
题意:给你一个数组含有n个数,同时进行q次操作,每次操作让x位置上的数乘上v,每次操作后输出给个数组的gcd。

最大公约数:
在这里插入图片描述
于是我们有这样的想法,对于每个素数,我们维护n个数中的最小值。显然区间最小值可以用线段树维护,但那样我们不是要开s课线段树?内存显然不够用。

1.考虑离线处理 每次算乘上这个数后对结果的贡献(指数是相加的),同样对于刚开始的n个数,我们可以看作最开始每个数都是1,然后依次乘上ai。

每次算贡献 我们可以一次把所有p的贡献算完,算完后再清空线段树就可以重复利用了。

#include<bits/stdc++.h>
using namespace std;

#define lsn (u << 1)
#define rsn (u << 1 | 1)
#define mid (l + r >> 1)

typedef long long ll;
typedef unsigned long long ull;

typedef pair<int, int> P;
typedef pair<double, double> PD;

const int MAXN = 2e5 + 10;
const int MAX_LEN = 100000 + 10;
const int MAX_LOG_V = 22;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-7;
const ull B = 100000007;

int n, q;

struct Node {
   
    int id, t, v;
};

vector<Node> a[MAXN];
int tr[4*MAXN];
ll ans[2*MAXN];

ll qpow(ll x, int y) {
   
    ll res = 1;
    while(y) {
   
        if(y & 1) res = res * x % mod;
        y >>= 1;
        x = x * x % mod;
    }
    return res;
} 

void pushup(int u) {
   
    tr[u] = min(tr[lsn], tr[rsn]);
}

void add(int u, int l, int r, int p, int v) {
   
    if(l == r && l == p) tr[u] += v;
    else {
   
        if(p <= mid) add(lsn, l, mid, p, v);
        else add(rsn, mid+
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值