题目传送门

  需要高级权限的传送门

题目大意

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

  三方dp是显然的,用$f_{i, j}$表示考虑前$i$个村庄,在第$i$个村庄建立基站的最小费用。

  预处理一下,每个村庄距离不超过$S_i$的村庄区间。然后考虑用某个数据结构来维护转移。

  将这些区间按照右端点排序,当当前考虑的$i$大于这个区间的右端点的时候,那么这个区间的左端点以前的状态的转移需要加上它的赔偿费用。

  然后就做完了。时间复杂度$O(nk\log n)$

Code

 /**
* bzoj
* Problem#1835
* Accepted
* Time: 2468ms
* Memory: 11300k
*/
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <queue>
using namespace std;
typedef bool boolean;
#define ll long long const signed int inf = (signed) (~0u >> );
const int N = 2e4 + , Kmx = ; typedef class Segment {
public:
int l, r, cost; boolean operator < (Segment s) const {
return r < s.r;
}
}Segment; typedef class SegTreeNode {
public:
int val, tg;
SegTreeNode *l, *r; void pushUp() {
val = (l->val < r->val) ? (l->val) : (r->val);
} void pushDown() {
l->val += tg, l->tg += tg;
r->val += tg, r->tg += tg;
tg = ;
}
}SegTreeNode; SegTreeNode pool[N << ];
SegTreeNode *top; SegTreeNode* newnode() {
top->val = inf, top->tg = ;
top->l = top->r = NULL;
return top++;
} typedef class SegTree {
public:
int n;
SegTreeNode* rt; SegTree() { }
SegTree(int n):n(n) {
top = pool;
build(rt, , n);
} void build(SegTreeNode*& p, int l, int r) {
p = newnode();
if (l == r)
return;
int mid = (l + r) >> ;
build(p->l, l, mid);
build(p->r, mid + , r);
} void update(SegTreeNode* p, int l, int r, int ql, int qr, int val) {
if (ql == l && r == qr) {
p->val += val;
p->tg += val;
return;
}
if (p->tg)
p->pushDown();
int mid = (l + r) >> ;
if (qr <= mid)
update(p->l, l, mid, ql, qr, val);
else if (ql > mid)
update(p->r, mid + , r, ql, qr, val);
else {
update(p->l, l, mid, ql, mid, val);
update(p->r, mid + , r, mid + , qr, val);
}
p->pushUp();
} void update(SegTreeNode* p, int l, int r, int idx, int val) {
if (l == r) {
p->val = val;
return;
}
if (p->tg)
p->pushDown();
int mid = (l + r) >> ;
if (idx <= mid)
update(p->l, l, mid, idx, val);
else
update(p->r, mid + , r, idx, val);
p->pushUp();
} int query() {
return rt->val;
} void update(int l, int r, int val) {
if (l > r)
return;
update(rt, , n, l, r, val);
} void update(int p, int val) {
update(rt, , n, p, val);
}
}SegTree; int n, K, tp = ;
int dist[N], cost[N], rang[N];
int comp[N];
int f[Kmx][N];
Segment sgs[N];
SegTree st; inline void init() {
scanf("%d%d", &n, &K);
dist[] = ;
for (int i = ; i <= n; i++)
scanf("%d", dist + i);
for (int i = ; i <= n; i++)
scanf("%d", cost + i);
for (int i = ; i <= n; i++)
scanf("%d", rang + i);
for (int i = ; i <= n; i++)
scanf("%d", comp + i);
} int res = ;
inline void solve() {
for (int i = ; i <= n; i++) {
int l = dist[i] - rang[i], r = dist[i] + rang[i];
sgs[i].l = lower_bound(dist + , dist + i + , l) - dist;
sgs[i].r = upper_bound(dist + i, dist + n + , r) - dist - ;
sgs[i].cost = comp[i];
} sort(sgs + , sgs + n + ); for (int i = ; i <= n; i++)
res += comp[i];
if (!K) {
printf("%d", res);
return;
} int costs = ;
Segment* p = sgs + , *ped = sgs + n + ;
for (int i = ; i <= n; i++) {
f[][i] = costs + cost[i];
while (p != ped && p->r <= i)
costs += p->cost, p++;
} for (int k = ; k <= K; k++) {
st = SegTree(n);
p = sgs + ;
for (int i = ; i <= n; i++) {
f[k + ][i] = st.query() + cost[i];
while (p != ped && p->r <= i)
st.update(, p->l - , p->cost), p++;
st.update(i, f[k][i]);
}
res = min(res, st.query());
}
printf("%d", res);
} int main() {
init();
solve();
return ;
}

