HDU-4918 Query on the subtree(树分治+树状数组)
来源:互联网 发布:淘宝官方优惠券app 编辑:程序博客网 时间:2024/05/21 17:38
Query on the subtree
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1193 Accepted Submission(s): 375
Problem Description
bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n. At the very begining, the i-th vertex is assigned with weight wi.
There are q operations. Each operations are of the following 2 types:
Change the weight of vertex v into x (denoted as "! v x"),
Ask the total weight of vertices whose distance are no more than d away from vertex v (denoted as "? v d").
Note that the distance between vertex u and v is the number of edges on the shortest path between them.
There are q operations. Each operations are of the following 2 types:
Change the weight of vertex v into x (denoted as "! v x"),
Ask the total weight of vertices whose distance are no more than d away from vertex v (denoted as "? v d").
Note that the distance between vertex u and v is the number of edges on the shortest path between them.
Input
The input consists of several tests. For each tests:
The first line contains n,q (1≤n,q≤105). The second line contains n integers w1,w2,…,wn (0≤wi≤104). Each of the following (n - 1) lines contain 2 integers ai,bi denoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following q lines contain the operations (1≤v≤n,0≤x≤104,0≤d≤n).
The first line contains n,q (1≤n,q≤105). The second line contains n integers w1,w2,…,wn (0≤wi≤104). Each of the following (n - 1) lines contain 2 integers ai,bi denoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following q lines contain the operations (1≤v≤n,0≤x≤104,0≤d≤n).
Output
For each tests:
For each queries, a single number denotes the total weight.
For each queries, a single number denotes the total weight.
Sample Input
4 31 1 1 11 22 33 4? 2 1! 1 0? 2 13 31 2 31 21 3? 1 0? 1 1? 1 2
Sample Output
32166
题解:树分治+树状数组
首先看到询问任意点对的距离不超过d就想到用树分治来写,通过不断找重心将树划分,递归层数不会超过logN。如果不进行修改操作,我们就只要用数组cnt[u][dis]储存到点u距离小于dis的权值和。
但是现在需要进行修改,因此需要用数据结构来维护:对于一个点u,他最多只属于logN个子树,也就是最多只属于logN个重心。所以我们可以预处理出每个点所属于的重心(这个可以在树分治时完成)以及到这些重心的距离,以每个重心建树状数组,每个点按照到重心的距离插入到树状数组中,然后每次查询到u距离不超过d的点的个数就通过树状数组求前缀和得到。
假设子树的重心为root,对于这颗子树的一个节点v,设subroot是root的子节点且是v的根节点,那么到u距离不超过d的点的个数为:T[root].sum[d-dis]-T[subroot].sum[d-dis]
关于这道题,鸟神的博客写的超级棒:点击打开链接
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MX = 1e5 + 5;const int MXM = 4e6 + 5;const int INF = 0x3f3f3f3f;struct Edge { int v, nxt;} E[MX * 2];int head[MX], rear;int fir[MX], tot;int sz[MX], maxv[MX], dep[MX], id[MX];int val[MX], vis[MX], n, cnt, Max, root;void init() { memset(vis, 0, sizeof(vis)); memset(head, -1, sizeof(head)); memset(fir, -1, sizeof(fir)); rear = cnt = tot = 0;}void add(int u, int v) { E[rear].v = v; E[rear].nxt = head[u]; head[u] = rear++;}struct Tree { int n ; vector < int > T ; void init (int sz) { T.clear(); n = sz; T.resize(n + 1); } void add (int x, int v) { for (int i = x; i <= n; i += i & -i) T[i] += v; } int sum (int x) { if (x > n) x = n; int ret = 0; for (int i = x; i > 0; i -= i & -i) ret += T[i]; return ret; }} T[MX << 1];//类似于领接表,node记录包含u的所有根节点以及根节点的子树struct node { int root, subroot; //根节点,根节点的子节点 int dis, nxt;} Node[MXM];void add_node(int u, int root, int subroot, int dis) { Node[tot].root = root; Node[tot].subroot = subroot; Node[tot].dis = dis; Node[tot].nxt = fir[u]; fir[u] = tot++;}void dfs_size(int u, int fa) { sz[u] = 1; maxv[u] = 0; for (int i = head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v] || v == fa) continue; dfs_size(v, u); sz[u] += sz[v]; maxv[u] = max(maxv[u], sz[v]); }}void dfs_root(int u, int fa, int rt) { maxv[u] = max(maxv[u], sz[rt] - sz[u]); if (maxv[u] < Max) { Max = maxv[u]; root = u; } for (int i = head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v] || v == fa) continue; dfs_root(v, u, rt); }}void dfs_deep(int u, int fa, int deep, int root, int subroot) { dep[u] = deep; T[root].add(dep[u], val[u]); T[subroot].add(dep[u], val[u]); add_node(u, root, subroot, dep[u]); for (int i = head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v] || v == fa) continue; dfs_deep(v, u, deep + 1, root, subroot); }}void DFS(int u) { Max = n; dfs_size(u, -1); dfs_root(u, -1, u); int rt = root; id[rt] = ++cnt; vis[rt] = 1; dep[rt] = 1; //设根节点深度为1 T[cnt].init(sz[u] + 1); T[cnt].add(1, val[rt]); add_node(rt, id[rt], 0, 1); for (int i = head[rt]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v]) continue; T[++cnt].init(sz[v] + 1); dfs_deep(v, rt, 2, id[rt], cnt); } for (int i = head[rt]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v]) continue; DFS(v); }}int main() { int m; //freopen("in.txt","r",stdin); while (~scanf("%d%d", &n, &m)) { init(); for (int i = 1; i <= n; i++) scanf("%d", &val[i]); for (int i = 1, u, v; i < n; i++) { scanf("%d%d", &u, &v); add(u, v); add(v, u); } DFS(1); char op[5]; int u, x; while (m--) { scanf("%s%d%d", op, &u, &x); if (op[0] == '!') { for (int i = fir[u]; ~i; i = Node[i].nxt) { int root = Node[i].root, subroot = Node[i].subroot, dis = Node[i].dis; T[root].add(dis, x - val[u]); if (subroot) T[subroot].add(dis, x - val[u]); } val[u] = x; } else { int ans = 0; for (int i = fir[u]; ~i; i = Node[i].nxt) { int root = Node[i].root, subroot = Node[i].subroot, dis = Node[i].dis - 1; ans += T[root].sum(x - dis + 1); if (subroot) ans -= T[subroot].sum(x - dis + 1); } printf("%d\n", ans); } } } return 0;}
阅读全文
0 0
- hdu 4918 Query on the subtree(树分治 + 树状数组)
- 【HDU】4918 Query on the subtree 点分治+树状数组
- HDU-4918 Query on the subtree(树分治+树状数组)
- [HDOJ 4918] Query on the subtree [树的分治+树状数组]
- 【hdu 4918】Query on the subtree 动态树分治
- hdu 4918 Query on the subtree (动态点分治+动态开点+线段树)
- HDU 4918 Query on the subtree
- hdu 4836 The Query on the Tree(线段树or树状数组)
- HDU4918-Query on the subtree
- hdu 5664 Lady CA and the graph (树分治,树状数组)
- HDU - 5324(分治+树状数组)
- hdu - 4339 - Query - 树状数组||线段树
- HDU 4339 Query(树状数组+二分)
- HDU-4339 Query(树状数组+二分)
- hdu 5324 Boring Class(树状数组+笛卡尔树 | 树状数组+cdq分治)
- HDU 4339 Query 树状数组
- Query on a string 暴力+树状数组
- hdu 4417 Super Mario(主席树||cdq分治+树状数组)
- 【JavaSE笔记】Java常用类及其方法(二)_String
- PAT(Basic Level)_1006_换个格式输出整数
- 【OpenPose-Windows】error2 win10-OpenPose-pose+hand/face中断问题
- 简单十步让你全面理解SQL
- 这是我第一次在CSDN上发表博客,新的一天不妨跟自己说一声:要好好的!
- HDU-4918 Query on the subtree(树分治+树状数组)
- 降薪求职对于应届毕业生来说是个选择
- 网页静态化和网页伪静态化之间的区别与选择
- PAT(Basic Level)_1007_素数对猜想
- 前端学习17/07/22
- PAT(Basic Level)_1008_数组元素循环右移问题
- 根据AQS推测Semaphore及源码分析
- PAT(Basic Level)_1009_说反话
- Python 3.x 连接数据库(pymysql 方式)