题目好神仙……这个叫长链剖分的玩意儿更神仙……

考虑dp,设\(f[i][j]\)表示以\(i\)为根的子树中到\(i\)的距离为\(j\)的点的个数,\(g[i][j]\)表示\(i\)的子树中有\(g[i][j]\)对点深度相同,他们到LCA的距离为\(d\),且他们的LCA到\(i\)的距离为\(d-j\)。或者换句话来说就是以\(i\)为根的子树中有这么多个点对,而且没有第三个点去和这些点对匹配,第三个点不在\(i\)的子树中且到\(i\)的距离为\(j\),\(g[i][j]\)表示这些点对的个数

设\(u\)为当前点,\(v\)为某一子树,那么转移方程如下
\[f[u][i]+=f[v][i+1]\]
\[g[u][i-1]+=g[v][i]\]
\[g[u][i+1]+=f[u][i+1]*f[v][i]\]
\[ans+=f[u][i-1]*g[v][i]+g[u][i+1]*f[v][i]\]

如果是原题的\(n\leq 5000\)已经足够了,然而当\(n\leq 100000\)的时候很明显gg了

发现状态数组的第二维实际上跟这个节点的深度有关,于是考虑用长链剖分优化。(不知道什么是长链剖分的可以看看蒟蒻的笔记)简单来说记每一个节点深度最大的儿子为它的重儿子。因为第一次转移的时候有\(f[u][i]=f[v][i-1],g[u][i]=g[v][i+1]\),于是可以类似于dsu on tree的思想,对于每个重儿子的信息直接继承,轻儿子暴力跑一遍。重儿子的信息可以直接用指针来达到\(O(1)\)的转移

这个时间复杂度大概是\(O(n)\)的,对于每个点转移的复杂度为\(\sum dep[v]-dep[son[u]]=\sum dep[v]-dep[u]+1\),然后所有点的加起来除了叶子结点都互相抵消,于是总的复杂度为\(O(n)\)

空间复杂度也是\(O(n)\),因为非叶节点的空间都是由它所在重链的儿子转移来的,所以对每个叶节点开正比于此重链长度的空间即可

//minamoto
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
int read(){int res,f=1;char ch;while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');return res*f;
}
const int N=1e5+5,M=1005;
int head[N],Next[N<<1],ver[N<<1],tot;
inline void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
ll memp[N*5],*f[N],*g[N],*to=memp+5,ans;
int n,dep[N],mx[N];
void dfs(int u,int fa){mx[u]=u;for(int i=head[u];i;i=Next[i]){int v=ver[i];if(v!=fa){dep[v]=dep[u]+1,dfs(v,u);if(dep[mx[v]]>dep[mx[u]])mx[u]=mx[v];}}for(int i=head[u];i;i=Next[i]){int v=ver[i];if(v!=fa&&(mx[v]!=mx[u]||u==1)){v=mx[v],to+=dep[v]-dep[u]+1;f[v]=to,g[v]=(to+=1),to+=(dep[v]-dep[u])*2+1;}}
}
void dp(int u,int fa){for(int i=head[u];i;i=Next[i]){int v=ver[i];if(v==fa)continue;dp(v,u);if(mx[v]==mx[u])f[u]=f[v]-1,g[u]=g[v]+1;}ans+=g[u][0],f[u][0]=1;for(int i=head[u];i;i=Next[i]){int v=ver[i];if(v==fa||mx[v]==mx[u])continue;for(int j=0;j<=dep[mx[v]]-dep[u];++j)ans+=f[u][j-1]*g[v][j]+g[u][j+1]*f[v][j];for(int j=0;j<=dep[mx[v]]-dep[u];++j){g[u][j-1]+=g[v][j];g[u][j+1]+=f[u][j+1]*f[v][j];f[u][j+1]+=f[v][j];}}
}
int main(){
//  freopen("testdata.in","r",stdin);n=read();for(int i=1,u,v;i<n;++i)u=read(),v=read(),add(u,v),add(v,u);while(to!=memp)*to=0,--to;*to=0,++to;dep[1]=1;dfs(1,0),dp(1,0);printf("%lld\n",ans);return 0;
}

转载于:https://www.cnblogs.com/bztMinamoto/p/9948324.html

