搜了一下,被告知是线段树优化dp
那么就瞎YY一下
考虑f[i][j]表示第村庄i建一个基站,1~i一共建了j个基站,前i个村庄的总代价最小是多少
那么我们可以考虑枚举倒数第二个基站进行转移
考虑补偿带来的代价,因为只考虑前i个村庄,所以也只考虑前i个村庄补偿带来的代价
每个村庄会对应一段区间,只要这个区间里有基站那么就不用补偿
那么考虑每如果i大于某一个村庄j的区间的右端点,那么在计算f[i]的时候如果倒数第二个基站<j的右端点,那么就要给j补偿
用堆维护<=i的村庄的区间的右端点,用线段树维护区间加区间取最小值来搞即可
统计答案的话可以在最后加一个距离为INF,话费为0的点,然后用这个点的f值更新答案即可
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 20010
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
struct data{
int l;
int r;
int x;
data(){
}
data(int _l,int _r,int _x){
l=_l;
r=_r;
x=_x;
}
friend bool operator <(data x,data y){
return x.r>y.r;
}
};
int n,k;
int d[MAXN],c[MAXN],s[MAXN],w[MAXN];
int v[MAXN<<2],ch[MAXN<<2];
int ans=INF;
int f[MAXN];
priority_queue<data>q;
inline void ud(int x){
v[x]=min(v[x<<1],v[x<<1|1]);
}
inline void toch(int x,int y){
v[x]+=y;
ch[x]+=y;
}
inline void pd(int x){
if(ch[x]){
toch(x<<1,ch[x]);
toch(x<<1|1,ch[x]);
ch[x]=0;
}
}
void build(int x,int y,int z){
ch[x]=0;
if(y==z){
v[x]=f[y];
return ;
}
int mid=y+z>>1;
build(x<<1,y,mid);
build(x<<1|1,mid+1,z);
ud(x);
}
void change(int x,int y,int z,int lim,int cv){
if(d[y]>=lim){
return ;
}
if(d[z]<=lim){
toch(x,cv);
return ;
}
pd(x);
int mid=y+z>>1;
change(x<<1,y,mid,lim,cv);
change(x<<1|1,mid+1,z,lim,cv);
ud(x);
}
int ask(int x,int y,int z,int l,int r){
if(y==l&&z==r){
return v[x];
}
pd(x);
int mid=y+z>>1;
if(r<=mid){
return ask(x<<1,y,mid,l,r);
}else if(l>mid){
return ask(x<<1|1,mid+1,z,l,r);
}else{
return min(ask(x<<1,y,mid,l,mid),ask(x<<1|1,mid+1,z,mid+1,r));
}
}
void ins(int x,int y,int z,int p,int iv){
if(y==z){
v[x]=iv;
return ;
}
pd(x);
int mid=y+z>>1;
if(p<=mid){
ins(x<<1,y,mid,p,iv);
}else{
ins(x<<1|1,mid+1,z,p,iv);
}
ud(x);
}
void work(){
int i;
while(!q.empty()){
q.pop();
}
build(1,0,n);
for(i=1;i<=n;i++){
q.push(data(d[i]-s[i],d[i]+s[i],i));
while(q.top().r<d[i]){
change(1,0,n,q.top().l,w[q.top().x]);
q.pop();
}
f[i]=ask(1,0,n,0,i-1)+c[i];
}
f[0]=INF;
ans=min(ans,f[n]);
}
int main(){
int i;
scanf("%d%d",&n,&k);
for(i=2;i<=n;i++){
scanf("%d",&d[i]);
}
for(i=1;i<=n;i++){
scanf("%d",&c[i]);
}
for(i=1;i<=n;i++){
scanf("%d",&s[i]);
}
for(i=1;i<=n;i++){
scanf("%d",&w[i]);
}
n++;
d[n]=INF*2+1;
d[0]=-INF*2-1;
memset(f,0x3f,sizeof(f));
f[0]=0;
for(i=1;i<=k;i++){
work();
}
printf("%d\n",ans);
return 0;
}
/*
3 2
1 2
2 3 2
1 1 0
10 20 30
*/