Flowerpot

来源:互联网 发布:手机动漫模型软件 编辑:程序博客网 时间:2024/05/16 05:07

题目
此题,他说用线段树,但我发现只要二分答案+two pointers,
二分出答案后,维护区间最大值最小值,来验证答案是否合法。
维护区间最小,就是维护最长不下降子序列。(因为,有比当前小的,直接替代了)
维护区间最大,就是维护最长不上升子序列。(有比当前大的,也直接替代了)

#include<iostream>#include<cstdio>using namespace std;int n,d,num;int q1[2000000],q2[2000000];int a1[2000000],a2[2000000];bool check(int x){  int head1=0,tail1=0;  int head2=0,tail2=0;  q1[0]=0;  q2[0]=0;  for (int i=0;i<=num;++i){    if (a1[i]!=0){      while (head1<tail1&&a1[q1[tail1-1]]>=a1[i])--tail1;      q1[tail1]=i;++tail1;    }    while (head1<tail1&&q1[head1]<i-x) ++head1;    if (a2[i]!=0){      while (head2<tail2&&a2[q2[tail2-1]]<=a2[i])--tail2;      q2[tail2]=i;++tail2;    }    while (head2<tail2&&q2[head2]<i-x) ++head2;    if (i>=x){      //cout<<a[q2[head2]]<<" "<<a[q1[head1]]<<endl;      if (a2[q2[head2]]-a1[q1[head1]]>=d) return true;    }  }   return false;}int main(){  scanf("%d%d",&n,&d);  num=0;  for (int i=1;i<=n;++i){    int x,y;    scanf("%d%d",&x,&y);    if (a1[x]==0)      a1[x]=y;    else a1[x]=min(a1[x],y);    a2[x]=max(a2[x],y);    num=max(num,x);  }  int l=0,r=num;  while (l<r){    int mid=(l+r)/2;    if (check(mid)==true) r=mid;    else l=mid+1;  }  if (check(r)==true) printf("%d\n",r);  else printf("-1\n");  return 0;}
原创粉丝点击