传送门

给出一棵n" role="presentation" style="position: relative;">nn个点的树,每个点上有Ci" role="presentation" style="position: relative;">CiCi头牛,问每个点k" role="presentation" style="position: relative;">kk步范围内各有多少头牛。

刚看完题惊了这东西不可做啊。

然后就开始想换根dp" role="presentation" style="position: relative;">dpdp,结果没杠出来。

继续读题发现k" role="presentation" style="position: relative;">kk很小啊,才20" role="presentation" style="position: relative;">2020,那这怕不是可以跑一个O(nk)" role="presentation" style="position: relative;">O(nk)O(nk)的算法哦。

然后发现确实可以O(nk)" role="presentation" style="position: relative;">O(nk)O(nk)做出来,方法是这样的。

我们仍然先选一个节点(为了方便我选的就是1" role="presentation" style="position: relative;">11)当根节点,然后用siz[p][k]" role="presentation" style="position: relative;">siz[p][k]siz[p][k]表示出以每个p" role="presentation" style="position: relative;">pp作为根节点的子树中距离p" role="presentation" style="position: relative;">pp不大于k" role="presentation" style="position: relative;">kk的节点的权值和,子树之外的节点都先不管。这个东西是可以先通过儿子的信息先转移出每个p" role="presentation" style="position: relative;">pp作为根节点的子树中距离p" role="presentation" style="position: relative;">pp等于k" role="presentation" style="position: relative;">kk的节点的权值和,然后再跑一边前缀和求出来的,时间复杂度O(nk)" role="presentation" style="position: relative;">O(nk)O(nk),然后对于每一个点u" role="presentation" style="position: relative;">uu,以它作为整个树的根节点时,整棵树的贡献就是沿着u" role="presentation" style="position: relative;">uu到1" role="presentation" style="position: relative;">11的链向上跳,跳到跳不动或者已经跳了k" role="presentation" style="position: relative;">kk步停止,跳的时候用简单的容斥原理统计答案(其实就是累加siz[fa][k]−siz[p][k−1]" role="presentation" style="position: relative;">siz[fa][k]−siz[p][k−1]siz[fa][k]−siz[p][k−1]),时间复杂度仍然是O(nk)" role="presentation" style="position: relative;">O(nk)O(nk)。

代码如下:

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int first[N],n,siz[N][21],cnt=0,dp[N],fa[N],k;
struct Node{int v,next;}e[N<<1];
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
inline void write(int x){
    if(x>9)write(x/10);
    putchar((x%10)^48);
}
inline void dfs(int p){
    for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa[p])continue;
        fa[v]=p;
        dfs(v);
        for(int j=1;j<=k;++j)siz[p][j]+=siz[v][j-1];
    }
}
inline int solve(int p){
    int ret=siz[p][k],pos=k-1;
    while(fa[p]&&pos!=-1){
        ret+=siz[fa[p]][pos]-(pos?siz[p][pos-1]:0);
        --pos,p=fa[p];
    }
    return ret;
}
int main(){
    n=read(),k=read();
    for(int i=1;i<n;++i){
        int u=read(),v=read();
        add(u,v),add(v,u);
    }
    for(int i=1;i<=n;++i)siz[i][0]=read();
    dfs(1);
    for(int i=1;i<=n;++i)for(int j=1;j<=k;++j)siz[i][j]+=siz[i][j-1];
    for(int i=1;i<=n;++i)write(solve(i)),puts("");
    return 0;
}

2018.07.22 洛谷P3047附近的牛(树形dp)的更多相关文章

  1. 洛谷P3047 [USACO12FEB]Nearby Cows(树形dp)

    P3047 [USACO12FEB]附近的牛Nearby Cows 题目描述 Farmer John has noticed that his cows often move between near ...

  2. 2018.07.22 洛谷P2986 伟大的奶牛聚集(树形dp)

    传送门 给出一棵树,树有边权和点权,若选定一个点作为中心,这棵树的代价是所有点权乘上到根的距离的和.求代价最小. 解法:一道明显的换根dp" role="presentation& ...

  3. 2018.07.22 洛谷P4316 绿豆蛙的归宿(概率dp)

    传送门 简单的递推. 由于是DAG" role="presentation" style="position: relative;">DAGDA ...

  4. 2018.07.22 洛谷P1967 货车运输(kruskal重构树)

    传送门 这道题以前只会树剖和最小生成树+倍增. 而现在学习了一个叫做kruskal" role="presentation" style="position: ...

  5. 2018.07.22 洛谷P3106 GPS的决斗Dueling GPS's(最短路)

    传送门 图论模拟题. 这题直接写3个(可以压成一个)spfa" role="presentation" style="position: relative;&q ...

  6. 2018.07.09 洛谷P2365 任务安排(线性dp)

    P2365 任务安排 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间 ...

  7. 洛谷 P3177 [HAOI2015]树上染色 树形DP

    洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...

  8. 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)

    P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...

  9. 2018.07.17 洛谷P1368 工艺(最小表示法)

    传送门 好的一道最小表示法的裸板,感觉跑起来贼快(写博客时评测速度洛谷第二),这里简单讲讲最小表示法的实现. 首先我们将数组复制一遍接到原数组队尾,然后维护左右指针分别表示两个即将进行比较的字符串的头 ...

随机推荐

  1. ABAP-BarCode-2-Excel打印二维码

    以前用Excel打印过二维码看板标签,将实现过程备注下. 1.安装控件 安装文件:TBarCodeOffice.exe 2.控件注册 打开Excel,找到[选项] 在打开的界面选择[加载项],在活动应 ...

  2. windows10配置java开发环境

    一.下载jdk 二.安装jdk路径,这个路径不能包含中文名 三.系统会提示安装jre,安装目录不要是jdk的安装目录,否则会覆盖掉jdk目录下的jre目录 四. .;%JAVA_HOME%\lib;% ...

  3. 原生nodejs 学习笔记1

    网上许多nodejs教程或书藉都是教你调用第三方模块来编写nodejs应用的,虽然这是非常便捷的,但是封装太厚,你基本一点东西还是没有学到.人家的模块,人家想怎么改就行,可以下一版本就改了接口,你的应 ...

  4. Rquest对象代码练习

    1.代码练习 <%@ page language="java" import="java.util.*" pageEncoding="utf-8 ...

  5. ingress 密码验证

    traefik ingress 上面的方式需要引入haprox或者nginx,多引入了一个代理转发层,其实ingress本身就提供了basic auth的支持,在ingress规则中添加额外的认证an ...

  6. 调试PHP如何让浏览器提示错误

    php.ini中的display_errors的值改为On:或者php代码页顶部加上ini_set("display_errors", "On"); error ...

  7. Docker Dockerfile 定制镜像(转)

    转自: https://yeasy.gitbooks.io/docker_practice/ 及 https://blog.csdn.net/wo18237095579/article/details ...

  8. django通过url传递参数(编辑操作页面)

    在做到编辑部分时,想到的办法是在编辑上跳转到页面时给他一个包含唯一标识id的url,然后通过这个url中的id去查询出该条数据,将数据内容显示在编辑页面.   1.编辑按钮 <button on ...

  9. VB 共享软件防破解设计技术初探(三)

    ×××××××××××××××××××××××××××××××××××××××××××××× 其他文章快速链接: VB 共享软件防破解设计技术初探(一)http://bbs.pediy.com/sho ...

  10. Distributing Ballot Boxes

    Distributing Ballot Boxes http://acm.hdu.edu.cn/showproblem.php?pid=4190 Time Limit: 20000/10000 MS ...