题目

抄题解.jpg

发现原来的\(O(n^2)\)的换根\(dp\)好像行不通了呀

我们考虑非常牛逼的长链剖分

我们设\(f[x][j]\)表示在\(x\)的子树中距离\(x\)为\(j\)的点有多少个

\(g[x][j]\)表示在\(x\)的子树里,满足如下条件的点对\((u,v)\)的个数

  1. 设\(k=LCA(u,v)\),满足\(dis(u,k)=dis(v,k)=d\)

  2. 满足\(dis(k,x)=d-j\)

我们发现可以如果\(v\)是\(x\)的儿子,那么距离\(v\)为\(j-1\)的点和\(x\)的距离就是\(j\),那么到\(k\)的距离就是\(d-j+j=d\),和点对到\(k\)的距离相等

于是我们可以这样合并

\[ans+=f[v][j-1]\times g[x][j]
\]

自然还有

\[ans+=f[x][j-1]\times g[v][j]
\]

\(f\)数组的更新非常简单啊,就是\(f[x][j]+=f[v][j-1]\),这个我们可以用长链剖分优化到\(O(n)\)

之后是\(g\)的更新

首先我们有\(g[x][j]+=g[v][j+1]\),就是到\(x\)距离为\(d-j\)的\(k\)到\(v\)的距离必然是\(d-j-1\),这里我们也可以直接长链剖分

之后\(g[x][j+1]+=f[x][j+1]\times f[v][j]\),这样产生的点对的\(LCA\)就是\(x\),到\(x\)的距离也就是\(j+1\),符合条件,这里直接暴力转移就好了

代码

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #define re register
  6. #define LL long long
  7. #define max(a,b) ((a)>(b)?(a):(b))
  8. #define min(a,b) ((a)<(b)?(a):(b))
  9. const int maxn=100006;
  10. inline int read() {
  11. char c=getchar();int x=0;while(c<'0'||x>'9') c=getchar();
  12. while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
  13. }
  14. struct E{int v,nxt;}e[maxn<<1];
  15. int head[maxn],len[maxn],n,num,son[maxn],deep[maxn];
  16. LL tax[maxn*6],*id=tax,*f[maxn],*g[maxn],ans;
  17. inline void add(int x,int y) {
  18. e[++num].v=y;e[num].nxt=head[x];head[x]=num;
  19. }
  20. void dfs1(int x) {
  21. for(re int i=head[x];i;i=e[i].nxt) {
  22. if(deep[e[i].v]) continue;
  23. deep[e[i].v]=deep[x]+1;
  24. dfs1(e[i].v);
  25. if(len[e[i].v]>len[son[x]]) son[x]=e[i].v;
  26. }
  27. len[x]=len[son[x]]+1;
  28. }
  29. void dfs(int x) {
  30. f[x][0]=1;
  31. if(son[x]) {
  32. g[son[x]]=g[x]-1;
  33. f[son[x]]=f[x]+1;
  34. dfs(son[x]);
  35. }
  36. ans+=g[x][0];
  37. for(re int i=head[x];i;i=e[i].nxt) {
  38. if(deep[e[i].v]<deep[x]||son[x]==e[i].v) continue;
  39. f[e[i].v]=id;id+=len[e[i].v]+1;
  40. g[e[i].v]=id+len[e[i].v]+1;id+=2*len[e[i].v]+2;
  41. dfs(e[i].v);
  42. for(re int j=len[e[i].v];j>=0;--j) {
  43. if(j) ans+=f[x][j-1]*g[e[i].v][j];
  44. ans+=g[x][j+1]*f[e[i].v][j];
  45. g[x][j+1]+=f[e[i].v][j]*f[x][j+1];
  46. }
  47. for(re int j=0;j<=len[e[i].v];j++) {
  48. if(j) g[x][j-1]+=g[e[i].v][j];
  49. f[x][j+1]+=f[e[i].v][j];
  50. }
  51. }
  52. }
  53. int main() {
  54. n=read();
  55. for(re int x,y,i=1;i<n;i++)
  56. x=read(),y=read(),add(x,y),add(y,x);
  57. deep[1]=1;dfs1(1);
  58. f[1]=id;id+=len[1]+1;
  59. g[1]=id+len[1]+1;//由于我们继承重儿子是g[son[x]]=g[x]-1,所以得在这个指针前面留一些空位置来让后面的状态继承
  60. id+=2*len[1]+2;
  61. dfs(1);printf("%lld\n",ans);
  62. return 0;
  63. }

