bzoj1835[ZJOI2010]基站选址

主席树+决策单调,重写一遍比之前短多了……题解:http://www.cnblogs.com/liu-runda/p/6051422.html 

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=20005;
int n;
struct node{
  int sum;node* ch[2];
  node(){}
  node(int x){sum=x;ch[0]=ch[1]=0;}
}t[maxn*50],*root[maxn];int cnt=0;
node* newnode(int x){t[++cnt]=node(x);return t+cnt;}
void Insert(node* rt0,node* &rt,int l,int r,int k,int x){
  rt=new node(rt0->sum+x);
  if(l==r)return;
  int mid=(l+r)>>1;
  if(k<=mid){
    Insert(rt0->ch[0],rt->ch[0],l,mid,k,x);
    rt->ch[1]=rt0->ch[1];
  }else{
    Insert(rt0->ch[1],rt->ch[1],mid+1,r,k,x);
    rt->ch[0]=rt0->ch[0];
  }
}
int query(node* rt0,node* rt1,int l,int r,int ql,int qr){
  if(ql>qr)return 0;
  if(ql<=l&&r<=qr)return rt1->sum-rt0->sum;
  int mid=(l+r)>>1,ans=0;
  if(ql<=mid)ans+=query(rt0->ch[0],rt1->ch[0],l,mid,ql,qr);
  if(qr>mid) ans+=query(rt0->ch[1],rt1->ch[1],mid+1,r,ql,qr);
  return ans;
}
int f[105][maxn];
int d[maxn],c[maxn],s[maxn],w[maxn];
struct data{
  int l,r,w;
}range[maxn];
vector<data> D[maxn];
void solve(int j,int l,int r,int L,int R){
  if(l>r)return;
  int mid=(l+r)>>1,g=0;
  f[j][mid]=0x7fffffff;
  for(int i=L;i<=R&&i<mid;++i){
    int tmp=f[j-1][i]+query(root[i],root[mid-1],1,n,i+1,mid-1)+c[mid];
    if(tmp<f[j][mid]){
      f[j][mid]=tmp;g=i;
    }
  }
  solve(j,l,mid-1,L,g);solve(j,mid+1,r,g,R);
}
int main(){
  int k;scanf("%d%d",&n,&k);
  d[0]=0x80808080;d[n+1]=0x7fffffff;
  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]);
  for(int i=1;i<=n;++i)scanf("%d",&w[i]);
  for(int i=1;i<=n;++i){
    range[i].l=lower_bound(d,d+n+2,d[i]-s[i])-d;range[i].r=upper_bound(d,d+n+2,d[i]+s[i])-d-1;
    range[i].w=w[i];
    D[range[i].l].push_back(range[i]);
  }
  root[0]=t+0;root[0]->ch[0]=root[0]->ch[1]=t+0;root[0]->sum=0;
  for(int i=1;i<=n;++i){
    root[i]=root[i-1];
    for(vector<data>::iterator pt=D[i].begin();pt!=D[i].end();++pt){
      Insert(root[i],root[i],1,n,pt->r,pt->w);
    }
  }
  root[n+1]=root[n];
  int ans=0;for(int i=1;i<=n;++i)ans+=w[i];
  for(int i=1;i<=n;++i){
    f[1][i]=query(root[0],root[i-1],1,n,1,i-1)+c[i];//printf("...%d\n",f[1][i]);
    ans=min(ans,f[1][i]+query(root[i],root[n],1,n,i+1,n));//printf("%d\n",ans);
  }//printf("%d\n",ans);
  for(int j=2;j<=k;++j){
        solve(j,1,n,0,n);
    for(int i=1;i<=n;++i)ans=min(ans,f[j][i]+query(root[i],root[n],1,n,i+1,n));
  }
  printf("%d\n",ans);
  return 0;
}

 

posted @ 2017-03-14 08:07  liu_runda  阅读(390)  评论(0编辑  收藏  举报
偶然想到可以用这样的字体藏一点想说的话,可是并没有什么想说的. 现在有了:文化课好难