Codeforces Round #200 (Div. 1)D. Water Tree

Codeforces Round #200 (Div. 1)D. Water Tree

问题描述

给定一棵$n$个节点的树和一个初始值为$0$的容器,你需要进行$ m$次操作。每一次操作都是向某一叶子节点加入一定数量的水,且加入的数量不得为负数。每个非叶子节点的水量是其所有子节点水量之和。每个叶子节点的水量可以是任意非负整数。给定所有操作后,你需要求出每个节点的最终水量。

解题思路

我们可以通过树形动态规划来解决这个问题。

假设$dp[i]$表示 $i$ 节点的水量,$son[i]$表示 $i$ 的儿子节点,$fa[i]$表示 $i$ 的父节点。

对于一个非叶子节点$i$,它的水量只取决于其所有儿子节点的水量之和,即:

$dp[i]=\sum\limits_{j=1}^k dp[son[i][j]]$

对于一个叶子节点$i$,它的水量为其初始值$s_i$加上所有向它加水的数量之和,即:

$dp[i]=s_i+\sum\limits_{j=1}^k c_j$

其中$c_j$表示第$j$次向节点$i$加水的数量。

我们可以按照题目要求模拟每一次向节点加入水的过程。具体而言,设$u$为向该节点加水的叶子节点,$w$为加入的水量,则:

  • 将$s_u$加上$w$;
  • 向父节点$f$进行递归,使得其水量加上$w$;
  • 最后使用dfs进行$dp$数组的树形DP。

代码实现

