Submission #1137133

#TimeUsernameProblemLanguageResultExecution timeMemory
1137133lucaskojimaRegions (IOI09_regions)C++17
100 / 100
2609 ms112420 KiB
#include "bits/stdc++.h"
#define ff first
#define ss second
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) (int)(x).size()

using namespace std;
using ll = long long;
using pii = pair<int, int>;

const char nl = '\n';
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;

int main() {
	ios::sync_with_stdio(0), cin.tie(0);

	int N, R, Q; cin >> N >> R >> Q;

	vector<vector<int>> adj(N + 1);
	vector<int> reg(N + 1), qnt(R + 1);

	cin >> reg[1];
	qnt[reg[1]]++;

	for (int i = 2; i <= N; i++) {
		int a, b; cin >> a >> b;
		adj[a].push_back(i);
		reg[i] = b;
		qnt[b]++;
	}

	vector<int> large_id(R + 1);
	const int C = N / sqrt(Q);
	int RR = 0;

	for (int i = 1; i <= R; i++)
		if (qnt[i] > C) large_id[i] = ++RR;

	vector dp(N + 1, vector<int>(RR + 1));

	auto dfs = [&](auto dfs, int x) -> void {
		for (int k : adj[x]) {
			dfs(dfs, k);

			dp[x][large_id[reg[k]]]++;
			for (int v = 1; v <= RR; v++)
				dp[x][v] += dp[k][v];
		}
	}; dfs(dfs, 1);

	vector ans(RR + 1, vector<int>(RR + 1));

	for (int i = 1; i <= N; i++)
		for (int j = 1; j <= RR; j++)
			ans[large_id[reg[i]]][j] += dp[i][j];

	vector<vector<int>> emp(R + 1), pre(R + 1), pos(R + 1);
	vector<int> tin(N + 1), tout(N + 1);
	int tcur = 0;

	auto euler = [&](auto euler, int x) -> void {
		tin[x] = ++tcur;
		pre[reg[x]].push_back(tin[x]);
		emp[reg[x]].push_back(x);

		for (int k : adj[x])
			euler(euler, k);

		tout[x] = tcur;
		pos[reg[x]].push_back(tout[x]);
	}; euler(euler, 1);

	// tin[x] <= tin[y] <= tout[x]
	auto query_dec = [&](int i, int l, int r) -> int {
		auto ll = lower_bound(all(pre[i]), l);
		auto rr = upper_bound(all(pre[i]), r);
		return rr - ll;
	};
	auto query_anc = [&](int i, int v) -> int {
		int a = upper_bound(all(pre[i]), v) - pre[i].begin();
		int b = lower_bound(all(pos[i]), v) - pos[i].begin();
		return a - b;
	};

	map<pii, int> memo;

	while (Q--) {
		int a, b; cin >> a >> b;

		if (memo[{a, b}] != 0) {
			cout << memo[{a, b}] << endl;
			continue;
		}

		int rsp = 0;
		if (!large_id[a])
			for (int x : emp[a])
				rsp += query_dec(b, tin[x], tout[x]);
		else if (!large_id[b])
			for (int y : emp[b])
				rsp += query_anc(a, tin[y]);
		else
			rsp = ans[large_id[a]][large_id[b]];

		memo[{a, b}] = rsp;
		cout << rsp << endl;
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...