可以很容易的写出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] && d[p]-s[p]>d[l]的点的w[p]之和)

考虑i+1,会对方程造成什么变化

w[l][i]会变得跟大了(满足d[p]+s[p]<d[i]的点更多了)

可以发现增长的是一个区间,求和也是一个区间

线段树解决

CODE:

#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

#include<vector>

using namespace std;

#define maxn 20100

#define inf 1000000000

struct node {

int l,r,mi,lz;

}t[maxn*8];

#define lc(x) (x<<1)

#define rc(x) ((x<<1)+1)

#define mi(x) t[x].mi

#define lz(x) t[x].lz

#define mid ((l+r)>>1)

#define update(x) mi(x)=min(mi(lc(x)),mi(rc(x)))

int f[maxn],pf[maxn];

int build(int x,int l,int r) {

t[x].l=l,t[x].r=r;

t[x].lz=0;

if (l==r) return t[x].mi=pf[l];

build(lc(x),l,mid);

build(rc(x),mid+1,r);

update(x);

return 0;

}

int pushback(int x) {

if (t[x].l==t[x].r) return 0;

lz(lc(x))+=lz(x),lz(rc(x))+=lz(x);

mi(lc(x))+=lz(x),mi(rc(x))+=lz(x);

lz(x)=0;

}

int query(int x,int x1,int y1){

int l=t[x].l,r=t[x].r;

if (y1<l||x1>r) return inf;

if (x1<=l&&y1<=r) return mi(x);

pushback(x);

return min(query(lc(x),x1,y1),query(rc(x),x1,y1));

}

int add(int x,int x1,int y1,int z) {

int l=t[x].l,r=t[x].r;

if (y1<l||x1>r) return 0;

if (x1<=l&&y1>=r) return lz(x)+=z,mi(x)+=z;

pushback(x);

add(lc(x),x1,y1,z),add(rc(x),x1,y1,z);

update(x);

}

int n,k;

int c[maxn],s[maxn],d[maxn],w[maxn];

int st[maxn],ed[maxn];

vector<int> list[maxn];

int solve(){

int sum=0;

for (int i=1;i<=n;i++) {

f[i]=sum+c[i];

for(int j=0;j<list[i].size();j++) sum+=w[list[i][j]];

}

int ans=f[n];

for (int i=1;i<=k;i++) {

//for (int i=1;i<=n;i++) printf("%d ",f[i]);printf("\n");

memcpy(pf,f,sizeof(pf));

for (int j=1;j<=n;j++) f[j]=inf;

build(1,1,n);

for (int j=1;j<=n;j++){

f[j]=min(f[j],query(1,1,j-1))+c[j];

for (int k=0;k<list[j].size();k++) add(1,1,st[list[j][k]]-1,w[list[j][k]]);

}

ans=min(ans,f[n]);

}

printf("%d\n",ans);

return 0;

}

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",w+i);

d[++n]=inf,c[n]=w[n]=s[n]=0;

for (int i=1;i<=n;i++) {

st[i]=lower_bound(d+1,d+1+n,d[i]-s[i])-d;

ed[i]=upper_bound(d+1,d+1+n,d[i]+s[i])-d-1;

list[ed[i]].push_back(i);

}

solve();

return 0;

}

BZOJ 1835: [ZJOI2010]base 基站选址(DP,线段树)的更多相关文章

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

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

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

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

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

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

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

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

  5. 2018.11.06 bzoj1835: [ZJOI2010]base 基站选址(线段树优化dp)

    传送门 二分出每个点不需要付www贡献的范围,然后可以推出转移式子: f[i][j]=f[i−1][k]+value(k+1,j)+c[i]f[i][j]=f[i-1][k]+value(k+1,j) ...

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

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

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

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

  8. bzoj 1835 base 基站选址 - 动态规划 - 线段树

    题目传送门 需要高级权限的传送门 题目大意 有$n$个村庄坐落在一条直线上,第$i \ \ \ (i>1)$个村庄距离第$1$个村庄的距离为$D_i$.需要在这些村庄中建立不超过$K$个通讯基站 ...

  9. BZOJ 1835 基站选址(DP+线段树)

    # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream& ...

随机推荐

  1. Java解析JSON文件的方法(一)

    一.首先需要在Eclipse工程中导入相关的jar包,jar包参见链接:http://yunpan.alibaba-inc.com/share/link/NdA5b6IFK 二.提供一份待解析的jso ...

  2. scrollview嵌套gridview滑动问题

    在开发过程总遇到ScrollView嵌套GridView,由于这两种控件都带有滚动条,当他们碰到一起的时候便会出问题,问题是gridview不滚动,并且只显示两行,为此看了官方文档,谷歌回答滚动里面没 ...

  3. 4、安卓数据存储——sqlite

    朋友圈里的每一个消息体里面的数据,当下拉刷新从服务器下载数据包后,存入sqlite:用户名.图片url.点赞.评论等等.上拉加载的时候,从数据库里取出最近的5条数据加载到朋友圈上. Android通过 ...

  4. 安卓自定义类似TabHost的导航栏

    有时候为了项目需要我们要自定义一些导航控件,类似下面这样. 下面给大家讲讲我是怎么实现的, 1.素材准备(这个都是美工的事情) 2.①资源文件共有五个 如下: activity_main_first. ...

  5. 关于IE6、IE7、IE8实现盒子阴影shadow的几个注意点

    通常,我们实现盒阴影都是通过这段代码来实现的 -moz-box-shadow: 3px 3px 4px #000; -webkit-box-shadow: 3px 3px 4px #000; box- ...

  6. delphi的TFileStream 内存流

    一.文件 文本文件是以行为单位进行读.写操作的.文本文件只能单独为读或写而打开,在一个打开的文本文件上同时进行读.写操作是不允许的. 二.定义 FileStream: TFileStream; 三.打 ...

  7. Angularjs在线api文档

    http://docs.ngnice.com/api            文档 http://www.ngnice.com/showcase/#/home/home                  ...

  8. Struts1、WebWork、Struts2介绍

    一.Struts1 1.Struts1原理简介 Struts1框架以ActionServlet作为控制器核心,整个应用由客户端请求驱动.当客户端向Web应用发送请求时,请求被Struts1的核心控制器 ...

  9. ORA-39002 ORA-39070 ORA-29283 ORA-06512 ORA-29283

    记一次expdp导出失败,报错如下 ORA-39002: invalid operation ORA-39070: Unable to open the log file. ORA-29283: in ...

  10. Android EditText获取焦点和失去焦点监听事件

    实现方法也很简单.那就是绑定OnFocusChangeListener事件.实现onFocusChange(View v, boolean hasFocus) 方法.第二个参数就是判断得到焦点或失去焦 ...