博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 1835 [ZJOI2010]基站选址 (线段树优化DP)
阅读量:5162 次
发布时间:2019-06-13

本文共 3134 字,大约阅读时间需要 10 分钟。

题目大意:略  

注意题目的描述,是村庄在一个范围内去覆盖基站,而不是基站覆盖村庄,别理解错了

定义$f[i][k]$表示只考虑前i个村庄,一共建了$k$个基站,最后一个基站建在了i处,最小的总花费

$f[i][k]=min(f[j][k]+calc(j,i))\;calc(j,i)$表示$i$和$j$之间,无法被覆盖的点,需要付的补偿总和

考虑如何求出$calc(j,i)$

定义$st_{i}$,$ed_{i}$表示第$i$个村庄能覆盖的最左端点和最右端点

即$st_{i}$到$ed_{i}$之间只要有一个村庄有基站,那么村庄i就不需要被补偿

可以用二分查找实现

把相同$ed_{i}$的村庄编号记录在$ed_{i}$这个位置

$DP$时,我们从左往右遍历要建基站的位置$x$,如果有一个村庄$i$的$ed_{i}<$当前位置$x$,那么如果$x$的决策如果选在了$[1,st_{i}-1]$,即上一个基站建在了$[1,st_{i}-1]$,那么村庄$i$需要被补偿,区间修改,用线段树实现

而转移就是查询区间最小值,同样用线段树实现即可

细节略多

 

1 #include 
2 #include
3 #include
4 #include
5 #define N1 20010 6 #define K1 105 7 #define ll long long 8 #define dd double 9 #define inf 0x3f3f3f3f3f3f3f3fll 10 using namespace std; 11 12 int gint() 13 { 14 int ret=0,fh=1;char c=getchar(); 15 while(c<'0'||c>'9'){
if(c=='-')fh=-1;c=getchar();} 16 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 17 return ret*fh; 18 } 19 20 struct SEG{ 21 ll mi[N1<<2],tag[N1<<2]; 22 inline void pushup(int rt){ mi[rt]=min(mi[rt<<1],mi[rt<<1|1]); } 23 inline void pushdown(int rt) 24 { 25 if(!tag[rt]) return; 26 mi[rt<<1]+=tag[rt]; mi[rt<<1|1]+=tag[rt]; 27 tag[rt<<1]+=tag[rt]; tag[rt<<1|1]+=tag[rt]; 28 tag[rt]=0; 29 } 30 void build(ll *f,int l,int r,int rt) 31 { 32 tag[rt]=0; 33 if(l==r){ mi[rt]=f[l]; return; } 34 int mid=(l+r)>>1; 35 build(f,l,mid,rt<<1); 36 build(f,mid+1,r,rt<<1|1); 37 pushup(rt); 38 } 39 void update(int L,int R,int l,int r,int rt,ll w) 40 { 41 if(L<=l&&r<=R){ mi[rt]+=w; tag[rt]+=w; return; } 42 int mid=(l+r)>>1; pushdown(rt); 43 if(L<=mid) update(L,R,l,mid,rt<<1,w); 44 if(R>mid) update(L,R,mid+1,r,rt<<1|1,w); 45 pushup(rt); 46 } 47 ll query(int L,int R,int l,int r,int rt) 48 { 49 if(L<=l&&r<=R) return mi[rt]; 50 int mid=(l+r)>>1; ll ans=inf; pushdown(rt); 51 if(L<=mid) ans=min(ans,query(L,R,l,mid,rt<<1)); 52 if(R>mid) ans=min(ans,query(L,R,mid+1,r,rt<<1|1)); 53 return ans; 54 } 55 }s; 56 57 vector
id[N1]; 58 int n,K; 59 int d[N1],c[N1],p[N1],w[N1],st[N1],ed[N1]; 60 ll f[N1]; 61 62 int main() 63 { 64 scanf("%d%d",&n,&K); 65 int i,j,k,l,r,x,mid; ll ans=inf; 66 for(i=2;i<=n;i++) d[i]=gint(); 67 for(i=1;i<=n;i++) c[i]=gint(); 68 for(i=1;i<=n;i++) p[i]=gint(); 69 for(i=1;i<=n;i++) w[i]=gint(); 70 for(i=1;i<=n;i++) 71 { 72 l=1,r=i,st[i]=i; 73 while(l<=r) 74 { 75 mid=(l+r)>>1; 76 if(d[mid]>=d[i]-p[i]) st[i]=mid,r=mid-1; 77 else l=mid+1; 78 } 79 l=i,r=n,ed[i]=i; 80 while(l<=r) 81 { 82 mid=(l+r)>>1; 83 if(d[mid]<=d[i]+p[i]) ed[i]=mid,l=mid+1; 84 else r=mid-1; 85 } 86 id[ed[i]].push_back(i); 87 } 88 memset(s.mi,0x3f,sizeof(s.mi)); 89 s.update(0,0,0,n,1,-(inf)); 90 for(k=1;k<=K;k++) 91 { 92 for(i=1;i<=n+1;i++) 93 { 94 f[i]=s.query(0,i-1,0,n,1)+c[i]; 95 for(j=0;j

 

转载于:https://www.cnblogs.com/guapisolo/p/10262701.html

你可能感兴趣的文章
js编码
查看>>
Pycharm Error loading package list:Status: 403错误解决方法
查看>>
steps/train_sat.sh
查看>>
转:Linux设备树(Device Tree)机制
查看>>
iOS 组件化
查看>>
(转)Tomcat 8 安装和配置、优化
查看>>
(转)Linxu磁盘体系知识介绍及磁盘介绍
查看>>
tkinter布局
查看>>
命令ord
查看>>
Sharepoint 2013搜索服务配置总结(实战)
查看>>
博客盈利请先考虑这七点
查看>>
使用 XMLBeans 进行编程
查看>>
写接口请求类型为get或post的时,参数定义的几种方式,如何用注解(原创)--雷锋...
查看>>
【OpenJ_Bailian - 2287】Tian Ji -- The Horse Racing (贪心)
查看>>
Java网络编程--socket服务器端与客户端讲解
查看>>
List_统计输入数值的各种值
查看>>
学习笔记-KMP算法
查看>>
Timer-triggered memory-to-memory DMA transfer demonstrator
查看>>
跨域问题整理
查看>>
[Linux]文件浏览
查看>>