[cf contest246] E - Blood Cousins Return
time limit per test3 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard outputPolycarpus got hold of a family tree. The found tree describes the family relations of n people, numbered from 1 to n. Every person in this tree has at most one direct ancestor. Also, each person in the tree has a name, the names are not necessarily unique.
We call the man with a number a a 1-ancestor of the man with a number b, if the man with a number a is a direct ancestor of the man with a number b.
We call the man with a number a a k-ancestor (k > 1) of the man with a number b, if the man with a number b has a 1-ancestor, and the man with a number a is a (k - 1)-ancestor of the 1-ancestor of the man with a number b.
In the tree the family ties do not form cycles. In other words there isn't a person who is his own direct or indirect ancestor (that is, who is an x-ancestor of himself, for some x, x > 0).
We call a man with a number a the k-son of the man with a number b, if the man with a number b is a k-ancestor of the man with a number a.
Polycarpus is very much interested in how many sons and which sons each person has. He took a piece of paper and wrote m pairs of numbers vi, ki. Help him to learn for each pair vi, ki the number of distinct names among all names of the ki-sons of the man with number vi.
InputThe first line of the input contains a single integer n (1 ≤ n ≤ 105) — the number of people in the tree. Next n lines contain the description of people in the tree. The i-th line contains space-separated string si and integer ri (0 ≤ ri ≤ n), where si is the name of the man with a number i, and ri is either the number of the direct ancestor of the man with a number i or 0, if the man with a number i has no direct ancestor.
The next line contains a single integer m (1 ≤ m ≤ 105) — the number of Polycarpus's records. Next m lines contain space-separated pairs of integers. The i-th line contains integers vi, ki (1 ≤ vi, ki ≤ n).
It is guaranteed that the family relationships do not form cycles. The names of all people are non-empty strings, consisting of no more than 20 lowercase English letters.
OutputPrint m whitespace-separated integers — the answers to Polycarpus's records. Print the answers to the records in the order, in which the records occur in the input.
Examplesinput6
pasha 0
gerald 1
gerald 1
valera 2
igor 3
olesya 1
5
1 1
1 2
1 3
3 1
6 1output2
2
0
1
0input6
valera 0
valera 1
valera 1
gerald 0
valera 4
kolya 4
7
1 1
1 2
2 1
2 2
4 1
5 1
6 1output1
0
0
0
2
0
0
题目大意:给定一棵树,给一些询问询问一个节点x子树里,与x距离为k(k不同)节点的值有多少种。
这里介绍一下dsu on tree这种东西。
这个方法是一种启发式的合并,一般与树剖合用。
思想是暴力思想的优化,与莫队思想类似。而时间复杂度的证明与轻重链(树链剖分)有关。
我先留坑吧。先放一个piano写的贴子。piano
声明一下dsu是一个离线算法,总复杂度一般是O(nlogn)的。要么就乘上一个统计的复杂度。
对于这题,我们主要思考如何统计?
用n个set维护一下就好了。复杂度是O(nlog2n)的。
code:
View Code1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <map> 5 #include <set> 6 #include <string> 7 #include <vector> 8 using namespace std; 9 10 const int N=100005; 11 int n,q,co[N]; 12 int tot,lnk[N],nxt[N],son[N]; 13 int fa[N],dep[N],siz[N],got[N]; 14 int skp,cnt[N],ans[N]; 15 map <string,int> rel; 16 set <int> ase[N]; 17 vector <pair <int,int> > a[N]; 18 void add (int x,int y) { 19 nxt[++tot]=lnk[x],lnk[x]=tot; 20 son[tot]=y; 21 } 22 namespace tcd { 23 void dfs_ppw (int x,int p) { 24 fa[x]=p,dep[x]=dep[p]+1; 25 siz[x]=1,got[x]=0; 26 for (int j=lnk[x]; j; j=nxt[j]) { 27 if (son[j]==p) continue; 28 dfs_ppw(son[j],x); 29 siz[x]+=siz[son[j]]; 30 if (siz[son[j]]>siz[got[x]]) got[x]=son[j]; 31 } 32 } 33 void calc (int x,int v) { 34 if (v>0&&x>1) ase[dep[x]].insert(co[x]); 35 else ase[dep[x]].erase(co[x]); 36 for (int j=lnk[x]; j; j=nxt[j]) { 37 if (son[j]==fa[x]||son[j]==skp) continue; 38 calc(son[j],v); 39 } 40 } 41 void main (int x,bool f) { 42 for (int j=lnk[x]; j; j=nxt[j]) { 43 if (son[j]==fa[x]||son[j]==got[x]) continue; 44 main(son[j],1); 45 } 46 if (got[x]) main(got[x],0),skp=got[x]; 47 calc(x,1),skp=0; 48 for (int i=0,c; i<a[x].size(); ++i) { 49 if (c=dep[x]+a[x][i].second>n+1) ans[a[x][i].first]=0; 50 else ans[a[x][i].first]=ase[dep[x]+a[x][i].second].size(); 51 } 52 if (f) calc(x,-1); 53 } 54 } 55 int main () { 56 int x,y,k=0; char s[40]; 57 scanf("%d",&n); 58 for (int i=2; i<=n+1; ++i) { 59 scanf("%s%d",s,&x),++x; 60 if (!rel[s]) rel[s]=++k; 61 co[i]=rel[s]; 62 add(x,i); 63 } 64 scanf("%d",&q); 65 for (int i=1; i<=q; ++i) { 66 scanf("%d%d",&x,&y),++x; 67 a[x].push_back(make_pair(i,y)); 68 } 69 dep[0]=0,siz[0]=0; 70 tcd::dfs_ppw(1,0); 71 tcd::main(1,1); 72 for (int i=1; i<=q; ++i) { 73 printf("%d\n",ans[i]); 74 } 75 return 0; 76 }