atcoder-ABC-202 - E - Count Descendants子树中距离根为D的点

atcoder-ABC-202 - E - Count Descendants子树中距离根为D的点

题目链接

题目大意

找到 u i u_i ui的子树中距离根(即1号点)为 d i d_i di的点的数量

思路

首先, n , q ≤ 2 ∗ 1 0 5 n,q\leq2*10^5 n,q2105我们不可以直接暴力去做,不然 T L E TLE TLE会追你5条街,所以我就想到了:我们在遍历树的过程中,可以很轻松的求出到点1距离相等的点的个数。

那我们就可以在每一个点 x x x开一个数组来存储点 x x x的子树内到点1距离相等的数的个数,即 t r e e i , j tree_{i,j} treei,j表示 i i i的子树内,到点1距离为 j j j的点的个数。但是啊, T L E TLE TLE旁边的 M L E MLE MLE二话不说就对我的代码十分感兴趣,那我们在化简一下思路。

我们可以先输入所有的 d i d_i di,这样的话我们就可以用 m a p map map类型的 t r e e i tree_i treei只记录距离 d i d_i di的点的个数。但如果每个 d i d_i di互不相同,那 M L E MLE MLE又可以快乐的找到我们了。

为躲避 M L E MLE MLE,我们再深入一下。既然我们都先输入了,那我们可以利用一些前缀和思想。

我们第一访问这个点的时候,把这个点要求的 d i d_i di远的点的个数从 t r e e 1 , d i tree_{1,d_i} tree1,di里拷贝一份,即 t r e e u i , d i = t r e e 1 , d i tree_{u_i,d_i}=tree_{1,d_i} treeui,di=tree1,di,这个时候的 t r e e u i , d i tree_{u_i,d_i} treeui,di是不包括 u i u_i ui的子树的点到点1距离 d i d_i di的点的个数。

等这一个点的儿子访问完以后,我们的 t r e e 1 , d i tree_{1,d_i} tree1,di就可以把这一棵子树里的点到点1距离是 d i d_i di的点的个数加入。

因为我们之前存下来的 t r e e u i , d i tree_{u_i,d_i} treeui,di是不包括这一棵子树的点到点1距离为 d i d_i di的点的个数,所以我们使 t r e e u i , d i = t r e e 1 , d i − t r e e u i , d i tree_{u_i,d_i}=tree_{1,d_i}-tree_{u_i,d_i} treeui,di=tree1,ditreeui,di, 即包括这一棵子树的点到点1距离为 d i d_i di的点的个数 减去 不包括这一棵子树的点到点1距离为 d i d_i di的点的个数 ,就可以得到真正的 t r e e u i , d i tree_{u_i,d_i} treeui,di

然后就可以输出了,啊哈哈哈,我的任务完成了。

CODE

#include<bits/stdc++.h>
using namespace std;

#define ll long long

const int maxn=1e6*2+5;

int n,m;
int dis[maxn],ns[maxn],nq[maxn],u[maxn],d[maxn];

bool vis[maxn],cis[maxn];

map<int,int>tree[maxn];
map<int,int>v[maxn];

vector<int>son[maxn];
vector<int>qt[maxn];

void dfs(int x)
{
    int i;
    // cout<<x<<endl;
    cis[x]=1;
    for(i=0;i<nq[x];i++)
    {
        if(dis[x]<=qt[x][i])
        {
            tree[x][qt[x][i]]=tree[1][qt[x][i]];
        }
    }
    if(vis[dis[x]]==1) tree[1][dis[x]]++;
    for(i=0;i<ns[x];i++)
    {
        if(!cis[son[x][i]])
        {
            dis[son[x][i]]=dis[x]+1;
            dfs(son[x][i]);
        }
    }
    if(x!=1)
    {
        for(i=0;i<nq[x];i++)
        {
            if(dis[x]<=qt[x][i])
            {
                tree[x][qt[x][i]]=tree[1][qt[x][i]]-tree[x][qt[x][i]];
            }
        }
    }
    return ;
}

int main()
{
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        son[x].push_back(i);
        ns[x]++;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&u[i],&d[i]);
        if(!v[u[i]][d[i]])
        {
            v[u[i]][d[i]]=1;
            qt[u[i]].push_back(d[i]);
            nq[u[i]]++;
            vis[d[i]]=1;
        }
    }
    dfs(1);
    for(int i=1;i<=m;i++)
    {
        printf("%d\n",tree[u[i]][d[i]]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在python-gitlab v3.14.0中,可以使用`group.descendants`方法获取指定组的所有后代子组。该方法的参数如下: ```python group.descendants(all=False, per_page=None, page=None) ``` 其中,`all`参数表示是否获取所有的后代子组,默认为`False`,表示只获取直接子组;`per_page`参数表示每页返回的子组数量,默认为`None`,表示使用 GitLab 默认的每页数量;`page`参数表示返回的页数,默认为`None`,表示返回第一页的数据。 例如,要获取ID为1的组的所有后代子组,可以使用以下代码: ```python group = gl.groups.get(1) descendants = group.descendants(all=True) ``` 此外,还可以使用`group.subgroups`方法获取指定组的直接子组。该方法的参数与`group.descendants`方法相同。例如,要获取ID为1的组的直接子组,可以使用以下代码: ```python group = gl.groups.get(1) subgroups = group.subgroups() ``` 另外,还可以使用`group.create_subgroup`方法创建一个新的子组。该方法的参数如下: ```python group.create_subgroup(name, path=None, **kwargs) ``` 其中,`name`参数表示子组的名称,`path`参数表示子组的路径,默认为`None`,表示与名称相同;`**kwargs`表示其他可选参数,包括描述、可见性、LFS启用状态等等。例如,要在ID为1的组下创建一个名为"Subgroup 1"的子组,可以使用以下代码: ```python group = gl.groups.get(1) subgroup = group.create_subgroup('Subgroup 1') ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值