[cf contest246] E - Blood Cousins Return

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Polycarpus 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 xx > 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 viki. Help him to learn for each pair viki the number of distinct names among all names of the ki-sons of the man with number vi.

Input

The 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 viki (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.

Output

Print 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.

Examples
input
6pasha 0gerald 1gerald 1valera 2igor 3olesya 151 11 21 33 16 1
output
22010
input
6valera 0valera 1valera 1gerald 0valera 4kolya 471 11 22 12 24 15 16 1
output
1000200

题目大意:给定一棵树,给一些询问询问一个节点x子树里,与x距离为k(k不同)节点的值有多少种。

这里介绍一下dsu on tree这种东西。

这个方法是一种启发式的合并,一般与树剖合用。

思想是暴力思想的优化,与莫队思想类似。而时间复杂度的证明与轻重链(树链剖分)有关。

我先留坑吧。先放一个piano写的贴子。piano

声明一下dsu是一个离线算法,总复杂度一般是O(nlogn)的。要么就乘上一个统计的复杂度。

对于这题,我们主要思考如何统计?

用n个set维护一下就好了。复杂度是O(nlog2n)的。

code:

 #include <cstdio>
 #include <cstring>
 #include <algorithm>
 #include <map>
 #include <set>
 #include <string>
 #include <vector>
 using namespace std;

 ;
 int n,q,co[N];
 int tot,lnk[N],nxt[N],son[N];
 int fa[N],dep[N],siz[N],got[N];
 int skp,cnt[N],ans[N];
 map <string,int> rel;
 set <int> ase[N];
 vector <pair <int,int> > a[N];
 void add (int x,int y) {
     nxt[++tot]=lnk[x],lnk[x]=tot;
     son[tot]=y;
 }
 namespace tcd {
     void dfs_ppw (int x,int p) {
         fa[x]=p,dep[x]=dep[p]+;
         siz[x]=,got[x]=;
         for (int j=lnk[x]; j; j=nxt[j]) {
             if (son[j]==p) continue;
             dfs_ppw(son[j],x);
             siz[x]+=siz[son[j]];
             if (siz[son[j]]>siz[got[x]]) got[x]=son[j];
         }
     }
     void calc (int x,int v) {
         &&x>) ase[dep[x]].insert(co[x]);
         else ase[dep[x]].erase(co[x]);
         for (int j=lnk[x]; j; j=nxt[j]) {
             if (son[j]==fa[x]||son[j]==skp) continue;
             calc(son[j],v);
         }
     }
     void main (int x,bool f) {
         for (int j=lnk[x]; j; j=nxt[j]) {
             if (son[j]==fa[x]||son[j]==got[x]) continue;
             main(son[j],);
         }
         ),skp=got[x];
         calc(x,),skp=;
         ,c; i<a[x].size(); ++i) {
             ) ans[a[x][i].first]=;
             else ans[a[x][i].first]=ase[dep[x]+a[x][i].second].size();
         }
         );
     }
 }
 int main () {
     ; ];
     scanf("%d",&n);
     ; i<=n+; ++i) {
         scanf("%s%d",s,&x),++x;
         if (!rel[s]) rel[s]=++k;
         co[i]=rel[s];
         add(x,i);
     }
     scanf("%d",&q);
     ; i<=q; ++i) {
         scanf("%d%d",&x,&y),++x;
         a[x].push_back(make_pair(i,y));
     }
     dep[]=,siz[]=;
     tcd::dfs_ppw(,);
     tcd::main(,);
     ; i<=q; ++i) {
         printf("%d\n",ans[i]);
     }
     ;
 }

