Description

给出一棵树求三元组 \((x,y,z)\,,x<y<z\) 满足三个点两两之间距离相等,求三元组的数量

Solution

考虑暴力 \(DP\)

设 \(f[i][j]\) 表示距离点 \(i\) 的子树内距离为 \(j\) 的点的数量

设 \(g[i][j]\) 表示 \(i\) 子树内的一个二元组 \((x,y)\) 满足 \(dis(x,lca)=dis(y,lca)=dis(i,lca)+j\) 的二元组的数量,可以视为等待与子树外合并的二元组的数量

显然有转移:

\(ans+=g[x][0]\)

\(ans+=f[son][j]*g[x][j+1]+f[x][j-1]*g[son][j]\)

\(f[x][j]=f[son][j-1]\)

\(g[x][j]=g[son][j+1]\)

\(g[x][j]=f[x][j]*f[son][j-1]\)

这样转移是 \(O(n^2)\) 的

对于深度为下标的树形 \(DP\),考虑长链剖分优化:

在 \(DP\) 转移之前, \(f[x],g[x]\) 是没有值的,初值要设为某个儿子的 \(DP\) 值

并且这个时候的转移仅仅是 \(f[x][j]=f[son][j-1]\),\(g[x][j]=g[son][j+1]\)

相当于一个数组位移,直接用指针优化,可以做到 \(O(1)\),所以用所在链最长的儿子来赋初值复杂度最优,其余儿子暴力转移

这样做复杂度均摊就是 \(O(n)\) 的了,一条链只会在链顶被枚举到,且链不相交,所以每个点只会被枚一次

空间对于每一个链动态开空间,空间复杂度也是 \(O(n)\) 的

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. template<class T>void gi(T &x){
  4. int f;char c;
  5. for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
  6. for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
  7. }
  8. typedef long long ll;
  9. const int N=1e5+10;
  10. int n,head[N],nxt[N*2],to[N*2],num=0,dep[N],mx[N];
  11. inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
  12. ll lis[N*5],*f[N],*g[N],*st=lis+5,ans=0;
  13. inline void dfs(int x,int fa){
  14. mx[x]=x;
  15. for(int i=head[x],u;i;i=nxt[i]){
  16. if((u=to[i])==fa)continue;
  17. dep[u]=dep[x]+1;dfs(u,x);
  18. if(dep[mx[u]]>dep[mx[x]])mx[x]=mx[u];
  19. }
  20. for(int i=head[x],u;i;i=nxt[i]){
  21. if((u=to[i])==fa || (mx[u]==mx[x] && x!=1))continue;
  22. st+=dep[mx[u]]-dep[x]+1;
  23. f[mx[u]]=st;
  24. g[mx[u]]=++st;
  25. st+=(dep[mx[u]]-dep[x])*2+1;
  26. }
  27. }
  28. inline void dfs2(int x,int fa){
  29. for(int i=head[x],u;i;i=nxt[i]){
  30. if((u=to[i])==fa)continue;
  31. dfs2(u,x);
  32. if(mx[u]==mx[x])f[x]=f[u]-1,g[x]=g[u]+1;
  33. }
  34. f[x][0]=1;ans+=g[x][0];
  35. for(int i=head[x],u;i;i=nxt[i]){
  36. if((u=to[i])==fa || mx[u]==mx[x])continue;
  37. for(int j=dep[mx[u]]-dep[x];j>=0;j--)
  38. ans+=g[x][j+1]*f[u][j]+g[u][j]*(j?f[x][j-1]:0);
  39. for(int j=dep[mx[u]]-dep[x];j>=0;j--){
  40. f[x][j+1]+=f[u][j];
  41. g[x][j]+=g[u][j+1];
  42. g[x][j]+=f[x][j]*(j?f[u][j-1]:0);
  43. }
  44. }
  45. }
  46. int main(){
  47. freopen("pp.in","r",stdin);
  48. freopen("pp.out","w",stdout);
  49. cin>>n;
  50. int x,y;
  51. for(int i=1;i<n;i++)gi(x),gi(y),link(x,y),link(y,x);
  52. dfs(1,1);dfs2(1,1);
  53. cout<<ans<<endl;
  54. return 0;
  55. }

