ARC076 F Exhausted? Hall定理 + 线段树扫描线
题目大意:
有n个人,m个座位,每个人可以匹配的座位是[1, li] || [ri, m],可能有人不需要匹配座位(默认满足),问最少有多少人不能被满足。
题解:
首先可以看出这是一个二分图匹配,根据hall定理,我们只需要求出max(人的子集大小 - 被选出的人可以选的座位集合大小)。
但是枚举人的复杂度太高,所以考虑枚举座位集合,因为每个人的可选区间都是一段前缀or后缀,因此要表达一个合法的座位集合,我们只需要所有人中最右边的li和最左边的ri即可。
如图所示:

因此这个时候要使得尽可能接近max,就要把所有可选区间不超过我们当前枚举的区间的人都加进来。
可以使用扫描线,求出对于每个R,所有的L相对应的值。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 400100
#define ac 1601000//error!!!数据范围是2 00000, 不是1开头!!! int n, m, ans = -INT_MAX, w;
int Head[AC], Next[ac], date[ac], tot;
int tree[ac], lazy[ac], l[ac], r[ac], l_[AC], r_[AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void add(int f, int w)
{
date[++tot] = w, Next[tot] = Head[f], Head[f] = tot;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} void pre()
{
n = read(), m = read();
for(R i = ; i <= n; i ++)
l_[i] = read(), r_[i] = read(), add(r_[i], i);
} inline void pushdown(int x)
{
if(lazy[x])
{
int ll = x * , rr = ll + ;
lazy[ll] += lazy[x], lazy[rr] += lazy[x];
tree[ll] += lazy[x], tree[rr] += lazy[x];//这里因为是+=,所以必须用lazy[x],不然会将lazy[ll]中的一些东西重复统计
lazy[x] = ;//最后才清空!!!!!!!!!!
}//error!!!是区间加,不是赋值,不能直接覆盖,要+=
} inline void update(int x)
{
tree[x] = max(tree[x * ], tree[x * + ]);
} void build(int x, int ll, int rr)
{
l[x] = ll, r[x] = rr;
if(ll == rr)
{
tree[x] = -ll + ;
return ;
}
int mid = (ll + rr) >> ;
build(x * , ll, mid);
build(x * + , mid + , rr);
update(x);
} void change(int x, int ll, int rr)
{
pushdown(x);
if(l[x] == ll && r[x] == rr)
{
lazy[x] += w, tree[x] += w;
return ;
}
int mid = (l[x] + r[x]) >> ;
if(rr <= mid) change(x * , ll, rr);
else if(ll > mid) change(x * + , ll, rr);
else
{
change(x * , ll, mid);
change(x * + , mid + , rr);
}
update(x);
} void find(int x, int ll, int rr)
{
pushdown(x);
if(l[x] == ll && r[x] == rr)
{
upmax(ans, tree[x]);
return ;
}
int mid = (l[x] + r[x]) >> ;
if(rr <= mid) find(x * , ll, rr);
else if(ll > mid) find(x * + , ll, rr);
else find(x * , ll, mid), find(x * + , mid + , rr);//这是取max啊,,,,
} void work()
{
int now;
ans = n - m;//r = 0的情况
for(R i = Head[m + ]; i; i = Next[i])
{
now = date[i], w = ;
change(, l_[now] + , m + );
//find(1, 4, 4);
}
//find(1, 4, 4);
upmax(ans, tree[]);
for(R i = m; i; -- i)
{
w = -;
change(, , i + );
for(R j = Head[i]; j; j = Next[j])
{
now = date[j], w = ;
change(, l_[now] + , i + );
}
find(, , i + );//左端点在后面就不合法了
}
printf("%d\n", ans);
} int main()
{
freopen("in.in", "r", stdin);
pre();
build(, , m + );//要多出一位来代表左端点取0的情况
work();//ri最大居然可以到m+1...
fclose(stdin);
return ;
}
ARC076 F Exhausted? Hall定理 + 线段树扫描线的更多相关文章
- 【AtCoder ARC076】F Exhausted? 霍尔定理+线段树
题意 N个人抢M个椅子,M个椅子排成一排 ,第i个人只能坐[1,Li]∪[Ri,M],问最多能坐多少人 $i$人连边向可以坐的椅子构成二分图,题意即是求二分图最大完美匹配,由霍尔定理,答案为$max( ...
- BZOJ.3693.圆桌会议(Hall定理 线段树)
题目链接 先考虑链.题目相当于求是否存在完备匹配.那么由Hall定理,对于任意一个区间[L,R],都要满足[li,ri]完全在[L,R]中的ai之和sum小于等于总位置数,即R-L+1.(其实用不到H ...
- BZOJ3693: 圆桌会议(Hall定理 线段树)
题意 题目链接 Sol 好的又是神仙题... 我的思路:对于区间分两种情况讨论,一种是完全包含,另一种是部分包含.第一种情况非常好判断,至于计算对于一个区间[l, r]的$\sum a[i]$就可以了 ...
- Codeforces 338E - Optimize!(Hall 定理+线段树)
题面传送门 首先 \(b_i\) 的顺序肯定不会影响匹配,故我们可以直接将 \(b\) 数组从小到大排个序. 我们考虑分析一下什么样的长度为 \(m\) 的数组 \(a_1,a_2,\dots,a_m ...
- LOJ.6062.[2017山东一轮集训]Pair(Hall定理 线段树)
题目链接 首先Bi之间的大小关系没用,先对它排序,假设从小到大排 那么每个Ai所能匹配的Bi就是一个B[]的后缀 把一个B[]后缀的匹配看做一条边的覆盖,设Xi为Bi被覆盖的次数 容易想到 对于每个i ...
- loj#6062. 「2017 山东一轮集训 Day2」Pair hall定理+线段树
题意:给出一个长度为 n的数列 a和一个长度为 m 的数列 b,求 a有多少个长度为 m的连续子数列能与 b匹配.两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当 ...
- 【BZOJ2138】stone Hall定理+线段树
[BZOJ2138]stone Description 话说Nan在海边等人,预计还要等上M分钟.为了打发时间,他玩起了石子.Nan搬来了N堆石子,编号为1到N,每堆包含Ai颗石子.每1分钟,Nan会 ...
- 模拟赛 怨灵退治 题解(Hall定理+线段树)
题意: 有 n 群怨灵排成一排,燐每秒钟会选择一段区间,消灭至多 k 只怨灵. 如果怨灵数量不足 k,则会消灭尽量多的怨灵. 燐作为一只有特点的猫,它选择的区间是不会相互包含的.它想要知道它每秒最多能 ...
- arc076 F - Exhausted? (霍尔定理学习)
题目链接 Problem Statement There are M chairs arranged in a line. The coordinate of the i-th chair ($$$1 ...
随机推荐
- 三、css篇
#这里强烈推荐一本书<css世界>,css第一书. #上面的层叠顺序得记住. 1.align-items justify-content 是flex(弹性盒模型)必须要会的属性,alig ...
- Angular简单总结
AngularJS AngularJS四大特征 MVC模式 双向绑定 依赖注入 模块化设计 AngularJS 表达式 AngularJS 表达式写在双大括号内{{expression }},可以包含 ...
- 13.4.3 鼠标与滚轮事件【JavaScript高级程序设计第三版】
鼠标事件是Web 开发中最常用的一类事件,毕竟鼠标还是最主要的定位设备.DOM3 级事件中定义了9 个鼠标事件,简介如下. click:在用户单击主鼠标按钮(一般是左边的按钮)或者按下回车键时触发.这 ...
- hadoop生态搭建(3节点)-02.ssh配置
# ssh免密码登录 # ==================================================================node1# 一路狂按回车,最终生成(id ...
- stm32+lwip(三):TCP测试
我是卓波,很高兴你来看我的博客. 系列文章: stm32+lwip(一):使用STM32CubeMX生成项目 stm32+lwip(二):UDP测试 stm32+lwip(三):TCP测试 stm32 ...
- Overview of the High Efficiency Video Coding (HEVC) Standard阅读笔记
1.INTRODUCTION High Efficiency Video Coding(HEVC) <-> H.265 MPEG-4 Advanced Video Coding(AVC) ...
- 剑指offer题目系列二
本篇延续上一篇,介绍<剑指offer>第二版中的四个题目:从尾到头打印链表.用两个栈实现队列.旋转数组的最小数字.二进制中1的个数. 5.从尾到头打印链表 题目:输入一个链表的头结点,从尾 ...
- 【Keras案例学习】 多层感知机做手写字符分类(mnist_mlp )
from __future__ import print_function # 导入numpy库, numpy是一个常用的科学计算库,优化矩阵的运算 import numpy as np np.ran ...
- I两种冒泡算法
两种冒泡算法: 第一个循环,I 定位当前坐标,第二个循环 把 I 之后的每个数都与 I 比较(比 I 小的都去坐标I),第二个循环之后 坐标 I 为数组里最小的数值. 效率比较高的冒泡算法: stat ...
- performance_schema实现套路
实现中大量使用多层次嵌套预编译,大量if else,wrapper等 不建议去看这个实现 start_mutex_wait_v1 if (flag_thread_instrumentation) ...