实战的时候逗比的使劲儿优化O(mnlgn)的算法,搞得吐血后才多对1个点,还是有2个点毫无压力的T啦
然后看了题解才发现自己逗比到一定境界了。。。。
我们的目的就是找到最小的j,使得j<i且s[j]<s[i]。只分析到这是不够的,因为我们不是要求每一个i对应的j,只要求出最大的j-i。
这样我们就可以去掉lgn了。把s最成一个单调下降的序列,现在队列求出n对应的j(很明显j存在于这个下降序列中),我们发现在找n-1对应的j中,若想更新答案,其对应的j必定比n对应的j小!
因此我们只用两个指针不停地移动就行了。复杂度O(nm)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int Maxn=1000005; int n,m,i,j,ans,l,r,mid,t,k,a[Maxn],q[Maxn]; LL s[Maxn]; int read(){ char ch=getchar(); int ret=0; while (ch<'0'||ch>'9')ch=getchar(); while (ch>='0'&&ch<='9') {ret=ret*10+ch-'0';ch=getchar();} return ret; } int main(){ n=read(); m=read(); for (i=1;i<=n;i++) a[i]=read(); while (m--){ k=read(); for (i=1,ans=0,t=0;i<=n;i++){ s[i]=s[i-1]+(LL)a[i]-k; if (s[q[t]]>s[i]) q[++t]=i; } for (i=n,j=t;j>=0&&i>=0;i--){ while (j>=0 && s[i]>=s[q[j]]) j--; j++; ans=max(ans,i-q[j]); } printf("%d",ans); if (m) printf(" "); else printf("\n"); } return 0; }