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> ...
随机推荐
- 新浪微博SSO授权后回调客户端没有执行sinaweiboDidLogIn&无法返回应用
TARGETS --> URL Types --> 添加 --> 在URL Schemes里填上sinaweibosso.XXXX(AppKey),Identifier这里可以随机 ...
- coffeescript 函数 箭头表达式
函数 do可以形成闭包,使方法作用域不受外部变化的影响. 隐式返回最后一个表达式的值 函数调用省略括号 用arguments数组访问传递给函数的所有对象(低可读性) @name为this.name的简 ...
- C#连接Oracle数据库字符串(引入DLL)
需求:从一台Oracle数据库获取数据,本以为是很简单的事情,直接将原来的SqlClient换成OracleClient调用,结果远没自己想的简单.要么安装Oracle客户端,要么安装PLSQL.网上 ...
- NS3中一些难以理解的常数
摘要:在NS3的学习中,PHY MAC中总有一些常数,需要理解才能修改.如帧间间隔等.那么,本文做个简单分析,帮助大家理解.针对802.11标准中MAC协议. void WifiMac::Conf ...
- 对Java中HashCode方法的深入思考
前言 最近在学习 Go 语言,Go 语言中有指针对象,一个指针变量指向了一个值的内存地址.学习过 C 语言的猿友应该都知道指针的概念.Go 语言语法与 C 相近,可以说是类 C 的编程语言,所以 Go ...
- 每天用SpringBoot,还不懂RESTful API返回统一数据格式是怎么实现的?
上一篇文章RESTful API 返回统一JSON数据格式 说明了 RESTful API 统一返回数据格式问题,这是请求一切正常的情形,这篇文章将说明如何统一处理异常,以及其背后的实现原理,老套路, ...
- vue+el-menu实现路由刷新和导航栏菜单状态保持(局部刷新页面)
一.菜单项激活状态保持 有时,我们在项目中会有这样一个需求,即实现 一个侧导航栏,点击不同的菜单项,右边内容会跟着变化,而页面手动刷新后想要使菜单激活状态保持,那么这个功能该如何实现呢? 现在给出以下 ...
- 100天搞定机器学习|Day19-20 加州理工学院公开课:机器学习与数据挖掘
前情回顾 机器学习100天|Day1数据预处理 100天搞定机器学习|Day2简单线性回归分析 100天搞定机器学习|Day3多元线性回归 100天搞定机器学习|Day4-6 逻辑回归 100天搞定机 ...
- (二十五)c#Winform自定义控件-有确定取消的窗体(一)
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
- Salesforce LWC学习(四) 父子component交互 / component声明周期管理 / 事件处理
我们在上篇介绍了 @track / @api的区别.在父子 component中,针对api类型的变量,如果声明以后就只允许在parent修改,son component修改便会导致报错. sonIt ...