列表

详情


NC20490. [ZJOI2010]BASE 基站选址

描述

有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

输出描述

输出文件中仅包含一个整数,表示最小的总费用。

示例1

输入:

3 2 1 2 2 3 2 1 1 0 10 20 30

输出:

4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 400ms, 内存消耗: 2860K, 提交时间: 2021-09-12 17:57:06

#include<bits/stdc++.h>
using namespace std;
int N,K;
int D[20005];
int S[20005];
long long C[20005];
long long W[20005];
long long dp[20005];
vector<int>v[20005];
struct node
{
    long long mi;
    long long lazy;
}A[80020];
void bt(int k,int l,int r)
{
    A[k].lazy=0;
    if(l==r)
    {
        A[k].mi=dp[l];
        return;
    }
    int mid=l+r>>1;
    bt(k<<1,l,mid);
    bt(k<<1|1,mid+1,r);
    A[k].mi=min(A[k<<1].mi,A[k<<1|1].mi);
    return;
}
void pd(int k)
{
    A[k<<1].mi+=A[k].lazy;
    A[k<<1|1].mi+=A[k].lazy;
    A[k<<1].lazy+=A[k].lazy;
    A[k<<1|1].lazy+=A[k].lazy;
    A[k].lazy=0;
    return;
}
void cg(int k,int l,int r,int z,int y,int x)
{
    if(z>y)
    {
        return;
    }
    if(l>=z&&r<=y)
    {
        A[k].mi+=x;
        A[k].lazy+=x;
        return;
    }
    if(A[k].lazy)
    {
        pd(k);
    }
    int mid=l+r>>1;
    if(z<=mid)
    {
        cg(k<<1,l,mid,z,y,x);
    }
    if(y>mid)
    {
        cg(k<<1|1,mid+1,r,z,y,x);
    }
    A[k].mi=min(A[k<<1].mi,A[k<<1|1].mi);
    return;
}
long long cx(int k,int l,int r,int z,int y)
{
    if(z>y)
    {
        return 0;
    }
    if(l>=z&&r<=y)
    {
        return A[k].mi;
    }
    long long ans=0x3f3f3f3f3f3f3f3f;
    int mid=l+r>>1;
    if(z<=mid)
    {
        ans=min(ans,cx(k<<1,l,mid,z,y));
    }
    if(y>mid)
    {
        ans=min(ans,cx(k<<1|1,mid+1,r,z,y));
    }
    return ans;
}
int main()
{
    scanf("%d %d",&N,&K);
    for(int i=2;i<=N;i++)
    {
        scanf("%d",D+i);
    }
    for(int i=1;i<=N;i++)
    {
        scanf("%d",C+i);
    }
    for(int i=1;i<=N;i++)
    {
        scanf("%d",S+i);
        v[upper_bound(D+i,D+N+1,D[i]+S[i])-D-1].push_back(i);
    }
    for(int i=1;i<=N;i++)
    {
        scanf("%d",W+i);
    }
    N++;
    K++;
    D[N]=0x3f3f3f3f;
    W[N]=0x3f3f3f3f3f3f3f3f;
    long long t=0;
    for(int i=1;i<=N;i++)
    {
        dp[i]=t+C[i];
        for(auto it:v[i])
        {
            t+=W[it];
        }
    }
    for(int k=2;k<=K;k++)
    {
        bt(1,1,N);
        for(int i=1;i<=N;i++)
        {
            dp[i]=min(dp[i],cx(1,1,N,1,i-1)+C[i]);
            for(auto it:v[i])
            {
                cg(1,1,N,1,lower_bound(D+1,D+it+1,D[it]-S[it])-D-1,W[it]);
            }
        }
    }
    printf("%lld\n",dp[N]);
    return 0;
}

上一题