黑掉的一定是一个长度为$lfloorfrac{n+1}{2} floor$的区间。
于是枚举初始点,然后查询包含它的区间的最小值。
通过维护前后缀最小值+单调队列$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; }