题目链接:世界树

  首先看到\(\sum m_i\le 3\times 10^5\)这个条件,显然这道题就需要用虚树了。

  在我们构建出虚树之后,就可以用两遍\(dfs\)来求出离每个点最近的议事处了。然后,如果一个点和它在虚树上的父亲所属的议事处不同,那么在原树中的两点之间的路径上就会存在一个分界点,倍增出这个分界点算答案即可。注意不能用路径长度来算,需要使用子树大小。

  然后我们还需要考虑那些不在虚树中的点。我们可以令\(f_x\)表示原树上\(x\)子树中和\(x\)属于同一个议事处的点的个数,那么我们可以把初值赋为\(size_x\),然后减去和它不属于同一个议事处的孩子的\(size\)和这条路径上点的个数即可。然后就可以直接用这个东西和上一部分的贡献一起算出答案了。

  想清楚了细节再写的话还是不难写的。

  下面贴代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
  7. #define maxn 300010
  8.  
  9. using namespace std;
  10. typedef long long llg;
  11.  
  12. int head[maxn],next[maxn<<1],to[maxn<<1],tt;
  13. int fa[maxn][19],dep[maxn],n,m,le[maxn],siz[maxn];
  14. int d[maxn],ld,S[maxn],top,qu[maxn],nu[maxn],lq;
  15. int fr[maxn],fd[maxn],ans[maxn],ji[maxn];
  16.  
  17. int getint(){
  18. int w=0;bool q=0;
  19. char c=getchar();
  20. while((c>'9'||c<'0')&&c!='-') c=getchar();
  21. if(c=='-') c=getchar(),q=1;
  22. while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
  23. return q?-w:w;
  24. }
  25.  
  26. bool cmp(int x,int y){return le[x]<le[y];}
  27. void link(int x,int y){
  28. to[++tt]=y;next[tt]=head[x];head[x]=tt;
  29. to[++tt]=x;next[tt]=head[y];head[y]=tt;
  30. }
  31.  
  32. void dfs(int u,int ff){
  33. fa[u][0]=ff; dep[u]=dep[ff]+1; le[u]=++tt; siz[u]=1;
  34. for(int i=1,now=2;now<dep[u];i++,now<<=1)
  35. fa[u][i]=fa[fa[u][i-1]][i-1];
  36. for(int i=head[u],v;v=to[i],i;i=next[i])
  37. if(v!=ff) dfs(v,u),siz[u]+=siz[v];
  38. }
  39.  
  40. int lca(int x,int y){
  41. if(dep[x]<dep[y]) swap(x,y); int t=1;
  42. for(int now=2;now<dep[x];now<<=1) t++;t--;
  43. for(int i=t;i>=0;i--)
  44. if(dep[fa[x][i]]>=dep[y])
  45. x=fa[x][i];
  46. if(x==y) return x;
  47. for(int i=t;i>=0;i--)
  48. if(fa[x][i]!=fa[y][i])
  49. x=fa[x][i],y=fa[y][i];
  50. return fa[x][0];
  51. }
  52.  
  53. bool pd(int a,int b,int c,int d){return (a<b || (a==b && fr[c]<fr[d]));}
  54. int dis(int x,int y){return dep[x]+dep[y]-(dep[lca(x,y)]<<1);}
  55. int jump(int x,int y){
  56. for(int i=18;i>=0;i--)
  57. if(dep[fa[x][i]]>dep[y]) x=fa[x][i];
  58. return x;
  59. }
  60.  
  61. void solve(int x,int y,int l){
  62. int x1=fd[x],x2=fd[y]+dep[x]-dep[y],u=x;
  63. for(int i=18,v,j=1<<18;i>=0;i--,j>>=1){
  64. v=fa[u][i]; if(dep[v]<=dep[y]) continue;
  65. if(pd(x1+j,x2-j,x,y)) x1+=j,x2-=j,u=fa[u][i];
  66. }
  67. ans[nu[fr[x]]]+=siz[u]-siz[x];
  68. ans[nu[fr[y]]]+=siz[l]-siz[u];
  69. }
  70.  
  71. void dfs1(int u,int ff){
  72. for(int i=head[u],v,x;v=to[i],i;i=next[i])
  73. if(v!=ff){
  74. dfs1(v,u);
  75. if(fr[v] && fd[u]){
  76. x=dis(u,fr[v]);
  77. if(pd(x,fd[u],v,u)) fd[u]=x,fr[u]=fr[v];
  78. }
  79. }
  80. }
  81.  
  82. void dfs2(int u,int ff){
  83. int x; ji[u]=siz[u];
  84. if(ff && fr[ff]!=fr[u]){
  85. x=dis(fr[ff],u);
  86. if(pd(x,fd[u],ff,u)) fd[u]=x,fr[u]=fr[ff];
  87. }
  88. for(int i=head[u],v;v=to[i],i;i=next[i])
  89. if(v!=ff){
  90. dfs2(v,u); x=jump(v,u);
  91. if(fr[v]!=fr[u]) ji[u]-=siz[v]+siz[x]-siz[v];
  92. else ans[nu[fr[u]]]-=ji[v],ji[u]-=siz[v]-ji[v];
  93. }
  94. x=jump(u,ff); ans[nu[fr[u]]]+=ji[u];
  95. if(ff && fr[u]!=fr[ff] && ff!=fa[u][0]) solve(u,ff,x);
  96. }
  97.  
  98. int main(){
  99. File("worldtree");
  100. n=getint();
  101. for(int i=2;i<=n;i++) link(getint(),getint());
  102. tt=0; dfs(1,0); tt=0; m=getint();
  103. for(int i=1;i<=n;i++) head[i]=0,fd[i]=n+1;
  104. while(m--){
  105. lq=getint(); tt=0; d[ld=1]=1;
  106. for(int i=1;i<=lq;i++){
  107. nu[qu[i]=getint()]=i;
  108. fr[qu[i]]=qu[i],fd[qu[i]]=0;
  109. }
  110. sort(qu+1,qu+lq+1,cmp); S[top=1]=1;
  111. for(int i=1,L,x;i<=lq;i++){
  112. x=qu[i]; L=lca(x,S[top]);
  113. while(top){
  114. if(top>1 && dep[S[top-1]]>dep[L]) link(S[top-1],S[top]),top--;
  115. else if(dep[S[top]]>dep[L]){link(L,S[top--]);break;}
  116. else break;
  117. }
  118. if(S[top]!=L) S[++top]=L,d[++ld]=L;
  119. if(x!=1) S[++top]=x,d[++ld]=x;
  120. }
  121. while(top>1) link(S[top-1],S[top]),top--;
  122. dfs1(1,0); dfs2(1,0);
  123. for(int i=1,u;u=d[i],i<=ld;i++) head[u]=fr[u]=0,fd[u]=n+1;
  124. for(int i=1;i<=lq;i++) printf("%d ",ans[i]);
  125. for(int i=1;i<=lq;i++) ans[i]=0;
  126. printf("\n");
  127. }
  128. return 0;
  129. }

BZOJ 3572 【HNOI2014】 世界树的更多相关文章

  1. BZOJ 3572: [Hnoi2014]世界树

    BZOJ 3572: [Hnoi2014]世界树 标签(空格分隔): OI-BZOJ OI-虚数 OI-树形dp OI-倍增 Time Limit: 20 Sec Memory Limit: 512 ...

  2. bzoj 3572: [Hnoi2014]世界树 虚树 && AC500

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 520  Solved: 300[Submit][Status] ...

  3. bzoj 3572 [Hnoi2014]世界树(虚树+DP)

    3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 645  Solved: 362[Submit][Status] ...

  4. bzoj 3572 [Hnoi2014]世界树——虚树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3572 关于虚树:https://www.cnblogs.com/zzqsblog/p/556 ...

  5. BZOJ 3572: [Hnoi2014]世界树 虚树 树形dp

    https://www.lydsy.com/JudgeOnline/problem.php?id=3572 http://hzwer.com/6804.html 写的时候参考了hzwer的代码,不会写 ...

  6. bzoj 3572: [Hnoi2014]世界树 虚树

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

  7. BZOJ 3572 [HNOI2014]世界树 (虚树+DP)

    题面:BZOJ传送门 洛谷传送门 题目大意:略 细节贼多的虚树$DP$ 先考虑只有一次询问的情况 一个节点$x$可能被它子树内的一个到x距离最小的特殊点管辖,还可能被管辖fa[x]的特殊点管辖 跑两次 ...

  8. BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]

    传送门 题意: 一棵树,多次询问,给出$m$个点,求有几个点到给定点最近 写了一晚上... 当然要建虚树了,但是怎么$DP$啊 大爷题解传送门 我们先求出到虚树上某个点最近的关键点 然后枚举所有的边$ ...

  9. 【BZOJ】3572: [Hnoi2014]世界树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3572 算是细节题了吧.. 构出虚树,考虑z正反DP两次求出虚树中每个点最近的议事处是哪一个 ...

  10. 【BZOJ】3572: [Hnoi2014]世界树 虚树+倍增

    [题意]给定n个点的树,m次询问,每次给定ki个特殊点,一个点会被最近的特殊点控制,询问每个特殊点控制多少点.n,m,Σki<=300000. [算法]虚树+倍增 [题解]★参考:thy_asd ...

随机推荐

  1. iOS面试2

    转:http://www.cocoachina.com/ios/20151106/14069.html 作者:seedante 授权本站转载. 题目来自博客:面试百度的记录,有些问题我能回答一下,不能 ...

  2. 根据Uri获取图片绝对路径,解决Android4.4以上版本Uri转换

    转:http://blog.csdn.net/q445697127/article/details/40537945 /** * 根据Uri获取图片绝对路径,解决Android4.4以上版本Uri转换 ...

  3. Docker容器之Nginx

    一,pull一个Nginx镜像 docker pull nginx 二,Nginx镜像文件说明 配置文件 /etc/nginx/nginx.conf 网站根目录 /usr/share/nginx/ht ...

  4. Instagram 架构分析笔记(转)

    原文:http://dbanotes.net/?s=Instagram+%E6%9E%B6%E6%9E%84%E5%88%86%E6%9E%90%E7%AC%94%E8%AE%B0 作者:冯大辉 In ...

  5. 【抓包】火狐浏览器F12

    页面请求服务器的get.post两种请求,还有其他种,但是其他中基本不用,所以只记住get和post两种请求方法即可. 1.get(当前页面向服务器传值--即请求服务器)---弊端--传值长度有限 F ...

  6. mysql 数据操作 单表查询 group by 聚合函数 没有group by情况下

    聚合函数只能用在组里使用 #没有group by 则默认算作一组 取出所有员工的最高工资 mysql> select max(salary) from employee; +---------- ...

  7. python初识(二)

    目录: 进制 基本数据类型 整形 布尔值 字符串 列表 元祖 字典 集合 range & enumerate 一.进制 二进制转换十进制计算: 十进制:==47 一个字节公式:==128 64 ...

  8. unittest框架(一)用例管理

    在unittest框架的自动化接口测试中,可以用yaml文件来管理用例,这样一方面,不会像excel管理用例那么死板:另一方面,数据读取出来就是一个字典,便于取值,用起来更灵活. 首先,需要安装一个模 ...

  9. 【译】Using Objects to Organize Your Code

    耗了一个晚上吐血翻译不过也学到了不少...<使用对象来组织你的代码>,翻译中发现原作者在原文中有部分代码有误或不全,本文已修改和添加~ 丽贝卡·墨菲原文链接:http://rmurphey ...

  10. PAT 1112 Stucked Keyboard[比较]

    1112 Stucked Keyboard(20 分) On a broken keyboard, some of the keys are always stucked. So when you t ...