HDU - 3966 树链刨分
操作就是询问某个点的值, 然后就是对一条路径上的值全部修改。
最基本的树刨题目了。
树刨的思想:
1. 对于每个点找到他的重儿子。
void dfs1(int o, int u){
sz[u] = ;
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(v == o) continue;
dfs1(u, v);
if(sz[v] > sz[son[u]]) son[u] = v;
sz[u] += sz[v];
}
}
2.求DFS序。对于每个节点记录下dfs序,他的父节点,他的祖先节点(也就是这条重链上最高的节点),这个点对应线段树的位置,线段树对应到节点的位置。
在DFS的过程中,先搜重儿子,然后再搜轻儿子,这样可以保证一条重链在线段树中是连续的,故可以用线段树区间修改。
void dfs2(int o, int u, int t){
deep[u] = deep[o] + ;
top[u] = t;
fa[u] = o;
dfn[u] = ++dtot;
dto[dtot] = u;
if(son[u]) dfs2(u, son[u], t);
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(v == o || v == son[u]) continue;
dfs2(u, v, v);
}
}
3. 接下来就是对路径的修改。
假如我们需要修改 u -- v 这条路径。
那么我们先令fu = top[u], fv = top[v], 如果不相等,则将深度大的往上跳,跳的时候完成你要的操作。
相等之后就说明在一条链上了, 这个时候完成操作后就可以退出了。
注意的是, 判断的是 fu 和 fv 的深度 而不是 u v 的深度。
void Updata_Path(int x, int y, int c){
int fx = top[x], fy = top[y];
while(fx != fy){
if(deep[fx] > deep[fy]){
Updata(dfn[fx],dfn[x],c,,n,);
x = fa[fx]; fx = top[x];
}
else {
Updata(dfn[fy],dfn[y],c,,n,);
y = fa[fy]; fy = top[y];
}
}
if(deep[x] < deep[y]) Updata(dfn[x], dfn[y], c, , n, );
else Updata(dfn[y], dfn[x], c, , n,);
}
代码:
/*
code by: zstu wxk
time: 2019/02/22
*/
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod = (int)1e9+;
const int N = 2e5 + ;
int n, m, p;
int tr[N<<], lz[N<<], a[N];
int head[N], nt[N], to[N], tot;
int sz[N], son[N];
int top[N], fa[N], dfn[N], dto[N], deep[N], dtot;
void Build(int l, int r, int rt){
lz[rt] = tr[rt] = ;
if(l == r){
tr[rt] = a[dto[l]];
return ;
}
int m = l+r >> ;
Build(lson); Build(rson);
return ;
}
void PushDown(int rt){
if(lz[rt]){
lz[rt<<] += lz[rt];
lz[rt<<|] += lz[rt];
tr[rt<<] += lz[rt];
tr[rt<<|] += lz[rt];
lz[rt] = ;
}
return ;
}
void add(int u, int v){
to[tot] = v;
nt[tot] = head[u];
head[u] = tot++;
}
void dfs1(int o, int u){
sz[u] = ;
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(v == o) continue;
dfs1(u, v);
if(sz[v] > sz[son[u]]) son[u] = v;
sz[u] += sz[v];
}
}
void dfs2(int o, int u, int t){
deep[u] = deep[o] + ;
top[u] = t;
fa[u] = o;
dfn[u] = ++dtot;
dto[dtot] = u;
if(son[u]) dfs2(u, son[u], t);
for(int i = head[u]; ~i; i = nt[i]){
int v = to[i];
if(v == o || v == son[u]) continue;
dfs2(u, v, v);
}
}
int Query(int x, int l, int r, int rt){
if(l == r)
return tr[rt];
int m = l+r >> ;
PushDown(rt);
if(x <= m) return Query(x, lson);
return Query(x, rson);
}
void Updata(int L, int R, int C, int l, int r, int rt){
// cout << L << " l with r " << r << endl;
if(L <= l && r <= R){
lz[rt] += C;
tr[rt] += C;
return ;
}
int m = l+r >> ;
PushDown(rt);
if(L <= m) Updata(L, R, C, lson);
if(m < R) Updata(L, R, C, rson);
return ;
}
void Updata_Path(int x, int y, int c){
int fx = top[x], fy = top[y];
while(fx != fy){
if(deep[fx] > deep[fy]){
Updata(dfn[fx],dfn[x],c,,n,);
x = fa[fx]; fx = top[x];
}
else {
Updata(dfn[fy],dfn[y],c,,n,);
y = fa[fy]; fy = top[y];
}
}
if(deep[x] < deep[y]) Updata(dfn[x], dfn[y], c, , n, );
else Updata(dfn[y], dfn[x], c, , n,);
}
void init(){
memset(head, -, sizeof(head));
memset(son, , sizeof son);
tot = dtot = ;
}
void Ac(){
for(int i = ; i <= n; ++i) scanf("%d", &a[i]);
for(int i = ,u,v; i < n; ++i){
scanf("%d%d", &u, &v);
add(u, v); add(v, u);
}
dfs1(,);
dfs2(,,);
Build(,n,);
char op[];
int x, y, c;
for(int i = ; i <= p; ++i){
scanf("%s", op);
if(op[] == 'Q') {
scanf("%d", &x);
printf("%d\n", Query(dfn[x], , n, ));
}
else {
scanf("%d%d%d", &x, &y, &c);
if(op[] == 'D') c = -c;
Updata_Path(x,y,c);
// Tdfs(1,n,1);
}
}
}
int main(){
while(~scanf("%d%d%d", &n, &m, &p)){
init();
Ac();
}
return ;
}
/*
3 2 5
1 2 3
2 1
1 3
I 2 3 5
Q 2 7 6 10
0 0 0 0 0 0 0
1 2
2 3
3 4
1 5
5 6
I 4 6 1
Q 1 */
HDU - 3966 树链刨分的更多相关文章
- hdu 5452(树链刨分)
看到题目,想了挺长时间,发现不会,然后看着样子像是树上成段操作,所以查了下树链刨分,结果真的就是这个东西... Minimum Cut Time Limit: 3000/2000 MS (Java/O ...
- bzoj 5210(树链刨分下做个dp)
5210: 最大连通子块和 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 211 Solved: 65[Submit][Status][Discus ...
- xcoj 1103 插线板(树链刨分求最大子段和)
1103: 插线板 时间限制: 1 Sec 内存限制: 128 MB提交: 14 解决: 7 标签提交统计讨论版EditTestData 题目描述 从前有一堆古老的插线板,任意两个插线板之间只有一 ...
- HDU 3966 (树链剖分+线段树)
Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板 ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
- 树链刨分(class版)
class版树链剖(刨)分 感谢沙华大佬的赞助 其实没什么太大变化,就是用了几次一顿乱指... CODE: #include<iostream> #include<cstdio> ...
- HDU 3966 /// 树链剖分+树状数组
题意: http://acm.hdu.edu.cn/showproblem.php?pid=3966 给一棵树,并给定各个点权的值,然后有3种操作: I x y z : 把x到y的路径上的所有点权值加 ...
- hdu 3966 树链剖分
思路:树链剖分入门题,我这门入得好苦啊,程序很快写出来了,可是在LCA过程中把update函数里的左右边界位置写反了,一直RE到死. #pragma comment(linker, "/ST ...
- HDU 3966 树链剖分后线段树维护
题意: 一棵树, 操作1.$path(a,b)$之间的点权$+k$ 操作2.单点查询 题解: 树链剖分即可,注意代码细节,双向映射 主要是记录一下板子 #include <string.h> ...
随机推荐
- .net持续集成单元测试篇之单元测试简介以及在visual studio中配置Nunit使用环境
系列目录 单元测试及测试驱动开发简介 什么是单元测试 单元测试是一段自动化的代码,这段代码调用被测试的工作单元,之后对这个单元的单个最终结果的某些假设进行检验.单元测试几乎都是用单元测试框架编写的.单 ...
- 【JDK】JDK源码分析-AbstractQueuedSynchronizer(1)
概述 前文「JDK源码分析-Lock&Condition」简要分析了 Lock 接口,它在 JDK 中的实现类主要是 ReentrantLock (可译为“重入锁”).ReentrantLoc ...
- oracle的自增序列
因为oracle中的自增序列与mysql数据库是不一样的,所以在这里唠嗑一下oracle的自增序列 1. 创建和修改自增序列 --创建序列的语法 -- create sequence [user.]s ...
- maysql的自增字段
因为mysql中的自增字段与oracle数据库是不一样的,所以在这里唠嗑一下mysql的自增字段 1.添加自增字段 1.1 在创建表时添加 create table emp( empno ) auto ...
- 用JavaScript带你体验V8引擎解析标识符过程
上一篇讲了字符串的解析过程,这一篇来讲讲标识符(IDENTIFIER)的解析. 先上知识点,标识符的扫描分为快解析和慢解析,一旦出现Ascii值大于128的字符或者转义字符,会进入慢解析,略微影响性能 ...
- React 基于antd+video.js实现m3u8格式视频播放及实时切换
文档连接地址(官网看起麻烦,看中文别人整理好的)https://blog.csdn.net/a0405221/article/details/80923090 React项目使用 安装依赖 npm ...
- spring boot 加载自定义log4j 文件路径
spring boot 使用log4j 打印时,需首先去除自带 Logger ,然后加入log4j 依赖 <dependencies> <!-- https://mvnreposit ...
- k8s+istio:流量控制之灰度发布
通过Kubernetes+Istio的流量控制实现灰度发布,主要演示通过流量权重实现蓝绿,通过http自定义头实现金丝雀 准备环境 k8s和istio不想自己装的话可以在云上买个按量付费集群,用完即删 ...
- 最新 Flutter 团队工程师中文演讲 | Flutter 的性能测试和理论
本视频为 Google Flutter 团队的软件工程师 Xiao Yu 在 2018 谷歌开发者大会做的演讲,演讲题目是<Flutter 的性能测试和理论>. 这个视频里将会通过近半个小 ...
- h5微信浏览器复制粘贴--ios兼容问题的解决方法(clipboard.js插件)
前段时间在做微信h5的时候,遇到了ios兼容,使用clipboard.js插件完美解决 下载地址:下载地址: https://github.com/zenorocha/clipboard.js cnd ...