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」,对应着回溯算法中走过的「路径」,当前的「选择列表」和「结束条件」. 某种 ...
随机推荐
- Unix系统介绍
一.基础知识 操作系统 用户与计算机硬件之间的界面,是控制.管理计算机内各种硬件与软件资源.它是一个多用户.多任务.分时的操作系统. 对于分时系统:假如a进程需要16个时间片,现在根据优先级只分配了1 ...
- Java基础:抽象类和接口
转载请注明出处:jiq•钦's technical Blog 一.引言 基于面向对象五大原则中的以下两个原则,我们应该多考虑使用接口和抽象类: 里氏替换原则:子类能够通过实现父类接口来替换父类,所以父 ...
- VS2012+Win7站点公布具体步骤
VS2012+Win7站点公布详细步骤 本机环境: 本文分三个部分介绍Web项目公布的常规方法,大神级别能够略过,主要是为了方便一些刚開始学习的人. 第一部分:VS2012把项目公布到文件系统. 第二 ...
- 服务管理-DHCP、NTP、SSH
DHCP协议的作用及原理 1.寻找server 当DHCP客户端第一次登陆网络的时候,也就是客户发现本机上没有任何ip资料设定,他会向网路发送一个dhcpdiscover封包.因为客户端还不知道自己属 ...
- iOS学习之iOS沙盒(sandbox)机制和文件操作1
iOS学习之iOS沙盒(sandbox)机制和文件操作 接上篇 iOS学习之iOS沙盒(sandbox)机制和文件操作(一) 我们看看如何获取应用程序沙盒目录.包括真机的沙盒的目录. 1.获取程序的H ...
- Java解析Property文件
在Java项目中一些配置參数保存在Property文件里,这样能保证不改动原代码直接改动Property文件. PropertyParser.java package com.discover.par ...
- 《UNIX 网络编程 第二版》编译环境的搭建( 运行本专栏代码必读 )
第一步:搭建基本的编译环境 安装gcc, g++, bulid-essential等编译软件 第二步:下载本书示例源码包 可在这里下载http://ishare.iask.sina.com.cn/f/ ...
- ios6.0,程序为横屏,出现闪退
本文转载至 http://blog.csdn.net/huanghuanghbc/article/details/10150355 ios6.0,程序为横屏,出现闪退 *** Terminatin ...
- linux修改进程的名字
1 修改linux进程名字的基本原理 linux进程以argv[0]作为进程的名字,因此只需要修改argv[0]处的字符串就修改了linux进程的名字. 2 直接修改argv[0]会导致的问题 如果名 ...
- Dropout: A Simple Way to Prevent Neural Networks fromOverfitting
https://www.cs.toronto.edu/~hinton/absps/JMLRdropout.pdf Deep neural nets with a large number of par ...