HDU 3966 Aragorn's Story(树链剖分)题解
题意:给一棵树,要求你对一个路径上的值进行加减,查询某个点的值
思路:重链剖分。
由于分了轻重儿子,我每次到重儿子的top只要O(1),经过的轻儿子最多logn条,那么我每次往上跳最多跳logn次。
所以总的路径可以分为:dfn[top[u]]到dfn[u]组成的完整路径,每次更新完走向fa[top[u]]防止重复操作。
参考:某大哥博客
代码:
#include<cmath> #include<set> #include<map> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 50000 + 5; const int M = 50 + 5; const ull seed = 131; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; int fa[maxn]; //父节点 int top[maxn]; //i所在重链的初始节点 int sz[maxn]; //i为根子树节点数 int son[maxn]; //重儿子 int deep[maxn]; //深度 int dfn[maxn], tol; //i的dfs序编号 int fd[maxn]; //dfs序编号是i的节点int aa[maxn]; int n, m; struct Edge{int v, next; }edge[maxn << 1]; int head[maxn], tot; void init(){memset(head, -1, sizeof(head));tot = tol = 0;memset(son, -1, sizeof(son)); } void addEdge(int u, int v){edge[tot].v = v;edge[tot].next = head[u];head[u] = tot++; } void dfs1(int u, int pre, int d){deep[u] = d;fa[u] = pre;sz[u] = 1;for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].v;if(v == pre) continue;dfs1(v, u, d + 1);sz[u] += sz[v];if(son[u] == -1 || sz[v] > sz[son[u]])son[u] = v;} } void dfs2(int u, int tp){ //得到toptop[u] = tp;dfn[u] = ++tol;fd[tol] = u;if(son[u] == -1) return;dfs2(son[u], tp);for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].v;if(v != son[u] && v != fa[u]){dfs2(v, v);}} }int sum[maxn << 2], lazy[maxn << 2]; void build(int l, int r, int rt){if(l == r){sum[rt] = aa[fd[l]];lazy[rt] = 0;return;}lazy[rt] = 0;int m = (l + r) >> 1;build(l, m, rt << 1);build(m + 1, r, rt << 1 | 1);sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void pushdown(int rt, int l, int r){int m = (l + r) >> 1;if(lazy[rt]){lazy[rt << 1] += lazy[rt];lazy[rt << 1 | 1] += lazy[rt];sum[rt << 1] += lazy[rt] * (m - l + 1);sum[rt << 1 | 1] += lazy[rt] * (r - m);lazy[rt] = 0;} } void update(int l, int r, int L, int R, int v, int rt){if(L <= l && R >= r){lazy[rt] += v;sum[rt] += v * (r - l + 1);return;}pushdown(rt, l, r);int m = (l + r) >> 1;if(L <= m)update(l, m, L, R, v, rt << 1);if(R > m)update(m + 1, r, L, R, v, rt << 1 | 1);sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } int query(int pos, int l, int r, int rt){if(l == r){return sum[rt];}pushdown(rt, l, r);int m = (l + r) >> 1;if(pos <= m)return query(pos, l, m, rt << 1);elsereturn query(pos, m + 1, r, rt << 1 | 1); }void add(int u, int v, int val){while(top[u] != top[v]){if(deep[top[u]] < deep[top[v]]) swap(u, v);update(1, n, dfn[top[u]], dfn[u], val, 1);u = fa[top[u]];}if(deep[u] > deep[v]) swap(u, v);update(1, n, dfn[u], dfn[v], val, 1); }int main(){int Q;while(~scanf("%d%d%d", &n, &m, &Q)){init();for(int i = 1; i <= n; i++){scanf("%d", &aa[i]);}for(int i = 0; i < m; i++){int u, v;scanf("%d%d", &u, &v);addEdge(u, v);addEdge(v, u);}dfs1(1, -1, 0);dfs2(1, 1);build(1, n, 1);while(Q--){char o[2];int a, b, c;scanf("%s", o);if(o[0] == 'I'){scanf("%d%d%d", &a, &b, &c);add(a, b, c);}else if(o[0] == 'D'){scanf("%d%d%d", &a, &b, &c);add(a, b, -c);}else{scanf("%d", &a);printf("%d\n", query(dfn[a], 1, n, 1));}}}return 0; }
转载于:https://www.cnblogs.com/KirinSB/p/11205336.html
HDU 3966 Aragorn's Story(树链剖分)题解相关推荐
- HDU - 3966 Aragorn's Story(树链剖分+线段树)
题目链接:点击查看 题目大意:给出一棵由n个点组成的树,每个点都有一个权值,接下来有k次操作,每次操作分为下面几种类型: I u v x:将u-v这条路径上的所有点权值加上x D u v x:将u-v ...
- HDU 3966 Aragorn's Story (树链点权剖分,成段修改单点查询)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 树链剖分的模版,成段更新单点查询.熟悉线段树的成段更新的话就小case啦. 1 //树链剖分 边 ...
- hdu 4897 Little Devil I (树链剖分+线段树)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4897 题意: 给你一棵树,一开始每条边都是白色,有三种操作: 1.将 u - v路径上的边转换颜色 ...
- [hdu3966 Aragorn's Story]树链剖分
题意:要求在一棵N(<=50000)个带权节点的树上支持3种操作 (1)I u v w,u到v的路径上每个节点权值增加w (2)D u v w,u到v的路径上每个节点权值减少w (3)Q u,求 ...
- 洛谷3384:【模板】树链剖分——题解
https://www.luogu.org/problemnew/show/P3384 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 ...
- HDU - 5242 Game(树形dp+树链剖分/树上贪心+思维)
题目链接:点击查看 题目大意:给出一棵包含n个节点的树,每个节点都有一个权值,整棵树的根是点1,问从点1开始向下一直走到叶子节点,可以走k次,怎么样走权值和最大,每个节点被走过一次后权值会变为0 题目 ...
- E:Tree Queries(假树链剖分写法)
博客园地址 E:Tree Queries 思路 当我写完A完这道题后,百度了一下,发现好像没有人是用类树链剖分来写的,都是LCALCALCA,于是我就来水一篇树链剖分题解了. 第一步:贪心取点 我们可 ...
- HDU - 3966 Aragorn's Story(树链剖分)
题目传送门:HDU - 3966 Aragorn's Story 题目大意: 存在一个树,树上每个节点为一个阵营,阵营中存在敌人,现在要进行以下操作 I C1 C2 K :将阵营C1到阵营C2路 ...
- HDU 3966 Aragorn's Story (树链剖分+线段树)
题意:给你一棵树,然后有三种操作 I L R K: 把L与R的路径上的所有点权值加上K D L R K:把L与R的路径上的所有点权值减去K Q X:查询节点编号为X的权值 思路:树链剖分裸题(我还没有 ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
最新文章
- hdu4280 最大流DINIC
- ASP.NET页面的CheckBoxList组件
- math标准库函数----python
- 关于cocopod命令
- linux 字符串加入中括号,Linux Shell 基础 -- 总结几种括号、引号的用法
- vue.js中mock本地json数据
- 设计模式记--Observer Pattern观察者模式
- ES6-set集合应用
- Amazon S3数据一致性模型
- Java并发(理论知识)—— 线程安全性
- 使用Dapper处理多个结果集和多重映射的教程
- python演化博弈仿真_基于matlab的演化博弈模型求解代码?
- 【测试面试题每日一刷】22道接口测试面试题,附答案
- vasp计算-INCAR文件
- SAPAS91导入期初固定资产数据往年购置与当年购置的区别
- dlut1216-位运算(异或)水题
- Excel按相同列内容合并表
- Golang 提取视频中音频,存为MP3格式 | Golang工具
- 【知识图谱】知识图谱数据构建的“硬骨头”,阿里工程师如何拿下?深度学习在知识图谱构建中的应用。
- PDF文件在线压缩方法
热门文章
- Nginx URL重写规则配置详解
- “梅丽莎”病毒背后的神秘黑客
- linux服务器磁盘陈列
- Zendframework 模块加载事件触发顺序。
- hdu 4828 Grids(拓展欧几里得+卡特兰数)
- 再见收费的 XShell,我改用国产良心工具,完全免费!
- 工作5年,别人成了架构师,你却还在基层打滚
- 百度统计挂了,分布式数据库异常引起,数据显示为空!
- 湖北经济学院计算机专业全国排名,2018年湖北经济学院世界排名、中国排名、专业排名...
- ssh java_java中的SSH的各自作用是什么-百度经验