BZOJ1835: [ZJOI2010]base 基站选址(线段树优化Dp)
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
Sample Output
100%的数据中,K<=N,K<=100,N<=20,000,Di<=1000000000,Ci<=10000,Si<=1000000000,Wi<=10000。
解题思路:
一道好题,不过我没时间写题解了,暂且咕在这里。
代码:
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define lll spc<<1
#define rrr spc<<1|1
typedef long long lnt;
const int N=;
struct trnt{
lnt lzt;
lnt minv;
}tr[N<<],stt;
int n,k;
lnt w[N],s[N],d[N],c[N];
int lp[N],rp[N];
lnt dp[N];
std::vector<lnt>lim[N];
void pushup(int spc)
{
tr[spc].minv=std::min(tr[lll].minv,tr[rrr].minv);
return ;
}
void add(int spc,lnt v)
{
tr[spc].minv+=v;
tr[spc].lzt+=v;
return ;
}
void pushdown(int spc)
{
if(tr[spc].lzt)
{
add(lll,tr[spc].lzt);
add(rrr,tr[spc].lzt);
tr[spc].lzt=;
}
return ;
}
void build(int l,int r,int spc)
{
tr[spc]=stt;
if(l==r)
{
tr[spc].minv=dp[l];
return ;
}
int mid=(l+r)>>;
build(l,mid,lll);
build(mid+,r,rrr);
pushup(spc);
return ;
}
void update(int l,int r,int ll,int rr,int spc,lnt v)
{
if(l>rr||ll>r)
return ;
if(ll<=l&&r<=rr)
{
add(spc,v);
return ;
}
int mid=(l+r)>>;
pushdown(spc);
update(l,mid,ll,rr,lll,v);
update(mid+,r,ll,rr,rrr,v);
pushup(spc);
return ;
}
lnt query(int l,int r,int ll,int rr,int spc)
{
if(l>rr||ll>r)
return 0x3f3f3f3f;
if(ll<=l&&r<=rr)
return tr[spc].minv;
int mid=(l+r)>>;
pushdown(spc);
return std::min(query(l,mid,ll,rr,lll),query(mid+,r,ll,rr,rrr));
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
scanf("%lld",&d[i]);
for(int i=;i<=n;i++)
scanf("%lld",&c[i]);
for(int i=;i<=n;i++)
scanf("%lld",&s[i]);
for(int i=;i<=n;i++)
scanf("%lld",&w[i]);
for(int i=;i<=n;i++)
{
lp[i]=rp[i]=i;
int l=,r=i-;
while(l<=r)
{
int mid=(l+r)>>;
if(d[i]-d[mid]<=s[i])
{
r=mid-;
lp[i]=mid;
}else
l=mid+;
}
l=i+,r=n;
while(l<=r)
{
int mid=(l+r)>>;
if(d[mid]-d[i]<=s[i])
{
l=mid+;
rp[i]=mid;
}else
r=mid-;
}
lim[rp[i]].push_back(i);
}
lnt sum=;
for(int i=;i<=n;i++)
{
dp[i]=c[i]+sum;
for(int j=;j<lim[i].size();j++)
sum+=w[lim[i][j]];
}
lnt ans=sum;
for(int i=;i<=k;i++)
{
build(,n,);
for(int j=;j<=n;j++)
{
dp[j]=query(,n,,j-,)+c[j];
for(int o=;o<lim[j].size();o++)
update(,n,,lp[lim[j][o]]-,,w[lim[j][o]]);
}
ans=std::min(ans,query(,n,,n,));
}
printf("%lld\n",ans);
return ;
}
BZOJ1835: [ZJOI2010]base 基站选址(线段树优化Dp)的更多相关文章
- 【BZOJ1835】[ZJOI2010]base 基站选址 线段树+DP
[BZOJ1835][ZJOI2010]base 基站选址 Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯 ...
- 洛谷$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 ...
- BZOJ 1835 [ZJOI2010]基站选址 (线段树优化DP)
题目大意:略 洛谷题面传送门 BZOJ题面传送门 注意题目的描述,是村庄在一个范围内去覆盖基站,而不是基站覆盖村庄,别理解错了 定义$f[i][k]$表示只考虑前i个村庄,一共建了$k$个基站,最后一 ...
- 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,但是作为脑子有坑选手,我们需要5k的做法: 主席树+决策单调性..... F[m][i]表示已经放置了m个基站,第m个基站放置在第i个村庄,第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 基站选址
新的一年新的开始.结果第一题就用了几乎一周.而且感觉很不好. 先检讨自己.最近写的各种数据结构模板基本没打过出来,各种细节崩盘,这题线段树都居然被lazy标记没清零卡挂. DP还是博大精深,这东西感觉 ...
随机推荐
- Display Video
###chromium webrtc视频显示 ###两个数据源:本地数据源: MediaStreamRemoteVideoSource(content/renderer/media/webrtc/me ...
- SPOJ8222 NSUBSTR - Substrings 后缀自动机_动态规划
讲起来不是特别好讲.总之,如果 $dp[i+1]>=dp[i]$,故$dp[i]=max(dp[i],dp[i+1])$ Code: #include <cstdio> #inclu ...
- JS动态创建表单post提交
<script> //@创建表单方法 function post(URL, PARAMS) { var temp = document.createElement("form&q ...
- Unity C# 设计模式(三)工厂方法模式
定义: 定义一个创建对象的接口(父类),由子类决定需要实例化哪一个类. 这样,核心工厂类成为了一个抽象角色,不再负责产品的创建,仅提供具体工厂类所必须实现的接口,这样进一步抽象化的好处是使得工厂方法模 ...
- 【Henu ACM Round#19 B】 Luxurious Houses
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 从右往左维护最大值. 看到比最大值小(或等于)的话.就递增到比最大值大1就好. [代码] #include <bits/std ...
- ArcGIS api for javascript——地图配置-定制导航箭头
描述 本例展示了如何为平移地图包括自定义的按钮.地图被放置在一个宽3列和高3行的HTML表格的固定宽度中心单元.表格里剩余的单元放置标签为8个主要方向的缩写的按钮.每个按钮调用地图上不同的平移函数.例 ...
- Attach、Detach和DeleteObject
原文:Attach.Detach和DeleteObject,想飞的梦想 1.CWnd Attatch和Detach的关系 首先,要明白Windows对象和MFC对象的区别. MFC对象实际上并没有把整 ...
- [Python] Slice the data with pandas
For example we have dataframe like this: SPY AAPL IBM GOOG GLD 2017-01-03 222.073914 114.311760 160. ...
- python in操作引发 TypeError
在看 networkx 源代码的时候认为疑惑.为什么外层 for 要注意 TypeError.里面就不用.相同是 in, 一直纠结 node 是不是有问题,比方 node 不能够被迭代什么的,那么里面 ...
- swust oj 2516 教练我想学算术 dp+组合计数
#include<stdio.h> #include<string.h> #include<iostream> #include<string> #in ...