Dynamic GCD

题意:一棵树,字词树链加,树链gcd


根据\(gcd(a,b)=gcd(a,a-b)\)

得到\(gcd(a_1, a_2, ..., a_i) = gcd(a_1, a_1-a_2, a_2-a_3,...)\)

同时维护原序列和差分序列就行了

无脑树剖,分成几段。不需要轻儿子的差分值。

注意最后答案取一下绝对值!!!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 5e4+5;
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
#define mid ((l+r)>>1)
#define lc x<<1
#define rc x<<1|1
#define lson lc, l, mid
#define rson rc, mid+1, r int n, Q, a[N], u, v, d;
char s[5];
struct edge {int v, ne;} e[N<<1];
int cnt, h[N];
inline void ins(int u, int v) {
e[++cnt] = (edge) {v, h[u]}; h[u] = cnt;
e[++cnt] = (edge) {u, h[v]}; h[v] = cnt;
}
int dfn[N], dfc, size[N], mx[N], fa[N], deep[N], top[N];
void dfs(int u) {
size[u] = 1;
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(v == fa[u]) continue;
fa[v] = u; deep[v] = deep[u]+1;
dfs(v);
size[u] += size[v];
if(size[v] > size[mx[u]]) mx[u] = v;
}
}
void dfs(int u, int anc) {
dfn[u] = ++dfc; top[u] = anc;
if(mx[u]) dfs(mx[u], anc);
for(int i=h[u]; i; i=e[i].ne) {
int v = e[i].v;
if(v != fa[u] && v != mx[u]) dfs(v, v);
}
} namespace t1 {
int c[N];
void add(int p, int v) {for(; p<=n; p+=p&-p) c[p]+=v;}
int que(int p) {int ans=0; for(; p; p-=p&-p) ans+=c[p]; return ans;}
void add(int l, int r, int d) {
add(l, d); add(r+1, -d);
}
} int gcd(int a, int b) {return !b ? a : gcd(b, a % b);}
namespace t2 {
int t[N<<2];
void build(int x, int l, int r) {
if(l == r) t[x] = a[l];
else {
build(lson); build(rson);
t[x] = gcd(t[lc], t[rc]);
}
}
void add(int x, int l, int r, int p, int v) {
if(l == r) t[x] += v;
else {
if(p <= mid) add(lson, p, v);
else add(rson, p, v);
t[x] = gcd(t[lc], t[rc]);
}
}
int que(int x, int l, int r, int ql, int qr) {
if(ql > qr) return 0;
if(ql <= l && r <= qr) return t[x];
else {
int ans = 0;
if(ql <= mid) ans = gcd(ans, que(lson, ql, qr));
if(mid < qr) ans = gcd(ans, que(rson, ql, qr));
return ans;
}
}
} int seg_gcd(int x, int y) {
int l = dfn[x], r = dfn[y];
int a = t1::que(l), b = t2::que(1, 1, n, l+1, r);
return gcd(a, b);
}
void quer(int x, int y) {
int ans = 0;
while(top[x] != top[y]) {
if(deep[top[x]] < deep[top[y]]) swap(x, y);
ans = gcd(ans, seg_gcd(top[x], x));
x = fa[top[x]];
}
if(dfn[x] > dfn[y]) swap(x, y);
ans = gcd(ans, seg_gcd(x, y));
if(ans < 0) ans = -ans;
printf("%d\n", ans);
}
void seg_add(int x, int y, int d) {
int l = dfn[x], r = dfn[y];
t1::add(l, r, d);
t2::add(1, 1, n, l, -d);
if(mx[y]) t2::add(1, 1, n, dfn[mx[y]], d);
}
void add(int x, int y, int d) { //printf("add %d %d %d\n", x, y, d);
while(top[x] != top[y]) {
if(deep[top[x]] < deep[top[y]]) swap(x, y);
seg_add(top[x], x, d);
x = fa[top[x]];
}
if(dfn[x] > dfn[y]) swap(x, y);
seg_add(x, y, d);
}
int main() {
//freopen("in", "r", stdin);
n = read();
for(int i=1; i<n; i++) ins(read()+1, read()+1);
dfs(1); dfs(1, 1);
//for(int i=1; i<=n; i++) printf("look %d %d %d %d\n", i, dfn[i], fa[i], mx[i]);
for(int i=1; i<=n; i++) a[dfn[i]] = read();
for(int i=1; i<=n; i++) t1::add(i, i, a[i]);// printf("%d ", a[i]); puts("");
for(int i=n; i>=1; i--) a[i] = a[i-1] - a[i];
t2::build(1, 1, n);
Q = read();
while(Q--) {
scanf("%s", s); u = read()+1; v = read()+1;
//printf("--------------------------%s %d %d\n", s, u, v);
if(s[0] == 'F') quer(u, v);
else d = read(), add(u, v, d);
//for(int i=1; i<=n; i++) printf("%d ", t1::que(i)); puts(" val");
//printf("seg_gcd %d\n", seg_gcd(1, 2));
}
}