[cf contest246] E - Blood Cousins Return的更多相关文章

  1. Codeforces 246E - Blood Cousins Return (树上启发式合并)

    246E - Blood Cousins Return 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor,每个节点有名字,名字不唯一.多次查询,给出 u k ...

  2. Codeforces 246E Blood Cousins Return(树上启发式合并)

    题目链接 Blood Cousins Return #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) f ...

  3. CF 246E. Blood Cousins Return [dsu on tree STL]

    题意: 一个森林,求k级后代中多少种不同的权值 用set维护每个深度出现的权值 一开始一直在想删除怎么办,后来发现因为当前全局维护的东西里都是当前子树里的,如果要删除那么当前一定是轻儿子,直接清空se ...

  4. codeforces246E Blood Cousins Return

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  5. 热身训练1 Blood Cousins Return

    点此看题 简要题面: 一棵树上有n个节点,每个节点有对应的名字(名字可重复). 每次询问,求深度比$vi$多$ki$的$vi$的儿子中,有多少种名字 分析: Step1: 我们可以懂$DFS$轻松找到 ...

  6. CF 208E - Blood Cousins dfs序+倍增

    208E - Blood Cousins 题目:给出一棵树,问与节点v的第k个祖先相同的节点数有多少个. 分析: 寻找节点v的第k个祖先,这不就是qtree2简化版吗,但是怎么统计该祖先拥有多少个深度 ...

  7. Codeforces 208E - Blood Cousins(树上启发式合并)

    208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...

  8. CF208E Blood Cousins

    Blood Cousins 题目描述 小C喜欢研究族谱,这一天小C拿到了一整张族谱. 小C先要定义一下k-祖先. x的1-祖先指的是x的父亲 x的k-祖先指的是x的(k-1)-祖先的父亲 小C接下来要 ...

  9. CF 208E. Blood Cousins [dsu on tree 倍增]

    题意:给出一个森林,求和一个点有相同k级祖先的点有多少 倍增求父亲然后和上题一样还不用哈希了... #include <iostream> #include <cstdio> ...

随机推荐

  1. Java-对象及变量的并发访问小结

    1)多线程环境下,方法内的变量是线程安全的 2)多个线程同时处理一个实例,这个实例内的变量是不安全的 3)不同线程中注入同一个类的不同实例,实例中的变量是安全的 4)Synchronized获取到的锁 ...

  2. JAVA锁有哪些种类,以及区别(转)

    在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级 ...

  3. Spring的事务

    事务:事务指的是逻辑上的一组操作,这组操作要么都成功,要么都失败. Transaction事务的四大特性ACID: 1.Atomicity原子性 事务的操作要么都成功,要么都不做,只要有一个失败,就会 ...

  4. 作业(更新ing)

    暴政警告 2019.4.19 1.YBT完成 7 道题目(1)广搜 3 道 (2)最短路 4 道 2.写至少 2 篇博客 (据说集中精力,一个上午/下午就能写完) 1.   一个 又一个 球细胞数目 ...

  5. Redis连接池

    package com.lee.utils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; impor ...

  6. RHCSA

     系统管理 redhat 7 破解修改root密码 修改系统主机名 修改系统地址掩码网关 创建系统默认软件仓库 安装系统内核升级 绑定到外部验证服务LDAP.配置 autofs 用户组管理 创建用户组 ...

  7. Oracle错误——tablespace 'XXXX' does not exist

    错误 在使用IMP命令导入Oracle数据的时候,因为导出数据的数据库表空间和导入数据的数据库表空间不同,导致导入数据失败,出现:tablespace 'XXXX' does not exist 在网 ...

  8. 访问github慢的解决方案

    问题描述 打开https://github.com很慢. 解决办法 1.打开文件C:\Windows\System32\drivers\etc\hosts 2.添加如下内容: 151.101.44.2 ...

  9. BASE64加解密

    - JDK 自带 - Commons Codec  地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi - Bou ...

  10. C# 封装SDK 获取摄像头的水平角度和垂直角度

    最近需要做一个C#版本的控制终端,控制摄像头,获取摄像头的水平角度和垂直角度 获取当前摄像头的角度,需要调用一个名为NET_DVR_GetDVRConfig的bool类型的函数 在C++中,函数定义: ...