Loading

Codeforces Round #316 (Div. 2) D Tree Requests

Tree Requests

判断 \(V_i\) 的子树中,深度为 \(h_i\) 的结点上所带有的字符,能否组成一个回文串

启发式合并

维护所有深度上不同字符的数量,并且维护其奇数字符出现的次数

如果若干个字符能组成一个回文串,必然有:

  • 偶数个字符,且不出现奇数次数的字符

  • 奇数个字符,只能出现一个奇数次数的字符

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
#define pii pair<int, int>
typedef long long ll;
const int maxn = 1e5 + 10;
vector<int>gra[maxn];
int col[maxn], cnt[maxn], fa[maxn];
int siz[maxn], hson[maxn], ans[maxn];
int L[maxn], R[maxn], tp = 0, rnk[maxn];
int sum[maxn];
vector<pii>qs[maxn];

void dfs1(int now, int pre)
{
    L[now] = ++tp;
    fa[now] = pre;
    siz[now] = 1;
    hson[now] = -1;
    rnk[tp] = now;
    for(int nex : gra[now])
    {
        if(nex == pre) continue;
        dfs1(nex, now);
        siz[now] += siz[nex];
        if(hson[now] == -1 || siz[nex] > siz[hson[now]])
            hson[now] = nex;
    }
    R[now] = tp;
}

inline void add(int now)
{
    cnt[col[now]]++;
    sum[cnt[col[now]]]++;
}

inline void del(int now)
{
    sum[cnt[col[now]]]--;
    cnt[col[now]]--;
}

void dfs2(int now, bool keep)
{
    for(int nex : gra[now])
        if(nex != fa[now] && nex != hson[now]) dfs2(nex, false);
    if(hson[now] != -1) dfs2(hson[now], true);
    for(int nex : gra[now])
    {
        if(nex == fa[now] || nex == hson[now]) continue;
        for(int i=L[nex]; i<=R[nex]; i++)
            add(rnk[i]);
    }
    add(now);
    for(auto [k, id] : qs[now])
        ans[id] = sum[k];
    if(!keep)
    {
        for(int i=L[now]; i<=R[now]; i++)
            del(rnk[i]);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    for(int i=1; i<=n; i++) cin >> col[i];
    for(int i=1; i<n; i++)
    {
        int a, b;
        cin >> a >> b;
        gra[a].push_back(b);
        gra[b].push_back(a);
    }
    for(int i=0; i<m; i++)
    {
        int a, b;
        cin >> a >> b;
        qs[a].push_back({b, i});
    }
    dfs1(1, 1);
    dfs2(1, true);
    for(int i=0; i<m; i++)
        cout << ans[i] << "\n";
    return 0;
}
posted @ 2022-09-19 00:32  dgsvygd  阅读(33)  评论(0编辑  收藏  举报