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

时间:2022-10-06 06:20:56

官方题解是离线询问,dfs树形转线性,然后二分找区间。

还有一种比较好的做法是直接dfs,将当前访问这个结点u相关的询问之前的状态存起来,然后访问完以后利用异或开关性,得到这颗子树上的答案。

代码是学习别人的http://blog.csdn.net/squee_spoon/article/details/47666667

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5+; char s[maxn]; int head[maxn],to[maxn],nxt[maxn],ecnt; void addEdge(int u,int v)
{
to[ecnt] = v;
nxt[ecnt] = head[u];
head[u] = ecnt++;
} int qhead[maxn],qnxt[maxn]; void init()
{
memset(head,-,sizeof(head));
memset(qhead,-,sizeof(qhead));
} struct Query
{
int h;
int other;
bool ans;
}query[maxn]; void addQuery(int v,int i)
{
qnxt[i] = qhead[v];
qhead[v] = i;
} bool ok(int n)
{
while(n){
if(n&){
return !(n>>);
}
n>>=;
}
return true;
}
int d[maxn];
int cnt[maxn];
void dfs(int u)
{
for(int i = qhead[u]; ~i; i = qnxt[i]){
query[i].other = cnt[query[i].h];
}
cnt[d[u]] ^= (<<(s[u]-'a'));
for(int i = head[u]; ~i; i = nxt[i]){
d[to[i]] = d[u]+;
dfs(to[i]);
}
for(int i = qhead[u]; ~i; i = qnxt[i]){
query[i].ans = ok(cnt[query[i].h]^query[i].other);
}
} int main()
{
init();
int n,m;
scanf("%d%d",&n,&m);
for(int i = ; i <= n; i++){
int fa; scanf("%d",&fa);
addEdge(fa,i);
}
scanf("%s",s+);
for(int i = ; i < m; i++){
int v; scanf("%d%d",&v,&query[i].h);
addQuery(v,i);
}
d[] = ;
dfs();
for(int i = ; i < m; i++){
query[i].ans?puts("Yes"):puts("No");
}
return ;
}