Prelude

题目传送门:ヾ(•ω•`)o


Solution

按照题意模拟即可。

维护一个优先队列,里面装的是正在运营中的出租车,关键字是乘客的下车时间。

维护一个线段树,第\(i\)个位置表示第\(i\)个房子前面有没有停放出租车,这样在有人需要打车的时候可以快速找到离她最近的车的位置。

对每个房子维护一个堆,里面装的是停在这个房子前面的出租车,关键字是出租车的编号和上一个乘客下车的时间,上一个乘客下车越早,等待时间越长。

然后模拟时间的流逝就可以了,代码非常好写。


Code

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <utility>
#include <cstdlib>
#include <cassert> using namespace std;
typedef long long ll;
const int MAXN = 200010;
const int INF = 0x3f3f3f3f;
int _w; int n, k, m, x[MAXN], a[MAXN], b[MAXN];
ll t[MAXN]; namespace SGT {
int sumv[MAXN<<2], ql, qr, qv;
void _add( int o, int L, int R ) {
sumv[o] += qv;
if( L == R ) return;
int M = (L+R)/2, lc = o<<1, rc = lc|1;
if( ql <= M ) _add(lc, L, M);
else _add(rc, M+1, R);
}
void add( int p, int v ) {
ql = p, qv = v;
_add(1, 1, n);
}
void _queryl( int o, int L, int R ) {
if( L >= ql && R <= qr ) {
if( !sumv[o] ) return;
while( L != R ) {
int M = (L+R)/2, lc = o<<1, rc = lc|1;
if( sumv[lc] ) o = lc, R = M;
else o = rc, L = M+1;
}
qv = L;
} else {
int M = (L+R)/2, lc = o<<1, rc = lc|1;
if( ql <= M && !qv ) _queryl(lc, L, M);
if( qr > M && !qv ) _queryl(rc, M+1, R);
}
}
int queryl( int l, int r ) {
ql = l, qr = r, qv = 0;
_queryl(1, 1, n);
return qv;
}
void _queryr( int o, int L, int R ) {
if( L >= ql && R <= qr ) {
if( !sumv[o] ) return;
while( L < R ) {
int M = (L+R)/2, lc = o<<1, rc = lc|1;
if( sumv[rc] ) o = rc, L = M+1;
else o = lc, R = M;
}
qv = L;
} else {
int M = (L+R)/2, lc = o<<1, rc = lc|1;
if( qr > M && !qv ) _queryr(rc, M+1, R);
if( ql <= M && !qv ) _queryr(lc, L, M);
}
}
int queryr( int l, int r ) {
ql = l, qr = r, qv = 0;
_queryr(1, 1, n);
return qv;
}
} struct Node {
ll t;
int id;
Node() {}
Node( ll t, int id ):
t(t), id(id) {}
bool operator<( const Node &rhs ) const {
return t == rhs.t ? id > rhs.id : t > rhs.t;
}
};
priority_queue<Node> pq[MAXN], evt; void prelude() {
for( int i = 1; i <= k; ++i ) {
pq[x[i]].push( Node(0, i) );
SGT::add(x[i], 1);
}
} void run( ll t ) {
while( !evt.empty() && evt.top().t <= t ) {
Node car = evt.top(); evt.pop();
SGT::add(x[car.id], 1);
// printf( "car.id = %d, x[id] = %d\n", car.id, x[car.id] );
pq[x[car.id]].push(car);
}
}
int use( int pos ) {
Node car = pq[pos].top(); pq[pos].pop();
SGT::add(pos, -1);
return car.id;
}
int freecar( int pos ) {
if( !SGT::sumv[1] ) return 0;
int left = SGT::queryr(1, pos);
int right = SGT::queryl(pos, n);
// printf( "left = %d, right = %d\n", left, right );
if( !left ) left = -INF;
if( !right ) right = INF;
if( left == right ) {
return use(left);
} else if( pos-left < right-pos ) {
return use(left);
} else if( right-pos < pos-left ) {
return use(right);
} else {
Node cl = pq[left].top(), cr = pq[right].top();
if( cl.t == cr.t ) {
if( cl.id < cr.id ) {
return use(left);
} else {
return use(right);
}
} else if( cl.t < cr.t ) {
return use(left);
} else {
return use(right);
}
}
}
void solve() {
ll now = 0;
for( int i = 0; i < m; ++i ) {
now = max(now, t[i]);
run(now);
int car = freecar( a[i] );
// printf( "now = %lld, car = %d\n", now, car );
if( !car ) {
now = max(now, evt.top().t);
run(now);
// printf( "now = %lld, car = %d\n", now, car );
car = freecar( a[i] );
}
// printf( "now = %lld, car = %d\n", now, car );
printf( "%d %lld\n", car, now - t[i] + abs(x[car] - a[i]) );
evt.push( Node(now + abs(x[car] - a[i]) + abs(a[i] - b[i]), car) );
x[car] = b[i];
}
} int main() {
_w = scanf( "%d%d%d", &n, &k, &m );
for( int i = 1; i <= k; ++i )
_w = scanf( "%d", x+i );
for( int i = 0; i < m; ++i )
_w = scanf( "%lld%d%d", t+i, a+i, b+i );
prelude(), solve();
return 0;
}

【题解】Berland.Taxi Codeforces 883L 模拟 线段树 堆的更多相关文章

  1. 【题解】P1712 [NOI2016]区间(贪心+线段树)

    [题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...

  2. Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)

    Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...

  3. CodeForces 91B Queue (线段树,区间最值)

    http://codeforces.com/problemset/problem/91/B B. Queue time limit per test: 2 seconds memory limit p ...

  4. Codeforces 343D WaterTree - 线段树, DFS序

    Description Translated by @Nishikino_Maki from Luogu 行吧是我翻的 Mad scientist Mike has constructed a roo ...

  5. codeforces 787D - Legacy 线段树优化建图,最短路

    题意: 有n个点,q个询问, 每次询问有一种操作. 操作1:u→[l,r](即u到l,l+1,l+2,...,r距离均为w)的距离为w: 操作2:[l,r]→u的距离为w 操作3:u到v的距离为w 最 ...

  6. Vasya and a Tree CodeForces - 1076E(线段树+dfs)

    I - Vasya and a Tree CodeForces - 1076E 其实参考完别人的思路,写完程序交上去,还是没理解啥意思..昨晚再仔细想了想.终于弄明白了(有可能不对 题意是有一棵树n个 ...

  7. BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流

    题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...

  8. ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(模拟+线段树)

    https://nanti.jisuanke.com/t/30996 题意 每天增加m个灯泡,n个房间,能一次性换就换,模拟换灯泡过程.询问第几天的状态 分析 离线做,按题意模拟.比赛时线段树写挫了. ...

  9. 题解——洛谷P2781 传教(线段树)

    可以说是数据结构学傻了的典型案例了 昨天跳到这题上 然后思考了一下 噫!好!线段树裸题 然后打完板子,发现\(  n \le 10^9 \) 显然线段树直接做不太行 然后这题又只有普及的难度 然后我就 ...

随机推荐

  1. C#判断字符串中是否有数字

    // <summary> /// 提取字符串中的数字字符串 /// </summary> /// <param name="str"></ ...

  2. 《Learning scikit-learn Machine Learning in Python》chapter1

    前言 由于实验原因,准备入坑 python 机器学习,而 python 机器学习常用的包就是 scikit-learn ,准备先了解一下这个工具.在这里搜了有 scikit-learn 关键字的书,找 ...

  3. Web全景图的原理及实现

    全景图的基本原理 全景图是一种广角图.通过全景播放器可以让观看者身临其境地进入到全景图所记录的场景中去.比如像是这个.这种看起来很高大上的效果其实背后的原理并不复杂. 通常标准的全景图是一张2:1的图 ...

  4. Thunder-Beta发布中间产物-2017秋-软件工程第十次作业

    Thunder-Beta发布中间产物(WBS&PSP) WBS: 分解方式:按照「爱阅」阅读器的实施过程分解 使用工具:visio 2013 PSP: PSP 实际时间 Planning 计划 ...

  5. 20162316刘诚昊 第八周实验报告:实验二 Java面向对象程序设计

    实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验要求 1.没有Linux基础的同学建议先学习<L ...

  6. c# richBox内容转图片

    1.自定义控件,继承richBox public class RichTextBoxPrintCtrl : RichTextBox { //private const double anInch = ...

  7. Python:模块学习——os模块

    os模块提供了多个访问操作系统服务的功能 os模块中一些重要的函数和变量 os.name 显示当前使用平台 os.getcwd() 显示当前Python脚本工作路径 os.listdir('dirna ...

  8. 获取emacs安装的elpa包名称

    | grep "./" | sed 's/\.\///g' | sed 's/-[0-9].*$//' | sort -u

  9. [CB] Windows10为什么质量变差 bug越来越多

    在 Windows 10 发布之后,微软转向了软件即服务模式,每半年释出一个新版本,通过增加更新频率将新的特性不断推送给用户. 在以前,微软产品发布周期是两到三年,其开发流程分成多个阶段:设计和策划. ...

  10. layabox 3d 入手

    最近受到打击了,3d效果远比2d效果好. 问题 laya3d 有正交相机没有? Laya.Sprite3D.load(XX.lh);   克隆Laya.Sprite3D.instantiate Lay ...