您的位置:首页 > 其它

BZOJ2851 极限满月

2016-06-13 14:25 369 查看
我们造一颗树,把B集合对应到树上,点i的B集合即为i到根的路径上的所有点,这样在构造点x的B集合的时候就相当于把所有A集合里的点取LCA,然后再LCA下面接上x

询问就相当于求询问点到根的路径并的长度,构虚树,每个点贡献为其深度减去其虚树上父亲的深度,不需要实际构造虚树,只要求出每个点的虚父亲即可

其实可以不用虚树,按dfn排序后所有点的dep减去每个相邻两点的lca的dep即可

有点卡常,加上读入优化就好了

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
char xB[1<<15],*xS=xB,*xT=xB;
#define getc() (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
inline int read(){
char ch=getc();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getc();}
return x*f;
}
struct vec{
int to;
int fro;
};
vec mp[MAXN];
int tai[MAXN],cnt;
int n;
int fa[MAXN][20],dep[MAXN];
int dfn[MAXN],tim;
int m;
int M;
int t[MAXN];
int st[MAXN],tp;
inline void be(int x,int y){
int t,j;
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
dep[y]=dep[x]+1;
for(t=x,j=1;t;j++){
fa[y][j]=t;
t=fa[t][j];
}
}
void dfs(int x){
int i,y;
dfn[x]=++tim;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
dfs(y);
}
}
int lca(int x,int y){
int i;
if(dep[x]<dep[y]){
swap(x,y);
}
for(i=19;i;i--){
if(dep[fa[x][i]]>=dep[y]){
x=fa[x][i];
}
}
for(i=19;i;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return x==y?x:fa[x][1];
}
bool cmp(int x,int y){
return dfn[x]<dfn[y];
}
int main(){
int i,x,y;
n=read();
dep[n+1]=1;
for(i=1;i<=n;i++){
x=read();
int l;
if(x){
l=read();
x--;
while(x--){
y=read();
l=lca(y,l);
}
}else{
l=n+1;
}
be(l,i);
}
dfs(n+1);
m=read();
while(m--){
M=read();
for(i=1;i<=M;i++){
t[i]=read();
}
sort(t+1,t+M+1,cmp);
st[tp=1]=n+1;
int ans=0;
for(i=1;i<=M;i++){
int l=lca(t[i],st[tp]);
while(dep[st[tp]]>dep[l]){
if(dep[st[tp-1]]>dep[l]){
ans+=dep[st[tp]]-dep[st[tp-1]];
}else{
ans+=dep[st[tp]]-dep[l];
}
tp--;
}
if(l!=st[tp]){
st[++tp]=l;
}
st[++tp]=t[i];
}
while(tp>1){
ans+=dep[st[tp]]-dep[st[tp-1]];
tp--;
}
printf("%d\n",ans);
}
return 0;
}

/*
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

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: