[CF1076E] Vasya and a Tree

这道题正解是KD-Tree或者一个奇妙的递归思路。因为我太菜了,这里只能提供一种部分分做法。
首先对树进行dfs,对于每个节点(u),维护出其dfs序和深度,这里用(dfn_u)表示其dfs序,(dep_u)表示其深度,(end_u)表示离开子树的时间((end_u = dfn_u + siz_u))。
对一个节点的d级子树进行修改,其实就是找到所有节点(v),满足(dfn_u leq dfn_v leq end_u)以及(dep_u leq dep_v leq dep_u + d)。那么我们不妨将每个节点用一个二元组((dfn_u,dep_u))表示,在平面内,每次修改相当于是找到一个左下角是((dfn_u,dep_u)),右上角是((end_u,dep_u + d))的矩形,将这个矩形内部所有点加上一个权值。而我因为不会KD-Tree,只好用二维树状数组维护,但是这里的空间复杂度高达(O(n imes maxdep)),如果树较为平衡则可过,但是若树退化成一条链则这个算法会爆空间。
放一个部分分代码随便搞搞qwq。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<iostream>
#include<queue>
#include<cctype>
using namespace std;
 
#define A(x) cout << #x << " " << x << endl;
#define AA(x,y) cout << #x << " " << x << #y << " " << y << endl;
#define B cout << "Break" << endl;
#define ll long long
#define inf 1000000000
 
int read()
{
	int c = getchar();
	int x = 0,f = 1;
	while(!isdigit(c))
	{
		if(c == '-') f = -1;
		c = getchar();
	}
	while(isdigit(c))
	{
		x = x * 10 + c - '0';
		c = getchar();
	}
	return f * x;
}
#define N 300010
vector<int>g[N];
int dfn[N],dep[N],til[N];
int n,m,maxdep,tim;
void dfs(int u,int fa)
{
	dfn[u] = ++tim;
	dep[u] = dep[fa] + 1;
	maxdep = max(dep[u],maxdep);
	for(auto v : g[u])
	{
		if(v == fa) continue;
		dfs(v,u);
	}
	til[u] = tim;
	return;
}
int c[N][250];
int lowbit(int x)
{
	return x & -x;
}
void Add(int x,int y,int k)
{
	for(int i = x;i <= n;i += lowbit(i))
		for(int j = y;j <= maxdep;j += lowbit(j))
			c[i][j] += k;
	return;
}
void add(int xa,int ya,int xb,int yb,int k)
{
	Add(xa,ya,k);
	Add(xa,yb + 1,-k);
	Add(xb + 1,ya,-k);
	Add(xb + 1,yb + 1,k);
	return;
}
int query(int x,int y)
{
	int ret = 0;
	for(int i = x;i > 0;i -= lowbit(i))
		for(int j = y;j > 0;j -= lowbit(j))
			ret += c[i][j];
	return ret;
}
int main()
{
	n = read();
	for(int i = 1;i < n;++i)
	{
		int u = read(),v = read();
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,0);
	m = read();
	while(m--)
	{
		int u = read(),d = read(),k = read();
		add(dfn[u],dep[u],til[u],dep[u] + d,k);
	}
	for(int i = 1;i <= n;++i)
	{
		printf("%d ",query(dfn[i],dep[i]));
	}
}
原文地址:https://www.cnblogs.com/lijilai-oi/p/12409595.html