• [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]));
    	}
    }
    
  • 相关阅读:
    ThreadLocal
    mysql查看和修改密码策略
    synchronized双重校验问题
    多线程下双重检查锁的问题及解决方法
    compiler explorer网站
    隐藏表格部分内容,开启宏自动显现
    powershell系列学习笔记二:变量
    强制用户启用宏
    poweshell系列学习笔记一:基础
    Cobalt Strike修改证书
  • 原文地址:https://www.cnblogs.com/lijilai-oi/p/12409595.html
Copyright © 2020-2023  润新知