【题目链接】

http://www.lydsy.com/JudgeOnline/problem.php?id=1835

【题意】

有n个村庄,每个村庄位于d[i],要求建立不多于k个基站,在第i个村庄建基站的费用为c[i],如果在距离村i不超过s[i]内有基站则该村被覆盖,村i不被覆盖的补偿费为w[i],求最少花费。

【思路】

设f[i][j]表示第i个村建第j个基站的最小花费,则有转移式:

f[i][j]=min{ f[k][j-1]+cost(k,i) } + c[i] ,j-1<=k<=i-1

cost(k,i)=sigma{ w[x] } k+1<=x<=i-1 , 且x未被覆盖

f[][]需要求一个区间最小值,我们尝试用线段树维护每一层的这个值。

枚举j,考虑每一层i。

我们设st[i],ed[i]分别表示在i左右距离i最远的st[i],ed[i]建基站依旧可以覆盖到i,假设我们已经求完了f[i][j]要求f[i+1][j],考虑那些恰可以被i覆盖到而不能被i+1覆盖到的,即满足ed[x]=i的点,将[1..st[x]-1]区间内的线段树值都加w[x],意为前一个基站k位于[1..st[x]-1]那么点x因不会被覆盖到需要做出赔偿。求f[i]的时候查询区间[1..i-1]内线段树值的最小即可。

其中st[i],ed[i]可以用二分法求。

线段树提供区间操作区间查询的操作。

总的时间复杂度为O(nmlogn)

