BZOJ 3351: [ioi2009]Regions

对于一个询问(x,y)对y出现次数分类,若<=lim,在儿子处统计答案,若>lim则y的种类肯定<lim,在祖先处统计(仿佛要去重?但是没去重也过了,那个时限仿佛怎么做都能过)

#include<cstdio>
#include<algorithm>
#include<vector>
#define pr pair<int,int>
#define mp make_pair
#define fr first
#define sc second
using namespace std;
int cnt,last[1000005],Sum[1000005],c[1000005],sz[1000005];
long long ANS[1000005];
vector<pr> vec1[1000005],vec2[1000005];
struct node{
	int to,next;
}e[1000005];
void add(int a,int b){
	e[++cnt].to=b;
	e[cnt].next=last[a];
	last[a]=cnt;
}
void solve1(int x,int fa){
	for (int i=0; i<(int)vec1[c[x]].size(); i++){
		pr q=vec1[c[x]][i];
		ANS[q.fr]+=Sum[q.sc];
	}
	Sum[c[x]]++;
	for (int i=last[x]; i; i=e[i].next){
		int V=e[i].to;
		if (V==fa) continue;
		solve1(V,x);
	}
	Sum[c[x]]--;
}
void solve2(int x,int fa){
	Sum[c[x]]++;
	for (int i=0; i<(int)vec2[c[x]].size(); i++){
		pr q=vec2[c[x]][i];
		ANS[q.fr]-=Sum[q.sc];
	}
	for (int i=last[x]; i; i=e[i].next){
		int V=e[i].to;
		if (V==fa) continue;
		solve2(V,x);
	}
	for (int i=0; i<(int)vec2[c[x]].size(); i++){
		pr q=vec2[c[x]][i];
		ANS[q.fr]+=Sum[q.sc];
	}
}
int main(){
	int n,R,q;
	scanf("%d%d%d",&n,&R,&q);
	scanf("%d",&c[1]);
	sz[c[1]]++;
	int lim=500;
	for (int i=2; i<=n; i++){
		int x;
		scanf("%d%d",&x,&c[i]);
		sz[c[i]]++;
		add(x,i);
		add(i,x);
	}
	for (int i=1; i<=q; i++){
		int X,Y;
		scanf("%d%d",&X,&Y);
		if (sz[Y]<=lim) vec1[Y].push_back(mp(i,X));
		else vec2[X].push_back(mp(i,Y));
	}
	solve1(1,0);
	solve2(1,0);
	for (int i=1; i<=q; i++) printf("%lld\n",ANS[i]);
	return 0;
}

  

posted @ 2018-10-24 14:49  ~Silent  阅读(294)  评论(0编辑  收藏  举报
Live2D