题解 [ZJOI2010]基站选址

题面

解析

首先考虑一个暴力的DP,

设\(f[i][k]\)表示第\(k\)个基站设在第\(i\)个村庄,且不考虑后面的村庄的最小费用.

那么有\(f[i][k]=\min(f[j][k-1]+cost(j,i))\),\(j\in[1,i-1]\)

其中\(cost(j,i)\)表示从\(j\)到\(i\)中间没有被覆盖的村庄的补偿.

但这显然会T...

首先可以考虑优化掉\(k\),

直接因为只有\(k-1\)有影响,直接提出来放外面循环就行了.

然后要优化掉\(cost(j,i)\)以及找到最小值,

这个可以用线段树来做.

具体来说,首先我们要找到能覆盖村庄\(i\)的最远的两个端点\(st[i]\)(左)和\(ed[i]\)(右)

如果当前到了\(i\)村庄,那么\(ed\)等于\(i\)的村庄\(x\),

在\(i+1\)到\(n\)的计算中,

就要被算到\(1\)到\(st[x]-1\)的村庄的\(cost\)中去了.

因此用邻接表存\(ed\)等于\(i\)的村庄,

再拿一个线段树区间加及求区间最小值就行了.

(线段树中的点\(j\)存的是\(f[j]+\)对以后有贡献的\(cost\))

注意:

  • 因为状态没有考虑后面的村庄,所以要在最后面加一个,距离设为inf(同时\(k\)也要++)
  • 每次新建一棵线段树,记得清空\(tag\)(WA到吐)

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
#define ls(a) a<<1
#define rs(a) a<<1|1
using namespace std; inline int read(){
int sum=0,f=1;char c=getchar();
while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0'){sum=(sum<<3)+(sum<<1)+c-'0';c=getchar();}
return sum*f;
} const int N=20005;
const int M=201;
const int INF=0x3f3f3f3f;
struct tree{int tag,minn,l,r;}t[N<<4];
struct edge{int to,next;}e[N<<1];
int n,K,d[N],c[N],s[N],w[N],f[N];
int st[N],ed[N];
int head[N],cnt; inline void pushup(int p){
t[p].minn=min(t[ls(p)].minn,t[rs(p)].minn);
} inline void pushdown(int p){
t[ls(p)].minn+=t[p].tag;
t[rs(p)].minn+=t[p].tag;
t[ls(p)].tag+=t[p].tag;
t[rs(p)].tag+=t[p].tag;
t[p].tag=0;
} inline void build(int p,int l,int r){
t[p].l=l;t[p].r=r;t[p].tag=0;
if(l==r){
t[p].minn=f[l];
return ;
}
int mid=(l+r)>>1;
build(ls(p),l,mid);build(rs(p),mid+1,r);
pushup(p);
} inline void change(int p,int l,int r,int sum){
if(l>r) return ;
if(t[p].l>=l&&t[p].r<=r){
t[p].minn+=sum;t[p].tag+=sum;
return ;
}
pushdown(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid) change(ls(p),l,r,sum);
if(r>mid) change(rs(p),l,r,sum);
pushup(p);
} inline int query(int p,int l,int r){
if(l>r) return INF;
if(t[p].l>=l&&t[p].r<=r) return t[p].minn;
pushdown(p);
int mid=(t[p].l+t[p].r)>>1,ret=INF;
if(l<=mid) ret=min(ret,query(ls(p),l,r));
if(r>mid) ret=min(ret,query(rs(p),l,r));
pushup(p);
return ret;
} inline void add(int x,int y){
e[++cnt]=(edge){head[x],y};head[x]=cnt;
} signed main(){
n=read();K=read();
for(int i=2;i<=n;i++) d[i]=read();
for(int i=1;i<=n;i++) c[i]=read();
for(int i=1;i<=n;i++) s[i]=read();
for(int i=1;i<=n;i++) w[i]=read();
d[++n]=INF;
for(int i=1;i<=n;i++){
st[i]=lower_bound(d+1,d+n+1,d[i]-s[i])-d;
ed[i]=upper_bound(d+1,d+n+1,d[i]+s[i])-d-1;
add(ed[i],i);
}
int ret=0;
for(int i=1;i<=n;i++){
f[i]=ret+c[i];
for(int j=head[i];j;j=e[j].to){
int k=e[j].next;ret+=w[k];
}
}
ret=f[n];
for(int q=1;q<=K;q++){
build(1,1,n);
for(int i=1;i<=n;i++){
f[i]=query(1,1,i-1)+c[i];
for(int j=head[i];j;j=e[j].to){
int k=e[j].next;
change(1,1,st[k]-1,w[k]);
}
}
ret=min(ret,f[n]);
}
printf("%lld\n",ret);
return 0;
}

