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; }