题目大意

​  给你一棵树,求有多少个组点满足\(x\neq y,x\neq z,y\neq z,dist_{x,y}=dist_{x,z}=dist_{y,z}\)

​  \(1\leq n\leq 100000\)

题解

​  问题转换为有多少个组点满足\(dist_{i,x}=dist_{i,y}=dist_{i,z}\)

​  我们考虑树形DP

​  \(f_{i,j}=\)以\(i\)为根的子树中与\(i\)的距离为\(j\)的节点数

​  \(g_{i,j}=\)以\(i\)为根的子树外选择一个点\(s\)满足\(s\)到\(i\)的距离为\(j\),能新增的的方案数

​  若\(v\)是\(u\)的重儿子,则:\(f_{u,j}+=f_{v,j-1},g_{u,j}+=g_{v,j+1}\),这样就可以由\(u\)的重儿子转移到\(u\)

​  否则:\(g_{u,j}+=g_{v,{j+1}}+f_{v,j-1}\times f_{u,j},f_{u,j}+=f_{v,j-1}\)

​  答案为\(\sum f_{x,j}\times g_{y,j}\),其中\(x\)是\(y\)的兄弟

​  可以用长链剖分辅助转移

​  时间复杂度:\(O(n)\)

​  gjs大爷的长链剖分讲解

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cstdlib>
  5. #include<ctime>
  6. #include<utility>
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int,int> pii;
  10. struct list
  11. {
  12. int v[200010];
  13. int t[200010];
  14. int h[100010];
  15. int n;
  16. void clear()
  17. {
  18. n=0;
  19. memset(h,0,sizeof h);
  20. }
  21. void add(int x,int y)
  22. {
  23. n++;
  24. v[n]=y;
  25. t[n]=h[x];
  26. h[x]=n;
  27. }
  28. };
  29. list l;
  30. ll ans;
  31. ll f[100010];
  32. ll g[200010];
  33. int d[100010];
  34. int bg[100010];
  35. int ed[100010];
  36. int ch[100010];
  37. int t[100010];
  38. int w[100010];
  39. int ti;
  40. void dfs(int x,int fa)
  41. {
  42. d[x]=1;
  43. ch[x]=0;
  44. int i;
  45. for(i=l.h[x];i;i=l.t[i])
  46. if(l.v[i]!=fa)
  47. {
  48. dfs(l.v[i],x);
  49. if(d[l.v[i]]+1>d[x])
  50. {
  51. d[x]=d[l.v[i]]+1;
  52. ch[x]=l.v[i];
  53. }
  54. }
  55. }
  56. void dfs2(int x,int fa,int top)
  57. {
  58. t[x]=top;
  59. w[x]=++ti;
  60. if(x==top)
  61. bg[top]=ti;
  62. ed[top]=ti;
  63. if(ch[x])
  64. dfs2(ch[x],x,top);
  65. int i;
  66. for(i=l.h[x];i;i=l.t[i])
  67. if(l.v[i]!=ch[x]&&l.v[i]!=fa)
  68. dfs2(l.v[i],x,l.v[i]);
  69. }
  70. ll& getf(int x,int y)
  71. {
  72. return f[w[x]+y];
  73. }
  74. ll& getg(int x,int y)
  75. {
  76. return g[2*(w[t[x]]-1)+2*d[t[x]]-d[x]+1-y];
  77. }
  78. void solve(int x,int fa)
  79. {
  80. if(ch[x])
  81. solve(ch[x],x);
  82. int i,j;
  83. for(i=l.h[x];i;i=l.t[i])
  84. if(l.v[i]!=fa&&l.v[i]!=ch[x])
  85. {
  86. int v=l.v[i];
  87. solve(v,x);
  88. for(j=0;j<d[v];j++)
  89. ans+=getf(v,j)*getg(x,j+1);
  90. for(j=1;j<d[v];j++)
  91. ans+=getg(v,j)*getf(x,j-1);
  92. for(j=0;j<d[v];j++)
  93. getg(x,j+1)+=getf(v,j)*getf(x,j+1);
  94. for(j=1;j<d[v];j++)
  95. getg(x,j-1)+=getg(v,j);
  96. for(j=0;j<d[v];j++)
  97. getf(x,j+1)+=getf(v,j);
  98. }
  99. ans+=getg(x,0);
  100. getf(x,0)++;
  101. }
  102. int main()
  103. {
  104. int n;
  105. scanf("%d",&n);
  106. l.clear();
  107. memset(bg,0,sizeof bg);
  108. memset(ed,0,sizeof ed);
  109. memset(f,0,sizeof f);
  110. memset(g,0,sizeof g);
  111. memset(d,0,sizeof d);
  112. memset(ch,0,sizeof ch);
  113. memset(t,0,sizeof t);
  114. memset(w,0,sizeof w);
  115. ans=0;
  116. ti=0;
  117. int i,x,y;
  118. for(i=1;i<n;i++)
  119. {
  120. scanf("%d%d",&x,&y);
  121. l.add(x,y);
  122. l.add(y,x);
  123. }
  124. dfs(1,0);
  125. dfs2(1,0,1);
  126. solve(1,0);
  127. printf("%lld\n",ans);
  128. return 0;
  129. }

