Description

有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di。需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci。如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了。如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi。现在的问题是,选择基站的位置,使得总费用最小。 输入数据 (base.in) 输入文件的第一行包含两个整数N,K,含义如上所述。 第二行包含N-1个整数,分别表示D2,D3,…,DN ,这N-1个数是递增的。 第三行包含N个整数,表示C1,C2,…CN。 第四行包含N个整数,表示S1,S2,…,SN。 第五行包含N个整数,表示W1,W2,…,WN。

Input

输出文件中仅包含一个整数,表示最小的总费用。

Output

3 2 1 2 2 3 2 1 1 0 10 20 30

Sample Input

4

Sample Output

40%的数据中,N<=500;
100%的数据中,K<=N,K<=100,N<=20,000,Di<=1000000000,Ci<=10000,Si<=1000000000,Wi<=10000。

HINT

Source

Day1

考虑转移方程,我们滚掉了第一维k:

其中cost(j+1,i)表示[j+1,i]之间不能覆盖的点的∑wi;

这样直接转移是n^3*k的,不行。。。

我们发现cost(j+1,i)特别不好算,我们需要改变计算方法;

我们记L[x]表示标号最小的能覆盖x的位置,R[x]表示标号最大的能覆盖x的位置;

我们只要在[L[x],R[x]]之间修基站,都不会付出w[x]的代价,但是一旦当前枚举的基站点i跨过R[x],从[1,L[x]-1]开始转移的dp值都需要加上w[x]的代价;

那么我们相当于进行一次区间加法操作,在每个右端点开一个vector,然后区间修改,zzd的某个联赛模拟题和这个计算代价的思想很像;

具体实现的话就是分k次更新,每次重新build;

注意末尾增加一个d[n+1]=Inf,w[n+1]=Inf的点,然后把k+1,可以免去末尾没有覆盖完的一系列特判;

//MADE BY QT666
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define lson x<<1
#define rson x<<1|1
using namespace std;
typedef long long ll;
const int N=100050;
const ll Inf=1926081719260817;
struct data{
int l,r,w;
}g[N];
vector<data> p[N];
ll tr[N*4],lazy[N*4],dp[N],w[N],c[N],d[N],s[N];
int n,k;
void build(int x,int l,int r){
lazy[x]=0;
if(l==r){tr[x]=dp[l];return;}
int mid=(l+r)>>1;
build(lson,l,mid);build(rson,mid+1,r);
tr[x]=min(tr[lson],tr[rson]);
}
void update(int x,int l,int r,int xl,int xr,int v){
if(xl>xr) return;
if(xl<=l&&r<=xr){
tr[x]+=v;lazy[x]+=v;return;
}
int mid=(l+r)>>1;
if(xr<=mid) update(lson,l,mid,xl,xr,v);
else if(xl>mid) update(rson,mid+1,r,xl,xr,v);
else update(lson,l,mid,xl,mid,v),update(rson,mid+1,r,mid+1,xr,v);
tr[x]=min(tr[lson],tr[rson])+lazy[x];
}
ll query(int x,int l,int r,int xl,int xr,int la){
if(xl<=l&&xr<=r) return tr[x]+la;
int mid=(l+r)>>1;la+=lazy[x];
if(xr<=mid) return query(lson,l,mid,xl,xr,la);
else if(xl>mid) return query(rson,mid+1,r,xl,xr,la);
else return min(query(lson,l,mid,xl,mid,la),query(rson,mid+1,r,mid+1,xr,la));
}
int main(){
scanf("%d%d",&n,&k);
for(int i=2;i<=n;i++) scanf("%d",&d[i]);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
for(int i=1;i<=n;i++) scanf("%d",&s[i]);
for(int i=1;i<=n;i++) scanf("%d",&g[i].w);
++n;d[n]=Inf,w[n]=Inf;s[n]=0;c[n]=0;
for(int i=1;i<=n;i++){
g[i].l=lower_bound(d+1,d+1+n,d[i]-s[i])-d;
g[i].r=lower_bound(d+1,d+1+n,d[i]+s[i])-d;
if(d[g[i].r]>d[i]+s[i]) g[i].r--;
p[g[i].r].push_back((data){g[i].l,g[i].r,g[i].w});
}
ll t=0;
for(int i=1;i<=n;i++){
dp[i]=t+c[i];
for(int j=0;j<p[i].size();j++) t+=p[i][j].w;
}
ll ans=Inf;
ans=min(ans,dp[n]);
memset(tr,127,sizeof(tr));
for(int j=2;j<=k+1;j++){
build(1,1,n);
for(int i=1;i<=n;i++){
dp[i]=query(1,1,n,1,i-1,0)+c[i];
for(int j=0;j<p[i].size();j++) update(1,1,n,1,p[i][j].l-1,p[i][j].w);
}
ans=min(ans,dp[n]);
}
cout<<ans<<endl;
return 0;
}

