[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 \times 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]));
    }
}

猜你喜欢

转载自www.cnblogs.com/lijilai-oi/p/12409595.html
今日推荐