[传送门](https://loj.ac/problem/2601)

题目大意

给定从左到右的$n$个车站以及两两之间通行的需要的时间。

有$m$个人,第$i$个人会在$T_i$时刻出现在$a_i$车站,目的地是$b_i$。

一辆车第$0$时刻出现在一号站台,从左向右驶去,每经过一个车站(包括$1$号),它会等待知道所有应该在该站台出现的乘客都出现才会继续驶向下一个站台。

定义一个人花费的时间是列车到达 $b_i$ 的时刻$-T_i$。你有$k$次机会使得某相邻两站花费的时间减少一个时间单位(需要始终保证非负),求这$m$个人花费时间之和的最小值。

题解

在$n,m,k$均很小的情况下可以用各种算法搞过去,但加强后不得不优化复杂度。

前置技能:$O(nk)$的贪心([你可以在洛谷中找到大量的题解](https://www.luogu.org/problemnew/solution/P1315))

先设一个最终答案为 $ans$,初始时 $ans=-\sum T_i$

仍是考虑设第$i$个车站最后一个人到达时间为$G_i$,到达$i$的时间比$G_i$多出了$S_i$的时间,第$i$个车站到第$i+1$个车站的距离为$D_i$,第 $i$ 个车站下车的人有 $V_i$ 个 。

那么 $S_i=\max\{0,S_{i-1}+G_{i-1}+D_{i-1}-G_{i}\},ans+=V_i(S_i+G_i)$

考虑一段区间$[L,R]$,若有$(L,R]$内的$S$均大于$0$,那么减少$D_L K$个单位可以使得所有$(L,R]$的到达时间减少$K$,那么最终答案减少的就是$K\times$区间内是终点的数量。

考虑用线段树维护$S$,将每一个有意义的$[L,R]$用一个大根堆存起来(以区间内终点数量为关键字)。

每次取出堆顶 $[L,R]$,求 $x=\min\{D_L,\min\{S_i\}i\in(L,R]\}$ 即为区间内可以减少的时间,那么将 $k$ 次机会中的 $x$ 个用与减少区间答案。

接下来一定会至少出现一个 $i$ 使得 $S_i=0$ 或 $k=0$ 或 $D_L=0$,那么原来有意义的区间至多分裂成两个有意义的区间,在分别丢进堆里不断处理即可。

可见,该算法的复杂度及基本与$k$无关,甚至与$m$无关。

复杂度仅为有意义的区间数量(不超过$2n$个)在带一个线段树的和堆的$log$,大概就是$O(n\log n)$。

```
#include<bits/stdc++.h>
#define LL long long
#define M 600020
using namespace std;
namespace IO{
const int BS=(1<<20)+5; char Buffer[BS],*HD,*TL;
char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
int read(){
int nm=0,fh=1; char cw=Getchar();
for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
}using namespace IO;
int n,m,p[M<<2],pos[M<<2],tg[M<<2],val[M],D[M],K,last;
LL ans,gt[M],st[M];
#define pushup int sn=(p[x<<1]<p[x<<1|1])?(x<<1):(x<<1|1);pos[x]=pos[sn],p[x]=p[sn]
struct seg{
int LS,RS;seg(){}
seg(int _LS,int _RS){LS=_LS,RS=_RS;}
bool operator<(const seg&ot)const{return val[RS]-val[LS]<val[ot.RS]-val[ot.LS];}
};priority_queue<seg>H;
void build(int x,int l,int r){
if(l==r){pos[x]=r,p[x]=st[r];return;}
int mid=((l+r)>>1); build(x<<1,l,mid);
build(x<<1|1,mid+1,r); pushup;
}
#define pushdown tg[x<<1]+=tg[x],tg[x<<1|1]+=tg[x],p[x<<1]-=tg[x],p[x<<1|1]-=tg[x],tg[x]=0
void mdf(int x,int l,int r,int ls,int rs,int dt){
if(ls<=l&&r<=rs){tg[x]+=dt,p[x]-=dt;return;}
if(r<ls||rs<l) return; int mid=((l+r)>>1); pushdown;
mdf(x<<1,l,mid,ls,rs,dt),mdf(x<<1|1,mid+1,r,ls,rs,dt); pushup;
}
int getnode(int x,int l,int r,int ls,int rs){
if(ls<=l&&r<=rs) return x;if(r<ls||rs<l) return 0;
int mid=((l+r)>>1); pushdown;
int t1=getnode(x<<1,l,mid,ls,rs);
int t2=getnode(x<<1|1,mid+1,r,ls,rs);
return p[t1]>p[t2]?t2:t1;
}
int main(){
n=read(),m=read(),K=read(),last=1,p[0]=1000000000;
for(int i=1;i<n;i++) D[i]=read();
for(int i=1;i<=m;i++){
int tim=read(),x=read(),y=read();
gt[x]=max(gt[x],(LL)tim),val[y]++,ans-=tim;
}
for(int i=2;i<=n;i++) val[i]+=val[i-1];
for(int i=2;i<=n;i++){
st[i]=max(0ll,st[i-1]+gt[i-1]+D[i-1]-gt[i]);
if(!st[i]) H.push(seg(last,i)),last=i;
ans+=(LL)(val[i]-val[i-1])*(gt[i-1]+st[i-1]+D[i-1]);
}
if(last<n) H.push(seg(last,n)); build(1,2,n);
while(K>0&&!H.empty()){
seg tmp=H.top();H.pop();int ls=tmp.LS,rs=tmp.RS,k=0;
if(ls+1<rs) k=getnode(1,2,n,ls+1,rs-1);
int dt,ks,t2=D[ls]; dt=min(K,min(t2,p[k])),ks=(dt==t2?ls+1:pos[k]);
ans-=(LL)dt*(LL)(val[rs]-val[ls]),K-=dt; if(K<=0) break;
if(dt&&ls+1<rs) mdf(1,2,n,ls+1,rs-1,dt); D[ls]-=dt;
if(ls<ks) H.push(seg(ls,ks)); if(ks<rs) H.push(seg(ks,rs));
} printf("%lld\n",ans); return 0;
}
```

NOIP2011 观光公交 加强版的更多相关文章

  1. NOIP2011 观光公交

    3.观光公交 (bus.cpp/c/pas) 风景迷人的小城 Y 市,拥有 n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特 意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 ...

  2. [NOIP2011] 观光公交(贪心)

    题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2 ...

  3. 题解【洛谷P1315】[NOIP2011]观光公交

    题目描述 风景迷人的小城 Y 市,拥有 \(n\) 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务. 观光公交车在第 \(0\) 分钟出现在 \( ...

  4. 贪心(模拟费用流):NOIP2011 观光公交

    [问题描述] 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0 分钟出现在1号景点,随后依次前往2. ...

  5. [NOIP2011]观光公交 题解

    题目大意: 就省了吧 思路: 应该算是贪心. 不难发现,加速只对所有在使用加速器之后连续的一段下车时不用等人的站点下车的人有用.这非常重要. 先算出不加速时的和,并预处理出每个站点最迟到的人的时间.每 ...

  6. [搬运] [贪心]NOIP2011 观光公交

    推荐这篇题解:http://www.cnblogs.com/Blacko/archive/2013/10/18/3376597.html 只不过这篇题解有一些细节没有说清,但建议自己思考- Codes ...

  7. [luogu]P1315 观光公交[贪心]

    [luogu]P1315 [NOIP2011]观光公交 ——!x^n+y^n=z^n 题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车, ...

  8. Luogu 1315 【NOIP2011】观光公交 (贪心)

    Luogu 1315 [NOIP2011]观光公交 (贪心) Description 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供 ...

  9. 洛谷P1315 [NOIP2011提高组Day2T3] 观光公交

    P1315 观光公交 题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号 ...

随机推荐

  1. [转]Linux下RPM软件包的安装及卸载 yum操作

    在 Linux 操作系统下,几乎所有的软件均通过RPM 进行安装.卸载及管理等操作.RPM 的全称为Redhat Package Manager ,是由Redhat 公司提出的,用于管理Linux 下 ...

  2. Linux中Nginx安装部署

    前言 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 Igor Sys ...

  3. centos 安装 谷歌BBR

    使用root用户登录,运行以下命令: wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.sh  ...

  4. Mybatis常见问题

    1.#和$的区别和联系 1.1#是占位符,会对Sql进行预编译,相当于?:$是做Sql拼接,有sql注入的隐患 1.2#不需要关注数据类型,Mybatis自动实现类型转换,$必须自己判断数据类型联系 ...

  5. UVA 10900 So you want to be a 2n-aire? (概率dp)

    题意:玩家初始的金额为1:给出n,表示有n道题目:t表示说答对一道题目的概率在t到1之间均匀分布. 每次面对一道题,可以选择结束游戏,获得当前奖金:或者回答下一道问题,答对的话奖金翻倍,答错的话结束游 ...

  6. 解析CEPH: 存储引擎实现之一 filestore

    Ceph作为一个高可用和强一致性的软件定义存储实现,去使用它非常重要的就是了解其内部的IO路径和存储实现.这篇文章主要介绍在IO路径中最底层的ObjectStore的实现之一FileStore. Ob ...

  7. angularjs1 自定义轮播图(汉字导航)

    本来想用swiper插件的,可是需求居然说要汉字当导航栏这就没办法了,只能自己写. directive // 自定义指令: Home页面的轮播图 app.directive('swiperImg', ...

  8. 简易的解决方式linker command failed with exit code 1 (use -v to see invocation)

    linker command failed with exit code 1 (use -v to see invocation) 遇到这个问题先不要慌,不用纠结是不是自己改动了什么代码导致的. 长话 ...

  9. python标准日志模块logging使用

    python的标准库里的日志系统从Python2.3开始支持.只要import logging这个模块即可使用.如果你想开发一个日志系统, 既要把日志输出到控制台, 还要写入日志文件,只要这样使用: ...

  10. (CSharp)克隆控件事件

    // https://stackoverflow.com/questions/6055038/how-to-clone-control-event-handlers-at-run-time // &q ...