下面是实现了上述思路的C++代码:

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int n,m,root,cnt,tot,head[MAXN],dfn[MAXN],leaf[MAXN],size[MAXN],son[MAXN],fa[MAXN],siz[MAXN],sizs[MAXN];
int w[MAXN];
bool v[MAXN];
struct Edge {
    int to,nxt;
} e[MAXN<<1];
inline int read() {
    int x=0,f=1; char c;
    while(!isdigit(c=getchar())) f=c=='-'?-1:1;
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
inline void add_edge(int u,int v) {
    e[++cnt]=(Edge){v,head[u]};
    head[u]=cnt;
}
inline void dfs1(int u,int fa) {
    dfn[++tot]=u;
    siz[u]=1;
    for(int i=head[u],v; i; i=e[i].nxt) {
        if((v=e[i].to)^fa) {
            dfs1(v,u);
            siz[u]+=siz[v];
            if(siz[v]>siz[son[u]]) son[u]=v;
        }
    }
}
inline void dfs2(int u,int fa,int topf) {
    fa[u]=topf,sizs[u]=w[u];
    if(son[u]) dfs2(son[u],u,topf),sizs[u]+=sizs[son[u]];
    for(int i=head[u],v; i; i=e[i].nxt) {
        if((v=e[i].to)^son[u] && v^fa[u]) dfs2(v,u,v);
    }
}
inline void dfs3(int u,int fa) {
    for(int i=head[u],v; i; i=e[i].nxt) {
        if((v=e[i].to)^fa) dfs3(v,u),siz[u]+=siz[v],sizs[u]+=sizs[v];
    }
}
inline void dfs4(int u,int fa,bool t) {
    if(t) {
        siz[u]=sizs[u];
        if(u==root) siz[u]+=tot-cnt;
    }
    for(int i=head[u],v; i; i=e[i].nxt) {
        if((v=e[i].to)^fa && (!son[u] || v^son[u])) dfs4(v,u,1);
    }
    if(t) {
        if(!son[u]) leaf[++leaf[0]]=u;
        if(u!=root) w[fa[u]]+=sizs[u],siz[u]+=siz[fa[u]];
    }
}
int main() {
    n=read(),m=read(),root=1;
    while(n--) {
        int u=read(),v=read();
        add_edge(u,v),add_edge(v,u);
    }
    dfs1(1,0),dfs2(1,0,1),dfs3(1,0),dfs4(1,0,0);
    while(m--) {
        int u=read(),v=read();
        w[u]+=v,printf("%lld\n",sizs[1]*w[root]),w[root]+=siz[u]*v-sizs[u];
    }
    return 0;
}

总结

"Codeforces Round #200 (Div. 1)D. Water Tree"这道题较难理解。我们可以通过模拟每一次向节点加水的过程来解决问题。需要注意的是,在计算非叶子节点的水量时,我们只需要遍历其所有的儿子节点即可。而在计算叶子节点的水量时,我们还需要累加所有向他加水的数量。完整的代码可以在Codeforces平台上找到该题目的原题链接进行提交以获得AC。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Codeforces Round #200 (Div. 1)D. Water Tree - Python技术站

(0)
上一篇 2023年3月28日
下一篇 2023年3月28日

相关文章

  • Python实现账号密码输错三次即锁定功能简单示例

    实现账号密码输错三次即锁定功能,可以使用Python中的数据结构和流程控制语句来完成。具体实现步骤如下: 1. 定义一个字典来存储账号和对应的密码 users = {‘Tom’:’123′, ‘Jerry’:’456′, ‘Bob’:’789′} 2. 循环询问用户输入账号和密码,并进行校验 使用while循环可以反复循环询问用户的账号和密码。使用if语句和…

    other 2023年6月27日
    00
  • 浅谈Python中的数据类型

    当我们在使用Python进行开发时,深入了解数据类型是非常重要的一步。在Python中,常用的数据类型包括数字、字符串、列表、元组、字典和集合等。本文将结合示例详细介绍Python中的数据类型。 数字类型 Python中的数字类型包括整数、浮点数和复数。其中整数和浮点数是我们最常用的数据类型。 整数 Python中的整数可以表示任意大小的整数,例如: x =…

    other 2023年6月27日
    00
  • eclipse如何创建web项目

    Eclipse如何创建Web项目 Eclipse是一种常用的集成开发环境(IDE),它可以帮助开发者更高效地写Java Web应用程序。本文将介绍如何在Eclipse中创建Web项目,提供两个示例说明。 步骤一:安装Eclipse 首先,我们需要从Eclipse官网下载Eclipse的最新版本,按照官方文档进行安装。 步骤二:创建Web项目 以下是一些常用的…

    other 2023年5月9日
    00
  • 网络通信-基本概念:网络、IP地址、端口、socket

    网络通信-基本概念:网络、IP地址、端口、socket 网络 网络是指两个或两个以上计算机设备间互相连接的通讯系统。网络的发展改变了人们之间的交流方式,它不仅能够将人们连接在一起,而且还能实现大规模信息交流。 IP地址 IP地址是指分配给网络上连接设备的唯一地址,用于在互联网中定位和寻找设备。它是一串用于标识设备的数字,分为IPv4和IPv6两种格式。IPv…

    其他 2023年3月28日
    00
  • es批量更新数据刷新

    es批量更新数据刷新 Elasticsearch(简称ES)被广泛应用在各种大数据应用场景中,基于其出色的搜索能力、灵活的数据结构和高性能的存储和检索能力而倍受青睐。在使用 ES 过程中,数据的批量更新和刷新是非常常见的操作,可以提高数据变更的效率和速度,本文将介绍 ES 批量更新数据刷新的具体实现方法。 什么是ES批量更新数据刷新 ES的一个特点就是,当文…

    其他 2023年3月29日
    00
  • SQl 语句(常见)

    SQL(Structured Query Language)是一种用于管理关系型数据库的语言。它是一种标准化的语言,基本规则适用于大多数数据库管理系统(DBMS)。在本篇文章中,我们将详细讲解常见的SQL语句,以及它们的作用和用法。 数据库的常见 SQL 语句 CREATE CREATE语句用于在数据库中创建新的表格、视图或者存储过程。 示例1 CREATE…

    other 2023年6月25日
    00
  • mac卸载nodejs

    Mac环境下卸载Node.js的方法 在Mac环境下,卸载Node.js可能并不是那么简单,可能需要多步骤进行操作。下面,我们将通过一系列步骤来带你了解Mac环境下如何卸载Node.js。 确认你已经安装了Node.js 在卸载Node.js之前,我们需要确认是否已经安装了Node.js。我们可以使用node -v命令来检查当前是否已经安装了Node.js。…

    其他 2023年3月28日
    00
  • 关于c#:计算两个日期之间的差异(天数)?

    以下是关于在C#中计算两个日期之间的差异(天数)的完整攻略,包括基本知识和两个示例。 基本知识 在C#中,使用DateTime类型来表示日期和时间。要计算两个日期之间的差异(天数),可以使用DateTime类型的Subtract方法。Subtract方法返回TimeSpan类型的对象,表示两个日期之间的时间间隔。可以使用TimeSpan类型的Days属性来获…

    other 2023年5月7日
    00
合作推广
合作推广
分享本页
返回顶部