多队列模拟. 与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. Java程序设计的DOS命令基础

    Java程序设计的DOS命令基础 用户使用操作系统和软件有两种方式:命令行界面(Command Line Interface,CLI)和图形界面(Graphical User Interface,GU ...

  2. int,long,unsigned的值范围

    unsigned   int   0-4294967295   int   2147483648-2147483647 unsigned long 0-4294967295long   2147483 ...

  3. MySql 中文乱码排查解决方案

    MySQL会出现中文乱码的原因不外乎下列几点: server本身设定问题,例如还停留在latin1 table的语系设定问题(包含character与collation) 客户端程式(例如php)的连 ...

  4. JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  5. MATLAB如何定义函数

    自定义函数的途径:M文件函数(M file function)在线函数(Inline Function)匿名函数(Anonymous Function)1.M文件函数范例function c=myad ...

  6. there is issue about change event of checkbox in the ie8 oe ie7

    some people said the change event of checkbox can not trigger in the ie7 or ie8,that's not true. thi ...

  7. HIbernate的增删改

    数据库是oracle 以一对多为例:user50一的一方      order50是多的一方 首先是实体类: 这里的实体是双向关系,既通过user50可以找到order50,通过order50可以找到 ...

  8. jQuery基础--样式篇(5)

    jQuery的属性与样式 (1).attr()与.removeAttr():每个元素都有一个或者多个特性,这些特性的用途就是给出相应元素或者其内容的附加信息. attr()有4个表达式 attr(传入 ...

  9. nginx 的动静分离配置(tomcat)

    nginx+tomcat是想动静分离配置 首先在nginx的配置文件中添加tomcat的的集群配置 upstream tomcats { ip_hash; server 192.168.0.251:8 ...

  10. 51nod 1163贪心

    用优先队列来贪心,是一个很好地想法.优先队列在很多时候可以维护最值,同时可以考虑到一些其他情况. http://www.51nod.com/onlineJudge/questionCode.html# ...