Description
有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di。需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci。如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了。如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi。现在的问题是,选择基站的位置,使得总费用最小。

Input
输入数据 (base.in) 输入文件的第一行包含两个整数N,K,含义如上所述。 第二行包含N-1个整数,分别表示D2,D3,…,DN ,这N-1个数是递增的。 第三行包含N个整数,表示C1,C2,…CN。 第四行包含N个整数,表示S1,S2,…,SN。 第五行包含N个整数,表示W1,W2,…,WN

Output
一行一个数,表示最小花费

Sample Input
3 2 1 2 2 3 2 1 1 0 10 20 30

Sample Output
4

分析:
设f[i]为在第i个村庄建通讯基站时的最小花费

则f[i]=min{f[j]+cost[j][i]}+c[i],1<=j<=i-1

cost[j][i]表示最后两个基站分别建在j和i时对于中间村庄的补偿W之和
暴力求cost[j][i]的话,时间复杂度会达到O(n^3),对于本题的数据规模来说是不令人满意的

假如f[j]与cost[j][i]为定值的话,显然可以用数据结构来维护min(f[j]+cost[j][i])
维护区间信息,我们一下子就想到了线段树

然而当i变为i+1时,cost[j][i]的值会变更,因为此时的基站的位置改变,需要给出的补偿也会改变
那么这个变化显然是由原来被i覆盖的村庄所影响的,

设l[x],r[x]表示在[l[x],r[x]]范围内建造基站村庄x能被覆盖

所以我们可以计算出每个村庄可以被覆盖的左端点与右端点l与r,

每次处理完x位置,枚举所有r[a]=x的村庄a,然后在线段树中把[1,l[a]-1]都加上w[a]
(在l[a]之前建一座基站覆盖不到a,花费要加上w,第二座基站在r[a]覆盖了a)

此外,由于答案最优时不一定需要在最后一个点建基站,我们可以新增一个点,
w[++n]=+oo,c[n]=0,++k
这样子就可以保证答案一定是f[n]

最外层循环基站个数从1到k时注意每次保留最优解,因为不一定建k个基站是最优的

最后总结一下写这个代码时犯的错误:

if (d[r[i]]>d[i]+s[i]) r[i]–;
//r[i]和l[i]记录的都是村庄的编号,而比较的时候比较的是距离

不会用lower_bound,vector

输出的变量写错(超zz)

ask,add时没有特判l>r的情况
//在处理第一个和最后一个时很有可能出现这种情况

tree[bh].lazy=0;
//最玄学的错误,因为是重构线段树,所以经过的每一个线段树的节点的标记都要清零

这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>using namespace std;const int INF=0x33333333;
const int N=100010;
int n,k;
int d[N],c[N],s[N],w[N],l[N],r[N],f[N];
struct node{int x,y,mn,lazy;
};
node tree[N<<2];
vector<int> g[N];
int ans;inline void update(int bh)
{tree[bh].mn=min(tree[bh<<1].mn,tree[bh<<1|1].mn);
}inline void push(int bh)
{if (tree[bh].lazy&&tree[bh].x!=tree[bh].y){int lc=bh<<1;int rc=bh<<1|1;tree[lc].lazy+=tree[bh].lazy;tree[rc].lazy+=tree[bh].lazy;tree[lc].mn+=tree[bh].lazy;  //最小花费 tree[rc].mn+=tree[bh].lazy;tree[bh].lazy=0;}return;
}void build(int bh,int l,int r)
{tree[bh].x=l;tree[bh].y=r;tree[bh].lazy=0;  //if (l==r){tree[bh].mn=f[l];return;}int mid=(l+r)>>1;build(bh<<1,l,mid);build(bh<<1|1,mid+1,r);update(bh);
}int ask(int bh,int l,int r)
{if (l>r) return 0;  //特判push(bh);if (tree[bh].x>=l&&tree[bh].y<=r){return tree[bh].mn;}int ans=1000010;int mid=(tree[bh].x+tree[bh].y)>>1;if (l<=mid) ans=min(ans,ask(bh<<1,l,r));if (r>mid) ans=min(ans,ask(bh<<1|1,l,r));return ans;
}void add(int bh,int l,int r,int z)
{if (l>r) return;  // push(bh);if (tree[bh].x>=l&&tree[bh].y<=r){tree[bh].mn+=z;tree[bh].lazy+=z;return;}int mid=(tree[bh].x+tree[bh].y)>>1;if (l<=mid) add(bh<<1,l,r,z);if (r>mid) add(bh<<1|1,l,r,z);update(bh);    ///
}void doit()
{int i,j;for (i=1;i<=k;i++)   //外层循环基站个数{if (i==1){int t=0;for (j=1;j<=n;j++){f[j]=t+c[j];int sz=g[j].size()-1;for (int s=0;s<=sz;s++) t+=w[g[j][s]];  //r[i]=j//动态数组从0开始记录 }ans=f[n];  //每次循环的答案都记录在f[n] continue;}build(1,1,n);  //每次dp就要重构,维护f[j]+cost[j][s];for (j=1;j<=n;j++){f[j]=ask(1,1,j-1)+c[j];   //询问在j之前的最优状态 int sz=g[j].size()-1;  //r==g[j]for (int s=0;s<=sz;s++)add(1,1,l[g[j][s]]-1,w[g[j][s]]);  //r[g[j][s]]==j}ans=min(ans,f[n]);} printf("%d",ans);
}int main()
{scanf("%d%d",&n,&k);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;w[n]=INF;//lower_bound大于等于value 的值for (int i=1;i<=n;i++){l[i]=lower_bound(d+1,d+1+n,d[i]-s[i])-d;r[i]=lower_bound(d+1,d+1+n,d[i]+s[i])-d;  //l,r记录的都是编号,至少在l[i]|r[i]建基站i才能被覆盖 if (d[r[i]]>d[i]+s[i]) r[i]--;  //计算距离i村庄最近的基站至少要在哪里 //这里之所以有这个操作是因为我们用的是lower_bound g[r[i]].push_back(i);  //g[x] r[i]==x的村庄编号 }doit();return 0;
}

转载于:https://www.cnblogs.com/wutongtong3117/p/7673508.html

bzoj1835基站选址(dp+线段树)相关推荐

  1. [ZJOI2010] 基站选址(线段树优化dp)

    problem luogu-P2605 solution 首先,肯定都能想到最暴力的 dpdpdp. dpi,j:idp_{i,j}:idpi,j​:i 个村庄为止一共选了 jjj 个基站,且第 ii ...

  2. hdu5489 Removed Interval dp+线段树优化

    现在看这题居然直接秒了...去年看的时候还以为神题.. 设以第i项为结尾的lis前缀为f[i],以第j项为结尾的lis后缀为g[i],如果求出f[i]和g[j],然后枚举i,快速找到最大的满足a[j] ...

  3. [动态dp]线段树维护转移矩阵

    背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...

  4. Codeforces Round #699 (Div. 2) E.Sorting Books(贪心+DP / 线段树)超高质量题解,看不懂来打我 ~

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 E - Sorting Books 一排书架上有 nnn 本书排成一排,每本书上有一个颜色 aia_i ...

  5. poj3171(dp + 线段树)

    (和 poj1769 几乎一样,利用线段树dp的基础题) 题目大概意思为选几个区间,使 M 到 E 全都被覆盖,求选取区间的最少数量 (我们把从 M 到 E 转化成从 1 到 E - M + 1 ) ...

  6. poj1769(dp + 线段树)

    题目大概意思为选几个区间,使 1 到 n 全都被覆盖,求选取区间的最少数量 dp[i][j] : 意思为到第 i 个区间为止,能刚好覆盖到 j 的最小区间数目 例:区间为[1,10],[5,20],则 ...

  7. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  8. BZOJ 1852 [MexicoOI06]最长不下降序列(贪心+DP+线段树+离散化)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1852 [题目大意] 给你N对数A1,B1--An,Bn.要求你从中找出最多的对, 把它 ...

  9. 【BZOJ】1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚(dp/线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1672 dp很好想,但是是n^2的..但是可以水过..(5s啊..) 按左端点排序后 f[i]表示取第 ...

  10. Codeforces 671D. Roads in Yusland(树形DP+线段树)

    调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...

最新文章

  1. 让Bootstrap 3兼容IE8浏览器
  2. 舞力全开加速_国行舞力全开评测:丝滑得不像是育碧服务器!
  3. GMQ集团推出全球创新型金融衍生品交易平台
  4. 如何提高电脑办公效能
  5. 关于SWT/JFace中其他常用的事件
  6. java web的动静分离_Apache结合Tomcat实现动静分离的方法
  7. Web前端 HTTP1.0、 HTTP 1.1 、 HTTP2.0 区别与联系
  8. (WCF)阅读WCF分布式开发步步为赢(2)自定义托管宿主WCF解决方案开发配置过程详解的一点心得...
  9. python image 转成字节_Python 办公自动化之 Excel(下)
  10. vue-cli 2.6.9 安装卸载及创建一个工程
  11. Java 将PDF转为OFD
  12. 安卓java虚拟机_Android虚拟机与Java虚拟机 两种虚拟机的比较
  13. fh 幅频特性曲线怎么画fl_开环幅相频率特性曲线和对数相频特性曲线的完整画法...
  14. bartender连接oracle,设置BarTender打印用的数据库连接
  15. python提取国家名称缩写_pycountries:转换国家名称(可能不完整!)国家代码
  16. 用acdsee制作html,ACDSee 制作网络像册
  17. 基于Springboot的Java邮件系统的设计与实现(附论文和源码)
  18. 用Python实现从Oracle到GreenPlum的表结构转换
  19. Ambari 安装多个impala deamon节点(apache impala)
  20. redis 获取验证码

热门文章

  1. 等待线程3秒返回结果_Excel小白超级讨厌的计算,原来只用3秒就能出结果!
  2. 前端小报 - 201812 月刊
  3. python3之udp
  4. 美景听听Ai语音导游,助力华为荣耀PLAY手机发布
  5. 端口目录Linux操作系统常用命令
  6. 修改软件的ico图片方法
  7. 是的,我们真的在遭遇有史以来最大的DDoS攻击,并且还在加剧
  8. RAC 修改 ASM实例名 的步骤
  9. mysql解决端口占用
  10. EMNLP 2017 北京论文报告会笔记