题目戳这里

村庄排序。状态\(f[j][i]\)表示考虑前\(i\)个村庄,造\(j\)个邮局且\(i\)造了邮局的最小代价。我们用\(Lb_i,Rb_i\)表示在第\(i\)个村庄造邮局,邮局最左和最右能够服务到的村庄。\(pre_i\)表示\(P\)的前缀和。

\[f[j][i] = C_i + \left\{
\begin{array}{ll}
\min (f[j-1][k]) & Rb_k\ge Lb_i\\
\min (f[j-1][k]+pre_{Lb_i-1}-pre_{Rb_k}) & Rb_k < Lb_i
\end{array} \right.\]

按\(Rb_i\)来建线段树,分别维护\(f[j-1][k]\)和\(f[j-1][k]-pre_{Rb_k}\)最小值即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std; const int maxn = 10010,maxm = 110; const int inf = 1<<30;
int N,M,X[maxn],C[maxn],R[maxn],Case,Lbound[maxn],Rbound[maxn],leaf[maxn];
int f[maxm][maxn],P[maxn],tree[4*maxn][2],ans; inline int gi()
{
char ch; int ret = 0,f = 1;
do ch = getchar(); while (!(ch >= '0'&&ch <= '9')&&ch != '-');
if (ch == '-') f = -1,ch = getchar();
do ret = ret*10+ch-'0',ch = getchar(); while (ch >= '0'&&ch <= '9');
return ret*f;
} inline void build(int now,int l,int r,int i)
{
if (l == r) { tree[now][0] = tree[now][1] = inf; leaf[l] = now; return; }
int mid = (l+r) >> 1;
build(now<<1,l,mid,i); build(now<<1|1,mid+1,r,i);
tree[now][0] = tree[now][1] = inf;
} inline void modify(int pos,int a,int b)
{
if (a < tree[leaf[pos]][0])
{
tree[leaf[pos]][0] = a;
for (int now = leaf[pos]>>1;now&&tree[now][0] > a;now >>= 1) tree[now][0] = a;
}
if (b < tree[leaf[pos]][1])
{
tree[leaf[pos]][1] = b;
for (int now = leaf[pos]>>1;now&&tree[now][1] > b;now >>= 1) tree[now][1] = b;
}
} inline int query(int i,int now,int l,int r,int ql,int qr)
{
if (l == ql&&r == qr) return tree[now][i];
int mid = (l+r)>>1;
if (qr <= mid) return query(i,now<<1,l,mid,ql,qr);
else if (ql > mid) return query(i,now<<1|1,mid+1,r,ql,qr);
else return min(query(i,now<<1,l,mid,ql,mid),query(i,now<<1|1,mid+1,r,mid+1,qr));
} int main()
{
freopen("4273.in","r",stdin);
freopen("4273.out","w",stdout);
while (++Case)
{
N = gi(); M = gi(); if (!N&&!M) break;
printf("Case %d: ",Case);
for (int i = 2;i <= N;++i) X[i] = gi();
for (int i = 1;i <= N;++i) C[i] = gi();
for (int i = 1;i <= N;++i) R[i] = gi();
for (int i = 1;i <= N;++i) P[i] = gi()+P[i-1];
for (int i = 1;i <= N;++i) Lbound[i] = lower_bound(X+1,X+N+1,X[i]-R[i])-X,Rbound[i] = upper_bound(X+1,X+N+1,X[i]+R[i])-X-1;
ans = P[N];
for (int i = 1;i <= N;++i) f[1][i] = C[i]+P[Lbound[i]-1],ans = min(ans,f[1][i]+P[N]-P[Rbound[i]]);
for (int i = 2;i <= M;++i)
{
build(1,1,N,i-1);
for (int j = i;j <= N;++j)
{
modify(Rbound[j-1],f[i-1][j-1],f[i-1][j-1]-P[Rbound[j-1]]);
f[i][j] = query(0,1,1,N,Lbound[j],N);
if (Lbound[j]-1) f[i][j] = min(f[i][j],query(1,1,1,N,1,Lbound[j]-1)+P[Lbound[j]-1]);
f[i][j] += C[j];
ans = min(ans,f[i][j]+P[N]-P[Rbound[j]]);
}
}
cout << ans << endl;
}
fclose(stdin); fclose(stdout);
return 0;
}

最新文章

  1. (Interface)接口特点
  2. ListView 重设Adapter后的动作,remove/add ListView 的动作
  3. 【原创】express3.4.8源码解析之中间件
  4. hdu 4901 The Romantic Hero (dp)
  5. 【进阶——种类并查集】hdu 1829 A Bug&#39;s Life (基础种类并查集)TUD Programming Contest 2005, Darmstadt, Germany
  6. bzoj 1411 [ZJOI2009]硬币游戏
  7. 校友信息管理&amp;SNS互动平台之前言、目录及说明
  8. Squares&lt;哈希&gt;
  9. delphi DCC32命令行方式编译delphi工程源码
  10. WIFI实时监控追踪小车演示视频——安卓端、小车
  11. Chapter 1 First Sight——37
  12. Lua API 小记1
  13. Django中数据查询(万能下换线,聚合,F,Q)
  14. Memcached的安装配置与测试
  15. JEECG 3.8宅男优化版本发布
  16. 利用pl/sql执行计划评估SQL语句的性能简析
  17. [No0000195]NoSQL还是SQL?这一篇讲清楚
  18. IDEA 图标介绍。 缓存和索引介绍、清理方法和Debug使用
  19. IdentityServer4 中文文档 -8- (快速入门)设置和概览
  20. ArcGIS Server生成文件的权限问题处理

热门文章

  1. scala成长之路(7)函数进阶——可能是史上最浅显易懂的闭包教程
  2. Python入门学习笔记4:他人的博客及他人的学习思路
  3. C语言实例解析精粹学习笔记——33(扑克牌的结构表示)
  4. git将本地项目上传到远程仓库
  5. c#获取当前运行程序所在的目录
  6. oracle 数据被修改怎么修复?(闪回)
  7. 【PHP】进一法取整、四舍五入取整、忽略小数等的取整数方法大全
  8. 通过数据库恢复SharePoint网站
  9. hadoop中的方法的作用
  10. mysqli函数库的使用