1835: [ZJOI2010]base 基站选址
Time Limit: 100 Sec Memory Limit: 64 MBSubmit: 1188 Solved: 558
[ Submit][ Status][ Discuss]
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
4
Sample Output
40%的数据中,N<=500;
100%的数据中,K<=N,K<=100,N<=20,000,Di<=1000000000,Ci<=10000,Si<=1000000000,Wi<=10000。
100%的数据中,K<=N,K<=100,N<=20,000,Di<=1000000000,Ci<=10000,Si<=1000000000,Wi<=10000。
HINT
Source
#define priority_queue pq
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 2E4 + 10;
const int T = 8;
const int INF = ~0U>>1;
struct data{
int posi,Num;
data(){}
data(int posi,int Num): posi(posi),Num(Num){}
bool operator < (const data &b) const {
return posi > b.posi;
}
};
typedef __gnu_pbds::pq<data,less<data>,__gnu_pbds::pairing_heap_tag> Heap;
int n,k,dis[maxn],w[maxn],v[maxn],L[maxn],R[maxn],
Add[maxn*T],Min[maxn*T],f[maxn][110],pay[maxn];
struct d2{
int posi,Num;
d2(){}
d2(int posi,int Num): posi(posi),Num(Num){}
bool operator < (const d2 &b) const {
return posi < b.posi;
}
};
typedef __gnu_pbds::pq<d2,less<d2>,__gnu_pbds::pairing_heap_tag> Heap2;
void pushdown(int o)
{
if (!Add[o]) return;
Min[o] += Add[o];
Add[o<<1] += Add[o];
Add[o<<1|1] += Add[o];
Add[o] = 0;
}
void maintain(int o)
{
pushdown(o<<1);
pushdown(o<<1|1);
Min[o] = min(Min[o<<1],Min[o<<1|1]);
}
void Insert(int o,int l,int r,int pos,int key)
{
pushdown(o);
maintain(o);
if (l == r) {
Min[o] += key;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) Insert(o<<1,l,mid,pos,key);
else Insert(o<<1|1,mid+1,r,pos,key);
Min[o] = min(Min[o<<1],Min[o<<1|1]);
}
void Modify(int o,int l,int r,int ml,int mr,int key)
{
if (ml > mr) return;
pushdown(o);
if (ml <= l && r <= mr) {
Add[o] += key;
return;
}
int mid = (l + r) >> 1;
if (ml <= mid) Modify(o<<1,l,mid,ml,mr,key);
if (mr > mid) Modify(o<<1|1,mid+1,r,ml,mr,key);
maintain(o);
}
int Query(int o,int l,int r,int ql,int qr)
{
if (ql > qr) return 0;
pushdown(o);
if (ql <= l && r <= qr) return Min[o];
int ret = ~0U>>1,mid = (l + r) >> 1;
if (ql <= mid) ret = Query(o<<1,l,mid,ql,qr);
if (qr > mid) ret = min(ret,Query(o<<1|1,mid+1,r,ql,qr));
return ret;
}
int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
void Clear()
{
memset(Min,0,sizeof(Min));
memset(Add,0,sizeof(Add));
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); k = getint();
int Ans = 0;
for (int i = 2; i <= n; i++)
dis[i] = getint();
for (int i = 1; i <= n; i++)
v[i] = getint();
for (int i = 1; i <= n; i++) {
int s = getint();
int tmp = dis[i] - s;
int pos = lower_bound(dis + 1,dis + n + 1,tmp) - dis;
L[i] = pos;
tmp = dis[i] + s;
pos = lower_bound(dis + 1,dis + n + 1,tmp) - dis;
if (dis[pos] > tmp) --pos;
R[i] = pos;
}
for (int i = 1; i <= n; i++)
w[i] = getint(),Ans += w[i];
for (int j = 1; j <= k; j++) {
Clear(); Heap Q;
for (int i = 1; i <= n; i++) {
if (i < j) {
if (i == j - 1)
Insert(1,0,n,i,f[i][j-1]);
continue;
}
while (!Q.empty()) {
data K = Q.top();
if (K.posi < i) {
if (j == 1) Modify(1,0,n,0,n,w[K.Num]);
else Modify(1,0,n,1,L[K.Num] - 1,w[K.Num]);
Q.pop();
}
else break;
}
f[i][j] = Query(1,0,n,j-1,i-1) + v[i];
Q.push(data(R[i],i));
Insert(1,0,n,i,f[i][j-1]);
}
}
Heap2 Q;
int tot = 0;
for (int i = n; i; i--) {
while (!Q.empty()) {
d2 K = Q.top();
if (K.posi > i) {
tot += w[K.Num];
Q.pop();
}
else break;
}
pay[i] = tot;
Q.push(d2(L[i],i));
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= k; j++) {
if (j > i) continue;
Ans = min(Ans,f[i][j] + pay[i]);
}
cout << Ans;
return 0;
}