【bzoj4543】[POI2014]Hotel加强版的更多相关文章

  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. BZOJ4543 [POI2014]Hotel加强版

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

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

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

  4. BZOJ4543[POI2014]Hotel加强版——长链剖分+树形DP

    题意参见BZOJ3522 n<=100000 数据范围增强了,显然之前的转移方程不行了,那么不妨换一种. 因为不能枚举根来换根DP,那么我们描述的DP方程每个点要计算三个点都在这个点的子树内的方 ...

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

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

  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】Hotel加强版(长链剖分)

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

  8. 4543: [POI2014]Hotel加强版

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

  9. 【BZOJ4543】Hotel加强版

    [BZOJ4543]Hotel加强版 题面 bzoj 洛谷 $ps:$在洛谷看题在bzoj交... 题解 我们分析一下这个问题,要怎么样的点才满足三点距离两两相等呢? 1.存在三个点有共同的$LCA$ ...

  10. bzoj4543[POI2014]Hotel

    题目链接 bzoj4543 [POI2014]Hotel 题解 这不是裸地点分嘛 ,我真傻,真的 n^2 这不是是sb题,~滑稽 ~ 枚举点转换为无根树,暴力子树中点的深度 计数转移 令a b c d ...

随机推荐

  1. 转载:SQL按照日、周、月、年统计数据的方法

    转载源:http://www.jb51.net/article/42613.htm SQL按照日.周.月.季度.年统计数据的方法 方式一: --按日 select sum(consume),day([ ...

  2. [日常] Redis基本使用测试

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(list ...

  3. Java多线程学习之线程的取消与中断机制

    任务和线程的启动很容易.在大多数情况下我们都会让他们运行直到结束,或是让他们自行停止.但是,有时我们希望提前结束任务或是线程,可能是因为用户请求取消,或是线程在规定时间内没有结束,或是出现了一些问题迫 ...

  4. SpringMVC的controller层接收来自jsp页面通过<a href="/user/userUpdateInfo/>的中文乱码问题

    这种情况是,jsp页面的中文正常显示,数据的中文也是正常显示,但是在Controller层接收到的中文是乱码,如下图所示: 解决方法:在Controller层对前台传递的中文乱码进行处理,将它转换成u ...

  5. CF954F Runner's Problem

    离散化+矩阵快速幂 首先看数据范围可以确定该题的算法为矩阵快速幂 然后易得转移矩阵 \[\begin{bmatrix} 1 & 1 & 0 \\ 1 & 1 & 1 \ ...

  6. Codeforces 750 F:New Year and Finding Roots

    传送门 首先如果一开始就找到了一个叶子,那么暴力去递归找它的父亲,每次随机一个方向(除了已知的儿子)走深度次,如果走到了一个叶子就不是这个方向 (设根的深度为 \(1\))这样子最后到达深度为 \(3 ...

  7. Java 之常用API(二)

    Object类 & System类 日期相关类 包装类 & 正则表达式 Object类 & System类 1.1 Object类 1.1.1 概述 Object类是Java语 ...

  8. Android之TabHost实现Tab切换

    TabHost是整个Tab的容器,包含TabWidget和FrameLayout两个部分,TabWidget是每个Tab的表情,FrameLayout是Tab内容. 实现方式有两种: 1.继承TabA ...

  9. idea 导入Mapper错误报错设置

    这个报错如图: 其实这个报错是错误,因为运行一切正常. 解决办法:

  10. maven一键部署linux的tomcat(wagon-maven-plugin)

    Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Depen ...