【BZOJ1835】[ZJOI2010]base 基站选址 线段树+DP
【BZOJ1835】[ZJOI2010]base 基站选址
Description
Input
Output
Sample Input
Sample Output
100%的数据中,K<=N,K<=100,N<=20,000,Di<=1000000000,Ci<=10000,Si<=1000000000,Wi<=10000。
题解:这题如果想不出来的话,多半是设的状态不对,多设几个可能的状态,很容易就能判断出自己设的状态能否转移了。
设f[i][j]表示在第i个村庄建一个基站,已经建了j个基站,此时前i个村庄需要的最少花费(先不考虑对后面的影响)。那么得到转移方程:
$f[i][j]=f[k][j-1]+C[k]+\sum\limits_{l=k+1}^{i-1}W[l][l既不能被i覆盖也不能被j覆盖]$
那么我们如何求出所有满足条件的W[l]之和呢?为了方便,我们先用二分预处理出对于每个l,能覆盖它的,最左边的村庄(记为lm[l])和最右边的村庄(记为rm[l])。那么l不能被k和i覆盖,当且仅当k<lm[l]且rm[l]<i。这就变成了问你一个区间中有多少个线段。我们可以用链表,将所有的l都挂链到rm[l]+1上,那么当i=rm[l]+1时,自然就满足了rm[l]<i的条件。然后我们取出挂在i上的所有l,用线段树,将[1,lm[l]-1]的所有点的f值都+=W[l],也就对应了k<lm[l]的限制。然后我们直接取出线段树中f最小的k来更新f[i][j]就行了。
请注意DP初值的设定!
#include <cstdio>
#include <cstring>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
typedef long long ll;
const int maxn=20010;
int n,m,cnt,now,ans;
int D[maxn],W[maxn],C[maxn],S[maxn];
int s[maxn<<4],t[maxn<<4],f[2][maxn],lm[maxn],rm[maxn],to[maxn],next[maxn],head[maxn];
void add(int a,int b)
{
to[++cnt]=b,next[cnt]=head[a],head[a]=cnt;
}
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void build(int l,int r,int x)
{
t[x]=0;
if(l==r)
{
s[x]=f[now][l];
return ;
}
int mid=l+r>>1;
build(l,mid,lson),build(mid+1,r,rson);
s[x]=min(s[lson],s[rson]);
}
void pushdown(int x)
{
if(t[x]) s[lson]+=t[x],s[rson]+=t[x],t[lson]+=t[x],t[rson]+=t[x],t[x]=0;
}
void updata(int l,int r,int x,int a,int b,int c)
{
if(a>b) return ;
if(a<=l&&r<=b)
{
s[x]+=c,t[x]+=c;
return ;
}
pushdown(x);
int mid=l+r>>1;
if(a<=mid) updata(l,mid,lson,a,b,c);
if(b>mid) updata(mid+1,r,rson,a,b,c);
s[x]=min(s[lson],s[rson]);
}
int query(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b) return s[x];
pushdown(x);
int mid=l+r>>1;
if(b<=mid) return query(l,mid,lson,a,b);
if(a>mid) return query(mid+1,r,rson,a,b);
return min(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
}
int main()
{
n=rd(),m=rd();
int i,j,k;
for(i=2;i<=n;i++) D[i]=rd();
for(i=1;i<=n;i++) C[i]=rd();
for(i=1;i<=n;i++) S[i]=rd();
for(i=1;i<=n;i++) W[i]=rd();
int l,r,mid;
for(i=1;i<=n;i++)
{
l=1,r=i;
while(l<r)
{
mid=l+r>>1;
if(D[i]-D[mid]<=S[i]) r=mid;
else l=mid+1;
}
lm[i]=r,l=i+1,r=n+1;
while(l<r)
{
mid=l+r>>1;
if(D[mid]-D[i]<=S[i]) l=mid+1;
else r=mid;
}
rm[i]=l-1,add(rm[i]+1,i);
}
ans=1<<30;
memset(f,0x3f,sizeof(f));
f[0][0]=0,ans=min(ans,f[0][n+1]);
for(j=1;j<=m+1;j++)
{
build(0,n,1),now^=1;
for(i=1;i<=n+1;i++)
{
for(k=head[i];k;k=next[k]) updata(0,n,1,0,lm[to[k]]-1,W[to[k]]);
f[now][i]=query(0,n,1,0,i-1)+C[i];
}
ans=min(ans,f[now][n+1]);
}
printf("%d",ans);
return 0;
}
【BZOJ1835】[ZJOI2010]base 基站选址 线段树+DP的更多相关文章
- BZOJ1835: [ZJOI2010]base 基站选址(线段树优化Dp)
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- BZOJ1835: [ZJOI2010]base 基站选址【线段树优化DP】
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- 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) ...
- bzoj1835[ZJOI2010]base基站选址
据说正解是什么线段树优化DP,但是作为脑子有坑选手,我们需要5k的做法: 主席树+决策单调性..... F[m][i]表示已经放置了m个基站,第m个基站放置在第i个村庄,第i个村庄及之前的村庄的总最少 ...
- bzoj1835: [ZJOI2010]base 基站选址
新的一年新的开始.结果第一题就用了几乎一周.而且感觉很不好. 先检讨自己.最近写的各种数据结构模板基本没打过出来,各种细节崩盘,这题线段树都居然被lazy标记没清零卡挂. DP还是博大精深,这东西感觉 ...
- BZOJ 1835: [ZJOI2010]base 基站选址 [序列DP 线段树]
1835: [ZJOI2010]base 基站选址 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立 ...
- [ZJOI2010]基站选址,线段树优化DP
G. base 基站选址 内存限制:128 MiB 时间限制:2000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离 ...
- bzoj 1835 [ZJOI2010]base 基站选址(DP+线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1835 [题意] 有n个村庄,每个村庄位于d[i],要求建立不多于k个基站,在第i个村庄 ...
- BZOJ 1835 [ZJOI2010]base 基站选址:线段树优化dp
传送门 题意 有 $ n $ 个村庄在一排直线上,现在要建造不超过 $ K $ 个通讯基站,基站只能造在村庄处. 第 $ i $ 个村庄距离第 $ 1 $ 个村庄的距离为 $ D_i $ .在此建造基 ...
随机推荐
- openshift scc解析
SCC使用UserID,FsGroupID以及supplemental group ID和SELinux label等策略,通过校验Pod定义的ID是否在有效范围内来限制pod的权限.如果校验失败,则 ...
- codevs——2894 Txx考试(背包)
时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description Txx是一个成绩很差的人,考试便成了他的噩梦.于是他常在考试时睡觉以 ...
- Docking For WPF–AvalonDock
桌面程序的应用,不可避免的就会用到大量的布局控件,之前的一个项目也想过去做类似于Visual Studio的那种灵活的布局控件,也就是界面上的控件能够实现拖拽放置.隐藏.窗口化等一系列的操作,但由于开 ...
- Blocks编程要点
[老狼推荐]Blocks编程要点原文:Blocks Programming Topics链接:http://developer.apple.com/library/ios/#documentation ...
- LAN、WAN、WLAN的区别
听语音 浏览:22034 | 更新:2015-06-22 20:10 | 标签:网线 1 2 3 4 5 6 7 分步阅读 好多朋友在群内问我路由器如何配置,本来还耐心解答,但是他竟然连LAN.WAN ...
- TortoiseGit在github上创建工程
一.前期准备 TortoiseGit官网下载地址:http://code.google.com/p/tortoisegit/ git下载地址:https://git-scm.com/download/ ...
- windows 控制台cmd乱码的解决办法
windows 控制台cmd乱码的解决办法 我本机的系统环境: OS Name: Microsoft Windows 10 企业版 OS Version: 10.0.14393 N/A Build 1 ...
- awstats的安装和配置
一.Awstats简介Awstats是一个免费非常简洁而且强大有个性的网站日志分析工具.它可以统计您站点的如下信息:一:访问量,访问次数,页面浏览量,点击数,数据流量等二:精确到每月.每日.每小时的数 ...
- Android--数据库数据显示至屏幕
MainActivity.java 这段代码的作用是从数据库中获取到数据并显示在界面上 import java.util.ArrayList; import java.util.List; impor ...
- 常见函数strlen、strcmp、strstr原型实现
数组元素的结束符为'\0'.串的结束符为NULL 一.strlen #include <iostream> using namespace std; long h_strlen(const ...