【BZOJ3522】【BZOJ4543】【POI2014】Hotel 树形DP 长链剖分 启发式合并的更多相关文章

  1. BZOJ4543 POI2014 Hotel加强版 【长链剖分】【DP】*

    BZOJ4543 POI2014 Hotel加强版 Description 同OJ3522 数据范围:n<=100000 Sample Input 7 1 2 5 7 2 5 2 3 5 6 4 ...

  2. 2019.01.08 bzoj4543: [POI2014]Hotel加强版(长链剖分+dp)

    传送门 代码: 长链剖分好题. 题意:给你一棵树,问树上选三个互不相同的节点,使得这个三个点两两之间距离相等的方案数. 思路: 先考虑dpdpdp. fi,jf_{i,j}fi,j​表示iii子树中离 ...

  3. 【BZOJ3522&BZOJ4543】Hotel加强版(长链剖分,树形DP)

    题意:求一颗树上三点距离两两相等的三元组对数 n<=1e5 思路:From https://blog.bill.moe/bzoj4543-hotel/ f[i][j]表示以i为根的子树中距离i为 ...

  4. 【BZOJ4543】Hotel加强版(长链剖分)

    [BZOJ4543]Hotel加强版(长链剖分) 题面 BZOJ,没有题面 洛谷,只是普通版本 题解 原来我们的\(O(n^2)\)做法是设\(f[i][j]\)表示以\(i\)为根的子树中,距离\( ...

  5. BZOJ4543/BZOJ3522 [POI2014]Hotel加强版(长链剖分)

    题目好神仙--这个叫长链剖分的玩意儿更神仙-- 考虑dp,设\(f[i][j]\)表示以\(i\)为根的子树中到\(i\)的距离为\(j\)的点的个数,\(g[i][j]\)表示\(i\)的子树中有\ ...

  6. 【BZOJ3522】[Poi2014]Hotel 树形DP

    [BZOJ3522][Poi2014]Hotel Description 有一个树形结构的宾馆,n个房间,n-1条无向边,每条边的长度相同,任意两个房间可以相互到达.吉丽要给他的三个妹子各开(一个)房 ...

  7. [2016北京集训试题7]thr-[树形dp+树链剖分+启发式合并]

    Description Solution 神仙操作orz. 首先看数据范围,显然不可能是O(n2)的.(即绝对不是枚举那么简单的),我们考虑dp. 定义f(x,k)为以x为根的子树中与x距离为k的节点 ...

  8. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  9. [bzoj3522][bzoj4543][POI2014]HOTEL

    题解: 比较难的一道题目 首先考虑暴力dp 我们会发现构成这种形状只有三种情况 1.三个点的lca相同 2.两个点lca相同,第三个点是lca的祖先 3.两个点lca相同,第三个点是lca祖先的子树中 ...

随机推荐

  1. c++之sizeof的用法

    在此温习一下c语言中sizeof的用法以及c++11.0的标准中,关于初始化的新方式,先上代码: # include "iostream" # include "stri ...

  2. Yii1.1框架实现PHP极光推送消息通知

    一.下载极光推送PHP SDK,解压后放在/protected/components/目录下,如下图所示: 二.完善修改下官方的demo例子,我这里复制一份demo,改为NotifyPush.php, ...

  3. Elasticsearch之配置详解

    Cluster 集群名称,默认为elasticsearch: cluster.name: elasticsearch 设置一个节点的并发数量,有两种情况,一种是在初始复苏过程中: cluster.ro ...

  4. React不同版本之间需要注意的地方

    React Fiber react fiber指的是react16.0机器之后的版本,相对于之前的版本来说,这一个版本的更新做了很多的优化,所以和之前的版本中的用法可能会发生不同,所以,平常开发中,主 ...

  5. Java.lang.OutOfMemoryError:Metaspace

    Understand the OutOfMemoryError Exceptionhttps://docs.oracle.com/javase/8/docs/technotes/guides/trou ...

  6. js根据ip自动获取地址(省市区)

    HTML: <html> <head> <meta charset="utf-8"> <meta name="viewport& ...

  7. java8新特性:interface中的static方法和default方法

    java8中接口有两个新特性,一个是静态方法,一个是默认方法. static方法 java8中为接口新增了一项功能:定义一个或者多个静态方法. 定义用法和普通的static方法一样: public i ...

  8. java类库

    Java的应用程序接口(API)以包的形式来组织,每个包提供大量的相关类.接口和异常处理类,这些包的集合就是Java的类库. Java类库可以分为两种 包名以java开始的包是Java核心包(Java ...

  9. Azure系列2.1.4 —— BlobInputStream

    (小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...

  10. oracle建表流程

    --创建表空间test1 create tablespace test1 datafile 'd:\test1.dbf' size 100m autoextend on next 10m --创建用户 ...