记录编号 147211 评测结果 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
题目名称 419.[IOI 2009]区域发展 最终得分 100
用户昵称 Asm.Def 是否通过 通过
代码语言 C++ 运行时间 36.921 s
提交时间 2015-01-26 21:37:03 内存使用 8.96 MiB
显示代码纯文本
/*====================Asm.Def========================*/
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <memory.h>
#include <iostream>
#include <vector>
using namespace std;
template <typename T>inline void getd(T &x){
	char ch = getchar();bool neg = 0;
	while(!isdigit(ch) && ch != '-')ch = getchar();
	if(ch == '-')ch = getchar(), neg = 1;
	x = ch - '0';
	while(isdigit(ch = getchar()))x = x * 10 + ch - '0';
	if(neg)x = -x;
}
/*======================================================*/
typedef long long LL;
const int maxn = 200002, maxr = 25002;
unsigned Sq;

struct SegT;
struct Node{
	int color, L, R;
	vector<Node*> son;
	SegT *ans;
	void dfs();
}node[maxn];
vector<int> Set[maxr], data[maxr];
#define pb push_back

struct SegT{//其实是个可持久化数组......我懒得敲Treap了= =
	int len, mid, val;
	SegT *L, *R;
	SegT(){}
	SegT(int l){
		len = l, mid = len >> 1;
		if(len == 1){val = 0;return;}
		L = new SegT(mid), R = new SegT(len - mid);
	}
	SegT(SegT *t){*this = *t;}
	void Add(int i){
		if(len == 1){++val;return;}
		if(i <= mid){
			L = new SegT(L);
			L->Add(i);
		}
		else{
			R = new SegT(R);
			R->Add(i - mid);
		}
	}
	int Query(int i){
		if(len == 1)return val;
		if(i <= mid)return L->Query(i);
		return R->Query(i - mid);
	}
};

#define GetS(color, i) (\
	upper_bound(data[color].begin(), data[color].end(), i) - 1 - data[color].begin()\
)

void Node::dfs(){
	static int iter = 0;
	L = ++iter;
	data[color].pb(iter);
	ans->Add(color);
	vector<Node*>::iterator it;
	for(it = son.begin();it != son.end();++it){
		(*it)->ans = new SegT(ans);
		(*it)->dfs();
	}
	R = iter;
}

int N, R, Q, Ans[700][700], Ind[700], num[maxr], Acnt = 0;

inline void prework(){
	int i, j, r1, r2;
	vector<int>::iterator it;
	static int Sum[maxn];
	for(j = 1;j <= Acnt;++j){
		r2 = Ind[j];
		memset(Sum, 0, sizeof(int) * (N+1));
		for(it = Set[r2].begin();it != Set[r2].end();++it)++Sum[node[*it].L];
		for(i = 1;i <= N;++i)Sum[i] += Sum[i-1];
		for(i = 1;i <= Acnt;++i){
			if(i == j)continue;
			r1 = Ind[i];
			for(it = Set[r1].begin();it != Set[r1].end();++it)
				Ans[i][j] += Sum[node[*it].R] - Sum[node[*it].L];
		}
	}
}

inline int log2(int x){
	int ans = 1;
	while(x)x >>= 1, ++ans;
	return ans;
}

inline void init(){
	int i, p;
	getd(N), getd(R), getd(Q);
	//Sq = (unsigned)sqrt((double)N);
	//Sq = (unsigned)pow(N, 0.3);
	Sq = (unsigned)(N / sqrt((double)Q * log2(N))) + 1;
	getd(node[1].color);
	Set[node[1].color].pb(1);
	for(i = 2;i <= N;++i){
		getd(p);getd(node[i].color);
		(node + p)->son.pb(node + i);
		Set[node[i].color].pb(i);
	}
	for(i = 1;i <= R;++i){
		data[i].pb(0);
		if(Set[i].size() > Sq){Ind[++Acnt] = i;num[i] = Acnt;}
	}
	node[1].ans = new SegT(R);
	node[1].dfs();
	prework();
}

int main(){
	#if defined DEBUG
	freopen("test", "r", stdin);
	freopen("output.txt", "w", stdout);
	#else
	freopen("region.in", "r", stdin);
	freopen("region.out", "w", stdout);
	#endif
	
	init();
	int x, y, ans, indx, indy;
	vector<int>::iterator it;
	while(Q--){
		getd(x), getd(y);
		indx = num[x], indy = num[y];
		if(indx && indy){
			printf("%d\n", Ans[indx][indy]);
			fflush(stdout);
			continue;
		}
		ans = 0;
		if(Set[x].size() <= Set[y].size())for(it = Set[x].begin();it != Set[x].end();++it){
			ans -= GetS(y, node[*it].L);
			ans += GetS(y, node[*it].R);
		}
		else for(it = Set[y].begin();it != Set[y].end();++it)
			ans += node[*it].ans->Query(x);
		printf("%d\n", ans);
		fflush(stdout);
	}
	
	#if defined DEBUG
	cout << endl << (double)clock()/CLOCKS_PER_SEC << endl;
	#endif
	return 0;
}