#Codeforces 381 [div2] D. Alyona and a tree 【树链剖分 + 优先队列】
来源:互联网 发布:长沙启航学校网络教育 编辑:程序博客网 时间:2024/05/16 08:17
题目:
D. Alyona and a tree
time limit per test 2 seconds
memory limit per test 256 megabytes
input standard input
output standard output
Alyona has atree with n vertices. The root of the tree is the vertex 1. In each vertexAlyona wrote an positive integer, in the vertex i she wrote ai. Moreover, thegirl wrote a positive integer to every edge of the tree (possibly, differentintegers on different edges).
Let's define dist(v, u) as the sumof the integers written on the edges of the simple path from v to u.
The vertex v controlsthe vertex u (v ≠ u) if and only if u is in thesubtree of v and dist(v, u) ≤ au.
Alyona wants tosettle in some vertex. In order to do this, she wants to know for each vertex v what isthe number of vertices u such that v controls u.
Input
The first linecontains single integer n (1 ≤ n ≤ 2·105).
The second linecontains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — theintegers written in the vertices.
The next (n - 1) linescontain two integers each. The i-th of these lines contains integers pi and wi (1 ≤ pi ≤ n, 1 ≤ wi ≤ 109) — theparent of the (i + 1)-th vertex in the tree and the number written on the edgebetween pi and (i + 1).
It is guaranteedthat the given graph is a tree.
Output
Print n integers —the i-th of thesenumbers should be equal to the number of vertices that the i-th vertexcontrols.
Examples
input
5
2 5 1 4 6
1 7
1 1
3 5
3 6
output
1 0 1 0 0
input
5
9 7 8 6 5
1 1
2 1
3 1
4 1
output
4 3 2 1 0
Note
In the exampletest case the vertex 1 controls the vertex 3, the vertex 3 controlsthe vertex 5 (note that is doesn't mean the vertex 1controls the vertex 5).
首先看出是一道递归求解题目,考虑到数据量很大,且存在点权和边权两种限制因素。故无法直接用树状dp处理。
可以想到,由于从下到上,树是逐渐归并的,所以对于每一个分支,只需维护一个优先队列,每次增加一条边后,将队列里长度小于(之前累加长度+新加入的边权)的点出队(因为如果无法到达这个点,更无法到达其父亲节点)。然后将该节点的权值 + 之前的累加值入队。(即,从这条边开始可以向后继续走 该点权值 的长度)
但如果每个点都开一个优先队列,必然会MLE,而且搬运数据的过程也会超时。
故,我们分情况讨论
首先,给每个节点(结构体)分配一个优先队列指针,方便在不搬运数据的情况下改变其内容。
如果这个节点是叶子节点,我们会为该节点分配一个新的优先队列,并将自身权值入队
如果这个节点只有一个儿子节点,我们会将其 累计边权 累加上这条边的长度。并直接将这个节点的优先队列指针指向其唯一儿子的优先队列。 (注意,处理完以后记着把自己入队)
如果这个节点有多个子节点,把该点的优先队列指针指向其儿子中 优先队列最长的一个(重链)。然后将其余优先队列的归并至该节点中。因为每次都选择最大的作为母版,故复杂度能够控制在 N * LOG N 以内
每个节点的ans 就是 该节点 优先队列的 size
代码:
#define _author "Reskip"#define _CRT_SECURE_NO_WARNINGS#include<iostream> #include<queue>#include<set>#include<algorithm>#include<vector>#include<string>#include<cstring>#include<cstdio>#include<sstream>#include<iomanip>#include<functional>using namespace std;#define maxn 200005struct node{long long dis;vector<int>con;vector<long long>far;long long ans;long long cntdis;int pq;}nodes[maxn];priority_queue<long long, vector<long long>, greater<long long>>que[maxn];int beg;int dfs(int x){int k = nodes[x].con.size();if (k == 0)//若为叶子{nodes[x].pq = beg;beg++;que[nodes[x].pq].push(nodes[x].dis);nodes[x].ans = 0;nodes[x].cntdis = 0;return nodes[x].pq;}if (k == 1)//一个儿子{int temp = dfs(nodes[x].con[0]);nodes[x].pq = temp;nodes[x].cntdis = nodes[nodes[x].con[0]].cntdis + nodes[x].far[0];while (!que[temp].empty() && que[temp].top() < nodes[x].cntdis){que[temp].pop();}nodes[x].ans = que[temp].size();que[temp].push(nodes[x].dis + nodes[x].cntdis);return temp;}//nodes[x].pq = beg;//beg++;//int pqn = beg - 1;int smaxn = 0;//多个儿子int tmpk;for (int i = 0; i < k; i++){dfs(nodes[x].con[i]);tmpk = que[nodes[nodes[x].con[i]].pq].size();if (tmpk > smaxn){smaxn = tmpk;nodes[x].pq = nodes[nodes[x].con[i]].pq;nodes[x].cntdis = nodes[nodes[x].con[i]].cntdis + nodes[x].far[i];}}for (int i = 0; i < k; i++){if (nodes[x].pq == nodes[nodes[x].con[i]].pq){continue;}int spq = nodes[nodes[x].con[i]].pq;long long sdis = nodes[x].far[i];sdis += nodes[nodes[x].con[i]].cntdis;while (!que[spq].empty()){if (que[spq].top() >= sdis){que[nodes[x].pq].push(que[spq].top() - sdis + nodes[x].cntdis);}que[spq].pop();}}while (!que[nodes[x].pq].empty() && que[nodes[x].pq].top() < nodes[x].cntdis){que[nodes[x].pq].pop();}nodes[x].ans = que[nodes[x].pq].size();que[nodes[x].pq].push(nodes[x].dis + nodes[x].cntdis);return nodes[x].pq;}int main(){int n;cin >> n;for (int i = 1; i <= n; i++){scanf("%I64d", &nodes[i].dis);}long long op, far;for (int i = 2; i <= n; i++){scanf("%I64d%I64d", &op, &far);nodes[op].con.push_back(i);nodes[op].far.push_back(far);}dfs(1);for (int i = 1; i <= n; i++){if (i != 1){printf(" ");}printf("%I64d", nodes[i].ans);}cout << "\n";//cin >> n;}
- #Codeforces 381 [div2] D. Alyona and a tree 【树链剖分 + 优先队列】
- Codeforces Round #381 (Div. 2)D. Alyona and a tree
- Codeforces Round #381 (Div. 2) D. Alyona and a tree
- Codeforces Round #381 (Div. 2) D. Alyona and a tree
- 【30.36%】【codeforces 740D】Alyona and a tree
- CodeForces 381 div.2 D. Alyona and a tree dfs序 二分 区间和
- Codeforces Round #381 (Div. 2) D Alyona and a tree(DFS树上搞事)
- Codeforces Round #381 (Div. 2) D. Alyona and a tree 树型前缀和+二分维护
- codeforces 739b Alyona and a tree
- CODEFORCES 739B Alyona and a tree
- Codeforces Round #381 (Div. 2) D. Alyona and a tree dfs+二分+线段树延迟操作、树形化线性
- Codeforces 740D Alyona and a tree 二分+树上差分
- #Codeforces 343 [div2] D. Babaei and Birthday Cake 【线段树优先队列查询优化】
- codeforces 381A. Alyona and copybooks=
- codeforces 739B B. Alyona and a tree
- 解题报告:Codeforces Round #381 (Div. 1)B. Alyona and a tree
- Codeforces Round #381 (Div. 1) B Alyona and a tree 树状数组
- codeforces 721D D. Maxim and Array (STL||优先队列)
- 第13周项目1-Prim的算法验证
- 搭建spring框架的时候,web.xml中的spring相关配置,可以不用配置ContextLoaderListener(即只配DispatcherServlet)吗?
- 第十三周项目1-dijkstra算法
- Java Web项目在Mac系统上启动时提示nodename nor servname provided的解决办法
- ubuntu 防火墙使用
- #Codeforces 381 [div2] D. Alyona and a tree 【树链剖分 + 优先队列】
- Android UI-聊天界面
- tools:context=".MainActivity的作用
- Android Image开源框架之ImageLoader(一)
- 树形DP之自驾旅行
- 【第十三周项目3---Dijkstra算法验证】
- 【Hadoop】Spark2.0.2在Hadoop2.7.3上的安装
- 第十二周 项目4-利用遍历思想求解图问题(3)(4)
- 第13周项目5-拓扑排序算法验证