ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

hall 定理 & loj#6062. 「2017 山东一轮集训 Day2」Pair

2022-08-05 16:03:03  阅读:29  来源: 互联网

标签:le cur loj sum Day2 mid int ch 6062


hall 定理:对于任意二分图的一部的子集 \(S\),这些点在另一部所连的点集并为 \(S'\),若有 \(|S|\le |S'|\),那么该二分图有完美匹配。

证明的话考虑归纳喽,对于一个新点,给它分配一个,那么剩下的就是 \(n-1\) 的情况了。

图论的知识要补了。。。。

https://loj.ac/p/6062

回到这题。

考虑先对 \(b\) 降序排,那么对于 \(a\) 能够匹配的 \(b\) 一定是一段前缀,记 \(v_i\) 为 \(a_i\) 能匹配 \(b\) 的 \([1,v_i]\)。

考虑钦定 \([1,i]\) 为子集并,那么显然只能取 \(v_i\) 在 \([1,i]\) 内的,那么需要满足 \(\sum [v_i\le i]\le i\)。但是有时候不一定恰好钦定就有。考虑对答案有无影响。

即 \(s\le i\),显然 \(s\le i+1\),所以对答案并没有影响。

然后就是 DS 憨憨题了。

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
int rd() {
	int sum=0,f=1; char ch=getchar();
	while(ch>'9'||ch<'0') {
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0') {
		sum=sum*10+ch-'0'; ch=getchar();
	}
	return sum*f;
}
const int N=(int)(1.5e+5);
int n,m,h,v[N],a[N],b[N];

bool cmp(const int &x,const int &y) {
	return x>y;
}

int fd(int x) {
	int l=1,r=m,res=0;
	while(l<=r) {
		int mid=(l+r)>>1;
		if(b[mid]>=x) res=mid,l=mid+1;
		else r=mid-1;
	}
	return res;
}

namespace BIT {
	#define ls (cur<<1)
	#define rs (ls|1)
	int mx[N<<2],tag[N<<2];
	void push_up(int cur) {
		mx[cur]=max(mx[ls],mx[rs]);
	}
	void push_down(int cur) {
		if(!tag[cur]) return ;
		tag[ls]+=tag[cur]; tag[rs]+=tag[cur];
		mx[ls]+=tag[cur]; mx[rs]+=tag[cur];
		tag[cur]=0; 
	}
	void build(int cur,int l,int r) {
		tag[cur]=0;
		if(l==r) {
			mx[cur]=-l; return ;
		}
		int mid=(l+r)>>1;
		build(ls,l,mid); build(rs,mid+1,r);
		push_up(cur);
	}
	void upt(int cur,int l,int r,int cl,int cr,int v) {
		if(cl<=l&&r<=cr) {
			mx[cur]+=v; tag[cur]+=v; return ;
		}
		int mid=(l+r)>>1;
		push_down(cur);
		if(cl<=mid) upt(ls,l,mid,cl,cr,v);
		if(cr>mid) upt(rs,mid+1,r,cl,cr,v);
		push_up(cur);
	}
}
using namespace BIT;
signed main() {
	n=rd(); m=rd(); h=rd();
	for(int i=1;i<=m;i++) b[i]=rd();
	for(int i=1;i<=n;i++) a[i]=rd();
	sort(b+1,b+1+m,cmp);
	for(int i=1;i<=n;i++) {
		v[i]=fd(h-a[i]);
	}
	build(1,0,m);
	int ans=0;
	for(int i=1;i<=n;i++) {
		upt(1,0,m,v[i],m,1);
		if(i>=m) {
			int qwq=mx[1];
			if(qwq<=0) ++ans;
			upt(1,0,m,v[i-m+1],m,-1);
		}
	}
	printf("%d",ans);
	return 0;
} 

标签:le,cur,loj,sum,Day2,mid,int,ch,6062
来源: https://www.cnblogs.com/xugangfan/p/16554636.html

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有