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. 移动端前端UI库—Frozen UI、WeUI、SUI Mobile

    [MUI]http://www.dcloud.io/ [Clouda]http://clouda.baidu.com/blend2是百度历时两年共同研发的开源App技术框架,基于Node.js,简单易 ...

  2. c#类库和可移值类库的区别

    所谓类库,只能指定一个类库的可运行平台. 而可移值类库,可以在无需修改代码的情况,同时可以在多平台上运行DLL文件.多平台如NET Framework.Silverlight.Windows Phon ...

  3. IIS7.5开启GZip压缩

    在IIS7.5选择要开启GZip压缩的网站,在功能视图中找到并双击"压缩"图标,在压缩界面中钩选"启用静态内容压缩"和"启用动态内容压缩", ...

  4. SQL复杂查询和视图

    子查询 现实中,很多情况下需要进行下述条件判断 某一元素是否是某一集合成员 某一集合是否包含另一集合 测试集合是否为空 测试集合是否存在另一元组 子查询是出现在WHERE子句中的SELECT语句被称为 ...

  5. 4-pwd 打印当前工作目录

    pwd print name of current/working directory 打印当前工作目录 [语法]: pwd [选项] [参数] [功能介绍] pwd命令以绝对路径的方式显示用户当前工 ...

  6. Openstack Basic Networking 翻译

    自己翻译,加强理解.并学习英文和写作. 英文地址:http://docs.openstack.org/networking-guide/intro_basic_networking.html 目录: ...

  7. 【转】JSP使用上传文件,并生产高清缩略图示例

    原文地址:http://blog.csdn.net/yakson/article/details/9875731 前言 刚开始本来只想来测试一下Thumbnails生成缩略图的效果的,顺便来学一下js ...

  8. java设计模式(八) 适配器模式

    [适配器模式]将一个类的接口,转换成客户期望的另外一个接口.适配器让原本接口不兼容的类可以合作无间. 1,Duck接口 package com.pattern.adapter; public inte ...

  9. LRU设计

    list是双向链表,map保存key对应到list中的迭代器的位置,list保存<key,value> class LRUCache{ public: LRUCache(int capac ...

  10. 在chrome下-webkit-box布局的一个bug

    chrome,也就是webkit内核下作的检测, chrome版本是40, -webkit-box这种布局在移动端用的比较多,主要是因为pc端的浏览器内核参差不齐. 因为在写HTML的时候看上了-we ...