Boxes

There are N

boxes, indexed by a number from 1 to N

. Each box may (or not may not) be put into other boxes. These boxes together form a tree structure (or a forest structure, to be precise).

You have to answer a series of queries of the following form: given a list of indices of the boxes, find the total number of boxes that the list of boxes actually contain.

Consider, for example, the following five boxes.

Figure 1: Sample input
  • If the query is the list “1”, then the correct answer is “5”, because box 1 contains all boxes.

  • If the query is the list “4 5”, then the correct answer is “2”, for boxes 4 and 5 contain themselves and nothing else.

  • If the query is the list “3 4”, then the correct answer is “2”.

  • If the query is the list “2 3 4”, then the correct answer is “4”, since box 2 also contains box 5.

  • If the query is the list “2”, then the correct answer is “3”, because box 2 contains itself and two other boxes.

Input

The first line contains the integer N

(1≤N≤200000

), the number of boxes.

The second line contains N

­integers. The ith integer is either the index of the box which contains the ith box, or zero if the i

th box is not contained in any other box.

The third line contains an integer Q

(1≤Q≤100000), the number of queries. The following Q lines will have the following format: on each line, the first integer M (1≤M≤20) is the length of the list of boxes in this query, then M

integers follow, representing the indices of the boxes.

Output

For each query, output a line which contains an integer representing the total number of boxes.

Sample Input 1 Sample Output 1
5
0 1 1 2 2
5
1 1
2 4 5
2 3 4
3 2 3 4
1 2
5
2
2
4
3

【分析】给出N个盒子,其中一些盒子可能会被放进另一些盒子里,Q个询问,每次询问给出M个盒子序号,求这M个盒子包含的盒子总数。

很容易想到这题就是建树,然后求子树的size。关键是如何合并这些点,即判断父子关系。有两种方法,一种是LCA,另一种是维护DFN序,然后区间合并。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
typedef long long ll;
using namespace std;
const int N = 2e5+;
const int M = 1e6+;
int n,m,k,tot=,tim=,ans;
int head[N],vis[N],in[N];
int bg[N],ed[N],sz[N];
vector<int>root;
struct man{
int to,next;
}edg[N*];
void add(int u,int v){
edg[tot].to=v;edg[tot].next=head[u];head[u]=tot++;
in[v]++;
}
void dfs(int u,int fa){
bg[u]=++tim;
sz[u]=;
for(int i=head[u];i!=-;i=edg[i].next){
int v=edg[i].to;
if(v!=fa){
dfs(v,u);
sz[u]+=sz[v];
}
}
ed[u]=tim;
}
int ispre(int u,int v){
if(u==v)return ;
else {
if(bg[u]<=bg[v]&&ed[u]>=ed[v])return ;
else if(bg[u]>=bg[v]&&ed[u]<=ed[v])return -;
}
return ;
}
int main() {
met(head,-);
int u,v;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&v);
if(v)add(v,i);
}
for(int i=;i<=n;i++)if(in[i]==)root.pb(i);
for(int i=;i<root.size();i++){
int rt=root[i];
dfs(rt,);
}
scanf("%d",&m);
vector<int>vec;
while(m--){
scanf("%d",&k);
vec.clear();ans=;
scanf("%d",&u);
vec.pb(u);
for(int i=;i<k;i++){
scanf("%d",&v);
bool f=false;
for(int j=;j<vec.size();j++){
u=vec[j];
if(ispre(u,v)==){
f=true;
break;
}
else if(ispre(u,v)==-){
vec.erase(vec.begin()+j);
j--;
}
}
if(!f)vec.pb(v);
}
for(int i=;i<vec.size();i++){
u=vec[i];
//printf("u : %d sz[u] : %d\n",u,sz[u]);
ans+=sz[u];
}
printf("%d\n",ans);
}
return ;
}