题解 [ZJOI2010]基站选址的更多相关文章

  1. 【题解】Luogu P2605 [ZJOI2010]基站选址

    原题传送门:P2604 [ZJOI2010]基站选址 看一眼题目,变知道这题一定是dp 设f[i][j]表示在第i个村庄修建第j个基站且不考虑i+1~n个村庄的最小费用 可以得出f[i][j] = M ...

  2. 【LG2605】[ZJOI2010]基站选址

    [LG2605][ZJOI2010]基站选址 题面 洛谷 题解 先考虑一下暴力怎么写,设\(f_{i,j}\)表示当前\(dp\)到\(i\),且强制选\(i\),目前共放置\(j\)个的方案数. 那 ...

  3. luogu P2605 [ZJOI2010]基站选址 线段树优化dp

    LINK:基站选址 md气死我了l达成1结果一直调 显然一个点只建立一个基站 然后可以从左到右进行dp. \(f_{i,j}\)表示强制在i处建立第j个基站的最小值. 暴力枚举转移 复杂度\(n\cd ...

  4. [ZJOI2010]基站选址,线段树优化DP

    G. base 基站选址 内存限制:128 MiB 时间限制:2000 ms 标准输入输出 题目类型:传统 评测方式:文本比较   题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离 ...

  5. 题解 P2605 【[ZJOI2010]基站选址】(From luoguBlog)

    线段树优化dp 数组f[i][j]表示在前i个村庄内,第j个基站建在i处的最小费用 根据交线牛逼法和王鹤松式可得方程 f[i][j]=min(f[k][j−1]+cost(k,i)) cost(k,i ...

  6. bzoj 1835: [ZJOI2010]基站选址

    Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...

  7. [ZJOI2010]基站选址

    题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄不超过Si的范 ...

  8. BZOJ1835 [ZJOI2010] 基站选址 【动态规划】【线段树】

    题目分析: 首先想一个DP方程,令f[m][n]表示当前在前n个村庄选了m个基站,且第m个基站放在n处的最小值,转移可以枚举上一个放基站的村庄,然后计算两个村庄之间的代价. 仔细思考两个基站之间村庄的 ...

  9. zjoi2010基站选址

    线段树优化dp 题解: 首先dp挺简单的 f[i,k]=f[j,k-1]+solve(i+1,j-1) 然后这个是可以n^2*k搞得 然后考虑这个solve(i+1,j-1) 当i延伸了一个位置的时候 ...

随机推荐

  1. 1254: 盒子游戏(Java)

    WUSTOJ 1254: 盒子游戏 参考博客 叶剑飞Victor的博客 盒子游戏--爱程序网 原理是从上面博客看的,我另外补充了几幅图,方便理解 Description 有两个相同的盒子,其中一个装了 ...

  2. asp.net core-13.Cookie-based认证实现

    1.打开visual studio code创建一个MVC项目

  3. MySQL 5.7 多源复制实践

    多源复制使用场景 数据分析部门会需要各个业务部门的部分数据做数据分析,这个时候就可以用到多源复制把各个主数据库的数据复制到统一的数据库中. 在从服务器进行数据汇总,如果我们的主服务器进行了分库分表的操 ...

  4. Centos7.3 为php7 安装swoole 扩展

    今天心血来潮想在服务器上安装一下swoole扩展  下面列一下教程: xshell进入你的服务器  然后目录自选吧  反正我放在根目录了 下面是扩展链接: wget https://github.co ...

  5. Java Web 深入分析(1)B/S架构概述

    B/S结构即浏览器和服务器结构.它是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构.在这种结构下,用户工作界面是通过WWW浏览器来实现,极少部分事务逻辑在前端(Browser)实 ...

  6. div上中下布局中间自适应

    需求1: 头尾固定高度,中间自适应 1.上部(header)Div高度固定100px,宽度100%: 2.下部(footer)Div高度固定100px,宽度100%: 3.中部(middle)DIV高 ...

  7. 使用帅气的cordic算法进行坐标系互转及log10的求解

    参考博客 https://blog.csdn.net/u010712012/article/details/77755567 https://blog.csdn.net/Reborn_Lee/arti ...

  8. Go微服务 grpc的简单使用

    作者:薇文文链接:https://www.jianshu.com/p/20ed82218163来源:简书 准备工作 先安装Protobuf 编译器 protoc,下载地址:https://github ...

  9. 【Distributed】网站跨域解决方案

    一.概述 1.1 什么是网站跨域 1.2 网站跨域报错案例 二.五种网站跨域解决方案 三.使用JSONP解决网站跨域[1] 3.1 前端代码 3.2 后端代码 四.使用设置响应头允许跨域[2] 4.1 ...

  10. Computer Vision_18_Image Stitching: Image Alignment and Stitching——2006

    此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...