题面

给出一个长度为

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定理,线段树)的更多相关文章

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

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

  2. 【LOJ6062】「2017 山东一轮集训 Day2」Pair(线段树套路题)

    点此看题面 大致题意: 给出一个长度为\(n\)的数列\(a\)和一个长度为\(m\)的数列\(b\),求\(a\)有多少个长度为\(m\)的子串与\(b\)匹配.数列匹配指存在一种方案使两个数列中的 ...

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

    这是Lowest JN dalao昨天上课讲的一道神题其实是水题啦 题意很简单,我们也很容易建模转化出一个奇怪的东西 首先我们对b进行sort,然后我们就可以通过二分来判断出这个数可以和哪些数配对 然 ...

  4. ACM-ICPC 2017 西安赛区现场赛 K. LOVER II && LibreOJ#6062. 「2017 山东一轮集训 Day2」Pair(线段树)

    题目链接:西安:https://nanti.jisuanke.com/t/20759   (计蒜客的数据应该有误,题目和 LOJ 的大同小异,题解以 LOJ 为准)     LOJ:https://l ...

  5. Loj #6069. 「2017 山东一轮集训 Day4」塔

    Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...

  6. Loj #6073.「2017 山东一轮集训 Day5」距离

    Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...

  7. Loj 6068. 「2017 山东一轮集训 Day4」棋盘

    Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...

  8. 「2017 山东一轮集训 Day5」苹果树

    「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...

  9. 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)

    [LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...

随机推荐

  1. 【动态规划】统计蚂蚁 (ants)

    题目 描述 蚂蚁山上有T(1<=T<=1,000)种蚂蚁,标记为1..T,每种蚂蚁有N_i只蚂蚁(1<=N_i<=100),现有A(A<=5000)只蚂蚁,从中选出S,S ...

  2. FlinkSQL源码阅读-schema管理

    在Flink SQL中, 元数据的管理分为三层: catalog-> database-> table, 我们知道Flink SQL是依托calcite框架来进行SQL执行树生产,校验,优 ...

  3. 2.shell脚本99乘法表

    shell脚本99乘法表 [root@localhost data]# vim cf.sh

  4. SAP 时区转换

    DATA:l_tzone TYPE tzonref-tzone.   "TIME ZONE    DATA:l_timesp TYPE tzonref-tstamps."TIME  ...

  5. 手写一个虚拟DOM库,彻底让你理解diff算法

    所谓虚拟DOM就是用js对象来描述真实DOM,它相对于原生DOM更加轻量,因为真正的DOM对象附带有非常多的属性,另外配合虚拟DOM的diff算法,能以最少的操作来更新DOM,除此之外,也能让Vue和 ...

  6. Tapdata 实时数据融合平台解决方案(二):理解数据中台

    作者介绍:TJ,唐建法,Tapdata 钛铂数据 CTO,MongoDB中文社区主席,原MongoDB大中华区首席架构师,极客时间MongoDB视频课程讲师. 数据中台定义: 以打通部门或数据孤岛的统 ...

  7. labview从入门到出家1--第一个加法程序

    概述: Labview在众多编程语言中排名靠后,显然在当今互联网,物联网时代并非主流语言.但是俗话说行行 出状元,即便不是立身于某个主流的领域,用好了依旧可以独领风骚,而且Labview对于硬件出身的 ...

  8. 时间模块之datatime模块、os模块、sys模块、json模块、json模块实操

    目录 一.模块的绝对导入和相对导入 二.包的概念 三.编程思想的转变 四.软件开发目录规范 五.常见的内置模块 一.时间模块之datatime模块 1.datetime.datetime.today( ...

  9. dos命令-*02

    1.cmd状态下 tab快速补充文件名 ↑↓快速填充之前输入的文件名 2.//这是Java的快速入门 //对代码的相关说明 //1.public class Hello 表示Hello是一个类,是一个 ...

  10. Jenkins性能优化

    jenkins性能优化 1.评估安装插件,插件数量过多,会导致界面加载慢: 2.添加slave节点: 01.禁止在master上构建性能耗费大的任务,可以使用标签的方式使其在slave上构建: 02. ...