多队列模拟. 与POJ #1025 Department类似, 不过简化很多. 貌似这类模拟题经常出现. 用STL中的优先队列 (priority_queue<>) 很好写.


这题我写得很不顺, 老年选手退步太快, 记录一下我犯的一个很隐蔽的错误, 从前对此毫无认识, 想想都可怕, 太菜了.

这道题优先队列里维护的事件 (event) 是等待.

释放这些等待的先后顺序如下:

在同一队列 (此"队列"指某个office门前的队列, 与"优先队列"中的"队列"含义不同;下同) 中的两个事件, 按(开始等待时刻, 学号)这两个关键字排序. 在不同队列中的两事件按开始等待的时刻排序.

思路是比较容易想到的. 但我的实现里有个很subtle的错误.

Wrong implementation

#include <bits/stdc++.h>
using namespace std; const int N{1<<14}, M{1<<7};
int s[N], res[N];
vector<pair<int,int>> r[N]; // registration
int avail[M];
int n, m, k; struct W{
int id, beg, idx;
int des()const{
return r[id][idx].first;
}
int dur()const{
return r[id][idx].second;
}
int num()const{
return s[id];
}
int end()const{
return max(beg, avail[des()])+dur(); // error-prone
}
W next(){
return {id, end()+k, idx+1};
}
void out(){
cout<<id<<' '<<beg<<' '<<idx<<' '<<avail[des()]<<endl;
}
}; // greater<_Tp> is a function object
// constexpr std::greater<_Tp>::operator()(const _Tp &, const_Tp &)const bool cmp(const W &a, const W &b){ //! > must be a const
if(a.des()!=b.des()){
return a.beg>b.beg;
}
else{
return a.beg!=b.beg?a.beg>b.beg:a.num()>b.num();
}
} priority_queue<W, vector<W>, decltype(cmp)*> que(cmp); int main(){
cin>>n>>m>>k;
for(int i=0; i<n; i++){
int q, t;
cin>>s[i]>>t>>q;
for(; q--; ){
int o, t;
cin>>o>>t;
r[i].push_back({o, t});
}
que.push({i, t+k, 0});
} for(; !que.empty(); ){
W top=que.top();
que.pop();
if(top.idx<r[top.id].size()-1){
que.push(top.next());
}
else{
res[top.id]=top.end();
}
avail[top.des()]=top.end();
}
for(int i=0; i<n; i++)
cout<<res[i]<<endl;
return 0;
}

注意其中的比较函数cmp:

bool cmp(const W &a, const W &b){  //! > must be a const
if(a.des()!=b.des()){
return a.beg>b.beg;
}
else{
return a.beg!=b.beg?a.beg>b.beg:a.num()>b.num();
}
}

首先必须认识到: 优先队列要求元素的键值 (key) 在所定义的比较函数下是全序的 (totally ordered).

If $X$ is totally ordered under $\le$, then the following statements hold for all $a, b$ and $c$ in $X$:

if $a \le b$ and $b \le a$ then $ a=b$ (antisymmetry);

if $a \le b$ and $b\le c$ then $a \le c$ (transitivity);

$a \le b$ or $b \le a$ (totality).

我所定义的比较函数并不是全序的. 问题中的集合$X$内的元素是一个三元组$(id, des, time)$. 我们定义的比较函数cmp是一个strict weak ordering (<). 这个binary relation应当满足

if $a < b$ and $b<c$, then $a<c$

$a< b$ or $ b<a$ or $a=b$.

但是据此会导出矛盾, 考虑

$a =(id_1, des_1, t), b=(id_2, des_1, t), c=(id_3, des_2, t), id_1 < id_2 \Longrightarrow a > b, a=c, b=c$.

矛盾!

因而这个比较函数不是全序的.

但是可以略微改一下:

以$time$为第一关键字, $des$为第二关键字, $id$为第三关键字.

这样不但思路更清楚, 代码也可以简化

Implementation

#include <bits/stdc++.h>
using namespace std; const int N{1<<14}, M{1<<7};
int s[N], res[N];
vector<pair<int,int>> r[N]; // registration
int avail[M];
int n, m, k; struct W{
int id, beg, idx;
int des()const{
return r[id][idx].first;
}
int dur()const{
return r[id][idx].second;
}
auto make_tuple()const{
return std::make_tuple(beg, des(), num());
}
int num()const{
return s[id];
}
bool operator<(const W &rhs)const{
return make_tuple() > rhs.make_tuple();
}
int end()const{
return max(beg, avail[des()])+dur(); // error-prone
}
W next(){
return {id, end()+k, idx+1};
}
void out(){
cout<<id<<' '<<beg<<' '<<idx<<' '<<avail[des()]<<endl;
}
}; priority_queue<W> que; int main(){
cin>>n>>m>>k;
for(int i=0; i<n; i++){
int q, t;
cin>>s[i]>>t>>q;
for(; q--; ){
int o, t;
cin>>o>>t;
r[i].push_back({o, t});
}
que.push({i, t+k, 0});
} for(; !que.empty(); ){
W top=que.top();
que.pop();
if(top.idx<r[top.id].size()-1){
que.push(top.next());
}
else{
res[top.id]=top.end();
}
avail[top.des()]=top.end();
}
for(int i=0; i<n; i++)
cout<<res[i]<<endl;
return 0;
}

