我的树形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+;
int head[N],nxt[N<<],to[N<<],cnt;
int n,k,a,b;
ll sz[N][],dp[N][],res;
void init(){
memset(head,-,sizeof(head));
res=cnt=;
memset(sz,,sizeof(sz));
memset(dp,,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[],tdp[]; //用以暂时保存从u到新的v子树节点的数据
for(int e=head[u];~e;e=nxt[e]){
int v=to[e];
if(v==pre) continue;
dfs(v,u);
memset(tsz,,sizeof(tsz));
memset(tdp,,sizeof(tdp));
for(int i=;i<k;i++)
tsz[(i+)%k]+=sz[v][i];
for(int i=;i<k;i++)
tdp[(i+)%k]+=dp[v][i];
tdp[%k]+=dp[v][]+sz[v][];
for(int k1=;k1<k;k1++){
for(int k2=;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=;i<k;i++)
dp[u][i]+=tdp[i],sz[u][i]+=tsz[i];
}
for(int i=;i<k;i++)
res+=dp[u][i];
sz[u][]++;
}
int main(){
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&k)){
init();
for(int i=;i<n;i++){
scanf("%d%d",&a,&b);
addEdge(a,b);
addEdge(b,a);
}
dfs(,);
printf("%I64d\n",res);
}
return ;
}

  参考题解:http://www.cnblogs.com/AOQNRMGYXLMV/p/6579771.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. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  3. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  4. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  5. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  6. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  7. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  8. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

  9. CodeForces - 696B Puzzles

    http://codeforces.com/problemset/problem/696/B 题目大意: 这是一颗有n个点的树,你从根开始游走,每当你第一次到达一个点时,把这个点的权记为(你已经到过不 ...

随机推荐

  1. ModelMap org.springframework.ui.ModelMap

    ModelMap实现了map接口,可以在其中存放属性,作用域同request,同时可与@SessionAttributes联合使用,把数据放入到session中去, 下面这个示例,我们可以在Model ...

  2. 九度oj 题目1050:完数

    题目1050:完数 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8778 解决:3612 题目描述: 求1-n内的完数,所谓的完数是这样的数,它的所有因子相加等于它自身,比如6有3个因子 ...

  3. 轰炸II

    题目背景 本题为轰炸数据加强版 题目描述 一个城市遭到了M次轰炸,每次都炸了一个每条边都与边界平行的矩形 在轰炸后,有N个关键点,指挥官想知道,它们有没有受到过轰炸,如果有,被炸了几次,最后一次是第几 ...

  4. Window-CPU-M Benchmark

    https://downloads.tomsguide.com/CPU-M-Benchmark,0301-48005.html docker FS, DB, ES 很慢,原来是31.26机器又问题,因 ...

  5. J - A Bug's Life 并查集

    Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes ...

  6. [bzoj 1093][ZJOI2007]最大半联通子图(强联通缩点+DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1093 分析: 首先肯定是先把强联通全部缩成一个点,然后成了一个DAG 下面要知道一点: ...

  7. Oracle Multitenant Environment (二) Purpose

    Purpose of a Multitenant Environment A multitenant environment enables the central management of mul ...

  8. Node: Updating npm's bundled node gyp

    Linux, Mac OS X, Solaris, etc. Unix is easy. Just run the following command. Use sudo if necessary. ...

  9. 跳過 Windows RT的UI

    RT启动进入常规桌面 微软Surface RT发布的时间已经不短了,相信很多朋友都已经熟悉了这个全新的平板,并且已经上手.Surface RT开机默认进入的界面为Windows UI,这对于经常使用A ...

  10. MySQL用户及数据安全专题

    1 简单介绍 1.1 概要 1.2 权限分类 2 加入用户     2.1 语法例如以下: CREATE USER user_specification [, user_specification] ...