題意:根據僞代碼 求出答案
思路:其實他要我們求的是一個符合他條件 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;
}