bzoj 4543: [POI2014]Hotel加强版的更多相关文章

  1. 【刷题】BZOJ 4543 [POI2014]Hotel加强版

    Description 同OJ3522 数据范围:n<=100000 Solution dp的设计见[刷题]BZOJ 3522 [Poi2014]Hotel 然后发现dp的第二维与深度有关,于是 ...

  2. BZOJ.4543.[POI2014]Hotel加强版(长链剖分 树形DP)

    题目链接 弱化版:https://www.cnblogs.com/SovietPower/p/8663817.html. 令\(f[x][i]\)表示\(x\)的子树中深度为\(i\)的点的个数,\( ...

  3. 4543: [POI2014]Hotel加强版

    4543: [POI2014]Hotel加强版 链接 分析: f[u][i]表示子树u内,距离u为i的点的个数,g[u][i]表示在子树u内,已经选了两个深度一样的点,还需要在距离u为i的一个点作为第 ...

  4. BZOJ3522&4543 [POI2014]Hotel加强版 长链剖分

    上上周见fc爷用长链剖分秒题 于是偷偷学一学 3522的数据范围很小 可以暴力枚举每个点作为根节点来dp 复杂度$O(n^2)$ 考虑令$f[x][j]$表示以$x$为根的子树内距离$x$为$j$的点 ...

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

  6. 【BZOJ4543】[POI2014]Hotel加强版 长链剖分+DP

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

  7. bzoj4543 [POI2014]Hotel加强版 长链剖分+树形DP

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4543 题解 这道题的弱化版 bzoj3522 [POI2014]Hotel 的做法有好几种吧. ...

  8. BZOJ4543 [POI2014]Hotel加强版

    题意 有一个树形结构,每条边的长度相同,任意两个节点可以相互到达.选3个点.两两距离相等.有多少种方案? 数据范围:n<=100000 分析 参照小蒟蒻yyb的博客. 我们先考虑一个\(O(n^ ...

  9. BZOJ.3522.[POI2014]Hotel(DP)

    题目链接 BZOJ 洛谷 以为裸点分治,但数据范围怎么这么小?快打完了发现不对.. n^2做的话其实是个水题.. 枚举每一个点为根,为了不重复计算,我们要求所求的三个点必须分别位于三棵子树上. 考虑当 ...

随机推荐

  1. (一)springmvc+spring+mybatis+maven框架搭建

    (一)springmvc+spring+mybatis+maven框架搭建 1.说明 工作之余,为了学习点东西.先搭建个框架. 以后要往里面加东西,比如rabbitMQ.redis.shiro等. 也 ...

  2. Sqoop 遇到的问题

    1.   想用 sqoop 增量的方式导入到 hive.运行下面的命令: sqoop import --connect jdbc:mysql://192.168.7.159:3306/test --u ...

  3. php 中 include 与 require 的区别

    以下内容转自:https://blog.csdn.net/hsd2012/article/details/51089785 网上太多关于php中include与require区别.其实说的都是经不起验 ...

  4. 【bzoj1022】[SHOI2008]小约翰的游戏John 博弈论

    Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取 的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不 ...

  5. 八大排序算法的python实现(七)基数排序

    代码: #coding:utf-8 #author:徐卜灵 import math #print math.ceil(3.2) 向上取整4.0 #print math.floor(3.2) 向下取整3 ...

  6. Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...

  7. C#图片处理3种高级应用(高缩略图清晰度、图片剪裁、图片水印)

    利用C#图片处理的一些基本和高级应用,解决了显示排版时想让相片缩略图列表非常统一.整齐.和美观,每张缩略图大小固定为120 x 90且不拉伸变形,用户头像让缩略图比原图更清晰,上传的图片下加一个半透明 ...

  8. Android---16进制与字节数组

    16进制字符串与字节数组进行转换 package string; import java.util.Arrays; /** * byte[]与16进制字符串相互转换 * * @date:2017年4月 ...

  9. 使用navicat将mysql转换成sqlserver

    使用navicat将mysql转换成sqlserver 1. 打开navicat,连接所需要装换的mysql数据库. 2. 选择所需要转换的数据源,点击右键选择数据传输.如图: 3. 打开数据传输面板 ...

  10. 设置select不可修改

    <s:select id="notSelectChange" list="#{'1':'表示每月几号','2':'表示每季度第几天','3':'表示每年第几月'}& ...