题目传送门

分析:

喜 闻 乐 见 的虚树

但是建好虚树后的DP也非常的恶心

我们先考虑每个关键点的归哪个点管

先DFS一次计算儿子节点归属父亲

再DFS一次计算父亲节点归属儿子

然后然后我们对于虚树上的每条边计算一下

首先先找到分割点mid

那么向上归属的是红色部分

向下的是绿色部分

对于每条边都算一下就好了

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector> #define maxn 600005
#define INF 1ll<<50 using namespace std; inline int getint()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
} int n;
int fir[maxn],nxt[maxn],to[maxn],cnt;
int f[maxn][21],dpt[maxn],sz[maxn];
int h[maxn],a[maxn];
int bl[maxn],F[maxn],ans[maxn];
int In[maxn],Out[maxn],cur;
int stk[maxn],top;
int pos[maxn],tot; inline bool cmp(int x,int y){return In[x]<In[y];}
inline void newnode(int u,int v)
{to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} inline void dfs(int u,int fa)
{
sz[u]=1;In[u]=++cur;
for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa)
{
f[to[i]][0]=u,dpt[to[i]]=dpt[u]+1;
dfs(to[i],u);
sz[u]+=sz[to[i]];
}
Out[u]=cur;
} inline int LCA(int u,int v)
{
if(dpt[u]<dpt[v])swap(u,v);
int d=dpt[u]-dpt[v];
for(int i=20;~i;i--)if(d&(1<<i))u=f[u][i];
if(u==v)return u;
for(int i=20;~i;i--)if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
return f[u][0];
} inline int getdis(int u,int v)
{return dpt[u]+dpt[v]-2*dpt[LCA(u,v)];} inline void dfs1(int u,int fa)
{
pos[++tot]=u;F[u]=sz[u];
for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa)
{
dfs1(to[i],u);
if(!bl[to[i]])continue;
if(!bl[u]){bl[u]=bl[to[i]];continue;}
int tmp1=getdis(bl[to[i]],u),tmp2=getdis(bl[u],u);
if(tmp1<tmp2||(tmp1==tmp2&&bl[to[i]]<bl[u]))bl[u]=bl[to[i]];
}
} inline void dfs2(int u,int fa)
{
for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa)
{
int tmp1=getdis(bl[u],to[i]),tmp2=getdis(bl[to[i]],to[i]);
if(tmp1<tmp2||(tmp1==tmp2&&bl[u]<bl[to[i]]))bl[to[i]]=bl[u];
dfs2(to[i],u);
}
} inline void solve(int fa,int u)
{
int son=u,mid=u;
for(int i=20;~i;i--)if(dpt[fa]+(1<<i)<dpt[son])son=f[son][i];
F[fa]-=sz[son];
if(bl[fa]==bl[u]){ans[bl[fa]]+=sz[son]-sz[u];return;}
for(int i=20;~i;i--)
{
int tmp=f[mid][i];
if(dpt[tmp]<=dpt[fa])continue;
int tmp1=getdis(tmp,bl[fa]);
int tmp2=getdis(tmp,bl[u]);
if(tmp2<tmp1||(tmp1==tmp2&&bl[u]<bl[fa]))mid=tmp;
}
ans[bl[fa]]+=sz[son]-sz[mid];
ans[bl[u]]+=sz[mid]-sz[u];
} inline void solve()
{
int K=getint();top=0;
int tt=K;
for(int i=1;i<=K;i++)a[i]=h[i]=getint(),bl[h[i]]=h[i];h[++K]=1;
sort(h+1,h+K+1,cmp);
for(int i=K-1;i;i--)h[++K]=LCA(h[i],h[i+1]);
sort(h+1,h+K+1,cmp);K=unique(h+1,h+K+1)-h-1;
stk[++top]=h[1];
for(int i=2;i<=K;i++)
{
while(top&&Out[stk[top]]<In[h[i]])top--;
newnode(stk[top],h[i]);
stk[++top]=h[i];
}
dfs1(h[1],h[1]),dfs2(h[1],h[1]);
for(int i=1;i<=K;i++)
for(int j=fir[pos[i]];j;j=nxt[j])
solve(pos[i],to[j]);
for(int i=1;i<=K;i++)ans[bl[pos[i]]]+=F[pos[i]];
for(int i=1;i<=tt;i++)printf("%d%c",ans[a[i]],(i==tt)?'\n':' ');
for(int i=1;i<=K;i++)F[h[i]]=ans[h[i]]=fir[h[i]]=bl[h[i]]=0;
cnt=tot=0;
} int main()
{
n=getint();
for(int i=1;i<n;i++)
{
int u=getint(),v=getint();
newnode(u,v),newnode(v,u);
}
dfs(1,1);
for(int j=1;j<=20;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];
memset(fir,0,sizeof fir);cnt=0;
int m=getint();
while(m--)solve();
}

