题意:根据伪代码 求出答案
思路:其实他要我们求的是一个符合他条件 a[] 的连续的子串有多少个 这个字串必须满足一个条件 就是经过和b[]任意的匹配后 每一对数之和需要大于等于 一个特定的值 那么 最优的方案就是贪心 子串最大的 和 最小的b[]的匹配 第二大和第二小的 。。。。 如此匹配 虽然源代码得到的最后匹配不是这个 但是如果不满足这个方案 就肯定无解
对于每个a[] 我们可以从b[]中知道在他可以匹配的最小b[]是多少 记位置为x 那么b[] x 到 m 小的值都可以匹配 于是用线段树来进行区间更新
ps:想到用区间更新了 但是以为自己想的那样会超时 结果就没写出来 看来别人代码才知道 底子不扎实 自己骗自己
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define N 150010
#define MOD 1000000009
#define LL long long
int a[N];
int b[N];
int c[N*4];
int p[N*4];
int q[N*4];
int n,m,k;
void update(int tt)
{
c[tt*2]+=p[tt];c[tt*2+1]+=p[tt];
p[tt*2]+=p[tt];p[tt*2+1]+=p[tt];
p[tt]=0;
}
void change(int l,int r,int tt,int x,int y,int k)
{
if(l==x&&r==y)
{
c[tt]+=k;
p[tt]+=k;
return ;
}
update(tt);
int mid=(l+r)/2;
if(x>mid)change(mid+1,r,tt*2+1,x,y,k);
else if(y<=mid)change(l,mid,tt*2,x,y,k);
else
{
change(mid+1,r,tt*2+1,mid+1,y,k);
change(l,mid,tt*2,x,mid,k);
}
c[tt]=min(c[tt*2],c[tt*2+1]);
}
int fd(int x)
{
int l=1,r=m,ret=m+1;
while(l<=r)
{
int mid=(l+r)/2;
if(x+a[mid]>=k)
{
ret=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
return ret;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+m+1);
for(int i=1;i<=m;i++) change(1,m,1,i,i,-i);
int ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
q[i]=fd(b[i]);
if(q[i]<=m)change(1,m,1,q[i],m,1);
if(i>m&&q[i-m]<=m)change(1,m,1,q[i-m],m,-1);
ans+=c[1]>=0;
}
printf("%d\n",ans);
return 0;
}