Codechef Dynamic GCD 题解

本文详细解析了如何解决Codechef上的动态GCD问题。通过差分操作和线段树维护区间gcd,结合树链剖分处理树结构的数据。在树链剖分的基础上,针对每条链进行gcd的更新,并利用标记永久化处理未完全使用的链。算法实现中需要注意节点值的增减以及避免计算误差。

Codechef Dynamic GCD

Codechef Dynamic GCD

就是考虑维护链上 gcd ⁡ \gcd gcd 和链加。我们先考虑这个东西放到序列上怎么做,首先进行差分,之后因为 gcd ⁡ \gcd gcd 是不变的,但是区间加可以直接变成了单点修改用线段树进行维护即可。


对于树上的情况,我们直接使用树链剖分进行分成若干条链进行计算。

具体来说我们考虑对于一条链 u , v , f a u = v u, v, fa_u = v u,v,fau=v,我们让节点 u u u 的值变成 a v − a u a_v - a_u avau 即可。对于链头的情况我们直接作为原来的值即可。

但是会有一个问题,如果我们一条链没有被使用完成我们就需要知道最上面的那个值。

对于这个我们只需要维护一下被加的值即可,为了方便使用了标记永久化。


一些细节:

  • 根据我们差分的定义,对于一个节点 u u u 增加了 c c c 的时候,其单点维护的 gcd ⁡ \gcd gcd 是要 − c - c c 的,其儿子是要 + c + c +c 的。当然对于 u = t o p u u = \tt{top}_u u=topu 的情况例外。
  • 我们进行最终计算答案的时候不要忘记计算最上面一个点的贡献,也不要多计算。
#include <bits/stdc++.h>
using namespace std;

//#define Fread
//#define Getmod

#ifdef Fread
char buf[1 << 21], *iS, *iT;
#define gc() (iS == iT ? (iT = (iS = buf) + fread (buf, 1, 1 << 21, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
#define getchar gc
#endif // Fread

template <typename T>
void r1(T &x) {
   
   
	x = 0;
	char c(getchar());
	int f(1);
	for(; c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
	for(; '0' <= c && c <= '9';c = getchar()) x = (x * 10) + (c ^ 48);
	x *= f;
}

template <typename T,typename... Args> inline void r1(T& t, Args&... args) {
   
   
    r1(t);  r1(args...);
}

#ifdef Getmod
const int mod  = 1e9 + 7;
template <int mod>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值