BZOJ4543/BZOJ3522 [POI2014]Hotel加强版(长链剖分)相关推荐

  1. 【BZOJ】4543: [POI2014]Hotel加强版-长链剖分DP

    传送门:bzoj4543 题解 三点两两距离相等的情况如下图: 设 f [ i ] [ j ] f[i][j] f[i][j]表示 i i i子树中与 i i i距离为 j j j(相对深度为 j j ...

  2. 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 ...

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

    传送门 题意:求树上满足三点之间距离两两相等的三元组个数 n≤1e5n\le 1e5n≤1e5 原题数据是n≤5000n\le5000n≤5000 考虑怎么做 f[u][i]f[u][i]f[u][i ...

  4. 【BZOJ4543】Hotel加强版【神仙树形dp】【长链剖分】

    题意:给一棵 nnn 个点的树,求两两距离相等的三元组个数. n≤105n\leq 10^5n≤105 显然相当于是找一个点到这三个点距离相等.子树内和子树外到当前点的距离为某个值的点的个数可以长链剖 ...

  5. bzoj4543. [POI2014]Hotel加强版

    bzoj4543. [POI2014]Hotel加强版 题面描述 Solution 先看n≤5e3n \leq 5e3n≤5e3怎么做. 考虑树形dpdpdp. 设f[i][j]f[i][j]f[i] ...

  6. P3565 [POI2014]HOT-Hotels(树形dp+长链剖分)

    P3565 [POI2014]HOT-Hotels 参考题解 题目大意: 给定一棵树,在树上选 3 个点,要求两两距离相等,求方案数. 三个点树上两两距离为d存在下面两种情况 某个点三个子树(保证该点 ...

  7. P5904-[POI2014]HOT-Hotels加强版【长链剖分,dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P5904 题目大意 nnn个点的一棵树,求有多少个点对(i,j,k)(i,j,k)(i,j,k)使得这三个点距离相等 ...

  8. 树链剖分之长链剖分 详解 题目整理

    树链剖分 题目中出现的树链剖分一般分为两种,重链剖分和长链剖分 重链剖分:选择子树最大的儿子, 将其归入当前点所在 的同一条重链 长链剖分:选择向下能达到的深 度最深的儿子,将其归 入当前点所在的同一 ...

  9. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

最新文章

  1. IBM之alphablox 数据源定义问题解决
  2. MPLS标签分配控制方式——Vecloud
  3. OpenCV信息流Alpha遮罩
  4. 谈谈多层架构和MVC
  5. 今天换了ubuntu10.04
  6. 项目中最困难的部分_微服务最难的部分是什么? 您的资料
  7. 嵌入式 U 盘自动挂载
  8. python运行需要联网吗_基于python分析你的上网行为 看看你平时上网都在干嘛
  9. 网易邮箱大师如何添加Word附件 添加附件方法步骤详细介绍
  10. 怎么用计算机打对错,丶符号怎么打-Word里的对√ 和 错× 怎么打出来的?
  11. 转:Delphi开发经验谈
  12. 网闸可以设置端口映射吗_路由器的外部端口和内部端口映射如何设置?
  13. SQL基础(廿)--- 抑制重复
  14. mysql主从配置duxi_[从0到1搭建ABP微服务] - 搭建授权服务
  15. Fresco图片加载+EventBus+Butterknife+Retrofit+RxJava+RxAndroid
  16. BLE 协议栈(Master,Slave;Standby,Advertiser,Scanner,Initiator;连接流程,连接参数)
  17. Xshell配色方案
  18. ChatGPT离自我意识还有多远
  19. 根据灰度直方图调整图象亮度
  20. 常见的6个agile方法

热门文章

  1. 一文读懂比特币UXTO,TA其实没那么神秘!
  2. 也许开发需要的只是一份简单明了的表格
  3. Linux系统搭建FTP服务器
  4. ssh开启root用户登录
  5. 配置openStack使用spice
  6. 作为程序员,这些地方不知道就out了!
  7. android 线程方式打印log到sd卡
  8. lvm扩张与收缩小结
  9. 7系列FPGA逻辑单元理解
  10. 基数排序中的LSD方法和MSD方法