Kattis

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.

includegraphics[width=0.5	extwidth ]{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

(1N200000

), 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

(1Q100000), the number of queries. The following Q lines will have the following format: on each line, the first integer M (1M20) 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 1Sample 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+10;
const int M = 1e6+10;
int n,m,k,tot=0,tim=0,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*2];
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]=1;
    for(int i=head[u];i!=-1;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 1;
    else {
        if(bg[u]<=bg[v]&&ed[u]>=ed[v])return 1;
        else if(bg[u]>=bg[v]&&ed[u]<=ed[v])return -1;
    }
    return 0;
}
int main() {
    met(head,-1);
    int u,v;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&v);
        if(v)add(v,i);
    }
    for(int i=1;i<=n;i++)if(in[i]==0)root.pb(i);
    for(int i=0;i<root.size();i++){
        int rt=root[i];
        dfs(rt,0);
    }
    scanf("%d",&m);
    vector<int>vec;
    while(m--){
        scanf("%d",&k);
        vec.clear();ans=0;
        scanf("%d",&u);
        vec.pb(u);
        for(int i=1;i<k;i++){
            scanf("%d",&v);
            bool f=false;
            for(int j=0;j<vec.size();j++){
                u=vec[j];
                if(ispre(u,v)==1){
                    f=true;
                    break;
                }
                else if(ispre(u,v)==-1){
                    vec.erase(vec.begin()+j);
                    j--;
                }
            }
            if(!f)vec.pb(v);
        }
        for(int i=0;i<vec.size();i++){
            u=vec[i];
            //printf("u : %d  sz[u] : %d
",u,sz[u]);
            ans+=sz[u];
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jianrenfang/p/6478335.html