loj#6062. 「2017 山东一轮集训 Day2」Pair

首先这题对于 $a[l,l+m-1]$ 能够成功匹配,当且仅当去连边,然后能形成完美匹配。

但是边数可能到 $m^2$ 的级别,所以跑不了 dinic,但我们只需要判断是否有。

于是,考虑 hall 定理,即对于二分图一部的子集 $S$,每个点在另一部连得边的并集 $S'$,有 $|S| le |S'|$,则该二分图有完美匹配。

考虑线段树维护前缀 $could_i-i$。

$$[1,r],rle could_r$$

$$[l,r],l-1le could_{l-1},rle could_{r}$$

$$r-(l-1)le could_{r}-could_{l-1}$$

$$could_i-ige0$$

对于一部的点集动态,就不能先 $build$ 了。

实际上 $b$ 升序/顺序没有影响。处理麻烦或简单而已。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <map>

#define ll long long

using namespace std;
int rd() {
	int f=1,sum=0; char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*f;
}
ll lrd() {
	ll f=1,sum=0; char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*f;
}
#define ls (cur<<1)
#define rs (ls|1)

const int N=(int)(1.5e5+5);
int mi[N<<2],tag[N<<2];
int n,m,h,a[N],b[N];

void push_up(int cur) {
	mi[cur]=min(mi[ls],mi[rs]);
}

void push_down(int cur) {
	if(!tag[cur]) return ;
	tag[ls]+=tag[cur]; tag[rs]+=tag[cur];
	mi[ls]+=tag[cur]; mi[rs]+=tag[cur];
	tag[cur]=0;
}

void build(int cur,int l,int r) {
	mi[cur]=0x3f3f3f3f;
	if(l==r) return mi[cur]=-l,void();
	int mid=(l+r)>>1;
	build(ls,l,mid); build(rs,mid+1,r);
	push_up(cur);
}

void update(int cur,int l,int r,int cl,int cr,int v) {
	if(cl<=l&&r<=cr) {
		tag[cur]+=v; mi[cur]+=v; return ;
	}
	push_down(cur);
	int mid=(l+r)>>1;
	if(cl<=mid) update(ls,l,mid,cl,cr,v);
	if(cr>mid) update(rs,mid+1,r,cl,cr,v);
	push_up(cur);
}

int 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);
	build(1,1,m);
	int ans=0; // a[i]+b[i]>=h a[i]-h>=b[i]
	for(int i=1;i<=m;i++) {
		int p=lower_bound(b+1,b+1+m,h-a[i])-b;
		if(p<=m) update(1,1,m,p,m,1);
	}
	ans+=mi[1]>=0;
	for(int i=m+1;i<=n;i++) {
		int p=lower_bound(b+1,b+1+m,h-a[i-m])-b;
		if(p<=m) update(1,1,m,p,m,-1);
		p=lower_bound(b+1,b+1+m,h-a[i])-b;
		if(p<=m) update(1,1,m,p,m,1);
		ans+=mi[1]>=0;
	}
	printf("%d",ans); return 0;
}

  

原文地址:https://www.cnblogs.com/xugangfan/p/15210578.html