[BZOJ]1835: [ZJOI2010]base 基站选址 线段树+DP
来源:互联网 发布:微软人工智能培训机构 编辑:程序博客网 时间:2024/06/05 10:28
Description
有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di。需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci。如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了。如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi。现在的问题是,选择基站的位置,使得总费用最小。 输入数据 (base.in) 输入文件的第一行包含两个整数N,K,含义如上所述。 第二行包含N-1个整数,分别表示D2,D3,…,DN ,这N-1个数是递增的。 第三行包含N个整数,表示C1,C2,…CN。 第四行包含N个整数,表示S1,S2,…,SN。 第五行包含N个整数,表示W1,W2,…,WN。
题解:
写得很好!点这里
代码:
#include<cstdio>#include<cstring>#include<vector>#include<iostream>#include<algorithm>using namespace std;const int maxn=20010;vector<int>g[maxn];int n,k,d[maxn],c[maxn],s[maxn],w[maxn],st[maxn],ed[maxn],f[maxn];struct Tree{int l,r,lc,rc,mn,lazy;}tr[maxn*2];int trlen;void build(int l,int r){ int t=++trlen; tr[t].l=l;tr[t].r=r;tr[t].lazy=0; if(l==r)tr[t].mn=f[l]; if(l<r) { int mid=l+r>>1; tr[t].lc=trlen+1;build(l,mid); tr[t].rc=trlen+1;build(mid+1,r); tr[t].mn=min(tr[tr[t].lc].mn,tr[tr[t].rc].mn); }}void work(int now,int x){ tr[now].lazy+=x; tr[now].mn+=x;}void update(int now){ int o=tr[now].lazy; tr[now].lazy=0; work(tr[now].lc,o);work(tr[now].rc,o);}void add(int now,int l,int r,int x){ if(l>r)return; if(tr[now].l==l&&tr[now].r==r) { work(now,x); return; } int lc=tr[now].lc,rc=tr[now].rc,mid=tr[now].l+tr[now].r>>1; if(tr[now].lazy)update(now); if(r<=mid)add(lc,l,r,x); else if(l>mid)add(rc,l,r,x); else add(lc,l,mid,x),add(rc,mid+1,r,x); tr[now].mn=min(tr[lc].mn,tr[rc].mn);}int query(int now,int l,int r){ if(l>r)return 0; if(tr[now].l==l&&tr[now].r==r)return tr[now].mn; int lc=tr[now].lc,rc=tr[now].rc,mid=tr[now].l+tr[now].r>>1; if(tr[now].lazy)update(now); if(r<=mid)return query(lc,l,r); else if(l>mid)return query(rc,l,r); else return min(query(lc,l,mid),query(rc,mid+1,r)); tr[now].mn=min(tr[lc].mn,tr[rc].mn);}int main(){ int ans; scanf("%d%d",&n,&k); for(int i=2;i<=n;i++)scanf("%d",&d[i]);d[1]=0; 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]); d[++n]=2000000000;w[n]=2000000000; for(int i=1;i<=n;i++) { st[i]=lower_bound(d+1,d+n+1,d[i]-s[i])-d; ed[i]=lower_bound(d+1,d+n+1,d[i]+s[i])-d; if(d[ed[i]]>d[i]+s[i])ed[i]--; g[ed[i]].push_back(i); } //dp[i]([j])=min(dp[k]([j-1])+cost)+c[i] dp[i]表示i这里建了通讯基站 (第二维滚动) cost表示中间的补偿费用 //我们用st[i]和ed[i]分别表示i最左端、最右端可以覆盖到i的通讯基站位置 //线段树维护dp[k]+cost的最小值 for(int j=0;j<=k;j++)//这就是被滚动的第二维 { if(j==0) { int t=0; for(int i=1;i<=n;i++) { f[i]=c[i]+t; for(int l=0;l<g[i].size();l++) t+=w[g[i][l]]; } ans=f[n]; continue; } trlen=0; build(1,n); for(int i=1;i<=n;i++) { f[i]=c[i]+query(1,1,i-1); for(int l=0;l<g[i].size();l++)//若ed[x]=i,那么当i变为i+1,1~st[x]-1的状态就不能覆盖到x,cost要加上w[x] add(1,1,st[g[i][l]]-1,w[g[i][l]]); } ans=min(ans,f[n]); } printf("%d",ans);}
阅读全文
2 0
- [BZOJ]1835: [ZJOI2010]base 基站选址 线段树+DP
- bzoj 1835: [ZJOI2010]base 基站选址 线段树优化dp
- bzoj 1835: [ZJOI2010]base 基站选址(线段树优化dp)
- bzoj1835 [ZJOI2010]base 基站选址(dp+线段树优化)
- BZOJ 1835 base 基站选址(DP 线段树)
- bzoj 1835: [ZJOI2010]base 基站选址
- 【bzoj1835】【ZJOI2010】【基站选址】【dp+线段树】
- 1835: [ZJOI2010]base 基站选址
- 1835: [ZJOI2010]base 基站选址
- 1835: [ZJOI2010]base 基站选址
- bzoj 1835 基站选址(线段树优化Dp)
- BZOJ1835 [ZJOI2010]base 基站选址
- [BZOJ1835][ZJOI2010]base 基站选址
- BZOJ1835 [ZJOI2010]base 基站选址
- bzoj1835基站选址(dp+线段树)
- BSOJ: 2699 【ZJOI2010】基站选址
- ★【动态规划】【线段树】基站选址
- 【动态规划03】bzoj1835基站选址(dp+线段树维护)
- Eclipse中 Run as --->Maven build 命令详解
- 庆科信息&阿里IoT“物联网创新应用大赛”正式开战
- 0xC0000005: 写入位置 0x00000000 时发生访问冲突
- Android-SnackBar
- 解压文件报错:gzip: stdin: not in gzip format tar: Child returned status 1 tar: Error is not recoverabl
- [BZOJ]1835: [ZJOI2010]base 基站选址 线段树+DP
- AJAX技术
- postgres创建和数据表相同结构的表的方法
- mysql学习
- 实验二:命令行菜单小程序V1.0
- AutoCompleteTextView与MultiAutoCompleteTextView简单使用
- (三)自己写一个HelloWorld类
- Spring AOP 切点语法详解
- 数据结构思维 第九章 `Map`接口