题面传送门

首先 \(b_i\) 的顺序肯定不会影响匹配,故我们可以直接将 \(b\) 数组从小到大排个序。

我们考虑分析一下什么样的长度为 \(m\) 的数组 \(a_1,a_2,\dots,a_m\) 能和 \(b\) 数组形成匹配。考虑对于 \(i,j\in [1,m]\),若 \(a_i+b_j\geq h\),就在 \(i,j\) 之间连边,那么形成的图必然是一张二分图,我们只需检验这张二分图是否存在完美匹配即可。

这时候就要用到一个叫做 Hall 定理的科技了。Hall 定理说的是这样一件事,对于二分图 \(G=(V_1,V_2,E)\),定义函数 \(f(V)(V\in V_1)\) 为与点集 \(V\) 中的点相连的点的(右部点)集合。那么二部图 \(G\) 有完美匹配的充要条件是 \(\forall V\subseteq V_1,|f(V)|\geq |V|\)

必要性:这个就比较显然了吧。。。记对于节点 \(u\),记 \(mch(u)\) 为与 \(u\) 匹配的节点。那么我们构造集合 \(V'=\{v|v=mch(u),u\in V\}\),那么 \(|V'|=|V|\),而根据 \(V'\) 的构造方式可知 \(\forall v\in V'\) 至少存在一个 \(u\in V\) 满足 \(u,v\) 间有边,故 \(V'\subseteq f(V)\),于是有 \(|V|=|V'|\leq f(V)\),得证。

充分性:这个就没那么显然了。考虑反证法,假设二分图 \(G\) 不存在完美匹配但满足 Hall 定理。那么我们构造出 \(G\) 的一种最大匹配,其中必存在某个非匹配点,假设其为 \(A\)。根据 Hall 定理 \(A\) 必定与另一边某个点相连,设其为 \(B\)。而 \(B\) 必须为匹配点,否则 \(A,B\) 就能形成新的匹配,不满足最大匹配的条件了,设 \(C\) 为与 \(B\) 相匹配的点。再对集合 \(\{A,C\}\) 使用 Hall 定理可知,\(\{A,C\}\) 除 \(B\) 外必与其它某个点相连,设其为 \(D\)。\(D\) 也必须为匹配点,否则根据之前的证明过程可知它不能与 \(A\) 相连,否则 \(A,D\) 能形成新的匹配,故它只能与 \(C\) 相连,而若它与 \(C\) 相连,那么将匹配边 \((B,C)\) 换为 \((A,B),(C,D)\) 可让匹配个数多 \(1\),不满足最大匹配的条件,故 \(D\) 一定与某个点 \(E\) 匹配。再对集合 \(\{A,C,E\}\) 使用 Hall 定理可得还存在某个点 \(F\) 与这三个点都相连且为匹配点。如此一直进行下去可进行无限轮,而点集的大小是有限的,矛盾!

回到本题来,设 \(c(j)\) 为排好序后与 \(b_j\) 能匹配的 \(a_i\) 的个数。由于我们 \(b\) 数组是有序的,那么就有 \(\forall i<j,c(i)<c(j)\),也就是说对于 \(i<j\),所有能与 \(b_i\) 匹配的 \(a_k\) 都能和 \(b_j\) 匹配。而根据 Hall 定理,原图存在完美匹配的充要条件是 \(\forall V\subseteq V_1,|f(V)|\geq |V|\),故对于大小为 \(k\) 的集合 \(S=\{b_{i_1},b_{i_2},\dots,b_{i_s}\}\) 必有 \(\max(f(i_1),f(i_2),\dots,f_(i_s))\geq k\),而显然所有这样的集合中 \(\max(f(i_1),f(i_2),\dots,f_(i_s))\) 的最小值为 \(f(k)\)。故连边形成的图存在完美匹配等价于 \(\forall i,f(i)\geq i\)。

最后考虑加上 \(a\) 数组之后怎样处理,考虑建一棵线段树维护 \(f(i)\)。显然对于每个 \(a_i\) 可二分找出最小的满足 \(b_j\geq h-a_i\) 的 \(j\) 并在线段树 \([j,m]\) 的位置整体加 \(1\)。那么怎么知道 \(\forall i,f(i)\geq i\) 是否成立呢?我们就初始在线段树上每个位置赋上 \(-i\) 并检查全局最小值是否 \(\geq 0\) 就行了。

