Classrooms

传送门


The new semester is about to begin, and finding classrooms for orientation activities is always a headache.

There are $k$ classrooms on campus and $n$ proposed activities that need to be assigned a venue. Every proposed activity has specfic starting time $s_i$ and ending time $f_i$. Any such an activity should take place at one of the classrooms. Any of the $k$ classrooms is big enough to hold any of the proposed activities, and each classroom can hold at most one activity at any time. No two proposed activities can take place at the same classroom at the same time. Even if two proposed activities overlap momentarily (the ending time of one activity equals the starting time another activity), they cannot be assigned to the same classroom.

There are so many proposed activities that there may not be enough classrooms to hold all the activities. It is desirable to have as many activities as possible. At most how many proposed activities can be assigned to the classrooms?

Input

The first line contains two positive integers $n$ and $k$ ($k \le n \le 200000$), representing the number of proposed activities and number of classrooms, respectively.

The following $n$ lines each contains two positive integers: the $i$-th line among these $n$ lines contains $s_i$ and $f_i$ ($1 \le s_i \le f_i \le 10^9$), indicating the starting time and ending time of proposed activity $i$.

Output

Output an integer indicating the maximum number proposed activities that can be scheduled.

Sample Input 1

4 2

1 4

2 9

4 7

5 8

Sample Output 1

3


Solution

从前在《挑战程序设计竞赛》看到过一个结论:

在$n$个区间$[l_1, r_1],\cdots, [l_n, r_n]$中选择最多的两两不相交的区间, 可按如下贪心策略:

每次都选当前可选的区间中结束时间最早的那个区间.

其实这是个求DAG上最长链的问题.

上述情形恰好是本题的一个特例 ($k=1$), 所以我第一个想法是:

将所有区间按右端点从大到小排序.

按此顺序将区间放到一个链表 (std::list) 里, 每次按上述贪心策略, 选择一个最长链, 并将这些区间从链表中删除.

可惜这做法是错的, 而且复杂度是$O(n^2)$.

然后就不知道怎么做了. 我做题有个不好的习惯: 每次WA后, 不会去动手出几组数据check以下, 验证自己想法的正确性.

其实对于我的做法反例很容易举出来:



后来在某博客上看到了正确的做法:

基本的想法也是对一个贪心策略的模拟:

仍然先将区间按右端点从小到大排序, 从左到右遍历这些区间, 同时用 std::multiset<int> 维护每个房间内当前正在进行那个活动的结束时间 (亦即区间右端点). 对于当前考虑的区间 $[l_i, r_i]$, 在multiset中查询小于 (早于) $l_i$的最大的某个右端点, $r^$. 若$r^$存在就将其更新为$r_i$, 否则若multisetsize()$<k$就将$r_i$插入multiset.

Implementation

考虑到std::multiset<>只支持lower_bound()upper_bound, 为了方便上述查询, 将区间右端点的相反数 (负值) 插入multiset中.

#include <bits/stdc++.h>
using namespace std; const int N{1<<18}; struct X{
int s, t;
void read(){
scanf("%d%d", &s, &t);
}
bool operator<(const X &rhs)const{
return t<rhs.t;
}
void out(){
cout<<s<<' '<<t<<endl;
}
}a[N]; multiset<int> mst; int main(){
int n, k;
cin>>n>>k;
for(int i=0; i<n; i++)
a[i].read();
sort(a, a+n);
int res=0;
for(int i=0; i<n; i++){
// a[i].out();
auto it=mst.upper_bound(-a[i].s);
if(it==mst.end()){
if(mst.size()<k){
// puts("ADD1");
res++;
mst.insert(-a[i].t);
}
}
else{
res++;
// puts("ADD2");
mst.erase(it);
mst.insert(-a[i].t);
}
}
cout<<res<<endl;
return 0;
}

当然, 取相反数也可以实现上述查询, 这时这要查询low_bound(r[i])的前趋.

#include <bits/stdc++.h>
using namespace std; const int N{1<<18}; struct X{
int s, t;
void read(){
scanf("%d%d", &s, &t);
}
bool operator<(const X &rhs)const{
return t<rhs.t;
}
void out(){
cout<<s<<' '<<t<<endl;
}
}a[N]; multiset<int> mst; int main(){
int n, k;
cin>>n>>k;
for(int i=0; i<n; i++)
a[i].read();
sort(a, a+n);
int res=0;
for(int i=0; i<n; i++){
// a[i].out();
auto it=mst.lower_bound(a[i].s);
if(it==mst.begin()){
if(mst.size()<k){
// puts("ADD1");
res++;
mst.insert(a[i].t);
}
}
else{
res++;
--it;
// puts("ADD2");
mst.erase(it);
mst.insert(a[i].t);
}
}
cout<<res<<endl;
return 0;
}

总结

这个贪心策略的正确性还是比较容易证明的.

