bzoj 1835: [ZJOI2010]base 基站选址
来源:互联网 发布:青岛优创数据英语 编辑:程序博客网 时间:2024/06/05 09:26
题意:
用最少代价,按题目要求覆盖所有点。
题解:
不怎么会做,orz状态表示,知道
因为只考虑i前的,所以统计答案就可以多加一个无限远的点,转移到那里就是答案了。
于是有
先上暴力dp的代码:
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#define LL long longusing namespace std;const int inf=(1<<28);int f[20010][110],n,k,sum[20010],s[20010],c[20010],w[20010];void cmin(int &x,int y){ if(x==-1) x=y; x=min(x,y);}int cost(int l,int r){ int ans=0; for(int i=l+1;i<r;i++) if(sum[i]+s[i]<sum[r]&&(l==0||sum[l]<sum[i]-s[i])) ans+=w[i]; return ans;}int main(){ scanf("%d %d",&n,&k); sum[1]=0; for(int i=2;i<=n;i++) scanf("%d",&sum[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]);//补偿费用 n++;sum[n]=inf;c[n]=0;k++; memset(f,-1,sizeof(f)); f[0][0]=0; for(int i=1;i<=n;i++) for(int j=1;j<=min(i,k);j++) { for(int k=0;k<i;k++) if(f[k][j-1]!=-1) cmin(f[i][j],f[k][j-1]+cost(k,i)); f[i][j]+=c[i]; } int ans=-1; for(int i=0;i<=k;i++) cmin(ans,f[n][i]); printf("%d",ans);}
然后可以发现能用线段树优化。
还要开个堆,维护当前接受范围最短的点。
然后二分出不能接受的点的影响范围,线段树随便搞搞用好了。
口胡能力不足,具体代码。
各种SB错误荒废一晚上。
code:
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<queue>#include<algorithm>#define LL long longusing namespace std;struct node{ LL x,i; bool operator < (node a) const{return a.x<x;}};priority_queue<node> b[110];const LL inf=(1<<29);LL f[20010][110],n,m,sum[20010],s[20010],c[20010],w[20010];struct trnode{ LL lc,rc,c; LL u;}tr[40010];LL tot=0;void cmin(LL &x,LL y){ if(x==-1) x=y; x=min(x,y);}void update(LL x){ LL c=tr[x].u,lc=tr[x].lc,rc=tr[x].rc; //if(!lc) lc=tr[x].lc=++tot; //if(!rc) rc=tr[x].rc=++tot; tr[lc].c+=c;tr[rc].c+=c; tr[lc].u+=c;tr[rc].u+=c; tr[x].u=0;}void change(LL x,LL l,LL r,LL k,LL c){ //if(!x) x=++tot; if(l==r){tr[x].c=c;return;} LL mid=(l+r)/2; if(tr[x].u!=0) update(x); if(k<=mid) change(tr[x].lc,l,mid,k,c); else change(tr[x].rc,mid+1,r,k,c); tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);}void add(LL x,LL l,LL r,LL fl,LL fr,LL c){ //if(!x) x=++tot; if(l==fl&&r==fr) { tr[x].u+=c; tr[x].c+=c; return; } if(tr[x].u!=0) update(x); LL mid=(l+r)/2; if(fr<=mid) add(tr[x].lc,l,mid,fl,fr,c); else if(fl>mid) add(tr[x].rc,mid+1,r,fl,fr,c); else add(tr[x].lc,l,mid,fl,mid,c),add(tr[x].rc,mid+1,r,mid+1,fr,c); tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);}LL findans(LL x,LL l,LL r,LL fl,LL fr){ //if(!x) return inf; if(l==fl&&r==fr) return tr[x].c; LL mid=(l+r)/2; if(tr[x].u!=0) update(x); if(fr<=mid) return findans(tr[x].lc,l,mid,fl,fr); if(fl>mid) return findans(tr[x].rc,mid+1,r,fl,fr); return min(findans(tr[x].lc,l,mid,fl,mid),findans(tr[x].rc,mid+1,r,mid+1,fr));}void solve(LL L,LL i){ if(sum[L]>=sum[i]-s[i]) return; LL l=L,r=i,ans; while(l<=r) { LL mid=(l+r)/2; if(sum[mid]<sum[i]-s[i]) l=mid+1,ans=mid; else r=mid-1; } add(1,1,n,L,ans,w[i]);}LL bt(LL l,LL r){ //printf("%lld %lld %lld\n",tot,l,r); LL x=++tot; tr[x].lc=tr[x].rc=0;tr[x].c=inf; tr[x].u=0; if(l!=r) { LL mid=(l+r)/2; tr[x].lc=bt(l,mid); tr[x].rc=bt(mid+1,r); } return x;}int main(){ //freopen("a.in","r",stdin); scanf("%lld %lld",&n,&m); sum[1]=0; for(LL i=2;i<=n;i++) scanf("%lld",&sum[i]);//距离 for(LL i=1;i<=n;i++) scanf("%lld",&c[i]);//建基站费用 for(LL i=1;i<=n;i++) scanf("%lld",&s[i]);//接受范围 for(LL i=1;i<=n;i++) scanf("%lld",&w[i]);//补偿费用 n++;sum[n]=inf;c[n]=0;m++;sum[0]=-inf;c[0]=0; memset(f,-1,sizeof(f)); tot=0; for(LL i=0;i<=n;i++) tot+=w[i],f[i][0]=tot; while(!b[1].empty()) b[1].pop(); tot=0; for(LL i=1;i<=n;i++) { while(!b[1].empty()&&b[1].top().x<sum[i]) tot+=w[b[1].top().i],b[1].pop();//printf("\n"); f[i][1]=tot+c[i]; node tmp;tmp.x=sum[i]+s[i];tmp.i=i; b[1].push(tmp); } for(LL j=2;j<=m;j++) { //memset(tr,0,sizeof(tr)); tot=0;bt(1,n); change(1,1,n,j-1,f[j-1][j-1]); while(!b[j].empty()) b[j].pop(); for(LL i=j;i<=n;i++) { while(!b[j].empty()&&b[j].top().x<sum[i]) solve(j-1,b[j].top().i),b[j].pop();//printf("\n"); f[i][j]=findans(1,1,n,j-1,i-1)+c[i]; change(1,1,n,i,f[i][j-1]); node tmp;tmp.x=sum[i]+s[i];tmp.i=i; b[j].push(tmp); } } LL ans=-1; for(LL i=0;i<=m;i++) cmin(ans,f[n][i]);//,printf("%lld ",f[n][i]);printf("\n"); printf("%lld",ans);}
阅读全文
1 0
- bzoj 1835: [ZJOI2010]base 基站选址
- 1835: [ZJOI2010]base 基站选址
- 1835: [ZJOI2010]base 基站选址
- 1835: [ZJOI2010]base 基站选址
- [BZOJ]1835: [ZJOI2010]base 基站选址 线段树+DP
- bzoj 1835: [ZJOI2010]base 基站选址 线段树优化dp
- BZOJ1835 [ZJOI2010]base 基站选址
- [BZOJ1835][ZJOI2010]base 基站选址
- BZOJ1835 [ZJOI2010]base 基站选址
- bzoj 1835: [ZJOI2010]base 基站选址(线段树优化dp)
- BZOJ 1835 base 基站选址(DP 线段树)
- bzoj1835 [ZJOI2010]base 基站选址(dp+线段树优化)
- BSOJ: 2699 【ZJOI2010】基站选址
- 【bzoj1835】【ZJOI2010】【基站选址】【dp+线段树】
- bzoj 1835 基站选址(线段树优化Dp)
- 基站选址
- 基站选址
- 【hihoCoder】基站选址
- 清除缓存
- Android第四节课之Intent
- 函数模板(十六)
- MySQL对数据表已有表进行分区表
- Android6.0------权限管理
- bzoj 1835: [ZJOI2010]base 基站选址
- js基础-引用类型-Date对象 ★☆
- @media 媒体查询
- 静态内部类
- wince开机启动进度条在上方
- 学渣理解的选择排序算法
- 改掉说教习惯
- 轮播图的指示点材料
- Spring Boot中的事务管理