树链剖分+差分

直接区间加显然是不行的,由于gcd(a,b,c)=gcd(a,a-b,b-c),那么我们对这些数差分,然后就变成单点修改。原本以为这道题很简单,没想到这么麻烦,就膜了发代码。

首先我们考虑如何在树上差分序列,每个节点有很多个儿子,如果把每个儿子都修改一下就GG了,其实我们可以这个样子,我们只维护重儿子的差分值,但是如果从轻儿子爬上来呢?我们就把父亲节点单独取出来做gcd,也就是我们再维护一个原序列的值,每次爬重链的时候就把链下面最深的点用原序列中的值来求,这样就可以了。然后还有各种修改,树状数组维护原序列比较简单,就是一个差分序列,但是树上要注意一些,每次要修改链头和链底的重儿子,注意这里和平常的差分不太一样,这里是父亲和儿子之间的差分,如果是一条被修改的路径那么就抵消,否则就差分,感觉还是挺巧妙的。

#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + ;
inline int rd()
{
int x = , f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = x * + c - ''; c = getchar(); }
return x * f;
}
int n, m, cnt, dfs_clock;
int head[N], a[N], fa[N], dfn[N], top[N], son[N], dep[N], size[N];
struct edge {
int nxt, to;
} e[N << ];
int gcd(int a, int b)
{
return !b ? a : gcd(b, a % b);
}
void link(int u, int v)
{
e[++cnt].nxt = head[u];
head[u] = cnt;
e[cnt].to = v;
}
void dfs(int u, int last)
{
size[u] = ;
for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last)
{
dep[e[i].to] = dep[u] + ;
fa[e[i].to] = u;
dfs(e[i].to, u);
size[u] += size[e[i].to];
if(size[e[i].to] > size[son[u]]) son[u] = e[i].to;
}
}
void dfs(int u, int last, int anc)
{
dfn[u] = ++dfs_clock;
top[u] = anc;
if(son[u]) dfs(son[u], u, anc);
for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last && e[i].to != son[u]) dfs(e[i].to, u, e[i].to);
}
namespace BIT
{
int tr[N];
void update(int x, int d)
{
if(!x) return;
for(; x <= n; x += x & -x) tr[x] += d;
}
int query(int x)
{
int ret = ;
for(; x; x -= x & -x) ret += tr[x];
return ret;
}
}
namespace Segment_Tree
{
int t[N << ];
void build(int l, int r, int x)
{
if(l == r)
{
t[x] = a[l];
return;
}
int mid = (l + r) >> ;
build(l, mid, x << );
build(mid + , r, x << | );
t[x] = gcd(t[x << ], t[x << | ]);
}
void update(int l, int r, int x, int p, int d)
{
if(l == r)
{
t[x] += d;
return;
}
int mid = (l + r) >> ;
if(p <= mid) update(l, mid, x << , p, d);
else update(mid + , r, x << | , p, d);
t[x] = gcd(t[x << ], t[x << | ]);
}
int query(int l, int r, int x, int a, int b)
{
if(l > b || r < a) return ;
if(l >= a && r <= b) return t[x];
int mid = (l + r) >> ;
return gcd(query(l, mid, x << , a, b), query(mid + , r, x << | , a, b));
}
}
namespace Operation
{
int ask(int u, int v)
{
int ret = ;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
ret = gcd(ret, gcd(Segment_Tree :: query(, n, , dfn[top[u]] + , dfn[u]), BIT :: query(dfn[top[u]])));
u = fa[top[u]];
}
if(dfn[u] < dfn[v]) swap(u, v);
return abs(gcd(ret, gcd(Segment_Tree :: query(, n, , dfn[v] + , dfn[u]), BIT :: query(dfn[v]))));
}
void change(int u, int v, int d)
{
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
Segment_Tree :: update(, n, , dfn[top[u]], -d);
if(son[u]) Segment_Tree :: update(, n, , dfn[son[u]], d);
BIT :: update(dfn[top[u]], d);
BIT :: update(dfn[u] + , -d);
u = fa[top[u]];
}
if(dfn[u] < dfn[v]) swap(u, v);
Segment_Tree :: update(, n, , dfn[v], -d);
if(son[u]) Segment_Tree :: update(, n, , dfn[son[u]], d);
BIT :: update(dfn[v], d);
BIT :: update(dfn[u] + , -d);
}
}
int main()
{
n = rd();
for(int i = ; i < n; ++i)
{
int u = rd() + , v = rd() + ;
link(u, v);
link(v, u);
}
dfs(, );
dfs(, , );
for(int i = ; i <= n; ++i)
{
a[dfn[i]] = rd();
BIT :: update(dfn[i], a[dfn[i]]);
BIT :: update(dfn[i] + , -a[dfn[i]]);
}
for(int i = n; i; --i) a[i] = a[i - ] - a[i];
Segment_Tree :: build(, n, );
m = rd();
while(m--)
{
char s[];
scanf("%s", s);
int u = rd() + , v = rd() + , d;
if(s[] == 'F') printf("%d\n", Operation :: ask(u, v));
if(s[] == 'C')
{
d = rd();
Operation :: change(u, v, d);
}
}
return ;
}