hihoCoder 1401 Registration的更多相关文章

  1. struts2启动报错:ERROR com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor - Conversion registration error

    [framework] 2019-12-05 11:34:05,441 - org.springframework.web.context.ContextLoader -5352 [RMI TCP C ...

  2. hihocoder -1121-二分图的判定

    hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ...

  3. Hihocoder 太阁最新面经算法竞赛18

    Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ...

  4. hihoCoder太阁最新面经算法竞赛15

    hihoCoder太阁最新面经算法竞赛15 Link: http://hihocoder.com/contest/hihointerview24 题目1 : Boarding Passes 时间限制: ...

  5. 【hihoCoder 1454】【hiho挑战赛25】【坑】Rikka with Tree II

    http://hihocoder.com/problemset/problem/1454 调了好长时间,谜之WA... 等我以后学好dp再来看为什么吧,先弃坑(╯‵□′)╯︵┻━┻ #include& ...

  6. 【hihocoder#1413】Rikka with String 后缀自动机 + 差分

    搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...

  7. 【hihoCoder】1148:2月29日

    问题:http://hihocoder.com/problemset/problem/1148 给定两个日期,计算这两个日期之间有多少个2月29日(包括起始日期). 思路: 1. 将问题转换成求两个日 ...

  8. 【hihoCoder】1288 : Font Size

    题目:http://hihocoder.com/problemset/problem/1288 手机屏幕大小为 W(宽) * H(长),一篇文章有N段,每段有ai个字,要求使得该文章占用的页数不超过P ...

  9. 【hihoCoder】1082: 然而沼跃鱼早就看穿了一切

      题目:http://hihocoder.com/problemset/problem/1082 输入一个字符串,将其中特定的单词替换成另一个单词   代码注意点: 1. getline(istre ...

随机推荐

  1. npm中package.json详解

    通常我们使用npm init命令来创建一个npm程序时,会自动生成一个package.json文件.package.json文件会描述这个NPM包的所有相关信息,包括作者.简介.包依赖.构建等信息,格 ...

  2. spring WebSocket详解

    场景 websocket是Html5新增加特性之一,目的是浏览器与服务端建立全双工的通信方式,解决http请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天.股票交易.游戏 ...

  3. 实验三 敏捷开发与XP实践

    实验内容 1. XP基础 2. XP核心实践 3. 相关工具 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程 2.完成实验 ...

  4. PhoneGap: Android平台入门例子(Hello World)

    Hello World Demo: http://docs.phonegap.com/en/2.0.0/guide_getting-started_android_index.md.html#Gett ...

  5. HTTP 状态代码表示什么意思?

    HTTP 状态代码表示什么意思? 如果某项请求发送到您的服务器要求显示您网站上的某个网页,服务器将会返回 HTTP 状态码响应请求.此状态代码提供关于请求状态的信息,一些常见的状态代码为: 200 - ...

  6. .NET基于Redis缓存实现单点登录SSO的解决方案

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  7. 在nodeJs的Express框架下用TypeScript编写router路由出现import关键字错误的解决方案

    问题出现场景 在项目中采用nodejs做中间层,做页面的首屏渲染,同时采用express作为主web框架,其中express的router页面路由我采用ts语言来编写.如下: //page.ts 文件 ...

  8. socket.io简单说明及在线抽奖demo

    socket.io简单说明及在线抽奖demo socket.io 简介 Socket.IO可以实现实时双向的基于事件的通信. 它适用于各种平台,浏览器或设备,也同样注重可靠性和速度. socket.i ...

  9. Bootstrap系列 -- 11. 基础表单

    表单主要功能是用来与用户做交流的一个网页控件,良好的表单设计能够让网页与用户更好的沟通.表单中常见的元素主要包括:文本输入框.下拉选择框.单选按钮.复选按钮.文本域和按钮等.其中每个控件所起的作用都各 ...

  10. promise的学习

    为了解决回调地狱的问题,所以出现了promise的设计思想. promise的三种状态: pending 等待状态 resolved 完成状态 rejected 拒绝状态 promise的三种状态,只 ...