我的树形dp果然是渣。。。

题意:给一棵树,共n(0<n<=15e4)个节点,可在树上进行跳跃,每次跳的最大距离为k(0<k<=5),定义f(s,t)为(dis(s,t)+k)/k,问Σf(s,t),s<t。

解题思路:

  显然是树形dp,问题在于怎么构建状态。

  最简单想到的就是,每到一个节点u,记录其子树中与其距离为d的的节点的数目,即(dis,cnt)对,则答案分两种情况,u到其子节点和以及子节点经过u到子节点,问题变得很简单,计算也不难——但问题在于极端情况下——比如树退化成链,时空复杂度都将高到无法忍受,于是卡在了这里……

  然后看了别人的题解,发现不需要构建(dis,cnt)对,而是构建(dis%k,cnt)对——这样复杂度枚举的最高复杂度也就只是k^2而不是dis^2,,,啊感觉自己宛若一个zz。

  定义,sz(u,i)表示与节点u的距离%k为 i 的节点数目,dp(u,i)表示从u到sz(u,i)中节点的跳数和。

  状态转移如下:

  (1)sz(u,(i+1)%k)+=sz(v,i)

  (2)dp(u,(i+1)%k)+=dp(v,i)  0<i<k

  (3)dp(u,1%k)+=dp(v,0)+sz(v,0)

  显然,与u的子节点v的距离%k大于0的,到v所需跳数与到u所需跳数是相同的(式子(2))。否则跳数需要+1,有sz(v,0)个点,故再加上sz(v,0)(式子(3))。

  接下来是统计答案,分两种情况,一个是u到其子节点,另一个是u到子节点到其它子节点(子节点间的最近公共祖先节点为u)。

  对于第一种,直接res+=Σdp[u][i]即可。

  对于第二种,将之前已经遍历过的子树节点都合并到dp[u][i]与sz[u][i]中,则与新的子树节点v合并时,枚举k1、k2,依次为已遍历过的子树节点与u的距离%k=k1,以及与v的子树中与u的距离%k为k2的节点(语文不好这段贼拗口……k^2的枚举就是这里了),分情况讨论:

  如果k1为0,则dp[u][k1]中则为恰好到达u的跳数(即每一跳距离都是k),则从sz[u][k1]中的节点到达 v的子树中的节点 所需跳数 恰好为二者相加之和,不需额外处理;如果k2为0,同理;当k1与k2都不为0时,考虑k1+k2<=k,则此时说明多计算了一跳,因此需要减去;当k1+k2>k时,恰好符合。

  综上,需要特判的也只有(k1&&k2&&k1+k2<=k)这种情况。

  代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
#define sqr(x) ((x)*(x))
const int N=2e5+10;
int head[N],nxt[N<<1],to[N<<1],cnt;
int n,k,a,b;
ll sz[N][6],dp[N][6],res;
void init(){memset(head,-1,sizeof(head));res=cnt=0;memset(sz,0,sizeof(sz));memset(dp,0,sizeof(dp));
}
void addEdge(int u,int v){nxt[cnt]=head[u];to[cnt]=v;head[u]=cnt++;
}
void dfs(int u,int pre){ll tsz[6],tdp[6];  //用以暂时保存从u到新的v子树节点的数据for(int e=head[u];~e;e=nxt[e]){int v=to[e];if(v==pre) continue;dfs(v,u);memset(tsz,0,sizeof(tsz));memset(tdp,0,sizeof(tdp));for(int i=0;i<k;i++)tsz[(i+1)%k]+=sz[v][i];for(int i=1;i<k;i++)tdp[(i+1)%k]+=dp[v][i];tdp[1%k]+=dp[v][0]+sz[v][0];for(int k1=0;k1<k;k1++){for(int k2=0;k2<k;k2++){res+=dp[u][k1]*tsz[k2]+sz[u][k1]*tdp[k2];if(k1&&k2&&k1+k2<=k) res-=sz[u][k1]*tsz[k2];}}//将v的子树节点情况合并到u下for(int i=0;i<k;i++)dp[u][i]+=tdp[i],sz[u][i]+=tsz[i];}for(int i=0;i<k;i++)res+=dp[u][i];sz[u][0]++;
}
int main(){//freopen("in.txt","r",stdin);while(~scanf("%d%d",&n,&k)){init();for(int i=1;i<n;i++){scanf("%d%d",&a,&b);addEdge(a,b);addEdge(b,a);}dfs(1,0);printf("%I64d\n",res);}return 0;
}

  参考题解:http://www.cnblogs.com/AOQNRMGYXLMV/p/6579771.html