bzoj 1835 base 基站选址 - 动态规划 - 线段树的更多相关文章

  1. BZOJ 1835 [ZJOI2010]base 基站选址:线段树优化dp

    传送门 题意 有 $ n $ 个村庄在一排直线上,现在要建造不超过 $ K $ 个通讯基站,基站只能造在村庄处. 第 $ i $ 个村庄距离第 $ 1 $ 个村庄的距离为 $ D_i $ .在此建造基 ...

  2. BZOJ1835: [ZJOI2010]base 基站选址【线段树优化DP】

    Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...

  3. 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) ...

  4. 【BZOJ1835】基站选址(线段树)

    [BZOJ1835]基站选址(线段树) 题面 BZOJ 题解 考虑一个比较暴力的\(dp\) 设\(f[i][j]\)表示建了\(i\)个基站,最后一个的位置是\(j\)的最小代价 考虑如何转移\(f ...

  5. BZOJ 1835 [ZJOI2010]基站选址 (线段树优化DP)

    题目大意:略 洛谷题面传送门 BZOJ题面传送门 注意题目的描述,是村庄在一个范围内去覆盖基站,而不是基站覆盖村庄,别理解错了 定义$f[i][k]$表示只考虑前i个村庄,一共建了$k$个基站,最后一 ...

  6. bzoj 1835: [ZJOI2010]基站选址

    Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...

  7. 【洛谷2605】[ZJOI2010] 基站选址(线段树维护DP)

    点此看题面 大致题意: 有\(n\)个村庄,每个村庄有\(4\)个属性:\(D_i\)表示与村庄\(1\)的距离,\(C_i\)表示建立基站的费用,\(S_i\)表示能将其覆盖的建基站范围,\(W_i ...

  8. BZOJ 1835 基站选址(线段树优化DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1835 题意:有N个村庄坐落在一条直线上,第 i(i>1)个村庄距离第1个村庄的距离 ...

  9. BZOJ 1835 基站选址(DP+线段树)

    # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream& ...

随机推荐

  1. STM32进入HardFault_Handler处理办法

    STM32进入HardFault_Handler处理办法 HardFault_Handler出现的情况一般有两种: 一种是:数组越界 一种是:堆栈溢出,程序指针指飞 方法一 在中断HardFault_ ...

  2. post数据过多时,有可能会丢失数据

    开奖时,post时请求的user_id过多,导致活动id丢失

  3. jquery和ajax和springmvc

    <script type="text/javascript" src="js/jquery-1.11.1.js"></script> $ ...

  4. 关于Could not load driverClass ${jdbc.driverClassName}问题解决方案

    在spring与mybatis3整合时一直遇到Could not load driverClass ${jdbc.driverClassName}报错如果将 ${jdbc.driverClassNam ...

  5. vc调试不能入断点

    确保输出目录和中间目录在同一个文件夹:

  6. Django之get请求url的参数

    当get网址是127.0.0.1:8000/mysite10这种类型的网址时 有两种方法: 1,在urls的路由的urlpatterns里面这样定义路由 re_path('^mysite(\d+)$' ...

  7. Ext 修改内容之后 不做任何动作 再次修改时的数据是原来第一次修改前的数据

    转自  http://blog.csdn.net/jaune161/article/details/18220257 在项目开发中遇到这样一个问题,点击Grid中的一条记录并修改,修改完后保存并且刷新 ...

  8. 面试题----入参两个Integer,无返回值,然后使这个两个值在调用函数后交换

    我最近看到过一个比较好玩的面试题. 写个方法,入参两个Integer,无返回值,然后使这个两个值在调用函数后交换 很有意思的一个题目,引发我的深思,根据一路的学习过来,下面把实现代码贴出来,方便学习. ...

  9. Spring 学习教程(二): IOC/DI+AOP

    1. IOC / DI Spring是一个基于IOC和AOP的结构J2EE系统的框架 IOC 反转控制 是Spring的基础,Inversion Of Control 简单说就是创建对象由以前的程序员 ...

  10. 001-CPU多级缓存架构

    一.基本概念 大致关系: CPU Cache --> 前端总线 FSB (下图中的Bus) --> Memory 内存 CPU 为了更快的执行代码.于是当从内存中读取数据时,并不是只读自己 ...