Dynamic Gcd
树链剖分+差分
直接区间加显然是不行的,由于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的更多相关文章
- 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- ...
- CodeChef DGCD Dynamic GCD
CodeChef题面 Time limit 210 ms Code length Limit //内存限制也不说一下,真是的-- 50000 B OS Linux Language limit C, ...
- CodeChef Dynamic GCD
嘟嘟嘟vjudge 我今天解决了一个历史遗留问题! 题意:给一棵树,写一个东西,支持一下两种操作: 1.\(x\)到\(y\)的路径上的每一个点的权值加\(d\). 2.求\(x\)到\(y\)路径上 ...
- CC DGCD:Dynamic GCD——题解
https://vjudge.net/problem/CodeChef-DGCD https://www.codechef.com/problems/DGCD 题目大意: 给一颗带点权的树,两个操作: ...
- scau 2015寒假训练
并不是很正规的.每个人自愿参与自愿退出,马哥找题(马哥超nice么么哒). 放假第一周与放假结束前一周 2015-01-26 http://acm.hust.edu.cn/vjudge/contest ...
- BZOJ 5028 小z的加油站
bzoj链接 Time limit 10000 ms Memory limit 262144 kB OS Linux 感想 树上动态gcd的第二题也好了. [x] BZOJ 2257 [JSOI200 ...
- 洛谷 P4571 BZOJ 2257 [JSOI2009]瓶子和燃料
bzoj题目链接 上面hint那里是选择第2个瓶子和第3个瓶子 Time limit 10000 ms Memory limit 131072 kB OS Linux Source Jsoi2009 ...
- 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 ...
- 动态规划系列(零)—— 动态规划(Dynamic Programming)总结
动态规划三要素:重叠⼦问题.最优⼦结构.状态转移⽅程. 动态规划的三个需要明确的点就是「状态」「选择」和「base case」,对应着回溯算法中走过的「路径」,当前的「选择列表」和「结束条件」. 某种 ...
随机推荐
- mysql大数据量下修改表结构的方法
http://www.blogjava.net/anchor110/articles/361152.html
- 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制
你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...
- 笔记11 export to excel
参考两篇博客:http://blog.csdn.net/zyming0815/article/details/5939104 http://blog.csdn.net/g710710/article/ ...
- SVProgressHUD 用法一
SVProgressHUD 用法一 SVProgressHUD 是一个第三方的控件,是一个弹出提示层,用来提示 网络加载 或 提示对错,看下面图,你就明白了: 那么,SVProgressHU ...
- mysql连接超时的问题
使用Hibernate + MySQL数据库开发,链接超时问题: com.mysql.jdbc.CommunicationsException: The last packet successfull ...
- AngularJs 在控制器中过滤
<html> <head> <title>Simple app</title> <script src="https://ajax.go ...
- maven的坑2
导入工程后,pom.xml文件中以下插件报错: <plugin> <groupId>com.jayway.maven.plugins.android.generation2&l ...
- CAS 单点登录原理
访问服务: 浏览器发送请求访问应用系统 定向认证: 应用系统重定向用户请求到 SSO 服务器. 用户认证:用户身份认证. 发放票据: 认证通过后,SSO 服务器会产生一个随机的 Service Tic ...
- 【BZOJ4407】于神之怒加强版 莫比乌斯反演
[BZOJ4407]于神之怒加强版 Description 给下N,M,K.求 Input 输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行, ...
- Hadoop实战-MapReduce之分组(group-by)统计(七)
1.数据准备 使用MapReduce计算age.txt中年龄最大.最小.均值name,min,max,countMike,35,20,1Mike,5,15,2Mike,20,13,1Steven,40 ...