blocks (单调栈)

题目描述

image

解析

对于这道题,他要求大于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;
}
posted @   _君の名は  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示