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; }