Codeforces570D Tree Requests
题目链接
题目大意
给定一个以\(1\)为根的n个节点的树,每个点上有一个字母\((a-z)\)
每个点的深度定义为该节点到1号节点路径上的点数.
每次询问 \(a,b\), 查询以 \(a\) 为根的子树内深度为 \(b\) 的节点上的字母重新排列之后是否能构成回文串.
解题思路
重排之后能否构成回文串,即判断出现次数为奇数的字符个数是否小于等于1
因为要多次询问以某个点为根深度为 \(b\) 的节点上的字母
所以可以对每个节点开个 \(vector\) ,再把和它有关的询问保存在\(vector\)里
然后在 \(dsu\) \(on\) \(tree\) 的过程进行到该节点时遍历这个节点的 \(vector\) (相关询问)
再对询问做判断→得到答案→保存答案
最后将保存的答案按照读入的顺序排个序输出即可
AC_Code
#include<bits/stdc++.h>
#define rep(i , a , b) for(int i = a ; i <= b ; i ++)
#define int long long
#define pb push_back
#define fi first
#define se second
using namespace std;
const int N = 5e5 + 10;
struct Edge
{
int nex , to;
} edge[N << 2];
int head[N] , TOT;
void add_edge(int u , int v)
{
edge[++ TOT].nex = head[u];
edge[TOT].to = v;
head[u] = TOT;
}
int cnt[N][26] , hson[N] , sz[N] , HH;
int n , m , col[N] , vis[N];
vector<pair<int ,int>>Q[N] , ans;
void dfs(int u , int far)
{
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == far) continue ;
dfs(v , u);
sz[u] += sz[v];
if(sz[v] > sz[hson[u]]) hson[u] = v;
}
sz[u] ++;
}
void calc(int u , int far , int val , int dep)
{
cnt[dep][col[u]] += val;
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == far || v == HH) continue ;
calc(v , u , val , dep + 1);
}
}
void dsu(int u , int far , int op , int dep)
{
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == hson[u] || v == far) continue ;
dsu(v , u , 0 , dep + 1);
}
if(hson[u]) dsu(hson[u] , u , 1 , dep + 1) , HH = hson[u];
calc(u , far , 1 , dep);
for(auto i : Q[u])
{
int b = i.fi , id = i.se , res = 0;
rep(j , 0 , 25)
{
if(cnt[b][j] & 1) res ++ ;
}
if(res > 1) ans.pb(make_pair(id , 0));
else ans.pb(make_pair(id , 1));
}
HH = 0;
if(!op) calc(u , far , -1 , dep);
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
cin >> n >> m;
rep(i , 2 , n)
{
int v;
cin >> v;
add_edge(i , v) , add_edge(v , i);
}
rep(i , 1 , n)
{
char ch;
cin >> ch;
col[i] = ch - 'a';
}
rep(i , 1 , m)
{
int a , b;
cin >> a >> b;
Q[a].pb(make_pair(b , i));
}
dfs(1 , 0);
dsu(1 , 0 , 0 , 1);
sort(ans.begin() , ans.end());
for(auto i : ans)
if(i.se) cout << "Yes\n" ;
else cout << "No\n";
return 0;
}
凡所不能将我击倒的,都将使我更加强大