LOJ6062「2017 山东一轮集训 Day2」Pair(Hall定理,线段树)
题面
给出一个长度为
n
n
n 的数列
{
a
i
}
\{a_i\}
{ai} 和一个长度为
m
m
m 的数列
{
b
i
}
\{b_i\}
{bi},求
{
a
i
}
\{a_i\}
{ai} 有多少个长度为
m
m
m 的连续子数列能与
{
b
i
}
\{b_i\}
{bi} 匹配。
两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当且仅当它们的和不小于
h
h
h。
1
≤
m
≤
n
≤
150000.
1\leq m\leq n\leq 150000.
1≤m≤n≤150000.
题解
条件等价于子二分图存在完备匹配。
我们从数列
B
B
B 的角度考虑,根据 Hall 定理,要保证
B
B
B 的任意子集
S
S
S 满足
∣
S
∣
≤
∣
N
(
S
)
∣
|S|\leq |N(S)|
∣S∣≤∣N(S)∣ ,
N
(
S
)
N(S)
N(S) 表示
S
S
S 中所有点的邻接点构成的集合。
然后,我们会发现连边具有单调性,
a
i
a_i
ai 可以和所有大于等于
h
−
a
i
h-a_i
h−ai 的
b
j
b_j
bj 连边。所以,我们把
B
B
B 从小到大排序,每个
a
i
a_i
ai 的邻接点集就是
B
B
B 的某段后缀。
这就意味着,对于
∀
i
<
j
≤
m
,
N
(
i
)
⊆
N
(
j
)
\forall i<j\leq m~,~N(i)\sube N(j)
∀i<j≤m , N(i)⊆N(j) ,即
i
i
i 的邻接点集一定是
j
j
j 的邻接点集的子集。很容易就能得到,如果
B
B
B 的某前缀
P
P
P 满足
∣
P
∣
≤
∣
N
(
P
)
∣
|P|\leq|N(P)|
∣P∣≤∣N(P)∣ ,那么对于任意
S
⊆
B
,
∣
S
∣
=
∣
P
∣
S\sube B,|S|=|P|
S⊆B,∣S∣=∣P∣ ,也一定满足
∣
S
∣
≤
∣
N
(
S
)
∣
|S|\leq|N(S)|
∣S∣≤∣N(S)∣ 。
于是,我们需要考虑的子集从
2
m
−
1
2^m-1
2m−1 个锐减至
m
m
m 个。而且,明显可以用线段树维护每个前缀的邻接点集大小,存在完备匹配的条件即
min
{
∣
N
(
P
)
∣
−
∣
P
∣
}
≥
0
\min\{|N(P)|-|P|\}\geq 0
min{∣N(P)∣−∣P∣}≥0 。
时间复杂度
O
(
n
log
m
)
O(n\log m)
O(nlogm) 。
CODE
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 150005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
LL read() {
LL f=1,x=0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s=getchar();}
while(s >= '0' && s <= '9') {x = (x<<3) + (x<<1) + (s^48);s = getchar();}
return f * x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);};
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
int n,m,s,o,k;
int H;
int a[MAXN],b[MAXN],ad[MAXN];
int tre[MAXN<<2],lz[MAXN<<2],M;
void maketree(int n) {
M=1;while(M<n+2)M<<=1;
for(int i = 1;i <= n;i ++) {
tre[M+i] = -i;
}
for(int i = M-1;i > 0;i --) {
tre[i] = min(tre[i<<1],tre[i<<1|1]);
}return ;
}
void addtree(int l,int r,int y) {
if(l > r) return ;
for(int s=M+l-1,t=M+r+1;s || t;s >>= 1,t >>= 1) {
if(s<M) tre[s] = min(tre[s<<1],tre[s<<1|1]) + lz[s];
if(t<M) tre[t] = min(tre[t<<1],tre[t<<1|1]) + lz[t];
if((s>>1) ^ (t>>1)) {
if(!(s&1)) tre[s^1] += y,lz[s^1] += y;
if(t & 1) tre[t^1] += y,lz[t^1] += y;
}
}return ;
}
int main() {
n = read();m = read();H = read();
for(int i = 1;i <= m;i ++) {
b[i] = read();
}
for(int i = 1;i <= n;i ++) {
a[i] = read();
}
sort(b + 1,b + 1 + m);
maketree(m);
int ans = 0;
for(int i = 1;i <= n;i ++) {
ad[i] = lower_bound(b + 1,b + 1 + m,H-a[i]) - b;
addtree(ad[i],m,1);
if(i > m) addtree(ad[i-m],m,-1);
if(tre[1] >= 0) ans ++;
}
AIput(ans,'\n');
return 0;
}
LOJ6062「2017 山东一轮集训 Day2」Pair(Hall定理,线段树)的更多相关文章
- loj#6062. 「2017 山东一轮集训 Day2」Pair hall定理+线段树
题意:给出一个长度为 n的数列 a和一个长度为 m 的数列 b,求 a有多少个长度为 m的连续子数列能与 b匹配.两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当 ...
- 【LOJ6062】「2017 山东一轮集训 Day2」Pair(线段树套路题)
点此看题面 大致题意: 给出一个长度为\(n\)的数列\(a\)和一个长度为\(m\)的数列\(b\),求\(a\)有多少个长度为\(m\)的子串与\(b\)匹配.数列匹配指存在一种方案使两个数列中的 ...
- LOJ #6062. 「2017 山东一轮集训 Day2」Pair
这是Lowest JN dalao昨天上课讲的一道神题其实是水题啦 题意很简单,我们也很容易建模转化出一个奇怪的东西 首先我们对b进行sort,然后我们就可以通过二分来判断出这个数可以和哪些数配对 然 ...
- ACM-ICPC 2017 西安赛区现场赛 K. LOVER II && LibreOJ#6062. 「2017 山东一轮集训 Day2」Pair(线段树)
题目链接:西安:https://nanti.jisuanke.com/t/20759 (计蒜客的数据应该有误,题目和 LOJ 的大同小异,题解以 LOJ 为准) LOJ:https://l ...
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- Loj 6068. 「2017 山东一轮集训 Day4」棋盘
Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...
- 「2017 山东一轮集训 Day5」苹果树
「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...
- 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)
[LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...
随机推荐
- Web自动化定位方法以及常用便捷操作
很遗憾现在才开始给大家逐步分享自动化教程,原本计划着将现有的接口以及app.pc网页端进行自动化处理后再逐步给大家好好分享一下,由于当前实在没必要自动化操作了,所以临时用脑海中的知识再为大家继续更一篇 ...
- Canal-监听数据库表的变化
1. 简介 Canal是阿里巴巴旗下的一款开源项目,纯Java开发.基于数据库增量日志解析,提供增量数据订阅&消费功能. 工作原理 Mysql主备复制原理 MySQL master 将数据变更 ...
- 10.Linux防火墙iptables之SNAT与DNAT
Linux防火墙iptables之SNAT与DNAT 目录 Linux防火墙iptables之SNAT与DNAT SNAT策略及应用 SNAT策略概述 SNAT策略典型应用环境 SNAT策略原理 SN ...
- BUUCTF-snake
snake 这是我最想吐槽的一个题目,搞这个蛇在这里.我看的这个图就头皮发麻. 最不愿意做的题,建议以后出题能不能搞个正常的啊. 16进制打开发现压缩包,binwalk提取,得到三个文件 key中是b ...
- 谷歌浏览器控制台 f12怎么设置成中文/英文 切换方法,一定要看到最后!!!
1.打开谷歌浏览器 2.右键选择检查或 f12 打开控制台 3.点击控制台右边的设置 4.中切英 选择偏好设置->语言=>English 5.英切中 6.选择中文 7.重启 8.切换中文成 ...
- 【WPF】CAD工程图纸转WPF可直接使用的xaml代码技巧
前言:随着工业化的进一步发展,制造业.工业自动化等多领域,都可能用到上位监控系统.而WPF在上位监控系统方面,应该算是当下最流行的前端框架之一了.而随着监控体系的不断完善与更新迭代,监控画面会变得越来 ...
- 高仿Android网易云音乐OkHttp+Retrofit+RxJava+Glide+MVC+MVVM
简介 这是一个使用Java(以后还会推出Kotlin版本)语言,从0开发一个Android平台,接近企业级的项目(我的云音乐),包含了基础内容,高级内容,项目封装,项目重构等知识:主要是使用系统功能, ...
- tauri+vue开发小巧的跨OS桌面应用-股票体检
最近打算写一个用于股票体检的软件,比如股权质押比过高的股票不合格,ROE小于10的股票不合格,PE大于80的股票不合格等等等等,就像给人做体检一样给股票做个体检.也实现了一些按照技术指标.基本面自动选 ...
- 基于后端和爬虫创建的代理ip池
搭建免费的代理ip池 需要解决的问题: 使用什么方式存储ip 文件存储 缺点: 打开文件修改文件操作较麻烦 mysql 缺点: 查询速度较慢 mongodb 缺点: 查询速度较慢. 没有查重功能 re ...
- from Crypto.Cipher import AES报错
python 在 Windows下使用AES时要安装的是pycryptodome 模块 pip install pycryptodome python 在 Linux下使用AES时要安装的是pyc ...