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. day25 CMDB(1)

    CMDB项目介绍 参考地址: http://www.cnblogs.com/wupeiqi/articles/4556300.html http://www.cnblogs.com/wupeiqi/a ...

  2. iOS 三种打电话方式

    //1,这种方法,拨打完电话回不到原来的应用,会停留在通讯录里,而且是直接拨打,不弹出提示 NSMutableString * str=[[NSMutableString alloc] initWit ...

  3. python 捕获异常

  4. 字体图标font-awesome

    其实有一些常见的图标使用字体图标比使用img来得好 Font Awesome 官网:http://fortawesome.github.io/Font-Awesome/ 字体代码:http://for ...

  5. [HLSL]HLSL 入门参考 (dx11龙书附录B译文)

    原文:[HLSL]HLSL 入门参考 (dx11龙书附录B译文) HLSL 高级着色语言 参考文档 龙书DirectX12现已推出中文版,其附录B的高级着色器语言参考的翻译质量比本文更高,有条件的读者 ...

  6. 2018-7-21-win10-uwp-调用-Microsoft.Windows.Photos_8wekyb3d8bbwe-应用

    title author date CreateTime categories win10 uwp 调用 Microsoft.Windows.Photos_8wekyb3d8bbwe 应用 linde ...

  7. 01docker简单使用和配置(容器、镜像)

    一:容器中运行简单应用程序 1:hello  world 使用docker可以在容器中运行应用程序,使用docker run命令即可.比如下面的命令: $ docker run ubuntu /bin ...

  8. Struts2整合Spring方法及原理

    一.   Struts 2框架整合Spring步骤 1. 复制文件.复制struts2-spring-plugin-x-x-x.jar和spring.jar到WEB-INF/lib目录下.其中的x对应 ...

  9. 全文索引——CONTAINS 语法

    Like直接在数据据中查找可以查到所有所需记录但是会扫描整个表会影响性能CONTAINS是基于全文索引进行查询,查询结果受系统全文索引分词的方法影响查询结果会不全.Select * FROM A Wh ...

  10. AtCoder Regular Contest 058

    这个应该是第一场有英文的atcoder吧??不过题解却没有英文的... 从前往后慢慢做... C こだわり者いろはちゃん / Iroha's Obsession 数据范围这么小,直接暴力 #inclu ...