可以先对
B
排序,然后
对于一个
由于图的特殊性,
这样就很简单了,只要满足对于所有
i
,
枚举所有可能子段,用线段树维护
N(i)−i
的最小值,就好了。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=200005;
int n,m,H,ans,a[maxn],b[maxn],L[maxn];
struct node{
int _min,tag; node* ch[2];
node(int x=0){_min=x;tag=0;ch[0]=ch[1]=0;}
void Plus(int x){ _min+=x; tag+=x; }
void pushdown(){ if(tag) ch[0]->Plus(tag), ch[1]->Plus(tag), tag=0; }
void maintain(){ _min=min(ch[0]->_min,ch[1]->_min); }
} *root, base[maxn*2], *p_top=base;
typedef node* P_node;
void Updata(P_node p,int L,int R,int qL,int qR,int val){
if(R<qL||qR<L||qL>qR) return;
if(qL<=L&&R<=qR){ p->Plus(val); return; }
int mid=(L+R)>>1; p->pushdown();
Updata(p->ch[0],L,mid,qL,qR,val); Updata(p->ch[1],mid+1,R,qL,qR,val);
p->maintain();
}
P_node newnode(){ *p_top=node(2e9); return p_top++; }
P_node Build(int L,int R){
P_node p=newnode();
if(L==R){ p->_min=-L; return p; }
int mid=(L+R)>>1;
p->ch[0]=Build(L,mid); p->ch[1]=Build(mid+1,R);
p->maintain(); return p;
}
int Find(int x){
int L=1,R=m,res=m+1;
while(L<=R){ int mid=(L+R)>>1; if(x<=b[mid]) R=mid-1, res=mid; else L=mid+1; }
return res;
}
int main(){
freopen("loj6062.in","r",stdin);
freopen("loj6062.out","w",stdout);
scanf("%d%d%d",&n,&m,&H);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
sort(b+1,b+1+m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),L[i]=Find(H-a[i]);
if(m>n) return puts("0"),0;
root=Build(1,m);
for(int i=1;i<=m;i++) Updata(root,1,m,L[i],m,1);
for(int i=m;i<=n;i++,Updata(root,1,m,L[i],m,1),Updata(root,1,m,L[i-m],m,-1))
if(root->_min>=0) ans++;
printf("%d\n",ans);
return 0;
}