【题解】Berland.Taxi Codeforces 883L 模拟 线段树 堆
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 模拟 线段树 堆的更多相关文章
- 【题解】P1712 [NOI2016]区间(贪心+线段树)
[题解]P1712 [NOI2016]区间(贪心+线段树) 一个observe是,对于一个合法的方案,将其线段长度按照从大到小排序后,他极差的来源是第一个和最后一个.或者说,读入的线段按照长度分类后, ...
- Codeforces 765F Souvenirs 线段树 + 主席树 (看题解)
Souvenirs 我们将询问离线, 我们从左往右加元素, 如果当前的位置为 i ,用一棵线段树保存区间[x, i]的答案, 每次更新完, 遍历R位于 i 的询问更新答案. 我们先考虑最暴力的做法, ...
- CodeForces 91B Queue (线段树,区间最值)
http://codeforces.com/problemset/problem/91/B B. Queue time limit per test: 2 seconds memory limit p ...
- Codeforces 343D WaterTree - 线段树, DFS序
Description Translated by @Nishikino_Maki from Luogu 行吧是我翻的 Mad scientist Mike has constructed a roo ...
- 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 最 ...
- Vasya and a Tree CodeForces - 1076E(线段树+dfs)
I - Vasya and a Tree CodeForces - 1076E 其实参考完别人的思路,写完程序交上去,还是没理解啥意思..昨晚再仔细想了想.终于弄明白了(有可能不对 题意是有一棵树n个 ...
- BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流
题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...
- ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(模拟+线段树)
https://nanti.jisuanke.com/t/30996 题意 每天增加m个灯泡,n个房间,能一次性换就换,模拟换灯泡过程.询问第几天的状态 分析 离线做,按题意模拟.比赛时线段树写挫了. ...
- 题解——洛谷P2781 传教(线段树)
可以说是数据结构学傻了的典型案例了 昨天跳到这题上 然后思考了一下 噫!好!线段树裸题 然后打完板子,发现\( n \le 10^9 \) 显然线段树直接做不太行 然后这题又只有普及的难度 然后我就 ...
随机推荐
- js操作对象属性值为字符串
今天在项目开发中遇到一个没遇到过的问题,这个问题是需要对比两个对象a和b,a是一个只有一个属性的对象,b是一个含有多个属性对象,如果b中包含和a一模一样的属性名和值,则把这个一样的属性和值从b中删除了 ...
- 基于spec探路者团队贪吃蛇作品的评论
1 运动功能 由以上两图贪吃蛇的位置不同可知,运动功能实现.并且我能够通过使用键盘上的上下左右方位键控制蛇的移动方向,蛇在控制的方向上进行直线前进. 2 吃食物功能 以上两图可知吃食物功能实现.当界面 ...
- FPGA的软核与硬核
硬核 zynq和pynq系列的fpga都是双ARM/Cortex-A9构成,这里的ARM处理器为硬核,Cortex-A9部分为FPGA部分.即整体分为两部分:PS/PL.PS部分为A9处理器部分,PL ...
- 【最小生成树+LCA】Imperial roads
http://codeforces.com/gym/101889 I 先跑一遍最小生成树,把经过的边和答案记录下来 对于每个询问的边,显然如果处于MST中,答案不变 如果不在MST中,假设这条边连上了 ...
- Alpha 冲刺(8/10)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 多次测试软件运行 学习OPENMP ...
- asp.net登录状态验证
文章:ASP.NET 登录验证 文章:ASP.NET MVC下判断用户登录和授权状态方法 文章:.net学习笔记---HttpHandle与HttpModule 第一篇文章,介绍了 1)早期的Base ...
- 老司机带你解读jQuery插件开发流程
jquery插件开发模式 jquery插件一般有三种开发方式: 通过$.extend()来扩展jQuery 通过$.fn 向jQuery添加新的方法 通过$.widget()应用jQuery UI的部 ...
- 《剑指offer》---左旋转字符串与右旋转字符串
本文算法使用python3实现 1. 问题1 1.1 题目描述: 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S, ...
- 判断字符串中是否存在的几种方案:string.indexof、string.contains、list.contains、list.any几种方式效率对比
我们在做项目时,可能会遇到这样的需求,比如判断,1,2,3,33,22,123, 中是否存在,3,. var str=",1,2,3,33,22,123,"; 一般有几种方式: 1 ...
- arp_filter的验证,使用net namespace
使用网络命名空间:net namespace 在namespace ns1中增加了两个网卡 sudo ip netns add ns1 sudo ip link add veth0 type veth ...