Codeforces传送门
洛谷传送门
题目描述
Arkady words in a large company. There are nn employees working in a system of a strict hierarchy. Namely, each employee, with an exception of the CEO, has exactly one immediate manager. The CEO is a manager (through a chain of immediate managers) of all employees.
Each employee has an integer rank. The CEO has rank equal to , each other employee has rank equal to the rank of his immediate manager plus .
Arkady has a good post in the company, however, he feels that he is nobody in the company’s structure, and there are a lot of people who can replace him. He introduced the value of replaceability. Consider an employee and an employee , the latter being manager of aa (not necessarily immediate). Then the replaceability of with respect to is the number of subordinates (not necessarily immediate) of the manager , whose rank is not greater than the rank of . Apart from replaceability, Arkady introduced the value of negligibility. The negligibility of employee aa equals the sum of his replaceabilities with respect to all his managers, i.e. , where the sum is taken over all his managers .
Arkady is interested not only in negligibility of himself, but also in negligibility of all employees in the company. Find the negligibility of each employee for Arkady.
输入输出格式
输入格式:
The first line contains single integer ( ) — the number of employees in the company.
The second line contains integers ( ), where if the -th employee is the CEO, otherwise equals the id of the immediate manager of the employee with id . The employees are numbered from to . It is guaranteed that there is exactly one among these values, and also that the CEO is a manager (not necessarily immediate) for all the other employees.
输出格式:
Print integers — the negligibilities of all employees in the order of their ids: .
输入输出样例
输入样例#1:
4
0 1 2 1
输出样例#1:
0 2 4 2
输入样例#2:
5
2 3 4 5 0
输出样例#2:
10 6 3 1 0
输入样例#3:
5
0 1 1 1 3
输出样例#3:
0 3 3 3 5
说明
Consider the first example:
- The CEO has no managers, thus .
- (employees and suit the conditions, employee has too large rank). Thus .
- Similarly,$ z_{4}=r(4,1)=2$ .
- (employee is a subordinate of and has suitable rank). (employees , , suit the conditions). Thus .
题目大意
给你一棵有根树, 设 为 的祖先节点, 表示在 子树中不超过 深度的点的个数(不包括 自己), 求对于所有点的 。
解题分析
很容易发现每个点 对于其他点 ( )的贡献就是 , 所以将所有点按深度从小到大排序, 每次处理同一深度的点, 在其到根节点的路径上区间 , 然后查询其到根节点的路径上的权值和即可, 总复杂度 , 卡卡常就过了。
这里有一种 的做法。我们可以发现 ,那么实际上我们只需要考虑同深度的点之间的贡献。
将同深度的点按 序排序, 那么可以发现对于一个排在第 位的点, 其前面的点从 开始, 它们的 的深度是递增的, 这样我们就可以维护一个单调栈, 维护其 深度, 同时记录数量, 扫过去即可。 最后再将数组翻转过来, 统计从后往前的贡献即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <vector>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 500500
#define ll long long
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
int dot, cnt, root, dc;
int head[MX], dep[MX], fat[MX], son[MX], siz[MX], topf[MX], sta[MX], dp[MX], ct[MX], dfn[MX];
ll ans[MX];
struct Edge {int to, nex;} edge[MX << 1];
IN void add(R int from, R int to) {edge[++cnt] = {to, head[from]}, head[from] = cnt;}
std::vector <int> dat[MX];
bool cmp(R int x, R int y) {return dfn[x] < dfn[y];}
void DFS(R int now)
{
siz[now] = 1; dfn[now] = ++dc;
for (R int i = head[now]; i; i = edge[i].nex)
{
if (edge[i].to == fat[now]) continue;
dep[edge[i].to] = dep[now] + 1;
fat[edge[i].to] = now;
DFS(edge[i].to);
siz[now] += siz[edge[i].to];
if (siz[edge[i].to] > siz[son[now]]) son[now] = edge[i].to;
}
}
void DFS(R int now, R int grand)
{
topf[now] = grand;
if (!son[now]) return;
DFS(son[now], grand);
for (R int i = head[now]; i; i = edge[i].nex)
{
if (edge[i].to == fat[now] || edge[i].to == son[now]) continue;
DFS(edge[i].to, edge[i].to);
}
}
IN int query(R int x, R int y)
{
W (topf[x] ^ topf[y])
{
if (dep[topf[x]] < dep[topf[y]]) std::swap(x, y);
x = fat[topf[x]];
}
return dep[x] < dep[y] ? x : y;
}
IN void solve(R int d)
{
ll res = 0;
R int top, lca, now;
for (R int i = 0; i < dat[d].size(); ++i)
{
now = dat[d][i];
if (!i) sta[top = 1] = now, dp[1] = ct[1] = 0;
else
{
W (233)
{
lca = query(sta[top], now);
if (dep[lca] >= dp[top])
{
sta[++top] = now;
dp[top] = dep[lca] + 1;
ct[top] = i; break;
}
res -= 1ll * (ct[top] - ct[top - 1]) * dp[top];
--top;
}
res += 1ll * (ct[top] - ct[top - 1]) * dp[top];
ans[now] += res;
}
}
}
int main(void)
{
in(dot); int a;
for (R int i = 1; i <= dot; ++i)
{
in(a);
if (!a) root = i;
else add(i, a), add(a, i);
}
DFS(root), DFS(root, root);
for (R int i = 1; i <= dot; ++i) dat[dep[i]].push_back(i);
for (R int i = 1; i < dot; ++i)
{
if (!dat[i].size()) break;
std::sort(dat[i].begin(), dat[i].end(), cmp);
for (R int j = 0; j < dat[i].size(); ++j) ans[dat[i][j]] += ans[fat[dat[i][j]]] + i;
solve(i); std::reverse(dat[i].begin(), dat[i].end());
solve(i);
}
for (R int i = 1; i <= dot; ++i) printf("%I64d ", ans[i]);
}