5月30日集训T1

来源:互联网 发布:瓷砖一开四加工费算法 编辑:程序博客网 时间:2024/05/23 12:18


做了一大波线段树,终于能A不是裸题的线段树的题了



这个题一看范围就知道是数据结构题 、

先离散化,之后预处理大于每个b数组里的数的需求是几个

如h=5

b1=2,b2=3,b3=3,b4=9;

那么  序列: 1号(>=2)=4   2号(>=3)=3 3号(>=9)=1

线段树维护 区间最大值、、 一开始每个叶子节点的都由上方法算出

然后就枚举a数组

加一个数,对应的需求就-1(1 到 它在b数组中的位置)

去一个数,对应的需求就+1(1到 它在b数组中的位置)

检验就看一下最大值是不是0就可以了


注意:不要用map!!!!!  cena会被卡常!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

码:

#include<iostream>#include<cstdio>using namespace std;#define zuo o<<1,l,mid#define you o<<1|1,mid+1,r#define N 150005#include<algorithm>int dui[N];int cnt,max1[N<<2],jj[N<<2],ans,qzh,sx[N],ll,rr,c,len,a[N],b[N],n,h,i,x,wz[N];void up(int o){max1[o]=max(max1[o<<1],max1[o<<1|1]);}void down(int o){int l=o<<1,r=o<<1|1;max1[l]+=jj[o];jj[l]+=jj[o];max1[r]+=jj[o];jj[r]+=jj[o];jj[o]=0;}void jian(int o,int l,int r){if(l==r){max1[o]=sx[l];return;}int mid=(l+r)>>1;jian(zuo);jian(you);up(o);}void gai(int o,int l,int r){if(l!=r)down(o);if(ll<=l&&rr>=r){max1[o]+=c;jj[o]+=c;return;}int mid=(l+r)>>1;if(ll<=mid)gai(zuo);if(rr>mid)gai(you);up(o);} int erfen(int o){int l=1,r=len+1,mid,lin=1;while(l<r){mid=(l+r)>>1;if(o==a[mid])return dui[mid];if(o<a[mid])r=mid;if(o>=a[mid])l=mid+1,lin=mid;}if(a[lin]>o)return dui[lin]-1;else return dui[lin];}int main(){scanf("%d%d%d",&n,&len,&h);for(i=1;i<=len;i++){scanf("%d",&x);a[i]=h-x;}for(i=1;i<=n;i++)scanf("%d",&b[i]);sort(a+1,a+1+len);for(i=1;i<=len;i++){     if(a[i]==a[i-1]){dui[i]=cnt,sx[cnt]++;continue;} ++cnt; dui[i]=cnt; sx[cnt]++;}    for(i=cnt-1;i>=1;i--)    {    sx[i]+=sx[i+1];    }jian(1,1,cnt);a[len+1]=1e9+7;for(i=1;i<=n;i++){wz[i]=erfen(b[i]);}for(i=1;i<=n;i++){ll=1;rr=wz[i];c=-1;if(rr>=ll)gai(1,1,cnt);   if(i>len)   {   ll=1;   rr=wz[i-len];   c=1;   if(rr>=ll)gai(1,1,cnt);      }if(max1[1]<=0)++ans;}  printf("%d",ans);}