标签:display turn 第一个 return eve sum swap 关系 宇宙
时间限制: 2000 ms 内存限制: 131072 KB
【题目描述】
公元2044年,人类将进入宇宙纪元。L国有n个星球,分别编号为1到n,每一星球上有一个球长。
因为历史的长期积淀,第i个星球上还有一位编号为i的德高望重的长者,因为长者德高望重,所以第i个星球的球长一定被第i位长者管辖且长者管辖自己。
每一位长者手里有一份名单Bi,上面记录着一些长者的编号。
因为一些奥妙重重的原因,第i位长者的名单上只可能有1至i-1中的一些编号并且保证不会重复。
因为长者都德高望重,所以第i位长者管辖第j位长者的充要条件是:对于每一个k属于Bi,第k位长者管辖第j位长者。
此时,有一位记者想对一些球长进行采访,为了保证采访顺利,他决定先与一些长者搞好关系,以便采访被这些长者管辖的球长。
为了与更多的球长谈笑风生,这位记者会给你提出m个询问。
第i个询问中记者会给你fi个长者的编号,你需要回答有多少个星球的球长至少直接或间接被一位长者管辖。m≤2000000 。
【输入】
第一行一个数n,表示星球的个数。
接下来n行,每一行描述一个Bi:首先给出Bi的大小szi(可能为0),接下来szi个数,描述Bi中的每一个元素。保证Bi中的数没有重复。
接下来一行,给出一个数m,表示询问的个数。
接下来m行,每一行描述一个询问:格式同上文对于集合Bi的格式。
【输出】
共m行,第i行输出第i次询问的答案。
【输入样例】
7
0
1 1
1 1
1 2
2 2 3
0
2 2 6
3
2 2 3
2 3 5
2 4 5
【输出样例】
3
3
4
【提示】
【样例解释】
对于第一个询问,2、3号长者都管辖1号长者,所以总共有3个球长可以被采访,编号分别为1,2,3。
对于第二个询问,3、5号长者都管辖1号长者,所以总共有3个球长可以被采访,编号分别为1,3,5。
对于第三个询问,4号长者管辖第1、2号长者,所以总共有4个球长可以被采访,编号分别为1,2,4,5。
特别说明:第5号长者没有管辖长者2,因为3∈B5但2不属于B3。但长者4管辖长者2,因为长者管辖自己。
说明:
图中省略了球长,编号代表长者有向边u→v表示u在Bv中
【数据规模及约定】
对于30%的数据,n,m≤100。
对于100%的数据,n,m≤200000,∑|Bi|≤2000000,询问中的∑|szi|≤2000000 。
【题解】
这题关键在于如何建树,发现如果令一个点的所有祖先均被他管辖,则第i个节点应该接到它名单中节点的lca下,因为需要被这些点都管辖。
边建树边倍增,建树复杂度nlogn。
考虑如何回答询问。
发现每个询问就是求给出所有点到根的并的节点数。考虑将所有节点按dfn排序,则将每个节点与其相邻的节点的lca加起来即为答案。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,last[N],size,f[N][20],m,dfn[N],hu[N],dep[N],cnt;
struct pigu
{
int dao,ne;
}a[N<<1];
inline void lingjiebiao(int x,int y)
{
a[++size].dao=y;
a[size].ne=last[x];
last[x]=size;
}
inline int read()
{
int x=0,f=1;
char c=getchar();
while(!isdigit(c)) {if(c==‘-‘) f=-1;c=getchar();}
while(isdigit(c)) {x=(x<<3)+(x<<1)+c-‘0‘;c=getchar();}
return x*f;
}
inline void lian(int x,int y)
{
f[x][0]=y;dep[x]=dep[y]+1;lingjiebiao(y,x);
for(int i=1;f[f[x][i-1]][i-1];i++) f[x][i]=f[f[x][i-1]][i-1];
}
inline int get_lca(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
for(int i=19;i>=0;i--)
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
if(x==y) return x;
for(int i=19;i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
inline void dfs(int now)
{
dfn[now]=++cnt;
for(int i=last[now];i;i=a[i].ne) dfs(a[i].dao);
}
inline bool cmp(int x,int y)
{
return dfn[x]<dfn[y];
}
int main()
{
n=read();
for(int i=1,x;i<=n;i++)
{
x=read();
int lca=0;
if(x) lca=read();
for(int j=1,y;j<=x-1;j++)
{
y=read();
lca=get_lca(lca,y);
}
lian(i,lca);
}
m=read();
dfs(0);
for(int i=1,x;i<=m;i++)
{
x=read();
for(int j=1;j<=x;j++) hu[j]=read();
sort(hu+1,hu+x+1,cmp);
int ans=dep[hu[1]];
for(int j=2;j<=x;j++) ans+=dep[hu[j]]-dep[get_lca(hu[j],hu[j-1])];
cout<<ans<<"\n";
}
}
标签:display turn 第一个 return eve sum swap 关系 宇宙
原文地址:https://www.cnblogs.com/betablewaloot/p/12207941.html