AT2645 [ARC076D] Exhausted?
解法一
引理:令一个二分图两部分别为 \(X, Y(|X| \le |Y|)\),若其存在完美匹配当且仅当 \(\forall S \subseteq X, f(S) \ge |S|\)(其中 \(f(S)\) 表示 \(S\) 连到的点集)。(即霍尔定律)
可以发现,原题要求的本质上就是最少添加几个椅子使得构成完美匹配。
那么添加的椅子能使得所有人都能选一定是最好的,故根据霍尔定律我们要求的本质上是 \(\max\limits_{S \subseteq X}{|S| - |f(S)|}\),即 \(\max\limits_{S \subseteq X} |S| - \bigcup\limits_{i \in S} [0, l_i] \cup [r_i, m]\)。
注意到并集是不好处理的,在我们知道全集的情况下可以反过来考虑求其补集的交即:\(\max\limits_{S \subseteq X} |S| + \bigcap\limits_{i \in S} [l_i, r_i] - m\)。
可以发现我们是不好直接枚举点集的,但是在枚举区间的情况下统计存在多少个包含这样区间的点有多少个是非常好统计的。
于是先预处理好每个位置包含多少个右端点和左端点然后使用前缀和容斥计算即可做到 \(\mathcal{O(n + m ^ 2)}\)。
考虑优化这个流程,只枚举左端点 \(l\) 然后动态维护所有点中左端点在 \(l\) 左侧的点所组成的点集对对于每个右端点的答案。
不难发现在左端点移动的时候只需要支持区间加和求区间最大值,使用线段树即可。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 2e5 + 5;
struct node { int l, r;} a[N];
int n, m, ans;
int read() {
char c; int x = 0, f = 1;
c = getchar();
while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
namespace ST {
#define ls (p << 1)
#define rs (p << 1 | 1)
#define mid (l + r >> 1)
struct tree { int mx, tag;} t[N << 2];
void lazy(int p, int k) { t[p].mx += k; t[p].tag += k;}
void pushup(int p) { t[p].mx = max(t[ls].mx, t[rs].mx);}
void down(int p) { lazy(ls, t[p].tag), lazy(rs, t[p].tag); t[p].tag = 0;}
void build(int p, int l, int r) {
if(l == r) { t[p].mx = l; return ;}
build(ls, l, mid), build(rs, mid + 1, r);
pushup(p);
}
void update(int p, int l, int r, int x, int y, int k) {
if(x > y) return ;
if(l >= x && r <= y) { lazy(p, k); return ;}
down(p);
if(mid >= x) update(ls, l, mid, x, y, k);
if(mid < y) update(rs, mid + 1, r, x, y, k);
pushup(p);
}
int query(int p, int l, int r, int x, int y) {
if(x > y) return 0;
if(l >= x && r <= y) return t[p].mx;
down(p); int ans = 0;
if(mid >= x) ans = max(ans, query(ls, l, mid, x, y));
if(mid < y) ans = max(ans, query(rs, mid + 1, r, x, y));
return ans;
}
}
bool cmp(node a, node b) { return a.l == b.l ? a.r > b.r : a.l < b.l;}
int main() {
n = read(), m = read() + 1;
rep(i, 1, n) a[i].l = read() + 2, a[i].r = read();
ST :: build(1, 1, m);
sort(a + 1, a + n + 1, cmp);
rep(i, 1, n) {
if(a[i].l > m || a[i].l > a[i].r) { ans = max(ans, n - m + 1); continue;}
ST :: update(1, 1, m, 1, min(a[i].r, m), 1);
ans = max(ans, ST :: query(1, 1, m, a[i].l, m) - a[i].l - m + 2);
}
printf("%d", ans);
return 0;
}
解法二
从特殊的情形出发,若只存在左端点的限制,那么我们只需将所有人按照左端点从小到大排序维护当前选到的最前位置然后贪心地让每个人选取即可。
此时出现了对于右端点的限制,可以调整上述这个贪心。
首先我们还是按照左端点排序,能选择选。
若出现不能选择的情况,那么此时 \(j\) 总是能替换掉之前选择过的一个人使得答案不变的,但显然的是不是所有情况都能替换。
近一步观察可以发现如果之前选择的 \(i\) 的 \(r_i < r_j\) 那么此时 \(j\) 替换 \(i\) 一定是更优的,因为将 \(i\) 留下放在右边的可能性比 \(j\) 大,同时为了最大化这个可能每次我们只能选择替换 \(r_i\) 最小的 \(i\),使用小根堆维护即可。
那么最后我们可以得到一个拿出来需要放置在右侧的一个序列,此时就只有右端点的限制了直接做最开始的贪心即可。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 2e5 + 5;
struct node { int l, r;} a[N];
int n, m, L, P, cnt, b[N];
priority_queue <int, vector <int>, greater <int> > Q;
bool cmp1(node a, node b) { return a.l < b.l;}
bool cmp2(int a, int b) { return a > b;}
int main() {
cin >> n >> m;
rep(i, 1, n) cin >> a[i].l >> a[i].r;
sort(a + 1, a + n + 1, cmp1);
P = 1;
rep(i, 1, n) {
if(P <= a[i].l) ++P, Q.push(a[i].r);
else {
if(!Q.empty() && a[i].r > Q.top()) b[++cnt] = Q.top(), Q.pop(), Q.push(a[i].r);
else b[++cnt] = a[i].r;
}
}
sort(b + 1, b + cnt + 1, cmp2);
L = P, P = m;
rep(i, 1, cnt) if(P >= b[i] && P >= L) --P;
printf("%d", n - (m - P + L - 1));
return 0;
}
在解法一当中,多次使用正难则反的思想,这是需要注意的解题关键。
在解法二当中,使用的是放宽条件特殊化问题之后通过调整使得其能适应原问题。
AT2645 [ARC076D] Exhausted?的更多相关文章
- 2017国家集训队作业[arc076d/f][Exhausted?]
2017国家集训队作业[arc076d/f][Exhausted?] 题意: 有\(N\)个人,\(M\)把椅子,给出\(...L_i.R_i\)表示第\(i\)个人可以选择编号为\(1\sim ...
- 【ARC076D/F】Exhausted?
Description 题目链接 Solution 场上尝试使用优化建图网络流实现,结果T到怀疑人生. 鉴于这是个匹配问题,考虑用贪心做一下. 先退一步,想一下如果每一个人只有\([1 ...
- php编译 :virtual memory exhausted: Cannot allocate memory
有时候用vps建站时需要通过编译的方式来安装主机控制面板.对于大内存的VPS来说一般问题不大,但是对于小内存,比如512MB内存的VPS来说,很有可能会出现问题,因为编译过程是一个内存消耗较大的动作. ...
- Cannot get a connection, pool exhausted解决办法
http://blog.163.com/it_message/blog/static/8892051200908102032653/ 连接池(Tomcat+oracle),运行一段时间后就会出现 Ca ...
- Fatal error: Allowed memory size of 524288000 bytes exhausted (tried to allocate 64 bytes) in D
Fatal error: Allowed memory size of 524288000 bytes exhausted (tried to allocate 64 bytes) in D 从数据库 ...
- inotify resources exhausted
inotify resources exhausted tail -f /var/log/kubelet.log tail: inotify resources exhausted tail: ino ...
- 编译时:virtual memory exhausted: Cannot allocate memory
一.问题 当安装虚拟机时系统时没有设置swap大小或设置内存太小,编译程序会出现virtual memory exhausted: Cannot allocate memory的问题,可以用swap扩 ...
- tomcat异常: Cannot get a connection, pool exhausted
1 问题描述Web程序在tomcat刚开始运行时速度很快,但过一段时间后发现速度变得很慢. 检查日志输出,发现异常如下:org.apache.commons.dbcp.SQLNestedExcepti ...
- ASM磁盘组空间不足--ORA-15041:DISGROUP DATA space exhausted (生产库案例)
原创作品,出自 "深蓝的blog" 博客,深蓝的blog:http://blog.csdn.net/huangyanlong/article/details/47277715 近日 ...
随机推荐
- 精通 MySQL 索引
索引概念: 概念:索引是提高mysql查询效率的数据结构.总的一句话概括就是索引是一种提高查询效率的数据结构. 数据库查询是数据库的最主要功能之一.设计者们都希望查询数据的速度能尽可能的快,因此数据库 ...
- 第二十八个知识点:什么是公钥密码学的IND-CCA安全定义?
第二十八个知识点:什么是公钥密码学的IND-CCA安全定义? 我们将在这篇博客中讨论公钥加密的IND-CCA安全. IND-CCA安全代表选择明文的不可伪造性.这样的安全方案的思想就是给定一个密文,攻 ...
- 一个不常遇到的HbuilderX自动化测试运行问题
晚上10点左右,刚好说想研究一下uniapp项目中怎么进行自动测试,于是跟着插件的官方教程开始配置测试环境,写好了一个简单的测试脚本,然后图形化操作IDE运行测试,却报错了一大片错误信息,如下所示: ...
- Max-Mahalanobis Linear Discriminant Analysis Networks
目录 概 主要内容 Pang T, Du C, Zhu J, et al. Max-Mahalanobis Linear Discriminant Analysis Networks[C]. inte ...
- WPF之AvalonEdit实现MVVM双向绑定
AvalonEdit简介 AvalonEdit是基于WPF开发的代码显示控件,默认支持多种不同语言的关键词高亮,并且可以自定义高亮配置.所以通过AvalonEdit可以快速开发出自己想要的代码编辑器. ...
- Sentry 开发者贡献指南 - SDK 开发(性能监控:Sentry SDK API 演进)
内容整理自官方开发文档 本文档的目标是将 Sentry SDK 中性能监控功能的演变置于上下文中. 我们首先总结了如何将性能监控添加到 Sentry 和 SDK, 然后我们讨论 identified ...
- .NET5.0 依赖注入,关于 Autofac 使用
前置 工具 VS2019 概念 关于以下几个概念,自行百度. 控制反转:IoC(Inversion of Control) 依赖注入: 容器:DI 容器(.NET Core 自带),Autofac(本 ...
- 在Java中为什么不同的返回类型不算方法重载?
本文已收录<Java常见面试题>:https://gitee.com/mydb/interview 方法重载是指在同一个类中,定义了多个同名方法,但每个方法的参数类型或者是参数个数不同就是 ...
- RSA非对称加密算法实现:Java
RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院工作.RSA ...
- Pytest_用例执行顺序(5)
在unittest中,测试用例的执行顺序与测试用例的名称有关,按照名称的ascii码排序的,并不是按照用例的编写顺序执行的. pytest默认是按用例的编写顺序执行的 我们可以通过第三方包 pytes ...