P2605 [ZJOI2010] 基站选址 sol
P2605 [ZJOI2010] 基站选址 - 洛谷
Observation 1
dp[i][k]: the former ith countrysides have k stations ,ith has one station
\[
dp[i][k]=\min dp[j][k-1]+cnt(j,i)+c[i]
\]
inside:
int cnt(int l,int r){
int res=0;
for(int i=l+1;i<r;++i){
if(d[i]-d[l]<=s[i]||d[r]-d[i]<=s[i])continue;
res+=w[i];
}return res;
}
and we can use node :n+1 to let the former nth node choose whether set station or not freely.
Observation 2
we can useL[i]
R[i]
to show the boundary which means ith contributes w[i] when all stations are out of it. \(\mathcal{O}(n\log n)\) is OK
then dp[i][j]
,when the j was fixed,we use \(\min\) dp[pos][j-1]
to update dp[i][j]
,so we can use segment tree to maintenance.
concretely,we know which points contribute w_pos, so when we are dealing with i_th we add(1,L[i]-1,\(\sum\)w[pos]).then just query by \(\mathcal{O}(\log n)\)
talk is cheap show you the code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e4+10,K=1011,inf=INT_MAX;
int n,k,d[N],c[N],s[N],w[N];
int dp[N],L[N],R[N];
vector<int>ed[N];
struct SegTr{
int l,r,val,tag;
}tr[N<<2];
/*
dp[i][k] the former ith countrysides have k stations ,ith has one station
dp[i][k]=\min dp[j][k-1]+cnt(j,i)+c[i]
*/
void init(){
for(int i=1;i<=n+1;++i){
L[i]=lower_bound(d+1,d+1+n+1,d[i]-s[i])-d;
R[i]=upper_bound(d+1,d+1+n+1,d[i]+s[i])-d-1;
ed[R[i]].push_back(i);
}
}
void pushup(int x){
tr[x].val=min(tr[x<<1].val,tr[x<<1|1].val);
}
void pushdown(int x){
tr[x<<1].val+=tr[x].tag;
tr[x<<1|1].val+=tr[x].tag;
tr[x<<1].tag+=tr[x].tag;
tr[x<<1|1].tag+=tr[x].tag;
tr[x].tag=0;
}
void build(int x,int l,int r){
tr[x]={l,r,dp[l],0};
if(l==r)return ;
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
void add(int x,int l,int r,int k){
if(l<=tr[x].l&&tr[x].r<=r){
tr[x].tag+=k;
tr[x].val+=k;
return ;
}
pushdown(x);
int mid=tr[x].l+tr[x].r>>1;
if(l<=mid)add(x<<1,l,r,k);
if(mid<r)add(x<<1|1,l,r,k);
pushup(x);
}
int q(int x,int l,int r){
if(l<=tr[x].l&&tr[x].r<=r)return tr[x].val;
pushdown(x);
int mid=tr[x].l+tr[x].r>>1,ans=inf;
if(l<=mid)ans=min(ans,q(x<<1,l,r));
if(mid<r)ans=min(ans,q(x<<1|1,l,r));
return ans;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>k;
for(int i=2;i<=n;++i)cin>>d[i];
for(int i=1;i<=n;++i)cin>>c[i];
for(int i=1;i<=n;++i)cin>>s[i];
for(int i=1;i<=n;++i)cin>>w[i];
w[n+1]=inf,c[n+1]=0,s[n+1]=0,d[n+1]=inf;
init();
int res=0;
for(int i=1;i<=n+1;++i) {
dp[i]=res+c[i];
for(auto v:ed[i])res+=w[v];
}int ans=dp[n+1];
for(int j=2;j<=k+1;++j){
build(1,1,n+1);
for(int i=1;i<=n+1;++i){
dp[i]=q(1,1,i-1)+c[i];
for(auto v:ed[i]) if(L[v]-1>=1)add(1,1,L[v]-1,w[v]);
}
ans=min(ans,dp[n+1]);
}
cout<<ans;
return 0;
}