codeforces570D Tree Requests

题目链接:codeforces570D

正解:$dsu$ $on$ $tree$

解题报告:

  考虑这又是一类子树内的不带修改统计问题,直接上$dsu$ $on$ $tree$好咯。

  直接按上一道题的做法做,类似地存一下每个深度每种字符的出现次数,对于每个点的询问,在每个点处查询一下就好了,只需奇数的个数$<=1$即可。

//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
#include <bitset>
using namespace std;
typedef long long LL;
typedef long double LB;
typedef complex<double> C;
const double pi = acos(-1);
const int MAXN = 500011;
const int MAXM = 1000011;
int n,m,ecnt,first[MAXN],to[MAXM],next[MAXM],Son,ans[MAXN];
int size[MAXN],son[MAXN],deep[MAXN],cnt[MAXN][26];
char ch[MAXN];
struct node{ int x,id; }tmp;
vector<node>w[MAXN];

inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
inline int getint(){
    int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
    if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
}

inline void dfs(int x,int fa){
	size[x]=1;
	for(int i=first[x];i;i=next[i]) {
		int v=to[i]; if(v==fa) continue;
		deep[v]=deep[x]+1;
		dfs(v,x); size[x]+=size[v];
		if(size[v]>size[son[x]]) son[x]=v;
	}
}

inline void add(int x,int fa,int val){
	cnt[ deep[x] ][ ch[x]-'a' ]+=val;
	for(int i=first[x];i;i=next[i]) {
		int v=to[i]; if(v==fa || v==Son) continue;
		add(v,x,val);
	}
}

inline void solve(int x,int fa,bool top){
	for(int i=first[x];i;i=next[i]) {
		int v=to[i]; if(v==fa || v==son[x]) continue;
		solve(v,x,1);
	}
	if(son[x])
		solve(son[x],x,0),Son=son[x];

	add(x,fa,1);
	Son=0;

	//处理在x上的询问
	for(int i=0,ss=w[x].size();i<ss;i++) {
		tmp=w[x][i]; if(tmp.x<deep[x]) { ans[tmp.id]=1; continue; }
		int cc=0,h=tmp.x;
		for(int j=0;j<26;j++) if(cnt[h][j]&1) cc++;
		if(cc>1) ans[tmp.id]=0;
		else ans[tmp.id]=1;
	}

	if(top)
		add(x,fa,-1);
}

inline void work(){
	n=getint(); m=getint();  int x,y;
	for(int i=2;i<=n;i++) { x=getint(); link(x,i); }
	scanf("%s",ch+1);
	deep[1]=1; dfs(1,0);
	for(int i=1;i<=m;i++) { x=getint(); y=getint(); tmp.x=y; tmp.id=i; w[x].push_back(tmp); }
	solve(1,0,1);
	for(int i=1;i<=m;i++)
		if(ans[i]) puts("Yes");
		else puts("No");
}

int main()
{
    work();
    return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。

  

原文地址:https://www.cnblogs.com/ljh2000-jump/p/6529123.html