Dynamic Gcd的更多相关文章

  1. codechef Dynamic GCD [树链剖分 gcd]

    Dynamic GCD 题意:一棵树,字词树链加,树链gcd 根据\(gcd(a,b)=gcd(a,a-b)\) 得到\(gcd(a_1, a_2, ..., a_i) = gcd(a_1, a_1- ...

  2. CodeChef DGCD Dynamic GCD

    CodeChef题面 Time limit 210 ms Code length Limit //内存限制也不说一下,真是的-- 50000 B OS Linux Language limit C, ...

  3. CodeChef Dynamic GCD

    嘟嘟嘟vjudge 我今天解决了一个历史遗留问题! 题意:给一棵树,写一个东西,支持一下两种操作: 1.\(x\)到\(y\)的路径上的每一个点的权值加\(d\). 2.求\(x\)到\(y\)路径上 ...

  4. CC DGCD:Dynamic GCD——题解

    https://vjudge.net/problem/CodeChef-DGCD https://www.codechef.com/problems/DGCD 题目大意: 给一颗带点权的树,两个操作: ...

  5. scau 2015寒假训练

    并不是很正规的.每个人自愿参与自愿退出,马哥找题(马哥超nice么么哒). 放假第一周与放假结束前一周 2015-01-26 http://acm.hust.edu.cn/vjudge/contest ...

  6. BZOJ 5028 小z的加油站

    bzoj链接 Time limit 10000 ms Memory limit 262144 kB OS Linux 感想 树上动态gcd的第二题也好了. [x] BZOJ 2257 [JSOI200 ...

  7. 洛谷 P4571 BZOJ 2257 [JSOI2009]瓶子和燃料

    bzoj题目链接 上面hint那里是选择第2个瓶子和第3个瓶子 Time limit 10000 ms Memory limit 131072 kB OS Linux Source Jsoi2009 ...

  8. Cache index coloring for virtual-address dynamic allocators

    A method for managing a memory, including obtaining a number of indices and a cache line size of a c ...

  9. 动态规划系列(零)—— 动态规划(Dynamic Programming)总结

    动态规划三要素:重叠⼦问题.最优⼦结构.状态转移⽅程. 动态规划的三个需要明确的点就是「状态」「选择」和「base case」,对应着回溯算法中走过的「路径」,当前的「选择列表」和「结束条件」. 某种 ...

随机推荐

  1. 修改 本地 IP 及 正则表达式 test exec match 的区别

    修改 IP 1.打开 "打开网络和共享中心" 2.打开 "更改适配器设置" 3.打开 "本地连接" 属性 4.修改 "协议版本 4 ...

  2. vim 查找整个工程

    1. 使用vim内置搜索引擎 vimgrep 格式::vim /patern/gj ** 命令::vim 或者 :vimgrep 模式: 查询模式包含在 / / 之间 参数: g 表示将同一行搜到的关 ...

  3. Python遍历列表

    #循环遍历列表 nums = [ss,gg,e,fff,bb] #while循环遍历,但是不推荐使用,因为还要把列表的元素数出来 i = 0 while i<5: print(nums[i]) ...

  4. smartUpload注意过程

    操作的过程中一定要注意的几个方面:       1.将smartUpload.jar拷贝到tomcat/lib以及项目的lib下面,最好是只多不少!       2.因为上传的文件一般都很大,所以应该 ...

  5. ecshop 国付宝支付接口

    function get_code($order, $payment){ $version = '2.2'; $charset = '1'; $language = '1'; $signType = ...

  6. 简化Android的startActivityForResult调用

    一个是解决在onActivityResult 中判断requestCode的问题,第二个是让调用代码的地方就知道我是如何处理对方activity 的返回的. 首先我们有一个ResultActivity ...

  7. wpf中的样式与模板

    1.WPF样式类似于Web应用程序中的CSS,在WPF中可以为控件定义统一的样式(Style).样式属于资源的一种,例如为Button定义统一的背景颜色和字体: <Window.Resource ...

  8. 基于EasyDarwin云平台实现的EasyClient客户端与EasyCamera摄像机之间的对讲与云台控制功能

    本文转自EasyDarwin团队Kim的博客,感谢Kim长期对EasyDarwin开源项目的贡献:http://blog.csdn.net/jinlong0603 EasyDarwin云平台是一套由E ...

  9. EasyDarwin开源流媒体云平台之语音对讲功能设计与实现

    本文由EasyDarwin开源团队成员Alex贡献:http://blog.csdn.net/cai6811376/article/details/52006958 EasyDarwin云平台一直在稳 ...

  10. 九度OJ 1094:String Matching(字符串匹配) (计数)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1259 解决:686 题目描述: Finding all occurrences of a pattern in a text is a p ...