您的位置:首页 > 其它

BZOJ1835 [ZJOI2010]base 基站选址

2017-03-21 18:15 337 查看
搜了一下,被告知是线段树优化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
);  
}  
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
=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 
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: