题目大意

  一个公交车在一条线上从1站、2站走到n站,站站间有距离。另有m个乘客在时间点t在a站等候要到b站。对于一个站,如果车比人早到,则车等人,如果人比车早到,则人等车(我一开始做题时把这个情况当作已知不可能发生了55555)。另外有D个空间瞬移器,使得汽车在0秒内前进一个单位距离。站与站间可重复用空间瞬移器,但用两站间使用空间瞬移器的数量不多于两站间距离。现在要求对空间瞬移器进行最优安排,使得所有乘客等车+在车上的时间和最小,输出这个最小值。

思路

不使用加速器?

  如果不使用加速器,那么汽车的时间安排肯定是在每个站点接到最后一个乘客后直接出发,否则浪费那时间干什么呢?

特殊情况?

  我们的入手点在于:在当前的形式下(用了加速器相当于两站点间的距离减少一,变成了同一个问题),我们要把当前的加速器用到哪一段路上。不要只想一个情况!以下将在一个站点最后一个开始等候的人简称为“人”。

  1. 在不使用加速器的情况下,所有站点都是车等人:如果在a站到b站间使用加速器,只有在b站下车的人被影响。因此我们在与前一站仍有距离的站中选择在此站下车的人最多的站的之前的路段使用加速器。
  2. 在不使用加速器的情况下,所有站点都是人等车:我们要在最一开始的路段上使用加速器,因为这样整条路上所有人的时间都会减少1。

加上另一种情况?

  1没有什么思路;但2有。如果站a、b为两个车等人的站,那么如果在站a和a+1之间使用加速器,则在[a+1,b]站下车的人的时间都会减少1!

  因此我们根据当前车等人的站将整个路段拆分成几个区间,我们每次都选出下车人最多的区间(统计下车人可以使用前缀和)(动态选出最多可以使用优先队列)。将其在一开始加速(意味着区间内所有站点车的到达时间(出发时间(人等车时,出发时间和))都-1)后,将该区间由人等车变为人车同时到的站点拆分成子区间再次加入队列,直到加速器用完为止。

具体实现细节

下定义

  提前把一些定义下好了,可以节省大量时间。如:

  • 能加速的区间:若在站点Range.L前能够使用加速器(与前一个站点有距离),则在站点[Range.L, Range.R]下车的人时间都会减少1。这些区间可放入优先队列。
  • Range::GetAccableSubranges:不管Range是个什么区间,提取出其能被加速的子区间。
  • 上述函数中的l,r:保证[l,r]包含于一个能加速的区间内。

整个路线的起点、终点如何处理?

  特殊的是终点,因为其肯定没有人等车了。那么此时“最后一个人在此站点等候的时间”必须要设为无穷大,否则其被认为是有一个人在0时间在最后一个站点等候,这就错了。

GetAccableSubranges时,如何处理两个站点间距离为0的情况?

  明确一点:距离为0的影响在于,对于一个全部都是人等车的区间,如果该区间的左端点之前的距离为0,则该区间不能被加速。(如果一个prevdist==0的站点之前是人等车的站,此时照常处理,所以不要在加速时assert(区间中当前节点的prevdist>0))而只有当左端点为初始态或被更改时(得到一个子区间[l,r],然后l=r+1)才有可能遇到上述情况,而此时r必然等于l。因此如果区间l的prevdist==0,则l跳过(l++),r随之更改(r++)。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <cassert>
using namespace std; const int MAX_PASS = 10010, MAX_STAT = 1010, INF = 0x3f3f3f3f;
int TotStat, TotPass, TotAcc;
int OffPassPrefix[MAX_STAT]; struct Stat
{
int InTime, OutTime;
int OffPassCnt, LastPassTime;
int PrevDist;
}_stats[MAX_STAT]; struct Pass
{
Stat *S, *T;
int Time; Pass(int s, int t, int time):S(_stats+s),T(_stats+t),Time(time){} Pass(){}
}_passes[MAX_PASS]; struct Range
{
int OffPassCnt;
int L, R; Range(int l, int r) :L(l), R(r), OffPassCnt(OffPassPrefix[r]-OffPassPrefix[l - 1]){} bool operator < (const Range& a) const
{
return OffPassCnt < a.OffPassCnt;
} void GetAccableSubranges(void(*func) (Range))
{
int tl = L;
for (int r = L; r <= R; r++)
{
if (_stats[tl].PrevDist == 0)
{
assert(tl == r);
tl++;
}
else if (_stats[r].InTime <= _stats[r].LastPassTime)
{
func(Range(tl, r));
tl = r + 1;
}
}
} void Accelerate()//Accelerate at Left Prev.
{
for (int i = L; i <= R - 1; i++)
{
assert(_stats[i].InTime == _stats[i].OutTime);
//assert(_stats[i].PrevDist);//Don't assert!
_stats[i].InTime--;
_stats[i].OutTime--;
}
_stats[R].InTime--;
_stats[L].PrevDist--;
TotAcc--;
}
}; void Read()
{
scanf("%d%d%d", &TotStat, &TotPass, &TotAcc);
for (int i = 2; i <= TotStat; i++)
scanf("%d", &_stats[i].PrevDist);
for (int i = 1; i <= TotPass; i++)
{
int s, t, sTime;
scanf("%d%d%d", &sTime, &s, &t);
_passes[i] = Pass(s, t, sTime);
}
} void Init()
{
for (int i = 1; i <= TotPass; i++)
{
_passes[i].S->OutTime = max(_passes[i].S->OutTime, _passes[i].Time);
_passes[i].T->OffPassCnt++;
_passes[i].S->LastPassTime = max(_passes[i].S->LastPassTime, _passes[i].Time);
}
for (int i = 2; i <= TotStat; i++)
{
_stats[i].InTime = _stats[i - 1].OutTime + _stats[i].PrevDist;
_stats[i].OutTime = max(_stats[i].OutTime, _stats[i].InTime);
}
_stats[TotStat].LastPassTime = INF;
for (int i = 1; i <= TotStat; i++)
OffPassPrefix[i] = _stats[i].OffPassCnt + OffPassPrefix[i - 1];
} priority_queue<Range> q; void InQ(Range r)
{
q.push(r);
} void DoAcc()
{
Range(1, TotStat).GetAccableSubranges(InQ);
while (!q.empty() && TotAcc)
{
Range cur = q.top();
q.pop();
cur.Accelerate();
cur.GetAccableSubranges(InQ);
}
} int GetAns()
{
int ans = 0;
for (int i = 1; i <= TotPass; i++)
ans += _passes[i].T->InTime - _passes[i].Time;
return ans;
} int main()
{
Read();
Init();
DoAcc();
printf("%d\n", GetAns());
return 0;
}

  

luogu1315 观光公交的更多相关文章

  1. $Noip2011/Luogu1315$ 观光公交 贪心

    $Luogu$ $Sol$ 觉得这题贪心要想很多事情,不适合我这种没脑子选手$ovo$.看题解还理解了很久. 最开始是这样想的:把所有的路段上的乘客按大小排个序用加速器就好了,这个想法被自己轻松$ha ...

  2. vijos1741 观光公交 (贪心)

    https://www.vijos.org/p/1741 P1741观光公交 请登录后递交 标签:NOIP提高组2011[显示标签]   描述 风景迷人的小城Y市,拥有n个美丽的景点.由于慕名而来的游 ...

  3. NOIP2011 观光公交

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

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

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

  5. NOIP观光公交

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

  6. noip 2011观光公交

    P1315 观光公交 95通过 244提交 题目提供者该用户不存在 标签贪心递推2011NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录   题目描述 风景迷人的小城Y 市,拥有n 个美 ...

  7. 观光公交 2011年NOIP全国联赛提高组(贪心,递推)

    观光公交 2011年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold       题目描述 Description 风景迷人的小城 Y 市 ...

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

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

  9. luoguP1315 观光公交 题解(NOIP2011)(贪心)

    P1315 观光公交 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cm ...

随机推荐

  1. Xcode控制台输出中文

    创建一个.m文件,然后将一下代码加入.m文件中即可实现控制台输出中文,具体代码如下: #ifndef Release @implementation NSSet(Log) - (NSString *) ...

  2. Centos6.6 安装Memcached

    一.环境介绍 1)Centos6.4 2) memcached-1.4.24 二.部署安装 计划具体部署步骤: 步骤1:安装 步骤2:配置 步骤3:运行 步骤4:检查 现在开始: 1)安装 $ yum ...

  3. Centos6.6 安装Subversion服务

    一.介绍 Subversion 简称就是svn服务器,用来托管代码的,类似的还有git 1)Centos6.6 2)Subversion 二.安装 yum -y install subversion ...

  4. C 预处理程序指令(CPP)

    #include 文件 提供的东西 stdio 提供 FILE.stdin.stdout.stderr 和 fprintf() 函数系列 stdlib 提供 malloc().calloc()和 re ...

  5. Apex语言(五)循环结构

    1.循环结构 循环语句允许我们多次执行一个语句或一组语句(重执行语句).  2.while语句 只要给定条件为真,目标语句就会重复执行. [格式] while (循环条件){ 语句; } [流程图] ...

  6. 09 Django组件之用户认证组件

    没有学习Django认证组件之前使用装饰器方法 from django.shortcuts import render, HttpResponse, redirect from app01.MyFor ...

  7. 终于等到你!微软正式上线 Windows Terminal 预览版

    前一段时间,一直在知乎.技术社区收到技术小伙伴们的终极拷问:微软Build 大会上提到的**6月中旬**要上Windows store 的 Windows Terminal 到底啥时候可以用到呀? 有 ...

  8. html第四节课

    css CSS(Cascading Style Sheet,叠层样式表),作用是美化HTML网页. /*注释区域*/    此为注释语法 一.样式表 (一)样式表的分类 1.内联样式表 和HTML联合 ...

  9. Layui 行点击追加元素效果

    /** * 单击事件 * @param obj */var dom;var state;WarningIllegalIntime.onRowClick=function(obj) { console. ...

  10. 递归、作用域、生命周期(day09)

    数组可以作为形式参数使用 数组做形式参数的时候真正的形式参数并 不是数组而是一个可以作为数组使用的 变量 数组形式参数里包含的存储区都不是被调用 函数提供的 声明数组形式参数的时候可以省略中括号 里的 ...