时间复杂度线对。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=1;
while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=neg;
}
const int MAXN=1.5e5;
const int INF=0x3f3f3f3f;
int n,m,k,a[MAXN+5],b[MAXN+5],pos[MAXN+5];
struct node{int l,r,mn,lz;} s[MAXN*4+5];
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;if(l==r){s[k].mn=-l;return;}
int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
s[k].mn=min(s[k<<1].mn,s[k<<1|1].mn);
}
void pushdown(int k){
if(s[k].lz!=0){
s[k<<1].mn+=s[k].lz;s[k<<1].lz+=s[k].lz;
s[k<<1|1].mn+=s[k].lz;s[k<<1|1].lz+=s[k].lz;
s[k].lz=0;
}
}
void modify(int k,int l,int r,int x){
if(l>r) return;
if(l<=s[k].l&&s[k].r<=r){s[k].mn+=x;s[k].lz+=x;return;}
pushdown(k);int mid=(s[k].l+s[k].r)>>1;
if(r<=mid) modify(k<<1,l,r,x);
else if(l>mid) modify(k<<1|1,l,r,x);
else modify(k<<1,l,mid,x),modify(k<<1|1,mid+1,r,x);
s[k].mn=min(s[k<<1].mn,s[k<<1|1].mn);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
a[0]=-INF;sort(a+1,a+m+1);build(1,1,m);
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
pos[i]=lower_bound(a,a+m+1,k-b[i])-a;
// printf("%d\n",pos[i]);
}
for(int i=1;i<m;i++) modify(1,pos[i],m,1);
int ans=0;
for(int i=m;i<=n;i++){
modify(1,pos[i],m,1);
// printf("%d\n",s[1].mn);
if(s[1].mn>=0) ans++;
modify(1,pos[i-m+1],m,-1);
} printf("%d\n",ans);
return 0;
}

Codeforces 338E - Optimize!(Hall 定理+线段树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. BZOJ1135 LYZ(POI2009) Hall定理+线段树

    做这个题之前首先要了解判定二分图有没有完备匹配的Hall定理: 那么根据Hell定理,如果任何一个X子集都能连大于等于|S|的Y子集就可以获得完备匹配,那么就是: 题目变成只要不满足上面这个条件就能得 ...

  8. ARC076 F Exhausted? Hall定理 + 线段树扫描线

    ---题面--- 题目大意: 有n个人,m个座位,每个人可以匹配的座位是[1, li] || [ri, m],可能有人不需要匹配座位(默认满足),问最少有多少人不能被满足. 题解: 首先可以看出这是一 ...

  9. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

随机推荐

  1. 分布式全局ID与分布式事务

    1. 概述 老话说的好:人不可貌相,海水不可斗量.以貌取人是非常不好的,我们要平等的对待每一个人. 言归正传,今天我们来聊一下分布式全局 ID 与分布式事务. 2. 分布式全局ID 2.1 分布式数据 ...

  2. 2021-2022 20211420 《信息安全专业导论》安装Linux操作系统并学习Linux基础

    作业信息 |作业属于|https://edu.cnblogs.com/campus/besti/2021-2022-1fois |作业要求|https://edu.cnblogs.com/campus ...

  3. NKOJ1828 Feed Ratios饲料调配

    题目 好题!高斯消元切了! (其实只是单纯地想吐槽这道出现在"高斯消元"专练里的题,暴搜能过,goudoubuxie"Gauss") 下面是暴搜: #pragm ...

  4. 常用Java API:HashMap 和 TreeMap

    摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实现,是无序的 clear()//清空. containsKey(Obje ...

  5. hdu 5092 Seam Carving (简单数塔DP,题没读懂,,不过可以分析样例)

    题意: 给一个m*n的矩阵,每格上有一个数. 找从第1行到第m行的一条路径,使得这条路径上的数之和最小. 路径必须满足相邻两行所选的两个数的纵坐标相邻(即一个格子必须是另一个格子的周围八个格子中的一个 ...

  6. hdu 5083 Instruction (稍比较复杂的模拟题)

    题意: 二进制指令转汇编指令,汇编指令转二进制指令. 思路: 额,条理分好,想全,思维不能乱. 代码: int findyu(char yu[50],char c){ int l=strlen(yu) ...

  7. 『学了就忘』Linux基础命令 — 18、Linux命令的基本格式

    目录 1.命令提示符说明 2.命令的基本格式 (1)举例ls命令 (2)说明ls -l命令的 输出内容 1.命令提示符说明 [root@localhost ~] # []:这是提示符的分隔符号,没有特 ...

  8. Matlab 中 arburg 函数的理解与实际使用方法

    1. 理解 1.1 Matlab 帮助: a = arburg(x,p)返回与输入数组x的p阶模型相对应的归一化自回归(AR)参数. 如果x是一个向量,则输出数组a是一个行向量. 如果x是矩阵,则参数 ...

  9. initNativeTransServiceId . ntrans:object componentId :-368613127 微信小程序

    二维码打开的页面是否存在 注意:体验版二维码默认路径是 pages/index/index 我的因为分包的原因调整了首页路径 所以路径是pages/tabBar/search/search 如果不是这 ...

  10. Docker多机网络

    前言 前面的文章主要聚焦于单机网络上,对于生产环境而言,单机环境不满足高可用的特点,所以是不具备上生产的条件,因此在开始Docker Swarm篇的时候我们先来聊聊多机网络之间Docker的通信如何做 ...