码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P2605 [ZJOI2010]基站选址

时间:2019-10-30 16:34:07      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:支持   更新   tor   build   clu   有关   fine   char   ref   

题目
首先设\(f_{i,j}\)表示在第\(i\)个村庄修了\(j\)个基站的答案。
那么\(f_{i,j}=c_i+\min\limits_{k\in[j-1,i)}(f_{k,j-1}+cost_{k,i})\)
其中\(cost_{k,i}\)表示只在\(k,i\)修基站的情况下\((k,i)\)中未被覆盖的村庄的\(w\)之和。
我们发现\(j\)可以滚掉,把枚举\(j\)放到外面一层来,就有\(f_i=c_i+\min\limits_{k\in[j-1,i)}(f_k+cost_{k,i})\)
这东西直接算肯定没法做,我们分析一下每个部分本质上是什么。
首先我们观察\(f_i\)的计算式,\(c_i\)是完全不变的,可以无视掉。
\(f_k+cost_{k,i}\)这个东西,在固定一个\(i\)时它是一个与\(k\)有关的变量。
那么一个比较自然的想法就是,每次将\(i-1\)扩展至\(i\)时,我们先求出\(f_i\)(在\(i\)位置修一个基站),然后对\(cost\)进行更新(在\(i\)位置不修基站)。
对于一个村庄\(i\),我们先预处理\(st_i,ed_i\),如果在\([st_i,ed_i]\)内没有哪个村庄修了基站的话这个村庄\(i\)就需要被赔偿。
因为\(i\)位置不修基站,所以我们需要处理所有\(ed_p=i\)\(p\)村庄对\(cost\)的影响。
\(p\)村庄需要被赔偿等价于上一个基站在\([1,st_p-1]\),也就是从\(f_1\sim f_{st_p-1}\)转移过来的需要加上\(w_p\),即把\(cost_{1,i}\sim cost_{st_p-1,i}\)加上\(w_p\)
那么我们用线段树维护\(f_k+cost_{k,i}\),支持区间加和区间求最小值即可。

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#define pb push_back
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
const int N=20007,inf=0x3f3f3f3f;
using namespace std;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
int max(int a,int b){return a>b? a:b;}
int min(int a,int b){return a<b? a:b;}
int d[N],c[N],s[N],w[N],f[N],st[N],ed[N],val[N<<2],tag[N<<2];
vector<int>edp[N];
void pushup(int p){val[p]=min(val[ls],val[rs]);}
void add(int p,int v){val[p]+=v,tag[p]+=v;}
void pushdown(int p){add(ls,tag[p]),add(rs,tag[p]),tag[p]=0;}
void build(int p,int l,int r)
{
    tag[p]=0;
    if(l==r) return (void)(val[p]=f[l]);
    build(ls,l,mid),build(rs,mid+1,r),pushup(p);
}
void update(int p,int l,int r,int L,int R,int v)
{
    if(L<=l&&r<=R) return (void)(tag[p]+=v,val[p]+=v);
    if(tag[p]) pushdown(p);
    if(L<=mid) update(ls,l,mid,L,R,v);
    if(R>mid) update(rs,mid+1,r,L,R,v);
    pushup(p);
}
int query(int p,int l,int r,int L,int R)
{
    if(L<=l&&r<=R) return val[p];
    if(tag[p]) pushdown(p);
    return min((L<=mid? query(ls,l,mid,L,R):inf),(R>mid? query(rs,mid+1,r,L,R):inf));
}
int main()
{
    int n=read(),k=read()+1,i,j,sum,ans;
    for(i=2;i<=n;++i) d[i]=read();
    for(i=1;i<=n;++i) c[i]=read();
    for(i=1;i<=n;++i) s[i]=read();
    for(i=1;i<=n;++i) w[i]=read();
    ++n,d[n]=w[n]=inf;
    for(i=1;i<=n;++i) st[i]=lower_bound(d+1,d+n+1,d[i]-s[i])-d,ed[i]=upper_bound(d+1,d+n+1,d[i]+s[i])-d-1,edp[ed[i]].pb(i);
    for(i=1,sum=0;i<=n;++i)
    {
    f[i]=sum+c[i];
    for(int p:edp[i]) sum+=w[p];
    }
    ans=f[n];
    for(i=2;i<=k;++i)
    {
    build(1,1,n);
    for(j=1;j<=n;++j)
    {
        f[j]=(j>i-1? query(1,1,n,i-1,j-1):0)+c[j];
        for(int p:edp[j]) if(st[p]>1) update(1,1,n,1,st[p]-1,w[p]);
    }
    ans=min(ans,f[n]);
    }
    printf("%d",ans);
}

Luogu P2605 [ZJOI2010]基站选址

标签:支持   更新   tor   build   clu   有关   fine   char   ref   

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11765391.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!