arc 076 d 题解 Exhausted?

本文深入探讨了二分图最大匹配问题的数学原理,通过解析Hall定理的应用,提出了一个新颖的算法思路,避免了传统的网络流方法,利用离散数学中的概念实现了高效的求解。

题目传送门
首先一个二分图的最大匹配=
∣ X ∣ − m a x { ∣ W ∣ − ∣ N G ( W ) ∣ } ( W ∈ X ) |X|-max\{|W|-|N_G(W)|\} (W\in X) Xmax{WNG(W)}(WX)
如果一个集合 W W W满足了那个max,也就是再加新的 ∣ N G ( W ) ∣ 增 加 的 比 ∣ W ∣ |N_G(W)|增加的比|W| NG(W)W快。
根据HMT可知剩下的存在匹配。
然后就可以发现对于任意的 W W W, N G ( W ) N_G(W) NG(W)是两段连续的区间:
[ 1 , l ] + [ r , ∣ Y ∣ ] [1,l]+[r,|Y|] [1,l]+[r,Y]组合而成。
这么看来, ∣ N G ( W ) ∣ = ∣ Y ∣ − m a x ( 0 , m i n { r x } − m a x { l y } ) ( y , x ∈ W ) |N_G(W)|=|Y|- max(0,min\{r_x\}-max\{l_y\})(y,x \in W) NG(W)=Ymax(0,min{rx}max{ly})(y,xW)
m i n { r x } − m a x { l y } min\{r_x\}-max\{l_y\} min{rx}max{ly}其实就是 N g ( W ) N_g(W) Ng(W)中间空出来的大小,一下用 e m p t y empty empty表示。
把最上面的式子转换一下:
∣ X ∣ − m a x { ∣ W ∣ − ∣ Y ∣ + e m p t y } ( W ∈ X ) |X|-max\{|W|-|Y|+empty\} (W\in X) Xmax{WY+empty}(WX)
显然可以把|Y|提出来:
∣ X ∣ + ∣ Y ∣ − m a x { ∣ W ∣ + e m p t y } ( W ∈ X ) |X|+|Y|-max\{|W|+empty\} (W\in X) X+Ymax{W+empty}(WX)
所以如果确定了empty的大小,就取用最大的 ∣ W ∣ |W| W去满足。
假设我们固定了empty的右边界R。
则可以选用的所有可以在W里的值都必须满足以下性质:
R x ≥ L R_x\geq L RxL
这样如果把所有可以选的x按照右边界的从小到大排个序:
x 1 , x 2 . . . , x m x_1,x_2...,x_m x1,x2...,xm,可以发现如果 x i x_i xi被选 x j ( j < i ) x_j(j<i) xj(j<i)全部选上不会使答案变的更差只会变好。有人可能会问了如果选上的数组成的empty的右边界不是R,怎么办呢?
其实仔细想一想就会发现这样的情况会被更优的答案覆盖。
这样就会做了。

代码:

/*
AuThOr Gwj
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define KEEP while(1)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define debug_pair(A) cerr<<A.FIR<<" "<<A.SEC<<endl;
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
typedef pair<mp,mp> superpair;
int n,m;
const int MAXN=1<<18;
int tree[MAXN*8],val[MAXN*8];
void increase(int a){
	a+=MAXN-1;
	tree[a]++;
	val[a]=tree[a]-(a-MAXN+1);
	a>>=1;
	while(a){
		tree[a]=tree[a<<1]+tree[(a<<1)+1];
		val[a]=max(val[a<<1],val[(a<<1)+1]+tree[a<<1]);
		a>>=1;
	}
}
int query(int a,int b,int now=1,int l=1,int r=MAXN+1){
	if(r<=a||l>=b){
		return -INF;
	}
	if(r<=b&&l>=a){
		return val[now];
	}
	int mid=(l+r)>>1;
	return max(query(a,b,now<<1,l,mid),query(a,b,(now<<1)+1,mid,r));
}
set<mp> s;
mp sq[200000+2];
bool cmp(mp A,mp B){
	return A.SEC<B.SEC;
}
int main(){
	fastio;
	cin>>n>>m;
	memset(val,-63,sizeof(val));
	rb(i,1,n)
		cin>>sq[i].FIR>>sq[i].SEC,sq[i].FIR++,sq[i].SEC--;
	sort(sq+1,sq+1+n,cmp);
	int it=n;
	int res=n;
	rl(i,m,1){
		while(it&&sq[it].SEC>=i){
			mp now=sq[it--];
			increase(now.FIR);
		}
		res=max(res,query(1,m+1)+i+1);
	}
	res=n+m-res;
	res=min(res,n);
	assert(res>=0);
	cout<<n-res<<endl;
	return 0;
}

启示:对于这类问题(比如 N G N_G NG比较特殊)不需要借助网络流来解决二分图匹配。

Codeforces 上的比赛结束后,题解的开放时间取决于比赛的类型和主办方的安排。通常情况下,**Educational Round** 和 **Regular Round** 的题解会在比赛结束后立即开放[^1]。然而,部分比赛可能会设置延迟开放题解的机制,以防止比赛期间解法被公开传播,尤其是在涉及排名或奖惩机制的正式比赛中。 对于大多数比赛,如果题解没有立即开放,通常会在几个小时内开放。有时主办方会在比赛结束后的 12 小时内开放题解,例如在 Educational Round 中,比赛结束后通常会有 12 小时的全网开放 hack 时间,之后题解也会同步开放[^1]。 如果用户在比赛结束后无法查看题解,并显示“N/A”,可能是由于以下原因: - 题解尚未开放,需等待主办方更新。 - 页面加载异常,可尝试刷新页面或清除浏览器缓存。 - 用户访问的页面并非官方题解页面,建议前往 Codeforces 的官方博客或比赛公告中查找题解链接。 此外,Codeforces 社区活跃,即使官方题解尚未开放,也可以在比赛结束后的讨论区、博客或评论区中找到参赛者分享的解题思路和代码[^3]。 ### 示例:获取 Codeforces 比赛题解的 Python 脚本 ```python import requests from bs4 import BeautifulSoup def fetch_solution(contest_id, problem_index): url = f"https://codeforces.com/contest/{contest_id}/problem/{problem_index}" response = requests.get(url) if response.status_code == 200: soup = BeautifulSoup(response.text, 'html.parser') solution = soup.find('div', {'class': 'problem-statement'}) if solution: return solution.get_text() else: return "题解尚未开放或页面结构异常。" else: return "无法访问该页面。" # 示例:获取某场比赛的 A 题题解 print(fetch_solution(1700, 'A')) ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值