BZOJ4123 : [Baltic2015]Hacker

黑掉的一定是一个长度为$\lfloor\frac{n+1}{2}\rfloor$的区间。

于是枚举初始点,然后查询包含它的区间的最小值。

通过维护前后缀最小值+单调队列$O(n)$解决。

 

#include<cstdio>
#define N 500010
int n,k,i,a[N<<1],s[N],pre[N],suf[N],q[N],h,t,ans;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void max(int b){if(ans<b)ans=b;}
inline int min(int a,int b){return a<b?a:b;}
int main(){
  read(n);k=(n+1)/2-1;
  for(i=1;i<=n;i++)read(a[i]),a[i+n]=a[i];
  for(i=2;i<=n*2;i++)a[i]+=a[i-1];
  for(i=1;i<=n;i++)s[i]=a[i+k]-a[i-1];
  for(pre[0]=s[i=1];i<=n;i++)pre[i]=min(pre[i-1],s[i]);
  for(suf[n+1]=s[i=n];i;i--)suf[i]=min(suf[i+1],s[i]);
  for(h=i=1;i<=k;q[++t]=i++){
    max(min(pre[i],suf[i+n-k]));
    while(h<=t&&s[q[t]]>=s[i])t--;
  }
  for(;i<=n;i++){
    while(h<=t&&s[q[t]]>=s[i])t--;q[++t]=i;
    while(i-q[h]>k)h++;
    max(s[q[h]]);
  }
  return printf("%d",ans),0;
}

  

posted @ 2015-06-25 10:19  Claris  阅读(339)  评论(0编辑  收藏  举报