辣鸡线段树,毁我青春(连个线段树都不会写了T^T

【代码】

 #include<set>
 #include<cmath>
 #include<queue>
 #include<vector>
 #include<cstdio>
 #include<cstring>
 #include<iostream>
 #include<algorithm>
 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 using namespace std;

 typedef long long ll;
 ;
 const int inf = 1e9;

 ll read() {
     char c=getchar();
     ll f=,x=;
     while(!isdigit(c)) {
         ; c=getchar();
     }
     while(isdigit(c))
         x=x*+c-',c=getchar();
     return x*f;
 }

 int n,K; ll f[N];
 ll d[N],c[N],s[N],w[N],st[N],ed[N];
 vector<ll> ep[N];

 struct Tnode {
     int l,r; ll v,tag;
 }T[N<<];

 void pushdown(int u)
 {
     if(T[u].l==T[u].r||(!T[u].tag)) return ;
     ll& t=T[u].tag;
     T[u<<].v+=t,T[u<<].tag+=t;
     T[u<<|].v+=t,T[u<<|].tag+=t;
     t=;
 }
 void maintain(int u)
 {
     T[u].v=min(T[u<<].v,T[u<<|].v);
 }
 void build(int u,int l,int r)
 {
     T[u].l=l,T[u].r=r;
     T[u].tag=;
     if(l==r) T[u].v=f[l];
     else {
         ;
         build(u<<,l,mid);
         build(u<<|,mid+,r);
         maintain(u);
     }
 }
 void Add(int u,int L,int R,ll x)
 {
     if(L>R) return ;                    //处理 L>R
     pushdown(u);
     if(L<=T[u].l&&T[u].r<=R)
         T[u].v+=x,T[u].tag+=x;
     else {
         ;
         ,L,R,x);
         |,L,R,x);
         maintain(u);
     }
 }
 ll query(int u,int L,int R)
 {
     ;
     pushdown(u);
     if(L<=T[u].l&&T[u].r<=R) return T[u].v;
     else {
         ; ll ans=inf;
         ,L,R));
         |,L,R));
         return ans;
     }
 }

 //lower_bound定义为找到第一个不小于v的数的指针
 void init()
 {
     n=read(),K=read();
     FOR(i,,n) d[i]=read();
     FOR(i,,n) c[i]=read();
     FOR(i,,n) s[i]=read();
     FOR(i,,n) w[i]=read();
     n++,K++;
     d[n]=inf; w[n]=inf;
     FOR(i,,n) {
         int l=d[i]-s[i],r=d[i]+s[i];
         l=lower_bound(d+,d+n+,l)-d;
         r=lower_bound(d+,d+n+,r)-d;
         if(d[i]+s[i]<d[r]) r--;
         st[i]=l,ed[i]=r;
         ep[ed[i]].push_back(i);
     }
 }
 ll dp()
 {
     ll ans,tmp=;
     FOR(i,,n) {
         f[i]=tmp+c[i];
         FOR(j,,()
             tmp+=w[ep[i][j]];
     }
     ans=f[n];
     FOR(j,,K) {
         build(,,n);
         FOR(i,,n) {
             f[i]=query(,,i-)+c[i];
             FOR(k,,() {
                 int x=ep[i][k];
                 Add(,,st[x]-,w[x]);
             }
         }
         ans=min(ans,f[n]);
     }
     return ans;
 }

 int main()
 {
     //freopen("in.in","r",stdin);
     //freopen("out.out","w",stdout);
     init();
     printf("%lld",dp());
     ;
 }

bzoj 1835 [ZJOI2010]base 基站选址(DP+线段树)的更多相关文章

  1. BZOJ 1835 [ZJOI2010]base 基站选址:线段树优化dp

    传送门 题意 有 $ n $ 个村庄在一排直线上,现在要建造不超过 $ K $ 个通讯基站,基站只能造在村庄处. 第 $ i $ 个村庄距离第 $ 1 $ 个村庄的距离为 $ D_i $ .在此建造基 ...

  2. BZOJ 1835: [ZJOI2010]base 基站选址 [序列DP 线段树]

    1835: [ZJOI2010]base 基站选址 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立 ...

  3. BZOJ 1835: [ZJOI2010]base 基站选址(DP,线段树)

    可以很容易的写出dp方程: F[i][j]=min(F[l][j-1]+w[l][i])+c[i] (w[i][j]是从l+1到i-1这些点p里,所有满足d[p]+s[p]<d[i] & ...

  4. BZOJ1835: [ZJOI2010]base 基站选址【线段树优化DP】

    Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...

  5. 2018.11.06 bzoj1835: [ZJOI2010]base 基站选址(线段树优化dp)

    传送门 二分出每个点不需要付www贡献的范围,然后可以推出转移式子: f[i][j]=f[i−1][k]+value(k+1,j)+c[i]f[i][j]=f[i-1][k]+value(k+1,j) ...

  6. bzoj 1835: [ZJOI2010]base 基站选址

    Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...

  7. bzoj[1835][ZJOI2010]base 基地选址

    bzoj[1835][ZJOI2010]base 基地选址 标签: 线段树 DP 题目链接 题解 这个暴力DP的话应该很容易看出来. dp[i][j]表示造了i个通讯站,并且j是第i个的最小费用. \ ...

  8. bzoj 1835 base 基站选址 - 动态规划 - 线段树

    题目传送门 需要高级权限的传送门 题目大意 有$n$个村庄坐落在一条直线上,第$i \ \ \ (i>1)$个村庄距离第$1$个村庄的距离为$D_i$.需要在这些村庄中建立不超过$K$个通讯基站 ...

  9. BZOJ 1835 基站选址(DP+线段树)

    # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream& ...

随机推荐

  1. 【原】SDWebImage源码阅读(四)

    [原]SDWebImage源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 SDWebImage中主要实现了NSURLConnectionDataDelega ...

  2. spring关于“transactionAttributes”的相关配置

    spring关于"transactionAttributes"的相关配置 <bean id="baseTransactionProxy" class=&q ...

  3. 分享功能使用的UIPopoverController在iOS9 过期,替换为popoverPresentationController

    记录一下 以备以后用到的时候拿出来看看.以前使用的: 1 if (UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom ...

  4. Hibernate分页

    1. HQL分页: Session session = HibernateUtil.getInstance().getSession(); Query query = session.createQu ...

  5. asp.net做的网站账号登陆后注销不管用了

    最近做了个项目用到了数据库登录,A登陆后把登录状态保,个人信息存在Session里,但是奇怪的是,只要有一个用户登录后在其他电脑上打开上述页面,则也显示A登录状态,注销也不管用了.以前还号的.求大神啊 ...

  6. SDAU课程练习--problemQ(1016)

    题目描述 FJ is surveying his herd to find the most average cow. He wants to know how much milk this 'med ...

  7. 分布式统一配置平台-Disconf.Net

    源码地址:https://github.com/qkbao/Disconf.Net 作者:青客宝  联系qq:后续奉上 为了更好的解决分布式环境下多台服务实例的配置统一管理问题,本文提出了一套完整的分 ...

  8. tcp/ip 卷一 读书笔记(5)arp和rarp 同网段和不同网段之间的通信过程

    arp和rarp 同网段和不同网段之间的通信过程 IPv6中已经没有arp rarp协议,所以这里都是IPv4. 链路层使用以太网地址来确定目的地址,应用则常使用ip地址通信 arp协议是指从ip地址 ...

  9. Nginx 常用配置

    Nginx的负载均衡方式 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. 2.weight 指定轮询几率,weight和访问比率成正比,用于后端 ...

  10. [Solution] 885. Spiral Matrix Ⅲ

    Difficulty: Medium Problem On a 2 dimensional grid with R rows and C columns, we start at (r0, c0) f ...