codechef Dynamic GCD [树链剖分 gcd]的更多相关文章

  1. 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治

    LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...

  2. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

  3. [Codechef - ADITREE] Adi and the Tree - 树链剖分,线段树

    [Codechef - ADITREE] Adi and the Tree Description 树上每个节点有一个灯泡,开始所有灯泡都是熄灭的.每次操作给定两个数 \(a,b\) ,将 \(a,b ...

  4. Codechef FIBTREE 树链剖分 主席树 LCA 二次剩余 快速幂

    原文链接https://www.cnblogs.com/zhouzhendong/p/CC-FIBTREE.html 题目传送门 - CC-FIBTREE 题意 给定一个有 $n$ 个节点,初始点权都 ...

  5. 【CodeChef EDGEST】Edges in Spanning Trees(树链剖分+树上启发式合并)

    点此看题面 大致题意: 给你两棵\(n\)个点的树,对于第一棵树中的每条边\(e_1\),求存在多少条第二棵树中的边\(e_2\),使得第一棵树删掉\(e_1\)加上\(e_2\).第二棵树删掉\(e ...

  6. BZOJ 2243 染色 (线段树+树链剖分)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9895  Solved: 3735[Submit][Status ...

  7. HDU 6162 Ch’s gift (线段树+树链剖分)

    题意:给定上一棵树,每个树的结点有一个权值,有 m 个询问,每次询问 s, t ,  a, b,问你从 s 到 t 这条路上,权值在 a 和 b 之间的和.(闭区间). 析:很明显的树链剖分,但是要用 ...

  8. HDU 3966 Aragorn's Story (简单树链剖分)

    题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上的所有点权值加上K D C1 C2 K:把C1与C2的路径上的所有点权值减去K Q C:查询节点编号为C ...

  9. D. Happy Tree Party CodeForces 593D【树链剖分,树边权转点权】

    Codeforces Round #329 (Div. 2) D. Happy Tree Party time limit per test 3 seconds memory limit per te ...

随机推荐

  1. hdu_1029_hash/map

    http://acm.hdu.edu.cn/showproblem.php?pid=1029 太水了,一次过,直接上代码吧,只想说最愚蠢的hash都要比map快! #include<cstdio ...

  2. 51 Nod 1119

    机器人走方格 V2 M * N的方格,一个机器人从左上走到右下,只能向右或向下走.有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果. Input 第1行,2个数M,N ...

  3. Spring框架学习笔记(10)——Spring中的事务管理

    什么是事务 举例:A给B转500,两个动作,A的账户少500,B的账户多500 事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用 一.注解添加事务管理方 ...

  4. html5 文本格式化

    通常标签 <strong> 替换加粗标签 <b> 来使用, <em> 替换 <i>标签使用.然而,这些标签的含义是不同的:<b> 与< ...

  5. 除了四大传统OA软件商,国内还有这些优秀的OA协同产品

    国内OA 软件市场经过多年的发展,在产品.应用.服务方面都已相对成熟,也出现了众多优秀的OA软件品牌. 据中国软件协会2017年公布的数据显示:泛微OA.致远OA.华天动力OA.蓝凌OA的销售仍稳居O ...

  6. JS实现单选按钮回显时页面效果出现,但选中单选框的值为空

    最近做了很多前端页面的工作,遇到的一个感觉很头疼的问题在这里记一下: 经常用JS回显单选框,但是明明从页面效果上来看,单选框已经被选中了,可是却不能触发单选框的change事件,取值的时候用某种方法取 ...

  7. linux 下CentOS 下 npm命令安装gitbook失败的问题

    运行环境 linux 服务器:CentOS 7.0 系统:安装了nodejs :使用 npm 安装 gitbook 出现错误提示: npm install -g gitbook-cli symbol ...

  8. HDU 2119 Matrix

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2119 解题思路: 处理数据,使用公式最小点覆盖数=最大匹配数,使用匈牙利算法求二分图最大匹配即可. ...

  9. file_get_contents("php://input")的使用方法

    $data = file_get_contents("php://input"); //input 是个可以访问请求的原始数据的只读流. POST 请求的情况下,最好使用 php: ...

  10. XHR

    xhr注入 XHR 注入技术是通过XMLHttpRequest来获取javascript的.但与eval不同的是,该机制是通过创建一个script的DOM元素,然后把XMLHttpRequest的响应 ...