题目描述
给出一个长度为 的数列{ }和一个长度为 的数列{ },求{ }有多少个长度为 的连续子数列能与{ }匹配。
两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当且仅当它们的和不小于 。
输入格式
第一行三个数字
。
第二行有
个数字
。
第三行有
个数字
。
输出格式
输出一个数字,{ }有多少个长度为 的连续子数列能与 { }匹配。
思路
将b排序,ai与b的匹配当做一条边,b的每一元素当做点,问题转化为判断aL到aR的线段与b的点的完美匹配是否存在。
代码
#include<cstdio>
#include<string>
#include<algorithm>
using namespace std;
const int maxn=150005,INF=0x3f3f3f3f;
int N,M,H,w,ans;
int a[maxn],b[maxn];
inline int read() {
int ret=0,f=1;char ch=getchar();
for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
return ret*f;
}
inline int Find(int x) {
x=H-x;
if (b[1]>=x) return 1;
if (b[M]<x) return M+1;
int L=1,R=M;
while (L<=R) {
int mid=L+R>>1;
if (b[mid]>=x&&b[mid-1]<x) return mid;
if (b[mid]>=x) R=mid-1;
else L=mid+1;
}
}
struct Seg{
#define ls (o<<1)
#define rs (o<<1|1)
#define mid (L+R>>1)
int minv[maxn<<2],laz[maxn<<2];
inline void pushup(int o) {minv[o]=min(minv[ls],minv[rs]);}
inline void pushdown(int o) {
if (laz[o])
minv[ls]+=laz[o],laz[ls]+=laz[o],
minv[rs]+=laz[o],laz[rs]+=laz[o];
laz[o]=0;
}
void Build(int o,int L,int R) {
if (L==R) {minv[o]=-L;return;}
Build(ls,L,mid),Build(rs,mid+1,R);
pushup(o);
}
void Updata(int o,int L,int R,int ql,int qr,int dat) {
if (ql<=L&&R<=qr) {minv[o]+=dat,laz[o]+=dat;return;}
if (qr<L||R<ql) return;
pushdown(o);
Updata(ls,L,mid,ql,qr,dat),Updata(rs,mid+1,R,ql,qr,dat);
pushup(o);
}
int Query(int o,int L,int R,int ql,int qr) {
if (ql<=L&&R<=qr) return minv[o];
if (ql<L||R<ql) return INF;
pushdown(o);
return min(Query(ls,L,mid,ql,qr),Query(rs,mid+1,R,ql,qr));
}
#undef ls
#undef rs
#undef mid
}T;
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);
T.Build(1,1,M);
for (int i=1; i<=M; i++) if ((w=Find(a[i]))<=M) T.Updata(1,1,M,w,M,1);
if (T.Query(1,1,M,1,M)>=0) ans++;
for (int i=M+1; i<=N; i++) {
if ((w=Find(a[i]))<=M) T.Updata(1,1,M,w,M,1);
if ((w=Find(a[i-M]))<=M) T.Updata(1,1,M,w,M,-1);
if (T.Query(1,1,M,1,M)>=0) ans++;
}
printf("%d\n",ans);
return 0;
}