首先将区间按活动的结束时间从早到晚排序, 按这样的顺序出个安排活动能够保证当对于任意两个相互冲突的两个活动, 我们优先选择结束时间较早的活动, 这显然比选结束时间晚的要更优.

Hong Kong Regional Online Preliminary 2016 C. Classrooms的更多相关文章

  1. Asia Hong Kong Regional Contest 2016

    A. Colourful Graph 可以在$2n$步之内实现交换任意两个点的颜色,然后就可以构造出方案. #include <bits/stdc++.h> using namespace ...

  2. 2019-2020 ICPC Asia Hong Kong Regional Contest

    题解: https://files.cnblogs.com/files/clrs97/19HKEditorial-V1.zip Code:(Part) A. Axis of Symmetry #inc ...

  3. Asia Hong Kong Regional Contest 2019

    A. Axis of Symmetry B. Binary Tree n 的奇偶性决定胜负. C. Constructing Ranches 路径上点权之和大于,极大值两倍,这是路径上点能拼出多边形的 ...

  4. 2019-2020 ICPC Asia Hong Kong Regional Contest J. Junior Mathematician 题解(数位dp)

    题目链接 题目大意 要你在[l,r]中找到有多少个数满足\(x\equiv f(x)(mod\; m)\) \(f(x)=\sum_{i=1}^{k-1} \sum_{j=i+1}^{k}d(x,i) ...

  5. 每日英语:Google Scraps Plan to Build Hong Kong Data Center

    Internet giant Google Inc. has scrapped a plan to build its own data center in Hong Kong and will in ...

  6. 每日英语:Hong Kong Lifestyle Strains City's Resources

    Hong Kong's rapacious consumption and waste production is straining its natural resources and could ...

  7. Neon Lights in Hong Kong【香港霓虹灯】

    Neon Lights in Hong Kong Neon is to Hong Kong as red phone booths are to London and fog is to San Fr ...

  8. URAL 1969. Hong Kong Tram

    有一个trick就是没想到,枚举第二段时间后,要检测该火车能否继续跑一圈来判断,不能先检测前半圈能不能跑加进去后在检测后半段: // **** 部分不能放在那个位置: 最近代码导致的错误总是找不出,贴 ...

  9. 2016-2017 ACM-ICPC East Central North America Regional Contest (ECNA 2016) F 区间dp

    Problem F Removal GameBobby Roberts is totally bored in his algorithms class, so he’s developed a li ...

随机推荐

  1. 资源搜集:Git精品文章推荐,常年更新

    以下放置的是搜集到的Git精品文章,常年更新: Git 常用命令详解(二) Git版本控制软件结合GitHub从入门到精通常用命令学习手册 Pro Git(中文版)

  2. c++ 头文件

    可以将程序分为二部分: 头文件:包含结构声明和使用这些结构的函数的原型 源代码文件: 包含与结构有关的函数的代码 不要将函数的定义或变量的声明放在头文件里, 一般头文件可以包含以下内容 >函数原 ...

  3. 用RxJava处理复杂表单验证问题

    用RxJava处理复杂表单验证问题 无论是简单的登录页面,还是复杂的订单提交页面,表单的前端验证(比如登录名和密码都符合基本要求才能点亮登录按钮)都是必不可少的步骤.本文展示了如何用RxJava来方便 ...

  4. JavaScript学习笔记-选择器集合调用方法

    <script type="text/javascript"> function uu(namePd) { //判断id var reId = new RegExp(/ ...

  5. XMl各种格式转换功能代码

    package com.cdv.test; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.File ...

  6. Ubuntu安装出现左上角光标一直闪解决方式

    Ubuntu安装出现左上角光标一直闪解决方式: 01下载ubunu http://cn.ubuntu.com/download/ 02.软碟通 http://pan.baidu.com/s/1qY8O ...

  7. 关于提高python程序执行效率的思路和想法

    相比编译型语言(C系列)python胜在简介的语法和优雅的动态编程体验,但是在执行效率上,python有解释性语言先天的劣势——执行效率较低,为了让编写出的程序获得更快的执行效率,开启此文章. pyt ...

  8. 如何设置unobtrusive的语言包

    场景:网站是用的validate.unotrusive.js验证的,网站的语言已经切换到繁体了,但是提示语言还是英文. 环境:asp.net mvc4,jquery.validate.unotrusi ...

  9. scrum阶段总结

    项目预期计划: 确定编码规范. 根据原型图,设计并实现UI,添加各个界面,按钮,对话框,列表,窗口,导航等,理清各个界面的跳转逻辑. 学习测试技巧,编写测试用例. 实现需求文档中提出的功能,分别为:景 ...

  10. 《精通CSS网页布局》读书报告 ----2016-12-5补充

    第一章:CSS布局基础 1.CSS的精髓是布局,而不是样式哦!  (定要好好的研究布局哦,尤其配合html5) 2. html标签的语义性,要好好的看看哦! 3.DTD:文档类型定义. 4.内联--& ...