bzoj 1835: [ZJOI2010]base 基站选址的更多相关文章

  1. BZOJ 1835: [ZJOI2010]base 基站选址 [序列DP 线段树]

    1835: [ZJOI2010]base 基站选址 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立 ...

  2. bzoj 1835 [ZJOI2010]base 基站选址(DP+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1835 [题意] 有n个村庄,每个村庄位于d[i],要求建立不多于k个基站,在第i个村庄 ...

  3. BZOJ 1835 [ZJOI2010]base 基站选址:线段树优化dp

    传送门 题意 有 $ n $ 个村庄在一排直线上,现在要建造不超过 $ K $ 个通讯基站,基站只能造在村庄处. 第 $ i $ 个村庄距离第 $ 1 $ 个村庄的距离为 $ D_i $ .在此建造基 ...

  4. BZOJ 1835: [ZJOI2010]base 基站选址(DP,线段树)

    可以很容易的写出dp方程: F[i][j]=min(F[l][j-1]+w[l][i])+c[i] (w[i][j]是从l+1到i-1这些点p里,所有满足d[p]+s[p]<d[i] & ...

  5. bzoj[1835][ZJOI2010]base 基地选址

    bzoj[1835][ZJOI2010]base 基地选址 标签: 线段树 DP 题目链接 题解 这个暴力DP的话应该很容易看出来. dp[i][j]表示造了i个通讯站,并且j是第i个的最小费用. \ ...

  6. 【BZOJ1835】[ZJOI2010]base 基站选址 线段树+DP

    [BZOJ1835][ZJOI2010]base 基站选址 Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯 ...

  7. bzoj 1835/luogu P2605 : [ZJOI2010]base 基站选址

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

  8. bzoj1835[ZJOI2010]base基站选址

    据说正解是什么线段树优化DP,但是作为脑子有坑选手,我们需要5k的做法: 主席树+决策单调性..... F[m][i]表示已经放置了m个基站,第m个基站放置在第i个村庄,第i个村庄及之前的村庄的总最少 ...

  9. BZOJ1835: [ZJOI2010]base 基站选址【线段树优化DP】

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

随机推荐

  1. 并行设计模式(二)-- Master-Worker模式

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Mast ...

  2. THinkPHP的认识

    四中路由方式:http://网址/index.php?m=分组&c=控制器&a=操作方法(但是这个不安全,不推荐使用)http://网址/index.php/分组/控制器/操作方法(默 ...

  3. 可靠的、可扩展的、可维护的数据系统 ------《Designing Data-Intensive Applications》读书笔记1

    坦白说也是机缘巧合,在硕士生阶段进入分布式系统领域学习.无论是大规模存储或计算,其核心也是运用分布式技术利用并行性来解决数据密集型应用的需求.最近开始在啃这本<Designing Data-In ...

  4. chrony时间同步 服务端 客户端 安装配置

    chrony时间同步 服务端 客户端 安装配置 原创内容http://www.cnblogs.com/elvi/p/7658021.html #!/bin/sh #运行环境 centos7 #chro ...

  5. MySql的技术规范-企业版(来源于MySql官网)

    MySQL技术规范 Oracle MySQL云服务 MySQL数据库即服务 灵活的架构 开源 多线程 可插拔的存储引擎架构 InnoDB,NDB集群 MyISAM,合并,内存,存档 ANSI SQL标 ...

  6. 简单的基于Vue-axios请求封装

    具体实现思路=>封装之前需要用npm安装并引入axios,使用一个单独的js模块作为接口请输出对象,然后export dafult 这个对象. 1.首先我们需要在Vue实例的原型prototyp ...

  7. ubuntu指令记录

    记录一些指令,便于查看使用. 1.sudo -以其他身份运行命令,预设身份为root. 2.ctrl+alt+T打开终端(命令行窗口) 3.如何判断linux系统是32位还是64位,指令:getcon ...

  8. poj 3111 K Best 最大化平均值 二分思想

    poj 3111 K Best 最大化平均值 二分思想 题目链接: http://poj.org/problem?id=3111 思路: 挑战程序竞赛书上讲的很好,下面的解释也基本来源于此书 设定条件 ...

  9. 三十天学不会TCP,UDP/IP编程--MAC地址和数据链路层

    这篇文章主要是来做(da)推(guang)介(gao)的!由于这两年接触到了比较多的这方面的知识,不想忘了,我决定把他们记录下来,所以决定在GitBook用半年时间上面写下来,这是目前写的一节,后面会 ...

  10. Codeforces Gym 101521A Shuttle Bus

    题意:给定一个2*N的方格,从左上角开始走,有些格子不能走,问能否一次遍历所有能走的方格 在Gym上看到一场香港的比赛,很好奇就去看了一下,发现第一题很有趣,并且很水,似乎讨论一下奇偶性就行了,然后. ...