BZOJ1835 [ZJOI2010]base 基站选址

来源:互联网 发布:怎么用mac剪辑视频 编辑:程序博客网 时间:2024/05/16 07:50

搜了一下,被告知是线段树优化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 */



0 0