제출 #660202

#제출 시각아이디문제언어결과실행 시간메모리
660202QwertyPiRegions (IOI09_regions)C++14
75 / 100
8080 ms122312 KiB
#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 11;
const int LGN = 20;
const int R = 2.5e4 + 11;
const int B = 400;
int p[N], r[N];
int tl[N], tr[N], preord[N], cnt[R];
int prec[N / B + 10][R], id[R], ids = 0;
int prec2[R][N / B + 10], id2[R], ids2 = 0;
vector<int> G[N];
vector<int> emp[N];
int n, rn, q;

int ct = 0;
void dfs(int v){
	tl[v] = ++ct; preord[ct] = v;
	for(auto u : G[v]){
		dfs(u);
	}
	tr[v] = ct;
}
void dfs_prec(int Co, int v, int acc = 0){
	for(auto u : G[v]){
		dfs_prec(Co, u, acc + (r[v] == Co));
	}
	prec[id[Co]][r[v]] += acc;
}

int dfs_prec2(int Co, int v){
	int acc = r[v] == Co;
	for(auto u : G[v]){
		acc += dfs_prec2(Co, u);
	}
	prec2[r[v]][id2[Co]] += acc;
	return acc;
}

namespace DS{
	int a[N] = {}, roots[N];
	int t[N * LGN * 8] = {};
	int lch[N * LGN * 8] = {};
	int rch[N * LGN * 8] = {};
	int cc = 0;
	
	int build(int rt, int l, int r){
		if(l == r) return rt;
		int m = (l + r) / 2;
		int lc = build(++cc, l, m);
		int rc = build(++cc, m + 1, r);
		lch[rt] = lc, rch[rt] = rc;
		return rt;
	}

	int add(int qi, int qv, int rt, int l, int r){
		if(l == r) { t[++cc] = t[rt] + qv; return cc; }
		int m = (l + r) / 2;
		if(qi <= m){
			int lc = add(qi, qv, lch[rt], l, m);
			int rc = rch[rt];
			lch[++cc] = lc, rch[cc] = rc;
		}else{
			int lc = lch[rt];
			int rc = add(qi, qv, rch[rt], m + 1, r);
			lch[++cc] = lc, rch[cc] = rc;
		}
		return cc;
	}

	int qry(int qi, int rt, int l, int r){
		if(l == r) return t[rt];
		int m = (l + r) / 2;
		if(qi <= m) return qry(qi, lch[rt], l, m);
		return qry(qi, rch[rt], m + 1, r);
	}
	
	void init(int n){
		for(int i = 1; i <= n; i++){
			a[i] = r[preord[i]];
		}
		roots[0] = build(0, 1, rn);
		for(int i = 1; i <= n; i++){
			roots[i] = add(a[i], 1, roots[i - 1], 1, rn);
		}
	}
};

int qry(int _l, int _r, int v){
	return DS::qry(v, DS::roots[_r], 1, rn) - DS::qry(v, DS::roots[_l - 1], 1, rn);
}

int main() {
	ios_base::sync_with_stdio(false);
	cin >> n >> rn >> q;
	cin >> r[1];
	for(int i = 2; i <= n; i++){
		cin >> p[i] >> r[i];
		G[p[i]].push_back(i);
		cnt[r[i]]++;
	}
	for(int i = 1; i <= n; i++){
		emp[r[i]].push_back(i);
	}
	dfs(1);
	for(int i = 1; i <= rn; i++){
		if(cnt[i] >= B){
			id[i] = ids;
			dfs_prec(i, 1);
			ids++;
		}
	}

	for(int i = 1; i <= rn; i++){
		if(cnt[i] >= B){
			id2[i] = ids2;
			dfs_prec2(i, 1);
			ids2++;
		}
	}
	
	DS::init(n);
	
	for(int i = 0; i < q; i++){
		int r1, r2; cin >> r1 >> r2;
		if(cnt[r1] >= B){
			cout << prec[id[r1]][r2] << endl;
		}else if(cnt[r2] >= B){
			cout << prec2[r1][id2[r2]] << endl;
		}else{
			int ans = 0;
			for(auto i : emp[r1]){
				ans += qry(tl[i], tr[i], r2);
			}
			cout << ans << endl;
		}
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...