《洛谷CF246E Blood Cousins Return》

其实不难但是被char*折磨死了。mp居然用了char*不能统计int。一定要string.

原理:好像两个值虽然相同,但是char*是地址,地址不同也算不同,所以不能判重。

回到正题:

和CF208E Blood Cousins基本一样的思路,只是这里加了个map判重。

然后上dsu on tree。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<string,int> pii;
const int N = 1e5+5;
const int M = 1e5+5;
const LL Mod = 199999;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;
void FRE(){/*freopen("data1.in","r",stdin);
freopen("data1.out","w",stdout);*/}

map<string,int> mp[N];
int n,ssize[N],son[N],Son,dep[N],ans[N],d[N],par[N];
string name[N];
struct Query{int id,d;};
vector<int> G[N];
vector<Query> vec[N];
void dfs(int u,int fa)
{
    ssize[u] = 1,dep[u] = dep[fa]+1;
    for(auto v : G[u])
    {
        dfs(v,u);
        ssize[u] += ssize[v];
        if(ssize[v] > ssize[son[u]]) son[u] = v;
    }
}
void Add_slove(int u)
{
    mp[dep[u]][name[u]]++;
    if(mp[dep[u]][name[u]] == 1) d[dep[u]]++;
    for(auto v : G[u]) if(v != Son) Add_slove(v);
}
void Del_slove(int u)
{
    mp[dep[u]][name[u]]--;
    if(mp[dep[u]][name[u]] == 0) d[dep[u]]--;
    for(auto v : G[u]) if(v != Son) Del_slove(v);
}
void dfs1(int u,int opt)
{
    for(auto v : G[u])
    {
        if(v == son[u]) continue;
        dfs1(v,0);
    }
    if(son[u]) dfs1(son[u],1),Son = son[u];
    Add_slove(u);
    for(auto t : vec[u]) ans[t.id] = d[dep[u]+t.d];
    Son = 0;
    if(opt == 0) Del_slove(u);
}
int main()
{
    n = read();
    for(rg int i = 1;i <= n;++i)
    {
        cin >> name[i] >> par[i];
        if(par[i] == 0) continue;
        G[par[i]].push_back(i);
    }
    int m;m = read();
    for(rg int i = 1;i <= m;++i)
    {
        int v,k;v = read(),k = read();
        vec[v].push_back(Query{i,k});
    }
    for(rg int i = 1;i <= n;++i) if(par[i] == 0) dfs(i,0);
    for(rg int i = 1;i <= n;++i) if(par[i] == 0) dfs1(i,0);
    for(rg int i = 1;i <= m;++i) printf("%d\n",ans[i]);
    system("pause");
}
View Code

那么,这里其实也可以用线段树合并。

对于每个点开n个深度的位置。

然后对于每个节点去维护一个set值。

复杂度nlogn^2。注意的是,直接对节点编号去维护set,不是把set放入结构体。而是直接用set数组。

posted @ 2020-09-04 10:38  levill  阅读(239)  评论(0编辑  收藏  举报