[bzoj2086][Poi2010]Blocks_單調棧_雙指針
阿新 • • 發佈:2018-08-05
ont ++ 一段 space include ... blocks mes while
Blocks bzoj-2086 Poi-2010
題目大意:題目鏈接。
註釋:略。
想法:首先,不難發現,如果連續的一段數的平均值不小於輸入的k的話,這段數是滿足題意的。
所以,我們再次簡化一下:將每個數都減去k,即求極大區間,使得區間和為正。
將所有數的前綴和自尾至頭壓進單調棧,然後左指針遍歷1->n,右指針在單調棧上掃即可。
最後,附上醜陋的代碼... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 1000010 using namespace std; typedef long long ll; ll q[N],top,n,m; ll a[N],sum[N]; inline char nc() { static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } ll read() { ll x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+c-‘0‘,c=nc(); return x; } void dispose(ll val) { ll ans=0; for(int i=1;i<=n;i++) { sum[i]=sum[i-1]+a[i]-val; } top=0; for(int i=1;i<=n;i++) { if(sum[q[top]]>sum[i]) q[++top]=i; } for(int i=n,j=top;i>=0;i--) { while(j&&sum[q[j-1]]<=sum[i]) j--; ans=max(ans,i-q[j]); } printf("%lld ",ans); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { a[i]=read(); } ll x; for(int i=1;i<=m;i++) { x=read(); dispose(x); } puts(""); return 0; }
小結:%%%xqz
[bzoj2086][Poi2010]Blocks_單調棧_雙指針