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. [洛谷P1317]低洼地

    题目大意:一组数,分别表示地平线的高度变化.高度值为整数,相邻高度用直线连接.找出并统计有多少个可能积水的低洼地?(首尾都为0) 题解:求出其中都多少个不严格下降子段和不严格上升子段所夹的位置,即为答 ...

  2. The 13th Zhejiang Provincial Collegiate Programming Contest - D

    The Lucky Week Time Limit: 2 Seconds      Memory Limit: 65536 KB Edward, the headmaster of the Marja ...

  3. 自定义orderBy字母函数

    orderedUsers: function () { var arr = this.users; for (var i = 0; i < arr.length - 1; i++) { for ...

  4. Spring学习--xml 中 Bean 的自动装配

    Spring IOC 容器可以自动装配 Bean. 只要在 <bean> 的 autowire 属性里指定自动装配的模式. byName(根据名称自动装配):必须将目标 Bean 的名称和 ...

  5. 解决在极光推送的时候会出现一个 JPush提示:缺少统计代码

    <span style="font-size:14px;"> @Override protected void onResume(){ super.onResume() ...

  6. 调整文本输入框placeholder的颜色等样式

    input::-webkit-input-placeholder{     color: white !important;}input:-moz-placeholder{    color: whi ...

  7. hive向表格中插入数据并分析语句

    1,---导入mds_imei_month_info ; //最大的动态分区表 set hive.support.concurrency=false; //是否支持并发 ; //each mapper ...

  8. java三

    1,深复制与浅复制 浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. 深复制:被复制对象 ...

  9. Idea导入的工程看不到src等代码

    问题描述: 从其他地方拷贝过来的工程,在本地导入到idea中时,展示如下的页面,里面的其他文件都看不到. 解决办法:(不知道是具体的什么原因引起的) 1. 关闭IDEA, 2.然后删除项目文件夹下的. ...

  10. [BZOJ1982][POJ1740][Spoj 2021]Moving Pebbles|解题报告

    这道题的题意BZ和POJ上的都不大清楚... 大概就是给出n堆石子,以及初始每堆石子的个数 两个玩家交替操作,每个操作可以任意在一堆中取任意多的石子 然后再从这堆里拿若干个石子放到某个当前还存在的堆里 ...