BZOJ 1835 [ZJOI2010]基站选址 (线段树优化DP)
注意题目的描述,是村庄在一个范围内去覆盖基站,而不是基站覆盖村庄,别理解错了
定义$f[i][k]$表示只考虑前i个村庄,一共建了$k$个基站,最后一个基站建在了i处,最小的总花费
$f[i][k]=min(f[j][k]+calc(j,i))\;calc(j,i)$表示$i$和$j$之间,无法被覆盖的点,需要付的补偿总和
考虑如何求出$calc(j,i)$
定义$st_{i}$,$ed_{i}$表示第$i$个村庄能覆盖的最左端点和最右端点
即$st_{i}$到$ed_{i}$之间只要有一个村庄有基站,那么村庄i就不需要被补偿
可以用二分查找实现
把相同$ed_{i}$的村庄编号记录在$ed_{i}$这个位置
$DP$时,我们从左往右遍历要建基站的位置$x$,如果有一个村庄$i$的$ed_{i}<$当前位置$x$,那么如果$x$的决策如果选在了$[1,st_{i}-1]$,即上一个基站建在了$[1,st_{i}-1]$,那么村庄$i$需要被补偿,区间修改,用线段树实现
而转移就是查询区间最小值,同样用线段树实现即可
细节略多
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 20010
#define K1 105
#define ll long long
#define dd double
#define inf 0x3f3f3f3f3f3f3f3fll
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
} struct SEG{
ll mi[N1<<],tag[N1<<];
inline void pushup(int rt){ mi[rt]=min(mi[rt<<],mi[rt<<|]); }
inline void pushdown(int rt)
{
if(!tag[rt]) return;
mi[rt<<]+=tag[rt]; mi[rt<<|]+=tag[rt];
tag[rt<<]+=tag[rt]; tag[rt<<|]+=tag[rt];
tag[rt]=;
}
void build(ll *f,int l,int r,int rt)
{
tag[rt]=;
if(l==r){ mi[rt]=f[l]; return; }
int mid=(l+r)>>;
build(f,l,mid,rt<<);
build(f,mid+,r,rt<<|);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt,ll w)
{
if(L<=l&&r<=R){ mi[rt]+=w; tag[rt]+=w; return; }
int mid=(l+r)>>; pushdown(rt);
if(L<=mid) update(L,R,l,mid,rt<<,w);
if(R>mid) update(L,R,mid+,r,rt<<|,w);
pushup(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) return mi[rt];
int mid=(l+r)>>; ll ans=inf; pushdown(rt);
if(L<=mid) ans=min(ans,query(L,R,l,mid,rt<<));
if(R>mid) ans=min(ans,query(L,R,mid+,r,rt<<|));
return ans;
}
}s; vector<int>id[N1];
int n,K;
int d[N1],c[N1],p[N1],w[N1],st[N1],ed[N1];
ll f[N1]; int main()
{
scanf("%d%d",&n,&K);
int i,j,k,l,r,x,mid; ll ans=inf;
for(i=;i<=n;i++) d[i]=gint();
for(i=;i<=n;i++) c[i]=gint();
for(i=;i<=n;i++) p[i]=gint();
for(i=;i<=n;i++) w[i]=gint();
for(i=;i<=n;i++)
{
l=,r=i,st[i]=i;
while(l<=r)
{
mid=(l+r)>>;
if(d[mid]>=d[i]-p[i]) st[i]=mid,r=mid-;
else l=mid+;
}
l=i,r=n,ed[i]=i;
while(l<=r)
{
mid=(l+r)>>;
if(d[mid]<=d[i]+p[i]) ed[i]=mid,l=mid+;
else r=mid-;
}
id[ed[i]].push_back(i);
}
memset(s.mi,0x3f,sizeof(s.mi));
s.update(,,,n,,-(inf));
for(k=;k<=K;k++)
{
for(i=;i<=n+;i++)
{
f[i]=s.query(,i-,,n,)+c[i];
for(j=;j<id[i].size();j++)
{
x=id[i][j];
s.update(,st[x]-,,n,,w[x]);
}
}
ans=min(ans,f[n+]);
s.build(f,,n,);
}
for(i=;i<=n;i++)
{
for(j=;j<id[i].size();j++)
{
x=id[i][j];
s.update(,st[x]-,,n,,w[x]);
}
}
ans=min(ans,s.query(,n,,n,));
printf("%lld\n",ans);
return ;
}
BZOJ 1835 [ZJOI2010]基站选址 (线段树优化DP)的更多相关文章
- 洛谷$P2605\ [ZJOI2010]$基站选址 线段树优化$dp$
正解:线段树优化$dp$ 解题报告: 传送门$QwQ$ 难受阿,,,本来想做考试题的,我还造了个精妙无比的题面,然后今天讲$dp$的时候被讲到了$kk$ 先考虑暴力$dp$?就设$f_{i,j}$表示 ...
- [ZJOI2010]基站选址,线段树优化DP
G. base 基站选址 内存限制:128 MiB 时间限制:2000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离 ...
- luogu P2605 [ZJOI2010]基站选址 线段树优化dp
LINK:基站选址 md气死我了l达成1结果一直调 显然一个点只建立一个基站 然后可以从左到右进行dp. \(f_{i,j}\)表示强制在i处建立第j个基站的最小值. 暴力枚举转移 复杂度\(n\cd ...
- luogu2605 基站选址 (线段树优化dp)
设f[i][j]表示在第i个村庄建第j个基站的花费 那么有$f[i][j]=min\{f[k][j-1]+w[k,i]\}$,其中w[k,i]表示在k,i建基站,k,i中间的不能被满足的村庄的赔偿金之 ...
- BZOJ1835: [ZJOI2010]base 基站选址(线段树优化Dp)
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- bzoj 1835: [ZJOI2010]基站选址
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- Codeforces Round #426 (Div. 2) D 线段树优化dp
D. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...
- BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】
BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...
- [AGC011F] Train Service Planning [线段树优化dp+思维]
思路 模意义 这题真tm有意思 我上下楼梯了半天做出来的qwq 首先,考虑到每K分钟有一辆车,那么可以把所有的操作都放到模$K$意义下进行 这时,我们只需要考虑两边的两辆车就好了. 定义一些称呼: 上 ...
随机推荐
- DJANGO里让用户自助修改密码
参考了网上的实现,最终实现的各代码如下: changepwd.html模板文件: {% extends "Prism/index.html" %} {% load staticfi ...
- 通过winrm使用powershell远程管理服务器
原文地址 在Linux中,我们可以使用安全的SSH方便的进行远程管理.但在Windows下,除了不安全的Telnet以外,从Windows Server 2008开始提供了另外一种命令行原创管理方式, ...
- HDU 3002
无向图最小割. #include <iostream> #include <cstdio> #include <cstring> using namespace s ...
- C语言数组和函数实例练习(二)
1.C语言中不允许函数的嵌套定义,但可以使用函数的嵌套调用. 例1:输入4个整数,找出其中最大的数. #include <stdio.h> #include <stdlib.h> ...
- session理解
Session,底层的实现就是一个Map<集合>,有些Data在Server内存中,APP要分层.Data在各个层之间肯定要以一种形态传递(泛型),之前Servlet dao.getLis ...
- luogu1771 方程的解
题目大意 对于不定方程a1+a2+…+ak-1+ak=g(x),其中k≥2且k∈N,x是正整数,g(x)=x^x mod 1000(即x^x除以1000的余数),x,k是给定的数.我们要求的是这个不定 ...
- oc7--内存分析
// // main.m // 第二个OC类 #import <Foundation/Foundation.h> @interface Person : NSObject { @publi ...
- python spark 随机森林入门demo
class pyspark.mllib.tree.RandomForest[source] Learning algorithm for a random forest model for class ...
- JavaScript:DOM对象
ylbtech-JavaScript:DOM对象 1. HTML DOM Document 对象返回顶部 1. HTML DOM Document 对象 HTML DOM 节点 在 HTML DOM ...
- php navigat备份
点击查询->新建查询->写sql查询出更新的数据部分(根据时间等条件) -> 点击上方工具菜单栏的导出向导 ,然后就可以根据选择导出文件了可以导出sql脚本excel等很多,绝对有你 ...