BZOJ 2648 世界树的更多相关文章

  1. BZOJ 3572 世界树

    Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持 ...

  2. BZOJ 2648: SJY摆棋子

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2968  Solved: 1011[Submit][Status][Disc ...

  3. BZOJ 2648: SJY摆棋子 kdtree

    2648: SJY摆棋子 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2648 Description 这天,SJY显得无聊.在家自己玩 ...

  4. BZOJ 2648/2716(SJY把件-KD_Tree)[Template:KD_Tree]

    2648: SJY把件 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1180  Solved: 391 [id=2648" style= ...

  5. kd-tree注解 &amp; bzoj 2648 &amp; 2716 &amp; 3053 解决问题的方法

    [KD-TREE简介]于SYC1999大神"迷住"下一个.我开始接触这样的算法. 首先.这个概念大概能去百度百科.详细的实施.我在看RZZ的代码长大的. 我们能够想象在平面上有N个 ...

  6. BZOJ 2648 SJY摆棋子(KD Tree)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2648 题意: 思路: KDtree模板题. 参考自http://www.cnblogs.com/ra ...

  7. bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree

    2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,S ...

  8. BZOJ 2648 kd-tree模板

    学习了一下kd-tree的基本写法 http://blog.csdn.net/jiangshibiao/article/details/34144829 配合 http://www.bilibili. ...

  9. bzoj 2648 SJY摆棋子——KDtree

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 第一道KDtree! 学习资料:https://blog.csdn.net/zhl30 ...

随机推荐

  1. Codeforces Round #524 (Div. 2) codeforces 1080A~1080F

    目录 codeforces1080A codeforces 1080B codeforces 1080C codeforces 1080D codeforces 1080E codeforces 10 ...

  2. .NET进阶篇07-.NET和COM

    知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂 内容目录 一.COM和.NET元数据内存管理接口注册线程编组二..NET客户端调用COM组件三.COM客户端调用.NET组件四.嵌入互操作类型五 ...

  3. EasyUI清空combotree下拉框图标

    代码: //清空combotree下拉框图标 $(".tree-icon,.tree-file").removeClass("tree-icon tree-file&qu ...

  4. centos7搭建hadoop2.10伪分布模式

    1.准备一台Vmware虚拟机,添加hdfs用户及用户组,配置网络见 https://www.cnblogs.com/qixing/p/11396835.html 在root用户下 添加hdfs用户, ...

  5. 程序员必须掌握的性能调优 X Y Z

    热评博文:<如何设计出优美的Web API?>,现阅读量超 2500,小伙伴们不要错过哦! 2003 ~ 2008 年,这五年老兵哥我在通信行业做实习生和开发岗,主要用 C / C++ / ...

  6. Java操作Jxl实现导出数据生成Excel表格数据文件

    实现:前台用的框架是Easyui+Bootstrap结合使用,需要引入相应的Js.Css文件.页面:Jsp.拦截请求:Servlet.逻辑处理:ClassBean.数据库:SQLserver. 注意: ...

  7. 从零开始のcocos2dx生活(九)CCBReader

    NodeLoaderLibrary是用来存储节点加载器类型的类,通过registerDefaultNodeLoaders()可以注册所有默认类型的加载器 在CocosBuilder的使用手册中: 1. ...

  8. 「Vijos 1283」「OIBH杯NOIP2006第二次模拟赛」佳佳的魔杖

    佳佳的魔杖 背景 配制成功了珍贵的0号药水,MM的病治好了.轻松下来的佳佳意外的得到了一个好东西--那就是--一种非常珍贵的树枝.这些树枝可以用来做优质的魔杖!当然了,不能只做自己的,至少还要考虑到M ...

  9. c语言中自定义bool类型模板

    首先,c语言中没有bool类型,只有c++中有,所以需要自定义,即c中表示bool类型的方法: 1.模板1 typedef int bool; #define false 0 #define true ...

  10. 1035 插入与归并 (25 分)C语言

    根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序. 归并排序进行如下迭 ...