树上差分基础

Eezie and Pie

时间限制: 3000MS
空间限制: 512MB
特判(Special Judge): 否
题目描述
Eezie, a pie maniac, would like to have some pies with her friends on a hot summer day. However, the weather is so hot that she can’t go outdoors and has to call for the delivery service.
The city Eezie lives in can be represented by $N$ nodes connected by $N - 1$ edges, and the city center is node 1. In other words, the city is a rooted tree, root of which is node 1. There are $N$ pie houses in the city, the $i$-th on node $i$. For some reason, a pie house on node $i$ can only deliver its pie to nodes on the simple path from node $i$ to node 1.
Eezie is a bit worried that a pie might lose its flavor during the deliver. After some careful calculation, she decided that a pie from the $i$-th pie house can maintain its flavor if the distance it is delivered does not exceed its flavor-loss-distance $d_i$​. The distance between two nodes on the tree is the number of edges on the simple path between them.
Now, Eezie wants to order some pies for all her friends who live on different nodes of the tree. Therefore, she wants you to calculate for each node how many pie houses can deliver their pie to the node without flavor loss.
输入描述
The first line contains an integer $N(1\le N \le 2\times 10^6)$, representing the number of nodes of the city Eezie lives in.
Each of the next $N - 1$ lines contains two integers $u, v(1\le u,v \le N)$, representing an edge. It is guaranteed that the edges form a tree.
The last line contains $N$ integers $d_1, d_2, \cdots, d_N(0\le d_i \le N)$, representing the maximum travel distances for pies from pie houses.
输出描述
Output $N$ integers in a line, the $i$-th integer representing the answer for node $i$.
样例
输入 复制
10
1 2
2 3
2 4
3 5
4 6
4 7
1 8
8 9
8 10
0 0 1 2 2 5 3 1 0 2
输出 复制
6 6 2 3 1 1 1 2 1 1
来源
2022年牛客第6场


树上差分:
找到i号店和i号店向上d[i]+1个店;然后进行差分操作,每个店操作完之后,进行一遍dfs求前缀和,每个店的val值就是自己加上他的子树,先dfs后操作;


Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 +10;
const int mod = 1e8;
int n;
vector<int> e[N];
int d[N],dep[N],fa[N][26],val[N];
void work(int u,int f) {
	dep[u] = dep[f] + 1;
	fa[u][0] = f;
	for(int i=0; fa[u][i]; i++) fa[u][i+1] = fa[fa[u][i]][i];

	for(auto i:e[u])
		if(i!=f) work(i,u);
}
int getfa(int u,int stp) {
	if(stp > dep[u]-1) return 0;
	if(stp == dep[u]-1) return 1;
	for(int i=25; i>=0; i--)
		if(stp>=(1<<i))
			stp-=(1<<i),u=fa[u][i];

	return u;
}
void dfs(int u,int f) {
	for(auto i:e[u]) {
		if(i!=f) {
			dfs(i,u);
			val[u] += val[i];
		}
	}
}
int main() {
	scanf("%d",&n);
	for(int i=1; i<n; i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for(int i=1; i<=n; i++) scanf("%d",&d[i]);
	work(1,0);
	for(int i=1; i<=n; i++) {
		val[i]++;
		val[getfa(i,d[i]+1)]--;
	}
	dfs(1,0);
	for(int i=1; i<=n; i++)
		printf("%d ",val[i]);
	return 0;
}

/*

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值