题面

给出一个长度为

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. Dev C++编写C/C++程序 出现[Error] ld returned 1 exit status报错分析及解决

    debug系列第一弹,不知道大家写程序的时候是不是都遇到过如题的报错. 我本人是经常遇到这行熟悉的令人不知所措的报错,可能是我太笨了 有时候百度无果也差不到原因,那就汇总一下目前我遇到的情况吧--持续 ...

  2. Mac Book安装Windows发烫的问题

    Mac Book安装Windows后,电脑发烫,风扇一直高速旋转.针对此问题百度搜索了一下, 大多数人说更改电源选项,由"平衡"模式改为"节能"模式,亲身体验了 ...

  3. 技术分享 | app自动化测试(Android)--高级定位技巧

    原文链接 XPath高级定位技巧 XPath 简介 XPath 的英文全称为:XML Path Language,意旨对 XML 中的元素进行路径定位的一种语言,它可适用 XML 标记语言,Html ...

  4. 【Redis】客观下线

    在sentinelHandleRedisInstance函数中,如果是主节点,需要做如下处理: void sentinelHandleRedisInstance(sentinelRedisInstan ...

  5. CentOS yum命令404

    1.获得新的repo列表文件 http://mirrors.163.com/.help/centos.html 2.备份 mv /etc/yum.repos.d/CentOS-Base.repo Ce ...

  6. Web开发小妙招:巧用ThreadLocal规避层层传值

    摘要:我们可以在处理每次请求的过程中,无需从Controller以及Service中的方法层层传值,只需要直接通过该局部变量取值即可. 本文分享自华为云社区<拦截器中巧用ThreadLocal规 ...

  7. 事务@Transactional注解的属性

    事务的传播行为 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.事务的传播行为可以由传播属性指定.Sprin ...

  8. 练习-用if语句替换三元运算符和选择结构-标准的switch语句

    if语句和三元运算符的互换 在某些简单的应用中,if语句是可以和三元运算符互换使用的 public static void main(String[] args) { int a = 10; int ...

  9. JetBrains系列软件激活

    1.将以下记录加入hosts文件 0.0.0.0 account.jetbrains.com0.0.0.0 www.jetbrains.com 2.激活方式选择licence server,填写以下激 ...

  10. Bash脚本debug攻略

    初学Bash时, 我从未想过想过bash也能debug, 也从未想过去debug Bash脚本. 随着技术的增长, 写的脚本越来越复杂, 使用echo打印日志来调试脚本的方式越来越捉襟见肘了. 直到某 ...