题目描述
解析
对于这道题,他要求大于k的数进行操作,所以直接让每个数减k,然后用前缀和维护一下与0比较就可以了,因为一段区间和的平
均值大于k的话,那么这就是一个合法区间,即为操作后的这个区间和大于0,我们可以用一个单调递减栈去维护,先把比0小的
推入栈中,因为要求最大区间,所以边界越靠后越好,所以倒叙遍历前缀和,找最左边界,当栈顶元素的前缀和小于当前元素的
前缀和,即证明从栈顶元素到当前元素之间的数相加大于0,即为一组合法解,然后pop出去,因为区间单调递减,所以当栈顶
元素前缀和大于当前元素前缀和时,即为当前解不合法,栈中其他解也就不合法了,最后求一下下标差的最大值即可
对了,记得开long long(血的教训)。。。
代码如下
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k,a[10000000],sum[10000000],ans,c,cc;
stack<int>q;
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),cc=max(cc,a[i]);
for(int z=1;z<=m;z++){
scanf("%lld",&k);
if(k>cc){
printf("0 ");
continue;
}
ans=0;
while(!q.empty())q.pop();
q.push(0);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]-k;
for(int i=1;i<=n;i++){
if(sum[q.top()]>sum[i])q.push(i);
}
for(int i=n;i>=0;i--){
while(!q.empty()&&sum[q.top()]<=sum[i])c=q.top(),q.pop();
if(sum[c]<=sum[i]) ans=max(ans,abs(i-c));
}
printf("%lld ",ans);
}
return 0;
}
标签:blocks,前缀,int,题解,元素,long,区间,大于
From: https://www.cnblogs.com/dfxjlsx/p/18024590