基站选址(base.c/cpp/pas)
基站选址(base.c/cpp/pas)
题目描述
有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di。需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci。如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了。如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi。现在的问题是,选择基站的位置,使得总费用最小。
输入
输入文件的第一行包含两个整数N,K,含义如上所述。
第二行包含N-1个整数,分别表示D2,D3,…,DN ,这N-1个数是递增的。
第三行包含N个整数,表示C1,C2,…CN。
第四行包含N个整数,表示S1,S2,…,SN。
第五行包含N个整数,表示W1,W2,…,WN。
输出
输出文件中仅包含一个整数,表示最小的总费用。
样例输入
1 2
2 3 2
1 1 0
10 20 30
样例输出
4
提示
40%的数据中,N<=500;
100%的数据中,K<=N,K<=100,N<=20,000,Di<=1000000000,Ci<=10000,Si<=1000000000,Wi<=10000。
solution
先列出DP式
f[i][j]表示当前建到i(i必建),已经建了j个的最小代价
f[i][j]=f[k][j-1]+cost(k+1,i-1)+c[i];
效率O(n^3)
因为j只和j-1有关,我们可以先枚举j,对于每一个j,考虑优化cost(k+1,i-1):
令l[i]为最左的能覆盖i的基站的位置,r[i]同理
用线段树存1~i-1 f[k][j-1]+cost(k+1,i-1 ) 的值
处理完i,将要加入i+1时对于r[x]=i的点显然无法被从右边覆盖,那么将1~l[x]-1加上w[x],
也就是如果f[i+1]由f[k]转移来,且k<l[x],那么x就不会被覆盖了,cost要加上w[x].
线段树维护区间加,单点查
效率O(nlogn)
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#define maxn 200005
#define inf 900000000
using namespace std;
int n,k,dp[maxn],d[maxn],c[maxn],s[maxn],w[maxn],lm[maxn],rm[maxn];
int x,tot,head[maxn];
struct node{
int nex,v;
}e[maxn*2];
struct no
{
int l,r,x,bj;
}tree[maxn*4];
void lj(int t1,int t2)
{
e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
}
void get(int k)
{
int l=1,r=k;
x=d[k];
while(l<r)
{
int mid=(l+r)/2;
if(x-d[mid]<=s[k])r=mid;
else l=mid+1;
}
lm[k]=l;
l=k,r=n;
while(l<r)
{
int mid=(l+r+1)/2;
if(d[mid]-x<=s[k])l=mid;
else r=mid-1;
}
rm[k]=l;
lj(l,k);
}
void wh(int k)
{
tree[k].x=min(tree[k*2].x,tree[k*2+1].x);
}
void build(int k,int L,int R)
{
tree[k].l=L,tree[k].r=R;tree[k].bj=0;
if(L==R){
tree[k].x=dp[L];
return;
}
int mid=(L+R)/2;
build(k*2,L,mid);build(k*2+1,mid+1,R);
wh(k);
}
void down(int k)
{
if(tree[k].bj>0)
{
tree[k*2].bj+=tree[k].bj;tree[k*2+1].bj+=tree[k].bj;
tree[k*2].x+=tree[k].bj;tree[k*2+1].x+=tree[k].bj;
tree[k].bj=0;
}
}
int ask(int k,int L,int R)
{
if(L>R)return 0;
down(k);
if(tree[k].l>=L&&tree[k].r<=R)
{
return tree[k].x;
}
int mid=(tree[k].l+tree[k].r)/2;
int u=inf;
if(L<=mid)u=min(u,ask(k*2,L,R));
if(R>mid)u=min(u,ask(k*2+1,L,R));
return u;
}
void lian(int k,int L,int R,int v)
{
if(L>R)return;
down(k);
if(tree[k].l>=L&&tree[k].r<=R)
{
tree[k].bj+=v;
tree[k].x+=v;
return;
}
int mid=(tree[k].l+tree[k].r)/2;
if(L<=mid)lian(k*2,L,R,v);
if(R>mid)lian(k*2+1,L,R,v);
wh(k);
}
int ss()
{
char ch;int v=0;
while(!isdigit(ch=getchar()));v=v+ch-'0';
while(isdigit(ch=getchar()))v=(v<<1)+(v<<3)+ch-'0';
return v;
}
int main()
{
n=ss();k=ss();
for(int i=2;i<=n;i++)d[i]=ss();
for(int i=1;i<=n;i++)c[i]=ss();
for(int i=1;i<=n;i++)s[i]=ss();
for(int i=1;i<=n;i++)w[i]=ss();
n++;d[n]=inf;
for(int i=1;i<=n;i++)get(i);
int tmp=0;
for(int i=1;i<=n;i++){
dp[i]=tmp+c[i];
int p=head[i];
while(p!=0)
{
tmp+=w[e[p].v];
p=e[p].nex;
}
}
int ans=dp[n];
for(int i=2;i<=k+1;i++)
{
build(1,1,n);
for(int j=1;j<=n;j++){
dp[j]=ask(1,1,j-1)+c[j];
int p=head[j];
while(p!=0){
lian(1,1,lm[e[p].v]-1,w[e[p].v]);
p=e[p].nex;
}
}
ans=min(ans,dp[n]);
}
cout<<ans<<endl;
return 0;
}
基站选址(base.c/cpp/pas)的更多相关文章
- BZOJ 1835: [ZJOI2010]base 基站选址 [序列DP 线段树]
1835: [ZJOI2010]base 基站选址 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立 ...
- 【BZOJ1835】[ZJOI2010]base 基站选址 线段树+DP
[BZOJ1835][ZJOI2010]base 基站选址 Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯 ...
- [ZJOI2010]基站选址,线段树优化DP
G. base 基站选址 内存限制:128 MiB 时间限制:2000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离 ...
- 【Bzoj 1835 基站选址】
基站选址的区间里隐藏着DP优化的机密…… 分析: 不论是做过乘积最大还是石子合并,或者是其他的入门级别的区间DP题目的人呐,大米并认为读题后就能够轻松得出一个简洁明了的Dp转移方程. ...
- 【题解】Luogu P2605 [ZJOI2010]基站选址
原题传送门:P2604 [ZJOI2010]基站选址 看一眼题目,变知道这题一定是dp 设f[i][j]表示在第i个村庄修建第j个基站且不考虑i+1~n个村庄的最小费用 可以得出f[i][j] = M ...
- Problem B. Market(market.c/cpp/pas)
Problem B. Market(market.c/cpp/pas)Time limit: 1 secondsMemory limit: 128 megabytes在比特镇一共有 n 家商店,编号依 ...
- 【BZOJ1835】基站选址(线段树)
[BZOJ1835]基站选址(线段树) 题面 BZOJ 题解 考虑一个比较暴力的\(dp\) 设\(f[i][j]\)表示建了\(i\)个基站,最后一个的位置是\(j\)的最小代价 考虑如何转移\(f ...
- 公路建设 (highway.c/cpp/pas)
2.公路建设 (highway.c/cpp/pas) 在滨海市一共有 n 个城市,编号依次为 1 到 n,它们之间计划修建 m 条双向道路,其中 修建第 i 条道路的费用为 ci. 海霸王作为滨海市公 ...
- 商店购物 (shopping.c/cpp/pas)
1.商店购物 (shopping.c/cpp/pas) 在滨海市开着 n 家商店,编号依次为 1 到 n,其中编号为 1 到 m 的商店有日消费量上 限,第 i 家商店的日消费量上限为 wi. 海霸王 ...
随机推荐
- Linux添加swap分区
swap分区的作用为当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用,那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到S ...
- MyEclipse的快捷键大全(超级实用,方便)
常用快捷键 1. [ALT+/] 能为用户提供内容的辅助,不要为记不全方法和属性名称犯愁,当记不全类.方法和属性的名字时,多体验一下[ALT+/]快捷键带来的好处吧. 2. [Ctrl+O] 显示类 ...
- 判断移动端和pc端最简单的方法
<!DOCTYPE html><html><head> <title></title> <script type="text ...
- Java面试宝典2017版
1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法. 1.一个".java&qu ...
- scrapy之分布式
分布式爬虫 概念:多台机器上可以执行同一个爬虫程序,实现网站数据的分布爬取. 原生的scrapy是不可以实现分布式爬虫? a) 调度器无法共享 b) 管道无法共享 工具 scrapy-redis组件: ...
- 残留的linux相关笔记
1. 设置网络环境1) 设置宿主机网络环境#ifconfig eth1 192.168.16.111 2) 设置开发板网络环境>pri>setenv ipaddr 192.168.16.2 ...
- TouTiao开源项目 分析笔记15 新闻详情之两种类型的实现
1.预览效果 1.1.首先看一下需要实现的效果. 第一种,文字类型新闻. 第二种,图片类型新闻. 1.2.在NewsArticleTextViewBinder中设置了点击事件 RxView.click ...
- 7 Django分页器文章分页
1.复习 2.这节课要解决的问题? 3.分页的原理 4.准备工作 (1)创建Django项目 C:\Users\Administrator\Desktop\root3>django-admin ...
- CentOS 7.X 设置系统时间
在CentOS 6版本,时间设置有date.hwclock命令, 硬件时钟和系统时钟 (1) 硬件时钟 RTC(Real-Time Clock)或CMOS时钟,一般在主板上靠电池供电,服务器断电后也会 ...
- 常见算法用Pascal实现
基本算法 这些都是非常基本的的算法,希望所有学习的人都能理解! 1.数论算法 求两数的最大公约数 function gcd(a,b:integer):integ ...