转载于:https://www.cnblogs.com/names-yc/p/6600972.html

Codeforces 771C相关推荐

  1. CodeForces 771C Bear and Tree Jumps 树形DP

    题意: 给出一棵树,一个人可以在树上跳,每次最多跳\(k(1 \leq k \leq 5)\)个点 定义\(f(s,t)\)为从顶点\(s\)跳到顶点\(t\)最少需要跳多少次 求\(\sum\lim ...

  2. CodeForces 375D Tree and Queries

    传送门:https://codeforces.com/problemset/problem/375/D 题意: 给你一颗有根树,树上每个节点都有其对应的颜色,有m次询问,每次问你以点v为父节点的子树内 ...

  3. 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

    题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...

  4. 【codeforces 812C】Sagheer and Nubian Market

    [题目链接]:http://codeforces.com/contest/812/problem/C [题意] 给你n个物品; 你可以选购k个物品;则 每个物品有一个基础价值; 然后还有一个附加价值; ...

  5. CodeForces 获得数据

    针对程序的输出可以看见 CodeForces :当输入.输出超过一定字符,会隐藏内容 所以:分若干个程序进行输入数据的获取 1. 1 for (i=1;i<=q;i++) 2 { 3 scanf ...

  6. codeforces水题100道 第二十七题 Codeforces Round #172 (Div. 2) A. Word Capitalization (strings)...

    题目链接:http://www.codeforces.com/problemset/problem/281/A 题意:将一个英文字母的首字母变成大写,然后输出. C++代码: #include < ...

  7. CodeForces 595A

    题目链接: http://codeforces.com/problemset/problem/595/A 题意: 一栋楼,有n层,每层有m户,每户有2个窗户,问这栋楼还有多少户没有睡觉(只要一个窗户灯 ...

  8. codeforces A. Jeff and Digits 解题报告

    题目链接:http://codeforces.com/problemset/problem/352/A 题目意思:给定一个只有0或5组成的序列,你要重新编排这个序列(当然你可以不取尽这些数字),使得这 ...

  9. Codeforces Round #506 (Div. 3)

    Codeforces Round #506 (Div. 3) 实习期间事不多,对div3 面向题解和数据编程了一波 A. Many Equal Substrings 题目链接 A题就是找后缀和前缀重合 ...

最新文章

  1. css3-transform
  2. 手把手教你如何制作可视化大屏!
  3. 扔掉源码,15张图带你彻底理解java AQS
  4. 移动端整屏滑动的实现
  5. 鸿蒙大陆武器合成,鸿蒙大陆9.1攻略(附隐藏英雄密码)
  6. spss相关性分析看结果_spss相关性分析
  7. 系统备份是对计算机硬件进行维户吗,计算机系统维护毕业论文_精品.doc
  8. 那些大学简称背后的“爱恨情仇”:东西南北中,就剩北大没人抢了
  9. 设计模式笔记(10)---装饰模式(结构型)
  10. ubuntu 的chmod 和 chown
  11. AI 写代码来了 - github 的 AI 写代码插件 copilot 发布
  12. win7计算机怎么初始化,Win7系统网络初始化的设置方法
  13. 《七哥说道》第十二章:稍息,窗外的都是兄弟
  14. Windbg 命令 (一)
  15. 小程序picker用法
  16. 总结在使用vue-photo-preview---图片查看大图插件,点击图片无法显示预览等问题
  17. Mysql rbo和cbo_oracle的优化——RBO和CBO简介以及optimizer_mode参数说明
  18. DBeaver 7.1.4下载
  19. 思科在中国已建成355所网络技术学院
  20. 泰坦尼克号数据之生还率分析

热门文章

  1. python 多线程ping测试_从线程ping多个ip时Python ICMP ping实现?
  2. python写入文件后换行_python向文件写入行避免fi末尾的换行
  3. c++ main函数调用 类中的枚举_为啥用枚举,枚举有哪些用法?
  4. spi iic和串口的区别_GMII、SGMII和SerDes的区别和联系
  5. 企业网络推广——企业网络推广专员提高网站更新讲策略
  6. linux shell概述,Linux学习 -- Shell基础 -- 概述
  7. centos7arm进入图形化_CentOS 7 安装图形化界面
  8. bash给脚本加进度条_进度条——shell脚本实现
  9. Java序列化闲聊:序列化和Json
  10. 诺基亚 IoT安全白皮书