JLOI2016 侦查守卫
侦查守卫
小R和B神正在玩一款游戏。这款游戏的地图由 N 个点和 N-1 条无向边组成,每条无向边连接两个点,且地图是连通的。换句话说,游戏的地图是一棵有 N 个节点的树。
游戏中有一种道具叫做侦查守卫,当一名玩家在一个点上放置侦查守卫后,它可以监视这个点以及与这个点的距离在 D 以内的所有点。这里两个点之间的距离定义为它们在树上的距离,也就是两个点之间唯一的简单路径上所经过边的条数。在一个点上放置侦查守卫需要付出一定的代价,在不同点放置守卫的代价可能不同。
现在小R知道了所有B神可能会出现的位置,请你计算监视所有这些位置的最小代价。
对于所有的数据,N<=500000,D<=20
题解
- 状态设计
假设当前到了 x 的子树,现在该合并 x 的第 k 个子树。
f[x][j] 表示 x 的前 k-1 个子树该覆盖的完全覆盖,而且还能向四周覆盖 j 层(不含 x )的最小代价。
对于第 k 个子树的意义就是,兄弟子树放置的守卫可以帮 x 的第 k 个子树覆盖前 j 层(第 1 层为 x 的子节点),那么相应的就要有一个状态来表示这个 可以让兄弟子树帮忙覆盖 的前 j 层。
g[x][j] 表示还需要覆盖 x 的前 k 个子树中的前 j 层(含 x),且第 j 层以下该覆盖的完全覆盖的最小代价。
- 状态转移
要能向 x 的四周覆盖 j 层,只需要 x 的子节点中有一个子节点 z 能向上覆盖 j+1 层即可。所以
f[x][j] = min(f[x][j]+g[y][j] ,f[y][j+1]+g[x][j+1])
g[x][j] += g[y][j-1]
但是有可能更新后 x 能向上恰好覆盖 j 层的代价要小于能向上恰好覆盖 j-1 层的代价;也有可能 x 需要向下覆盖 j 层的代价小于再向下覆盖 j+1 层的代价。
所以将f的状态定义改为 向上覆盖至少j层的最小代价
同理,g的状态定义改为还需要覆盖至多j层的最小代价
所以要对f[x]做一个后缀最小值,g[x]做一个前缀最小值。
时间复杂度\(O(ND)\)。
#include<bits/stdc++.h>
#define co const
#define il inline
template<class T> T read(){
T x=0,w=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-') w=-w;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*w;
}
template<class T> il T read(T&x){
return x=read<T>();
}
using namespace std;
typedef long long LL;
co int N=500000+10,D=21;
int n,dis,w[N],use[N];
vector<int> to[N];
int f[N][D],g[N][D];
void dfs(int x,int fa){
for(int i=1;i<=dis;++i) f[x][i]=w[x];
if(use[x]) g[x][0]=f[x][0]=w[x];
f[x][dis+1]=1e9;
for(int i=0;i<(int)to[x].size();++i){
int y=to[x][i];
if(y==fa) continue;
dfs(y,x);
for(int j=0;j<=dis;++j)
f[x][j]=min(f[x][j]+g[y][j],f[y][j+1]+g[x][j+1]);
for(int j=dis;j>=0;--j)
f[x][j]=min(f[x][j],f[x][j+1]);
g[x][0]=f[x][0];
for(int j=1;j<=dis;++j)
g[x][j]+=g[y][j-1];
for(int j=1;j<=dis;++j)
g[x][j]=min(g[x][j],g[x][j-1]);
}
}
int main(){
read(n),read(dis);
for(int i=1;i<=n;++i) read(w[i]);
for(int m=read<int>();m--;) use[read<int>()]=1;
for(int i=1;i<n;++i){
int x=read<int>(),y=read<int>();
to[x].push_back(y),to[y].push_back(x);
}
dfs(1,0);
printf("%d\n",g[1][0]);
return 0;
}
JLOI2016 侦查守卫的更多相关文章
- [BZOJ4557][JLOI2016]侦查守卫
4557: [JLoi2016]侦察守卫 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 297 Solved: 200[Submit][Status ...
- BZOJ 4557 JLOI2016 侦查守卫 树形dp
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4557 题意概述: 给出一棵树,每个点付出代价w[i]可以控制距离和它不超过d的点,现在给 ...
- BZOJ 4557 (JLOI 2016) 侦查守卫
4557: [JLoi2016]侦察守卫 Time Limit: 20 Sec Memory Limit: 256 MB Submit: 493 Solved: 342 [Submit][Status ...
- loj #2024. 「JLOI / SHOI2016」侦查守卫
#2024. 「JLOI / SHOI2016」侦查守卫 题目描述 小 R 和 B 神正在玩一款游戏.这款游戏的地图由 nnn 个点和 n−1n - 1n−1 条无向边组成,每条无向边连接两个点, ...
- bzoj4557【JLOI2016】侦查守卫
这道题对于我来说并不是特别简单,还可以. 更新一下blog 树形DP f[i][j]表示i的子树中,最高覆盖到i向下第j层的最小花费. g[i][j]表示i的子树全部覆盖,还能向上覆盖j层的最小花费. ...
- BZOJ 4557 侦查守卫
好迷的树形dp... #include<iostream> #include<cstdio> #include<cstring> #include<algor ...
- 【LOJ】#2024. 「JLOI / SHOI2016」侦查守卫
题解 童年的回忆! 想当初,这是我考的第一次省选,我当时初二,我什么都不会,然后看着这个东西,是不是能用我一个月前才会的求lca,光这个lca我就调了一个多小时= =,然后整场五个小时,我觉得其他题不 ...
- 解题:JLOI 2016 侦查守卫
题面 经典的$cov-unc$树形dp(这词是你自己造的吧=.=) 设$cov[i][j]$表示覆盖完$i$的子树后至少向外再覆盖$j$层的最小代价,$unc[i][j]$表示$i$的子树中还剩下至少 ...
- bzoj4557侦查守卫
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4557 树形DP.和“河流”有点像,也有一个类似“承诺”的东西. 就是用 f 表示当前节点向下 ...
随机推荐
- 解决从github上下载代码仓库慢的问题
一,打开命令提示符,最好之前准备一个仓库地址,这样下载下来的文件方便查看,这里打开你想要的下载根目录,进行下载. github上下载代码仓库慢的问题"> 二:复制代码仓库的地址 三:右 ...
- LeetCode 第 14 场双周赛
基础的 api 还是不够熟悉啊 5112. 十六进制魔术数字 class Solution { public: char *lltoa(long long num, char *str, int ra ...
- Python 解leetcode:3. Longest Substring Without Repeating Characters
题目描述:求一个字符串的不含重复字符的最长连续子串的长度: 思路: 使用一个哈希表保存字符出现的位置: 使用left和right分别表示子串的最左和最右字符的下标: 遍历字符串,如果当前字符在哈希表中 ...
- eclipse scala Could not reserve enough space for object heap
[学习笔记] 防盗版实名手机尾号:73203 Could not reserve enough space for object heap 解决方法:下面的缩写中:一个是memory max(Xmx) ...
- (三)mysql SQL 基本操作
文章目录 MySQL服务器对象 mysql 的基本操作 SQL的注释 库操作 表(字段)操作 数据操作 MySQL服务器对象 mysql 服务器对象内部分成了 4 层: 系统(DBMS)----> ...
- ubuntu 连接宽带
ubuntu 连接宽带 链接: https://blog.csdn.net/selous/article/details/55520765 主要命令 pppoeconf pon dsl-provide ...
- wpf 判断项目中的某个窗体是否已经打开或者已经存在
foreach (Window item in Application.Current.Windows) { if (item is window1) return; }
- c# 图文添加文字斜水印 优化
之前一篇给图片加水印的功能,加出来水印的图片位置有一点问题,并且如果图片分辨率有变动的话,水印会有层次不齐的问题. 目前只能优化到增加一条居中显示的斜水印,在不同分辨率不同大小的图片中,都能保证文字水 ...
- javascript 利用数组制作分页效果
代码 参数: pageSize:一页的总数 currentPage:当前的页数 skipNum:跳过的数量 arr:数组 返回值: newArr分页后的数组 var pagination = func ...
- java中long类型转换为int类型
由int类型转换为long类型是向上转换,可以直接进行隐式转换,但由long类型转换为int类型是向下转换,可能会出现数据溢出情况: 主要以下几种转换方法,供参考: 一.强制类型转换 [java] l ...