codeforces 246E(dsu on tree )

链接: http://codeforces.com/problemset/problem/246/E

题意: 现在有一些树,树的节点有一个颜色(用字符串给出) 和他的父亲,父亲如果是0 表明是根节点,然后m次查询,每次查询一个u 和k 问你在u这棵子树上,与u 相距为k的点的颜色个数。

思路:首先应该是用dsu on tree 来解决这个问题, 如果我们把当前询问的u节点当做标准的话,那么在向上回溯的时候肯定是不好转移的,所以直接以根节点作为标准,set 统计颜色个数。然后就是对于节点u,k 我查询深度为k+dep【u】 的set就可以了。有个坑点就是dep[ u ]+k 可能会越界 。

代码:

#include<bits/stdc++.h>

using namespace std;
const int N =1e5+5;

set<int >se[N];
multiset<int >mse[N];
int col[N];
struct node
{
    int k;
    int id;
    int ans;
};
vector< int >ve[N];
vector< node >qu[N];
int n,m;
map<string ,int >mp;
int tot;
int dep[N];
int sz[N];
bool big[N];
node xun[N];

bool cmp1(node a,node b)
{
    return a.id<b.id;
}

void dfs1(int u,int deep)
{
    dep[u]=deep;
    sz[u]=1;
    for(int i=0;i<ve[u].size();i++){
        int v=ve[u][i];
        dfs1(v,deep+1);
        sz[u]+=sz[v];
    }
}

void add(int u,int flag)
{
    int deep=dep[u];
    if(flag==1){
        se[deep].insert(col[u]);
        mse[deep].insert(col[u]);
    }
    else{
        mse[deep].erase(col[u]);
        if(mse[deep].find(col[u])==mse[deep].end()){
            se[deep].erase(col[u]);
        }
    }
    for(int i=0;i<ve[u].size();i++){
        int v=ve[u][i];
        if(big[v]) continue;
        add(v,flag);
    }
}

void dfs(int u,int keep)
{
    int mx=-1,bigc=-1;
    for(int i=0;i<ve[u].size();i++){
        int v=ve[u][i];
        if(sz[v]>mx){
            mx=sz[v];
            bigc=v;
        }
    }
    for(int i=0;i<ve[u].size();i++){
        int v=ve[u][i];
        if(v!=bigc){
            dfs(v,0);
        }
    }
    if(bigc!=-1){
        dfs(bigc,1);
        big[bigc]=1;
    }

    add(u,1);
    // tongji
    for(int i=0;i<qu[u].size();i++){
        int k=qu[u][i].k;
        if(dep[u]+k>1e5) continue;
        qu[u][i].ans=se[dep[u]+k].size();
    }
    if(bigc!=-1){
        big[bigc]=0;
    }
    if(keep==0){
        add(u,-1);
    }
}

int rt[N];
int rttot;

int main()
{
    scanf("%d",&n);
    int fa; string s;
    int r;
    for(int i=1;i<=n;i++){
        cin>>s>>fa;
        if(fa==0){
            rt[++rttot]=i;
        }
        if(mp[s]==0){
            ve[fa].push_back(i);
            col[i]=++tot;
            mp[s]=tot;
        }
        else{
            ve[fa].push_back(i);
            col[i]=mp[s];
        }
    }

    int u,k;
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d %d",&u,&k);
        qu[u].push_back((node){k,i,0});
    }
    for(int i=1;i<=rttot;i++){
        r=rt[i];
        dfs1(r,0);
        dfs(r,0);
    }
    tot=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<qu[i].size();j++){
            xun[++tot]=qu[i][j];
        }
    }

    sort(xun+1,xun+tot+1,cmp1);
    for(int i=1;i<=tot;i++){
        printf("%d\n",xun[i].ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/82657106
今日推荐