树链剖分+差分

直接区间加显然是不行的,由于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. Distinct Subsequences(不同子序列的个数)——b字符串在a字符串中出现的次数、动态规划

    Given a string S and a string T, count the number of distinct subsequences ofT inS. A subsequence of ...

  2. MySQL 压缩解决方案

    From:https://www.qcloud.com/community/article/876100 导语 描述 MySQL 压缩的使用场景和解决方案,包括压缩传输协议.压缩列解决方案和压缩表解决 ...

  3. 对OpenCV中Haar特征CvHaarClassifierCascade等结构理解

    首先说一下这个级联分类器,OpenCV中级联分类器是根据VJ 04年的那篇论文(Robust Real-Time Face Detection)编写的,查看那篇论文,知道构建分类器的步骤如下: 1.根 ...

  4. vue-导入静态文件

    vue导入静态文件不用像网上说的那么麻烦,其实跟普通Django项目导入类似,vue项目中有一个static文件,将你的静态文件放入到里面,然后引入就好 导入的时候和普通Django程序类似:↓ &l ...

  5. IMDB-WIKI - 具有年龄和性别标签的500k +脸部图像

    Rasmus Rothe, Radu Timofte, Luc Van Gool DEX:从单一形象深刻地看待年龄 观看 人物研讨会国际计算机视觉大会(ICCV),2015*获胜LAP面对年龄估计的挑 ...

  6. 神经网络实现Discuz验证码识别

    最近自己尝试了网上的验证码识别代码项目,该小项目见以下链接: https://cuijiahua.com/blog/2018/01/dl_5.html 数据也就用了作者上传的60000张Discuz验 ...

  7. 在VC++空工程中使用MFC类,采用Unicode字符集后,运行工程程序报错的解决方案

    创建一个VC++空工程,将Project Properties->General->Use of MFC改为Use MFC in a Shared DLL 新建一个源文件,内容如下 #in ...

  8. what??|诞生才一年的BCH竟面临硬分叉的抉择

    BCH才刚过一周岁生日一个星期,BCH社区的主力之一Bitcoin ABC(BCH全网接近三分之二节点运行的软件系统由Bitcoin ABC开发)就搅动了社区的涟漪.8月8号,Bitcoin ABC公 ...

  9. Django学习之站点缓存详解

      本文和大家分享的主要是django缓存中站点缓存相关内容,一起来看看吧,希望对大家学习django有所帮助. 缓存整个站点,是最简单的缓存方法 在 MIDDLEWARE_CLASSES 中加入 “ ...

  10. git基本操作---持续更新(2017-08-11)

    git 强制push $ git push -u origin master -f 查看本地标签 $ git tag 打标签并添加备注 $ git tag 20170811 -m"图片保存多 ...