Kattis - boxes (dfn序)的更多相关文章

  1. 洛谷P4689 [Ynoi2016]这是我自己的发明(莫队,树的dfn序,map,容斥原理)

    洛谷题目传送门 具体思路看别的题解吧.这里只提两个可能对常数和代码长度有优化的处理方法. I 把一个询问拆成\(9\)个甚至\(16\)个莫队询问实在是有点珂怕. 发现询问的一边要么是一个区间,要么是 ...

  2. 线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)

    闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...

  3. 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)

    洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...

  4. 树的遍历顺序 - dfs序|欧拉序|dfn序(备忘)

    (仅作备忘) dfs序是dfs过程中对于某节点进入这个节点的子树和离开子树的顺序 满足每个节点都会在dfs序上出现恰好两次 任意子树的dfs序都是连续的 欧拉序是dfs过程中经过节点的顺序 每个节点至 ...

  5. bzoj 3779 重组病毒 好题 LCT+dfn序+线段树分类讨论

    题目大意 1.将x到当前根路径上的所有点染成一种新的颜色: 2.将x到当前根路径上的所有点染成一种新的颜色,并且把这个点设为新的根: 3.查询以x为根的子树中所有点权值的平均值. 分析 原题codec ...

  6. bzoj 2819 Nim dfn序+树状数组维护区间异或值

    题目大意 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...

  7. 51nod 1576 Tree and permutation(树的重心+dfn序)

    乍一看我不会. 先不考虑加点. 先考虑没有那个除\(2\). 考虑每一条边的贡献,假设某一条边把这棵树分成大小为x,y的两个部分. 那么这条边最多可以被使用\(min(x,y)*2\)次(因为有进有出 ...

  8. BZOJ2819 Nim 【dfn序 + lca + 博弈论】

    题目 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略的. ...

  9. Kattis - boxes (LCA)

    Boxes There are NN boxes, indexed by a number from 11 to NN. Each box may (or not may not) be put in ...

随机推荐

  1. HDU 6153 A Secret(扩展KMP模板题)

    A Secret Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others) Total ...

  2. 某ISP的流氓行径 劫持用户HTTP请求插入js代码

    最近公司搞的项目有用户反应点击任意链接后偶尔会跳到一个“莫名奇妙”的网站………… 喏,就是这个咯.

  3. BZOJ_DAY6???

    昨天没睡好啊啊啊,真是要命,睡不着,今天状态爆炸...34题击破. 下一步目标:网络流24题,树链剖分. (洛谷比赛了好开心,希望这次能比以前强吧,嗯)

  4. BZOJ 3270 博物馆 && CodeForces 113D. Museum 期望概率dp 高斯消元

    大前提,把两个点的组合看成一种状态 x 两种思路 O(n^7) f[x]表示在某一个点的前提下,这个状态经过那个点的概率,用相邻的点转移状态,高斯一波就好了 O(n^6) 想象成臭气弹,这个和那个的区 ...

  5. 2017年研究生数学建模D题(前景目标检测)相关论文与实验结果

    一直都想参加下数学建模,通过几个月培训学到一些好的数学思想和方法,今年终于有时间有机会有队友一起参加了研究生数模,but,为啥今年说不培训直接参加国赛,泪目~_~~,然后比赛前也基本没看,直接硬刚.比 ...

  6. 状压dp的题目列表 (一)

    状压dp的典型的例子就是其中某个数值较小. 但是某个数值较小也不一定是状压dp,需要另外区分的一种题目就是用暴力解决的题目,例如UVA818 紫书215 题目列表: ①校长的烦恼 UVA10817 紫 ...

  7. bzoj1575 [Usaco2009 Jan]气象牛Baric

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1575 [题解] 动态规划,令f[i,j]表示前i个选了j个,且第i个必选的最小值. 转移就枚 ...

  8. centos 下构建lamp环境

    构建准备: 1.配置防火墙,开启80端口.3306端口 vi /etc/sysconfig/iptables -A INPUT -m state --state NEW -m tcp -p tcp - ...

  9. DotNETCore 学习笔记 依赖注入和多环境

    Dependency Injection ------------------------------------------------------------------------ ASP.NE ...

  10. Python小程序之sed命令替换

    需求: 编写sed命令脚本 代码如下 # Author:Lee Sir import sys,os des_file = r'E:\StartPython\day3\test.txt' des_fil ...