A - Aragorn's Story HDU - 3966 树剖裸题
这个题目是一个比较裸的树剖题,很好写。
http://acm.hdu.edu.cn/showproblem.php?pid=3966
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <iostream>
- #include <algorithm>
- #include <cstdlib>
- #include <vector>
- #include <stack>
- #include <map>
- #include <string>
- #define inf 0x3f3f3f3f
- #define inf64 0x3f3f3f3f3f3f3f3f
- using namespace std;
- typedef long long ll;
- const int maxn = 5e4 + 10;
- int f[maxn];//f 保存u的父亲节点
- int dep[maxn];//dep保存节点u 的深度
- int siz[maxn];//siz保存以u为根的子节点的个数
- int son[maxn];//son 保存u的重儿子
- int rk[maxn];//rk当前dfs序在树中所对应的节点
- int top[maxn];// top保存当前结点所在链的顶端结点
- int id[maxn];//dfs的执行顺序
- int a[maxn];
- int n;
- ll sum[maxn * 4], lazy[maxn * 4];
- //------------------线段树部分---------------//
- void push_up(int id) {
- sum[id] = sum[id << 1] + sum[id << 1 | 1];
- // printf("sum[%d]=%d sum[%d]=%d\n", id << 1, sum[id << 1], id << 1 | 1, sum[id << 1 | 1]);
- // printf("sum[%d]=%d\n", id, sum[id]);
- }
- void build(int id, int l, int r) {
- lazy[id] = 0;
- if (l == r) {
- sum[id] = a[rk[l]];
- // printf("id=%d sum=%d\n", id, sum[id]);
- return;
- }
- int mid = (l + r) >> 1;
- build(id << 1, l, mid);
- build(id << 1 | 1, mid + 1, r);
- push_up(id);
- }
- void push_down(int id, int len1, int len2) {
- if (lazy[id] == 0) return;
- sum[id << 1] += lazy[id] * len1;
- lazy[id << 1] += lazy[id];
- sum[id << 1 | 1] += lazy[id] * len2;
- lazy[id << 1 | 1] += lazy[id];
- lazy[id] = 0;
- }
- void update(int id, int l, int r, int x, int y, int val) {
- // printf("id=%d l=%d r=%d x=%d y=%d val=%d\n", id, l, r, x, y, val);
- if (x <= l && y >= r) {
- // printf("id=%d sum=%d\n", id, sum[id]);
- sum[id] += val * (r - l + 1);
- lazy[id] += val;
- // printf("%d\n", sum[id]);
- return;
- }
- int mid = (l + r) >> 1;
- push_down(id, mid - l + 1, r - mid);
- if (x <= mid) update(id << 1, l, mid, x, y, val);
- if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, val);
- push_up(id);
- }
- ll query(int id, int l, int r, int x, int y) {
- if (x <= l && y >= r) return sum[id];
- int mid = (l + r) >> 1;
- ll ans = 0;
- push_down(id, mid - l + 1, r - mid);
- if (x <= mid) ans = (ans + query(id << 1, l, mid, x, y));
- if (y > mid) ans = (ans + query(id << 1 | 1, mid + 1, r, x, y));
- return ans;
- }
- //------------------------树链剖分-------------------//
- // int f[maxn];//f 保存u的父亲节点
- // int dep[maxn];//dep保存节点u 的深度
- // int siz[maxn];//siz保存以u为根的子节点的个数
- // int son[maxn];//son 保存u的重儿子
- // int rk[maxn];//rk当前dfs序在树中所对应的节点
- // int top[maxn];// top保存当前结点所在链的顶端结点
- // int id[maxn];//dfs的执行顺序
- struct node {
- int v, nxt;
- node(int v = 0, int nxt = 0) :v(v), nxt(nxt) {}
- }ex[maxn];
- int head[maxn], cnt = 0, tot;
- void init() {
- cnt = 0, tot = 0;
- memset(son, 0, sizeof(son));
- memset(head, -1, sizeof(head));
- }
- void add(int u, int v) {
- ex[cnt] = node(v, head[u]);
- head[u] = cnt++;
- ex[cnt] = node(u, head[v]);
- head[v] = cnt++;
- }
- void dfs1(int u, int fa, int depth) {
- f[u] = fa; dep[u] = depth; siz[u] = 1;
- for (int i = head[u]; i != -1; i = ex[i].nxt) {
- int v = ex[i].v;
- if (v == fa) continue;
- dfs1(v, u, depth + 1);
- siz[u] += siz[v];
- if (siz[v] > siz[son[u]]) son[u] = v;
- }
- }
- void dfs2(int u, int t) {
- top[u] = t;
- id[u] = ++tot;//标记dfs序
- rk[tot] = u;//序号tot对应的结点u
- if (!son[u]) return;
- dfs2(son[u], t);
- /*我们选择优先进入重儿子来保证一条重链上各个节点dfs序连续,
- 一个点和它的重儿子处于同一条重链,所以重儿子所在重链的顶端还是t*/
- for (int i = head[u]; i != -1; i = ex[i].nxt) {
- int v = ex[i].v;
- if (v != son[u] && v != f[u]) dfs2(v, v);//一个点位于轻链底端,那么它的top必然是它本身
- }
- }
- void update2(int x, int y, int z)//修改x到y路径的值
- {
- while (top[x] != top[y])//不在同一条链上
- {
- if (dep[top[x]] < dep[top[y]]) swap(x, y);//x为深度大的链
- update(1, 1, n, id[top[x]], id[x], z);//x为深度大的链
- x = f[top[x]];//深度大的向上跳
- }
- if (dep[x] > dep[y]) swap(x, y); //这里x和y在同一条链
- update(1, 1, n, id[x], id[y], z); //x和y这条链的更新
- }
- ll query2(int x, int y) {
- ll ret = 0;
- while (top[x] != top[y]) {
- if (dep[top[x]] < dep[top[y]]) swap(x, y);
- ret = (ret + query(1, 1, n, id[top[x]], id[x]));
- x = f[top[x]];
- }
- if (dep[x] > dep[y]) swap(x, y);
- ret = (ret + query(1, 1, n, id[x], id[y]));
- return ret;
- }
- //------------------树链剖分结束-------------------//
- int main() {
- int m, p;
- while (scanf("%d%d%d", &n, &m, &p) != EOF) {
- init();
- for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
- for (int i = 1; i < n; i++) {
- int u, v;
- scanf("%d%d", &u, &v);
- add(u, v);
- }
- dfs1(1, -1, 1), dfs2(1, 1);
- build(1, 1, n);
- while (p--) {
- char s[10];
- int l, r, k;
- scanf("%s", s);
- if (s[0] == 'I') {
- scanf("%d%d%d", &l, &r, &k);
- update2(l, r, k);
- }
- else if (s[0] == 'D') {
- scanf("%d%d%d", &l, &r, &k);
- update2(l, r, -k);
- }
- else {
- scanf("%d", &l);
- ll ans = query(1, 1, n, id[l], id[l]);
- printf("%lld\n", ans);
- }
- }
- }
- return 0;
- }
A - Aragorn's Story HDU - 3966 树剖裸题的更多相关文章
- Aragorn's Story HDU - 3966 -树剖模板
HDU - 3966 思路 :树链剖分就是可以把一个路径上的点映射成几段连续的区间上.这样对于连续的区间可以用线段树维护, 对于每一段连续的区间都可以通过top [ ]数组很快的找到这段连续区间的头. ...
- 树剖裸题——BZOJ1036 树的统计
#include<cstring> #include<cmath> #include<algorithm> #include<cstdio> #defi ...
- HDU 3966 (树链剖分+线段树)
Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板 ...
- AC日记——Aragorn's Story HDU 3966
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 洛谷树剖模板题 P3384 | 树链剖分
原题链接 对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树 剩下的就和树剖一样了 #include< ...
- 树剖想法题——BZOJ3626
本来是打算作为树剖练习的最后一题的,结果一直WA. 本来以为是自己写的太丑. 最后发现5w的数据 我开了10w的数组 然而有一个数组要×2 哦,好棒棒. #include<cstring> ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
- 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 ...
随机推荐
- spring 管理事务配置时,结果 报错: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here这个异常
java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not al ...
- mysql 的CURDATE() 与 NOW() 的区别
SELECT CURDATE() 查询出的是当前天的开始时间点,比如今天是 2015.02.03号,那不管我在今天什么时间点查询,结果都是今天的凌晨,即今天的开始的那个时间点,因为它只具体到年月日,没 ...
- MAC 上brew 更新 出错
在MAC上brew update的时候出现报错:Error: /usr/local must be writable! 错误,在该文章中也给出解决办法(sudo chown -R $(whoami) ...
- ES5与ES6 this 指向详细解析(箭头函数)
首先要明白箭头函数的作用: 箭头函数除了让函数的书写变得很简洁,可读性很好外:最大的优点是解决了this执行环境所造成的一些问题.比如:解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性) ...
- 用threejs 实现3D物体在浏览器展示
用threejs 实现3D物体在浏览器展示,通过鼠标平移,缩放,键盘箭头按钮左右移动等功能展示. <!DOCTYPE html> <html> <head> < ...
- Julia的基本知识
知识来源 1.变量.整数和浮点数 Julia和Matllab挺像的,基本的变量,数值定义都差不多,所以就没必要记录了. 2.数学运算 3.函数
- 一口气带你踩完五个 List 的大坑,真的是处处坑啊!
List 可谓是我们经常使用的集合类之一,几乎所有业务代码都离不开 List.既然天天在用,那就没准就会踩中这几个 List 常见坑. 今天我们就来总结这些常见的坑在哪里,捞自己一手,防止后续同学再继 ...
- [HarekazeCTF2019] web
在 buuoj 上看到的这个比赛题目,期间平台关了,就拿了 Dockerfile 本地做了,web 题目感觉还不错 encode_and_encode [100] 打开靶机,前两个页面都是 html ...
- jmeter json path espressions学习
jsonpath表达式可以使用点或者括号来取值 管方详细介绍:https://goessner.net/articles/JsonPath/ $ :表示根对象 @:表示当前对象 . 或者[]:表示子运 ...
- 【mybatis xml】数据层框架应用--Mybatis 基于XML映射文件实现数据的CRUD
使用MyBatis框架进行持久层开发 MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBa ...