反正肯定要建虚树,考虑建完之后怎么做

先随便dp一下算出来距离某点最近的询问点mi[x](因为有的虚树上的点它不是询问点嘛)

那我们对于某条链x到fa[x]上的非虚树上的点(包括他们的非虚树上的孩子),要么把它分给mi[x],要么分给mi[fa[x]]

我找到这个中间点以后,在原树上倍增跳过去,算他的size

这个分法是以$\frac{len[mi[x]]+len[x]+len[mi[fa[x]]]}{2}$再加加减减一些细节决定的(len[x]表示x到fa[x]的链的长度)

除此之外,每个在虚树上的点x(以及它不在虚树上的孩子),都归属于mi[x]

  1. #include<bits/stdc++.h>
  2. #define mp make_pair
  3. #define CLR(a,x) memset(a,x,sizeof(a))
  4. using namespace std;
  5. typedef long long ll;
  6. typedef unsigned long long ull;
  7. typedef pair<int,int> pa;
  8. const int maxn=3e5+,inf=1e9;
  9.  
  10. inline ll rd(){
  11. ll x=;char c=getchar();int neg=;
  12. while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
  13. while(c>=''&&c<='') x=x*+c-'',c=getchar();
  14. return x*neg;
  15. }
  16.  
  17. int N,Q;
  18. int eg[maxn*][],egh[maxn],ect;
  19. int fa[maxn][],dep[maxn],dfn[maxn],tot,siz[maxn];
  20.  
  21. inline void adeg(int a,int b){
  22. eg[++ect][]=b,eg[ect][]=egh[a],egh[a]=ect;
  23. }
  24.  
  25. inline void dfs1(int x){
  26. dfn[x]=++tot;
  27. for(int i=;fa[x][i]&&fa[fa[x][i]][i];i++){
  28. fa[x][i+]=fa[fa[x][i]][i];
  29. }
  30. siz[x]=;
  31. for(int i=egh[x];i;i=eg[i][]){
  32. int b=eg[i][];if(b==fa[x][]) continue;
  33. fa[b][]=x,dep[b]=dep[x]+;
  34. dfs1(b);siz[x]+=siz[b];
  35. }
  36. }
  37.  
  38. inline int jump(int x,int d){
  39. int i=;
  40. while(d){
  41. if(d&) x=fa[x][i];
  42. i++,d>>=;
  43. }return x;
  44. }
  45.  
  46. inline int getlca(int x,int y){
  47. if(dep[x]<dep[y]) swap(x,y);
  48. for(int i=log2(dep[x]-dep[y]);i>=&&dep[x]!=dep[y];i--){
  49. if(dep[fa[x][i]]>=dep[y])
  50. x=fa[x][i];
  51. }
  52. if(x==y) return x;
  53. for(int i=log2(dep[x]);i>=;i--){
  54. if(fa[x][i]!=fa[y][i])
  55. x=fa[x][i],y=fa[y][i];
  56. }
  57. return fa[x][];
  58. }
  59.  
  60. inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
  61.  
  62. int xfa[maxn],xsh[maxn],xbr[maxn];
  63.  
  64. int h[maxn],stk[maxn],hd,len[maxn];
  65. int ans[maxn],id[maxn],pct;
  66. bool rea[maxn];
  67. inline void connect(int x,int y){
  68. // printf("\t\tconnect:%d %d\n",x,y);
  69. xfa[x]=y,xbr[x]=xsh[y],xsh[y]=x,len[x]=dep[x]-dep[y];
  70. }
  71. inline void build(int m){
  72. sort(h+,h+m+,cmp);
  73. stk[hd=]=;id[++pct]=;
  74. for(int i=;i<=m;i++){
  75. rea[h[i]]=;id[++pct]=h[i];
  76. int lca=getlca(stk[hd],h[i]);
  77. int lst=;
  78. while(dfn[stk[hd]]>dfn[lca]){
  79. if(lst) connect(lst,stk[hd]);
  80. lst=stk[hd--];
  81. }if(stk[hd]!=lca) stk[++hd]=lca,id[++pct]=lca;
  82. if(lst) connect(lst,stk[hd]);
  83. if(h[i]!=) stk[++hd]=h[i];
  84. }
  85. while(hd>) connect(stk[hd],stk[hd-]),hd--;
  86. }
  87. pa up[maxn],dw[maxn];
  88. inline void dfs2(int x){
  89. if(rea[x]) dw[x]=mp(,x);
  90. else dw[x]=mp(inf,);
  91. for(int i=xsh[x];i;i=xbr[i]){
  92. dfs2(i);
  93. dw[x]=min(dw[x],mp(dw[i].first+len[i],dw[i].second));
  94. }
  95. }
  96. inline void dfs3(int x){
  97. if(rea[x]) up[x]=mp(,x);
  98. else if(x==) up[x]=mp(inf,);
  99. pa m=mp(inf,),s=mp(inf,);
  100. for(int i=xsh[x];i;i=xbr[i]){
  101. s=min(s,mp(dw[i].first+len[i],dw[i].second));
  102. if(s<m) swap(s,m);
  103. }
  104. for(int i=xsh[x];i;i=xbr[i]){
  105. up[i]=mp(up[x].first+len[i],up[x].second);
  106. if(dw[i].first+len[i]==m.first&&dw[i].second==m.second){
  107. up[i]=min(up[i],mp(s.first+len[i],s.second));
  108. }else up[i]=min(up[i],mp(m.first+len[i],m.second));
  109. dfs3(i);
  110. }
  111. if(x!=){
  112. int n=min(dw[x],up[x]).first+len[x]+min(dw[xfa[x]],up[xfa[x]]).first,mi=min(dw[xfa[x]],up[xfa[x]]).second;
  113. if(!(n&)&&mi<min(dw[x],up[x]).second) n--;
  114. n>>=,n-=min(dw[x],up[x]).first;
  115. if(n>len[x]) n--;
  116. if(n>=){
  117. int y=jump(x,n),z=jump(x,len[x]-);
  118. ans[min(dw[x],up[x]).second]+=siz[y]-siz[x],ans[mi]+=siz[z]-siz[y];
  119. }
  120.  
  121. }
  122. int ss=siz[x];
  123. for(int i=xsh[x];i;i=xbr[i]) ss-=siz[jump(i,len[i]-)];
  124. ans[min(dw[x],up[x]).second]+=ss;
  125. }
  126.  
  127. int hh[maxn];
  128. int main(){
  129. //freopen("","r",stdin);
  130. int i,j,k;
  131. N=rd();
  132. for(i=;i<N;i++){
  133. int a=rd(),b=rd();
  134. adeg(a,b);adeg(b,a);
  135. }dep[]=;dfs1();
  136. // for(i=1;i<=N;i++) printf("~%d %d\n",i,siz[i]);
  137. Q=rd();
  138. for(i=;i<=Q;i++){
  139. int m=rd();
  140. for(j=;j<=m;j++) hh[j]=h[j]=rd();
  141. build(m);
  142. dfs2(),dfs3();
  143. for(j=;j<=m;j++) printf("%d ",ans[hh[j]]);
  144. printf("\n");
  145. for(;pct;pct--) xfa[id[pct]]=xbr[id[pct]]=xsh[id[pct]]=rea[id[pct]]=ans[id[pct]]=;
  146. }
  147. return ;
  148. }
  149. /*
  150. 21
  151. 1 2
  152. 2 3
  153. 2 4
  154. 3 9
  155. 4 5
  156. 5 6
  157. 6 7
  158. 6 8
  159. 2 18 2 19 2 20 2 21
  160. 9 13 9 14
  161. 5 17
  162. 4 15 4 16
  163. 6 10 10 11 10 12
  164. 1
  165. 3
  166. 9 7 8
  167. */

luogu3233 世界树 (虚树)的更多相关文章

  1. 【BZOJ-3572】世界树 虚树 + 树形DP

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

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

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

  3. 【BZOJ3572】[Hnoi2014]世界树 虚树

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

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

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

  5. bzoj3572[Hnoi2014] 世界树 虚树+dp+倍增

    [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1921  Solved: 1019[Submit][Status][Dis ...

  6. BZOJ 3572 世界树(虚树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3572 思路:建立虚树,然后可以发现,每条边不是同归属于一端,那就是切开,一半给上面,一半给下面. # ...

  7. bzoj 3572世界树 虚树+dp

    题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...

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

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

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

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

随机推荐

  1. Linux 典型应用之缓存服务

    memcached 安装和简单使用 yum install memcached 启动 -d 表示以守护进程的方式启动 memcached -d 安装telnet 它可以检测某个端口是否是通的,可以发送 ...

  2. 在tomcat8.0.x和tomcat9.0.x之间么突然冒出个tomcat 8.5

    Apache Tomcat 8 (8.5.38) - Documentation Indexhttps://tomcat.apache.org/tomcat-8.5-doc/index.html to ...

  3. Linux (Redhat / Fedora / CentOS) 更改 hostname 的方式

    Linux (Redhat / Fedora / CentOS) 更改 hostname 的方式 [蔡宗融個人網站]https://www.ichiayi.com/wiki/tech/linux_ho ...

  4. php之IP

    常用的获取客户端的IP地址的方法: 1) function getRemoteIp(){ if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ $ip = $_SE ...

  5. 微信小程序开发的基本流程

    微信小程序开发的基本流程 一,微信小程序简介 1,微信小程序简称小程序,张小龙在微信公开课 Pro 上发布的小程序正式上线,时间是2017年1月9日. 2,微信小程序这个词可以分解为“微信”和“小程序 ...

  6. [转帖]Linux:cut命令详解

    Linux:cut命令详解 https://www.cnblogs.com/Spiro-K/p/6361646.html cut -f cut -f -d cut -c1- 这三个命令好像最常见, 记 ...

  7. [转帖]TCP和UDP的135、137、138、139、445端口的作用

    TCP和UDP的135.137.138.139.445端口的作用 https://www.cnblogs.com/IvanChen/p/4500698.html 竟然不知道 端口具体是干什么的.. 如 ...

  8. 5款Python程序员高频使用开发工具推荐

    很多Python学习者想必都会有如下感悟:最开始学习Python的时候,因为没有去探索好用的工具,吃了很多苦头.后来工作中深刻体会到,合理使用开发的工具的便利和高效.今天,我就把Python程序员使用 ...

  9. SSM+shiro及相关插件的整合maven所有依赖,详细注释版,自用,持续更新

    整合了SSM+shiro框架,slf4j+logback日志,及一些好用的插件PageHelper,mybatis-generator,Lombok,fastjson等等 <?xml versi ...

  10. JSTL 之 <c:out>

    jstl的<c:out value="${hello}"></c:out> EL表达式的${hello },两者一般没什么不同,但是EL表达式输出的时候回尝 ...