HDU3669 Aragorn's Story 树链剖分 点权

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966

题意:

n个点的,m条边,每个点都 有点权

修改 从u->v上所有点的点权

查询单点点权

题解:

树链剖分裸题

树链剖分就是将树分割为多条边,然后利用数据结构来维护这些链的一个技巧

  • 重儿子:父亲节点的所有儿子中子树结点数目最多( sizesiz**e 最大)的结点;
  • 轻儿子:父亲节点中除了重儿子以外的儿子;
  • 重边:父亲结点和重儿子连成的边;
  • 轻边:父亲节点和轻儿子连成的边;
  • 重链:由多条重边连接而成的路径;
  • 轻链:由多条轻边连接而成的路径;

1.求出子树大小和每个点的重儿子,处理sz数组,son数组,fa数组和dep数组

2.连接重链,记录dfs序,每个链的顶端节点,处理出rank数组,top数组,id数组

3.维护链上信息

代码:

#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f; int n, m, Q;
int a[maxn], sz[maxn], dep[maxn], fa[maxn], top[maxn], id[maxn], son[maxn], Rank[maxn];
int sum[maxn << 2], lazy[maxn << 2]; struct EDGE {
int u, v, nt;
} edge[maxn << 1];
int head[maxn], summ, cnt; void add_edge(int u, int v) {
edge[++summ].u = u; edge[summ].v = v; edge[summ].nt = head[u]; head[u] = summ;
} void dfs1(int u) {
sz[u] = 1; son[u] = 0;
for (int i = head[u]; ~i; i = edge[i].nt) {
int v = edge[i].v;
if (v != fa[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
}
} void dfs2(int u, int tp, int x) {
top[u] = tp; id[u] = ++cnt; Rank[cnt] = u;
if (son[u]) dfs2(son[u], tp, 1);
for (int i = head[u]; ~i; i = edge[i].nt) {
int v = edge[i].v;
if (v == son[u] || v == fa[u]) continue;
dfs2(v, v, 2);
}
} void init() {
memset(head, -1, sizeof(head));
summ = 1; cnt = 0;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) {
int u, v;
scanf("%d %d", &u, &v);
add_edge(u, v); add_edge(v, u);
}
dep[1] = 1; fa[1] = 0;
dfs1(1);
dfs2(1, 1, 1);
} void pushup(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
} void pushdown(int rt, int mid) {
if (lazy[rt]) {
lazy[rt << 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
sum[rt << 1] += lazy[rt] * (mid - mid / 2);
sum[rt << 1 | 1] += lazy[rt] * (mid / 2);
lazy[rt] = 0;
}
} void build(int l, int r, int rt) {
lazy[rt] = 0;
if (l == r) {
sum[rt] = a[Rank[l]];
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
} void update(int L, int R, int val, int l, int r, int rt) {
if (L <= l && r <= R) {
sum[rt] += val * (r - l + 1);
lazy[rt] += val;
return;
}
pushdown(rt, r - l + 1);
int mid = (l + r) >> 1;
if (L <= mid) update(L, R, val, lson);
if (mid < R) update(L, R, val, rson);
pushup(rt);
} int query(int pos, int l, int r, int rt) {
if (l == r) {
return sum[rt];
}
pushdown(rt, r - l + 1);
int mid = (l + r) >> 1;
if (pos <= mid) return query(pos, lson);
if (mid < pos) return query(pos, rson);
} void change(int x, int y, int val) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) std::swap(x, y);
update(id[top[x]], id[x], val, 1, n, 1);
x = fa[top[x]];
}
if (dep[x] > dep[y]) std::swap(x, y);
update(id[x], id[y], val, 1, n, 1);
} int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
while (~scanf("%d %d %d", &n, &m, &Q)) {
init();
build(1, n, 1);
while (Q--) {
char s[2];
int x, y, z;
scanf("%s", s);
if (s[0] == 'I') {
scanf("%d %d %d", &x, &y, &z);
change(x, y, z);
}
if (s[0] == 'D') {
scanf("%d %d %d", &x, &y, &z);
change(x, y, -z);
}
if (s[0] == 'Q') {
scanf("%d", &x);
printf("%d\n", query(id[x], 1, n, 1));
}
}
}
}

HDU3669 Aragorn's Story 树链剖分 点权的更多相关文章

  1. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  2. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  3. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  4. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

  5. HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树

    HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...

  6. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  7. HDU 3966 Aragorn's Story(树链剖分)(线段树区间修改)

    Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  8. Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)

    题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2 ...

  9. hdu3966 Aragorn's Story 树链剖分

    题目传送门 题目大意: 有n个兵营形成一棵树,给出q次操作,每一次操作可以使两个兵营之间的所有兵营的人数增加或者减少同一个数目,每次查询输出某一个兵营的人数. 思路: 树链剖分模板题,讲一下树链剖分过 ...

随机推荐

  1. SPARK-SQL内置函数之字符串函数

    转载请注明转自:http://www.cnblogs.com/feiyumo/p/8763186.html 1.concat对于字符串进行拼接 concat(str1, str2, ..., strN ...

  2. 判断字符s是否为正整数和正小数

    下面一段代码是判断是否为正整数和正小数的:

  3. AtCoder Beginner Contest 084 C - Special Trains

    Special Trains Problem Statement A railroad running from west to east in Atcoder Kingdom is now comp ...

  4. Java注解初步了解 2016-07-24 22:20 240人阅读 评论(21) 收藏

    Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据. Java语言中的类.方法.变量.参数和包等都可以被标注.Java标注和Javadoc不同,标注有自反性.在编 ...

  5. ELK2之ELK的语法学习

    1.回顾 (1)es是什么? es是基于Apache Lucene的开源分布式(全文)搜索引擎,提供简单的RESTful API来隐藏Lucene的复杂性. es除了全文搜索引擎之外,还可以这样描述它 ...

  6. java 根据秘钥,对数据进行加解密

    package test; import com.alibaba.fastjson.JSONObject; import sun.misc.BASE64Decoder; import sun.misc ...

  7. 2018-8-10-win10-uwp-如何在DataTemplate绑定方法

    title author date CreateTime categories win10 uwp 如何在DataTemplate绑定方法 lindexi 2018-08-10 19:16:50 +0 ...

  8. 08Redis入门指南笔记(集群)

    即使使用哨兵,此时的 Redis 集群的每个数据库依然存有集群中的所有数据,从而导致集群的总数据存储量受限于所有节点中,内存最小的数据库节点,形成木桶效应. 对 Redis 进行水平扩容,在旧版Red ...

  9. 模板—点分治B(合并子树)(洛谷P4149 [IOI2011]Race)

    洛谷P4149 [IOI2011]Race 点分治作用(目前只知道这个): 求一棵树上满足条件的节点二元组(u,v)个数,比较典型的是求dis(u,v)(dis表示距离)满足条件的(u,v)个数. 算 ...

  10. 如何用JS和HTML 做一个桌面炒股小插件【原创】

    首先,使用node-webkit 做环境,废话不多说,直接贴HTML <!DOCTYPE html> <html xmlns="http://www.w3.org/1999 ...