树上启发式合并 #1 MLE求助
查看原帖
树上启发式合并 #1 MLE求助
487885
C某某是个人楼主2024/7/1 09:25
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;

const int N = 5e5+10;

int n, m;
unordered_map<int, int> cnt[N], ch, hay, dpth, odd;
vector<int> g[N], q[N], qes;
queue<int> ans[N];

int dfs(int u, int p, int d)
{
	int h = 1, mx = 0, mx_v = 0;
	dpth[u] = d;
	for(int i = 0; i < g[u].size(); i++)
	{
		int v = g[u][i];
		if(v == p) continue;
		int hv = dfs(v, u, d+1);
		if(hv > mx)
		{
			mx = hv;
			mx_v = v;
		}
		h += hv;
	}
	hay[u] = mx_v;
	return h;
}

void update(int u, int p, int k)
{
	cnt[dpth[u]][ch[u]] += k;
	if(cnt[dpth[u]][ch[u]] % 2) ++odd[dpth[u]];
	else --odd[dpth[u]];
	for(int i = 0; i < g[u].size(); i++)
	{
		int v = g[u][i];
		if(v == p) continue;
		update(v, u, k);
	}
}

void dot(int u, int p, int cl)
{
	for(int i = 0; i < g[u].size(); i++)
	{
		int v = g[u][i];
		if(v == p || v == hay[u]) continue;
		dot(v, u, 1);
	}
	if(hay[u]) dot(hay[u], u, 0);
	if(++cnt[dpth[u]][ch[u]] % 2) ++odd[dpth[u]];
	else --odd[dpth[u]];
	for(int i = 0; i < g[u].size(); i++)
	{
		int v = g[u][i];
		if(v == p || v == hay[u]) continue;
		update(v, u, 1);
	}
	for(int i = 0; i < q[u].size(); i++)
	{
		if(odd[q[u][i]] > 1) ans[u].push(0);
		else ans[u].push(1);
	}
	if(cl) update(u, p, -1);
}

int main()
{
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> n >> m;
	for(int i = 2; i <= n; i++)
	{
		int t;
		cin >> t;
		g[i].push_back(t);
		g[t].push_back(i);
	}
	for(int i = 1; i <= n; i++)
	{
		char t;
		cin >> t;
		ch[i] = t;
	}
	dfs(1, -1, 1);
	for(int i = 1; i <= m; i++)
	{
		int a, b;
		cin >> a >> b;
		q[a].push_back(b);
		qes.push_back(a);
	}
	dot(1, -1, 0);
	for(int i = 0; i < qes.size(); i++)
	{
		int tmp = qes[i];
		cout << (ans[tmp].front() ? "Yes\n" : "No\n"); ans[qes[i]].pop();
	}
	return 0;
}
2024/7/1 09:25
加载中...