~~~题面~~~

题目大意:

  有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定理 + 线段树扫描线的更多相关文章

  1. 【AtCoder ARC076】F Exhausted? 霍尔定理+线段树

    题意 N个人抢M个椅子,M个椅子排成一排 ,第i个人只能坐[1,Li]∪[Ri,M],问最多能坐多少人 $i$人连边向可以坐的椅子构成二分图,题意即是求二分图最大完美匹配,由霍尔定理,答案为$max( ...

  2. BZOJ.3693.圆桌会议(Hall定理 线段树)

    题目链接 先考虑链.题目相当于求是否存在完备匹配.那么由Hall定理,对于任意一个区间[L,R],都要满足[li,ri]完全在[L,R]中的ai之和sum小于等于总位置数,即R-L+1.(其实用不到H ...

  3. BZOJ3693: 圆桌会议(Hall定理 线段树)

    题意 题目链接 Sol 好的又是神仙题... 我的思路:对于区间分两种情况讨论,一种是完全包含,另一种是部分包含.第一种情况非常好判断,至于计算对于一个区间[l, r]的$\sum a[i]$就可以了 ...

  4. Codeforces 338E - Optimize!(Hall 定理+线段树)

    题面传送门 首先 \(b_i\) 的顺序肯定不会影响匹配,故我们可以直接将 \(b\) 数组从小到大排个序. 我们考虑分析一下什么样的长度为 \(m\) 的数组 \(a_1,a_2,\dots,a_m ...

  5. LOJ.6062.[2017山东一轮集训]Pair(Hall定理 线段树)

    题目链接 首先Bi之间的大小关系没用,先对它排序,假设从小到大排 那么每个Ai所能匹配的Bi就是一个B[]的后缀 把一个B[]后缀的匹配看做一条边的覆盖,设Xi为Bi被覆盖的次数 容易想到 对于每个i ...

  6. loj#6062. 「2017 山东一轮集训 Day2」Pair hall定理+线段树

    题意:给出一个长度为 n的数列 a和一个长度为 m 的数列 b,求 a有多少个长度为 m的连续子数列能与 b匹配.两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当 ...

  7. 【BZOJ2138】stone Hall定理+线段树

    [BZOJ2138]stone Description 话说Nan在海边等人,预计还要等上M分钟.为了打发时间,他玩起了石子.Nan搬来了N堆石子,编号为1到N,每堆包含Ai颗石子.每1分钟,Nan会 ...

  8. 模拟赛 怨灵退治 题解(Hall定理+线段树)

    题意: 有 n 群怨灵排成一排,燐每秒钟会选择一段区间,消灭至多 k 只怨灵. 如果怨灵数量不足 k,则会消灭尽量多的怨灵. 燐作为一只有特点的猫,它选择的区间是不会相互包含的.它想要知道它每秒最多能 ...

  9. arc076 F - Exhausted? (霍尔定理学习)

    题目链接 Problem Statement There are M chairs arranged in a line. The coordinate of the i-th chair ($$$1 ...

随机推荐

  1. Java源码解析——集合框架(四)——LinkedListLinkedList原码分析

    LinkedList源码分析 LinkedList也和ArrayList一样实现了List接口,但是它执行插入和删除操作时比ArrayList更加高效,因为它是基于链表的.基于链表也决定了它在随机访问 ...

  2. 吐血分享:QQ群霸屏技术教程(利润篇)

    QQ群技术,不论日进几百,空隙时间多的可以尝试,日进100问题不大. QQ群技术,如何赚钱,能赚多少钱?不同行业,不同关键词,不同力度,不一样的产出. 群费 群费,这个和付费群是有区别的,群费在手机端 ...

  3. git的初始配置(简易的命令行)

    Git 全局设置: git config --global user.name "You name" git config --global user.email "Yo ...

  4. doc命令操作数据库(下)

    1.给数据表添加一组数据: 2.给数据表添加多组数据: 3.对数据进行删除和修改: 4.用select查询单个或多个数据信息: 5.去除重复值: 6.查询的各种用法: between的用法: 查询排序 ...

  5. 实验吧编程题python

    网址:http://ctf5.shiyanbar.com/jia 之后第一步就是刷新一下网页,发现给的公式会变,(废话,要不直接算数不就行了...)但是格式不会变. 所以那就暴力一点好了,我们看一下这 ...

  6. logger模块的使用

    logging模块 下面是logger模块的配置文件,在写程序需要记录日志可以直接拿过来用,但是要经过相应配置的一些修改. 对于如何使用,在我上一篇随笔<ATM程序规范练习>中的记录日志的 ...

  7. Angularjs 跨域post数据到springmvc

    先贴网上己有解决方案链接: http://www.tuicool.com/articles/umymmqY  (讲的是springmvc怎么做才可以跨域) http://my.oschina.net/ ...

  8. [Windows]_[C/C++]_[如何调试子进程]

    场景 1.VC++ 的程序A在启动程序C时, 如果需要调试程序C的话一般有两种, 一种是通过菜单 调试->附加到进程的方式来调试程序, 缺点就是这个进程必须先启动, 但是一启动的话有可能就执行了 ...

  9. 深度学习(deep learning)优化调参细节(trick)

    https://blog.csdn.net/h4565445654/article/details/70477979

  10. C++学习014函数值传递和地址传递

    当我们给一个函数传参数的时候,可以直接值传入函数,也给可以把一个地址传入函数 区别就是一个本身不被改变,而另一本身也在改变, 在开发时候都会用到, 这里做下记录 #include <iostre ...