实战的时候逗比的使劲儿优化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;
}