luogu P2605 [ZJOI2010]基站选址
先考虑朴素dp,设\(f_{i,j}\)表示在第\(i\)个村庄放了基站,一共放了\(j\)次,且只考虑前面村庄影响的答案.这里可以把\(j\)放在外面枚举,然后从\(f_{k,j-1}(k<i)\)转移到\(f_{i,j}\)
这里对于每个村庄,能影响它的基站是在一个区间里的,我们先二分找出能影响到它的最左边以及最右边基站位置.然后转移的时候还要考虑一些没被覆盖的村庄的代价,对于\(x\)村庄,如果\(k<L_x\)并且\(i>R_x\),那么要加上\(w_x\)的代价.考虑优化此过程,我们把\(f_{k,j-1}\)的贡献放在以\(k\)为下标的线段树上,每次取前缀最大值转移.然后如果处理完当前的\(i\),然后有些村庄的\(R_x=i\),那么以后的转移放的基站都不能直接覆盖\(x\)了,那么从\(<L_x\)转移过来的基站都要加上\(w_x\)的代价,线段树区间加即可.然后贡献答案是要加上后面没被覆盖的村庄代价
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define db double
using namespace std;
const int N=20000+10;
const LL inf=1ll<<40;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n,kk,d[N],p[N][2];
LL f[2][N],dt[N],ans,c[N],w[N];
vector<int> op[N],ad[N];
vector<int>::iterator it;
LL mi[N<<2],tg[N<<2];
void add(int o,LL x){mi[o]+=x,tg[o]+=x;}
void psdn(int o){if(tg[o]) add(o<<1,tg[o]),add(o<<1|1,tg[o]),tg[o]=0;}
void psup(int o){mi[o]=min(mi[o<<1],mi[o<<1|1]);}
void modifc(int o,int l,int r,int lx,LL x)
{
if(l==r){mi[o]=x;return;}
psdn(o);
int mid=(l+r)>>1;
if(lx<=mid) modifc(o<<1,l,mid,lx,x);
else modifc(o<<1|1,mid+1,r,lx,x);
psup(o);
}
void modifa(int o,int l,int r,int ll,int rr,LL x)
{
if(ll<=l&&r<=rr){add(o,x);return;}
psdn(o);
int mid=(l+r)>>1;
if(ll<=mid) modifa(o<<1,l,mid,ll,rr,x);
if(rr>mid) modifa(o<<1|1,mid+1,r,ll,rr,x);
psup(o);
}
LL quer(int o,int l,int r,int ll,int rr)
{
if(ll<=l&&r<=rr) return mi[o];
psdn(o);
LL an=inf,mid=(l+r)>>1;
if(ll<=mid) an=min(an,quer(o<<1,l,mid,ll,rr));
if(rr>mid) an=min(an,quer(o<<1|1,mid+1,r,ll,rr));
psup(o);
return an;
}
int main()
{
n=rd(),kk=rd();
for(int i=2;i<=n;++i) d[i]=rd();
for(int i=1;i<=n;++i) c[i]=rd();
for(int i=1;i<=n;++i)
{
int x=rd();
p[i][0]=i;
int l=1,r=i-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(d[i]-d[mid]<=x) p[i][0]=mid,r=mid-1;
else l=mid+1;
}
p[i][1]=i;
l=i+1,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(d[mid]-d[i]<=x) p[i][1]=mid,l=mid+1;
else r=mid-1;
}
ad[p[i][0]].push_back(i);
op[p[i][1]].push_back(i);
}
int nw=1,la=0;
for(int i=0;i<=n;++i) f[0][i]=f[1][i]=inf;
f[la][0]=0;
for(int i=1;i<=n;++i)
{
w[i]=rd();
ans+=w[i];
}
for(int i=n,dd=0;i;--i)
{
dt[i]=dd;
for(it=ad[i].begin();it!=ad[i].end();++it) dd+=w[*it];
}
while(kk--)
{
modifc(1,0,n,0,f[la][0]);
for(int i=1;i<=n;++i)
{
f[nw][i]=quer(1,0,n,0,i-1)+c[i];
ans=min(ans,f[nw][i]+dt[i]);
modifc(1,0,n,i,f[la][i]);
for(it=op[i].begin();it!=op[i].end();++it) modifa(1,0,n,0,p[*it][0]-1,w[*it]);
}
for(int i=0;i<=n;++i) f[la][i]=inf;
nw^=1,la^=1;
}
printf("%lld\n",ans);
return 0;
}
luogu P2605 [ZJOI2010]基站选址的更多相关文章
- 【题解】Luogu P2605 [ZJOI2010]基站选址
原题传送门:P2604 [ZJOI2010]基站选址 看一眼题目,变知道这题一定是dp 设f[i][j]表示在第i个村庄修建第j个基站且不考虑i+1~n个村庄的最小费用 可以得出f[i][j] = M ...
- luogu P2605 [ZJOI2010]基站选址 线段树优化dp
LINK:基站选址 md气死我了l达成1结果一直调 显然一个点只建立一个基站 然后可以从左到右进行dp. \(f_{i,j}\)表示强制在i处建立第j个基站的最小值. 暴力枚举转移 复杂度\(n\cd ...
- P2605 [ZJOI2010]基站选址
题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄不超过Si的范 ...
- 洛谷$P2605\ [ZJOI2010]$基站选址 线段树优化$dp$
正解:线段树优化$dp$ 解题报告: 传送门$QwQ$ 难受阿,,,本来想做考试题的,我还造了个精妙无比的题面,然后今天讲$dp$的时候被讲到了$kk$ 先考虑暴力$dp$?就设$f_{i,j}$表示 ...
- 【LG2605】[ZJOI2010]基站选址
[LG2605][ZJOI2010]基站选址 题面 洛谷 题解 先考虑一下暴力怎么写,设\(f_{i,j}\)表示当前\(dp\)到\(i\),且强制选\(i\),目前共放置\(j\)个的方案数. 那 ...
- 题解 [ZJOI2010]基站选址
题解 [ZJOI2010]基站选址 题面 解析 首先考虑一个暴力的DP, 设\(f[i][k]\)表示第\(k\)个基站设在第\(i\)个村庄,且不考虑后面的村庄的最小费用. 那么有\(f[i][k] ...
- [ZJOI2010]基站选址,线段树优化DP
G. base 基站选址 内存限制:128 MiB 时间限制:2000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离 ...
- bzoj 1835/luogu P2605 : [ZJOI2010]base 基站选址
题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄不超过Si的范 ...
- 题解 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 ...
随机推荐
- UFLDL(Unsupervised Feature Learning and Deep Learning)
UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...
- Python基于Pymssql模块实现连接SQL Server数据库的方法
首先,安装pymssql第三方库pip install pymssql 其次,导入pymssql库 最后们就可以连接数据库了 import pymssql server = "10.10.9 ...
- 用js脚本实现链接
使用json实现分页的时候,扩展了一下如何使用JS现实链接,其实很简单,但是之前我没用过... 就以分页的上一页,下一页来举例: <script type="text/javascri ...
- [shell]上一个命令执行完成,才执行下一个操作 | shell脚本中判断上一个命令是否执行成功
shell脚本中判断上一个命令是否执行成功 shell中使用符号“$?”来显示上一条命令执行的返回值,如果为0则代表执行成功,其他表示失败.结合if-else语句实现判断上一个命令是否执行成功. 场 ...
- JAVA记事本的图形用户界面应用程序含过滤
JAVA记事本的图形用户界面应用程序 过滤 题目简介: 整体分析: 实验代码: package note; import java.awt.EventQueue; import java.awt.ev ...
- rocketmq的windows版客户端的启动步骤
一.下载RocketMQ首先,我们去下载RocketMQ,RocketMQ 是一个开源的东西,可以去github上面下载,地址是:https://github.com/alibaba/RocketMQ ...
- ButterKnifer使用
ButterKnifer使用 1.集成 github地址: https://github.com/JakeWharton/butterknife 1.1在主Moduel中的使用 在主moduel中的b ...
- php文件上传系统
一般10M以下的文件上传通过设置Web.Config,再用VS自带的FileUpload控件就可以了,但是如果要上传100M甚至1G的文件就不能这样上传了.我这里分享一下我自己开发的一套大文件上传控件 ...
- 使用shell脚本常见的一些问题
Jdk版本:jdk-8u102-linux-x64 Tomcat版本:apache-tomcat-7.0.92 Redis版本:redis-5.0.0 由于公司项目的需要,要在多台服务器上面部署一些应 ...
- 从内存上看python的对象
python中有一个说法:一切皆是对象,怎么理解这句话呢?我们可以通过查看数字,字符串在内存中的表示形式来对这句话有个更深的认识. 那么,怎么查看对象在内存中是什么样的呢?可以先参考一些这篇文章:ht ...