Codeforces 771C
我的树形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相关推荐
- CodeForces 771C Bear and Tree Jumps 树形DP
题意: 给出一棵树,一个人可以在树上跳,每次最多跳\(k(1 \leq k \leq 5)\)个点 定义\(f(s,t)\)为从顶点\(s\)跳到顶点\(t\)最少需要跳多少次 求\(\sum\lim ...
- CodeForces 375D Tree and Queries
传送门:https://codeforces.com/problemset/problem/375/D 题意: 给你一颗有根树,树上每个节点都有其对应的颜色,有m次询问,每次问你以点v为父节点的子树内 ...
- 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)
题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...
- 【codeforces 812C】Sagheer and Nubian Market
[题目链接]:http://codeforces.com/contest/812/problem/C [题意] 给你n个物品; 你可以选购k个物品;则 每个物品有一个基础价值; 然后还有一个附加价值; ...
- CodeForces 获得数据
针对程序的输出可以看见 CodeForces :当输入.输出超过一定字符,会隐藏内容 所以:分若干个程序进行输入数据的获取 1. 1 for (i=1;i<=q;i++) 2 { 3 scanf ...
- codeforces水题100道 第二十七题 Codeforces Round #172 (Div. 2) A. Word Capitalization (strings)...
题目链接:http://www.codeforces.com/problemset/problem/281/A 题意:将一个英文字母的首字母变成大写,然后输出. C++代码: #include < ...
- CodeForces 595A
题目链接: http://codeforces.com/problemset/problem/595/A 题意: 一栋楼,有n层,每层有m户,每户有2个窗户,问这栋楼还有多少户没有睡觉(只要一个窗户灯 ...
- codeforces A. Jeff and Digits 解题报告
题目链接:http://codeforces.com/problemset/problem/352/A 题目意思:给定一个只有0或5组成的序列,你要重新编排这个序列(当然你可以不取尽这些数字),使得这 ...
- Codeforces Round #506 (Div. 3)
Codeforces Round #506 (Div. 3) 实习期间事不多,对div3 面向题解和数据编程了一波 A. Many Equal Substrings 题目链接 A题就是找后缀和前缀重合 ...
最新文章
- css3-transform
- 手把手教你如何制作可视化大屏!
- 扔掉源码,15张图带你彻底理解java AQS
- 移动端整屏滑动的实现
- 鸿蒙大陆武器合成,鸿蒙大陆9.1攻略(附隐藏英雄密码)
- spss相关性分析看结果_spss相关性分析
- 系统备份是对计算机硬件进行维户吗,计算机系统维护毕业论文_精品.doc
- 那些大学简称背后的“爱恨情仇”:东西南北中,就剩北大没人抢了
- 设计模式笔记(10)---装饰模式(结构型)
- ubuntu 的chmod 和 chown
- AI 写代码来了 - github 的 AI 写代码插件 copilot 发布
- win7计算机怎么初始化,Win7系统网络初始化的设置方法
- 《七哥说道》第十二章:稍息,窗外的都是兄弟
- Windbg 命令 (一)
- 小程序picker用法
- 总结在使用vue-photo-preview---图片查看大图插件,点击图片无法显示预览等问题
- Mysql rbo和cbo_oracle的优化——RBO和CBO简介以及optimizer_mode参数说明
- DBeaver 7.1.4下载
- 思科在中国已建成355所网络技术学院
- 泰坦尼克号数据之生还率分析
热门文章
- python 多线程ping测试_从线程ping多个ip时Python ICMP ping实现?
- python写入文件后换行_python向文件写入行避免fi末尾的换行
- c++ main函数调用 类中的枚举_为啥用枚举,枚举有哪些用法?
- spi iic和串口的区别_GMII、SGMII和SerDes的区别和联系
- 企业网络推广——企业网络推广专员提高网站更新讲策略
- linux shell概述,Linux学习 -- Shell基础 -- 概述
- centos7arm进入图形化_CentOS 7 安装图形化界面
- bash给脚本加进度条_进度条——shell脚本实现
- Java序列化闲聊:序列化和Json
- 诺基亚 IoT安全白皮书