首页 > 其他分享 >Blocks

Blocks

时间:2024-02-22 18:14:01浏览次数:26  
标签:正整数 int 元素 样例 long 大于 Blocks

题目描述

给出N个正整数a[1..N],再给出一个正整数k,现在可以进行如下操作:每次选择一个大于k的正整数a[i],将a[i]减去1,选择a[i-1]或a[i+1]中的一个加上1。经过一定次数的操作后,问最大能够选出多长的一个连续子序列,使得这个子序列的每个数都不小于k。 总共给出M次询问,每次询问给出的k不同,你需要分别回答。

输入格式

第一行两个正整数N (N <= 1,000,000)和M (M <= 50)。 第二行N个正整数,第i个正整数表示a[i] (a[i] <= 10^9)。 第三行M个正整数,第i个正整数表示第i次询问的k (k <= 10^9)。

输出格式

共一行,输出M个正整数,第i个数表示第i次询问的答案。

样例

样例输入

5 6
1 2 1 1 5
1 2 3 4 5 6

样例输出

5 5 2 1 1 0

思路:求平均值大于等于k的最长子序列。

因为求的是区间的最大平均值,所以不能以单个数进出栈的情况来考虑。

所以我们将每个数减去k,用前缀和来维护,与0进行比较。

如果一段区间的平均值大于k,那么这段区间是合法的,即这段区间的前缀和大于0。

我们用一个单调递减栈来维护,先将小于0的压入栈中(一定不为答案)但区间外不一定,因此答案越靠后越好,所以我们倒序遍历。

当栈顶元素小于当前元素,即栈顶元素到当前元素和大于0,为一组解。弹出栈顶元素。

当栈顶元素大于当前元素,当前解不合法,栈中其他解也不合法。

最后求出下标差的最大值。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+50;
long long n,m,k,ans,ans1,ma;
long long a[N],sum[N];
stack<int> s;
void getmin(){
	for(int i=1;i<=n;i++){
	    sum[i]=sum[i-1]+a[i]-k;
		while(sum[s.top()]>sum[i]) s.push(i);
	}
	for(int i=n;i>=1;i--){
		while(!s.empty()&&sum[s.top()]<=sum[i]){
			ans1=s.top();
			s.pop();	
		}
		if(sum[ans1]<=sum[i])
		ans=max(ans,abs(i-ans1));
	}
    printf("%lld ",ans);
}
int main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		ma=max(ma,a[i]);
	}
	for(int i=1;i<=m;i++){
		scanf("%lld",&k);
		memset(sum,0,sizeof(sum));
		while(!s.empty()) s.pop();
		s.push(0);
		ans=0;
		if(k>ma){
			printf("0 ");
			continue;	
		}
		getmin();
	}
	return 0;
}

注意,需要开long long

标签:正整数,int,元素,样例,long,大于,Blocks
From: https://www.cnblogs.com/yht8866/p/18027883

相关文章

  • Blocks(单调栈)
    Blocks题目描述给出N个正整数a[1..N],再给出一个正整数k,现在可以进行如下操作:每次选择一个大于k的正整数a[i],将a[i]减去1,选择a[i-1]或a[i+1]中的一个加上1。经过一定次数的操作后,问最大能够选出多长的一个连续子序列,使得这个子序列的每个数都不小于k。总共给出M次询问,每次询问......
  • Blocks(单调栈)
    题目链接因为可以操作无限次,所以相当于只要一个区间中的所有数相加的平均值大于k即成立首先,我们需要通过前缀和维护,可以在加的时候减去一个k,这样只用判断\(i>j且sum[i]-sum[j]>0\)则在[j+1,i]区间中存在满足题目的连续序列如图用红线指的是存入的<0并且单调递减的前缀和su......
  • blocks 单调栈、单调队列题解
    blocks题解:1、题面:2、分析:题意大概就是说,找一段最长的区间,并且这段区间的平均值>=k,那么我们可以对他的每一个值减去k,最终求和>=0即可。那我们需要对每个可能的左端点和右端点进行考虑,并以此让他们进行配对,看他们之间的区间和是否非负。那么我们先定住一个右端点,再依次考虑......
  • Blocks—单调栈
    思路:题目意思是求平均数>=k的最长序列先求出a[i]-k的前缀和就是求sum[i]-sum[j]>=0的最大i-j当j<=k<=isum[j]<=sum[k]j<=k<=isum[j]<=sum[k]更新i的时候,k就不如j优所以处理出来一个单调上升的数组(stak),那答案就在里面选倒序更新,单调栈一直减减就好因为如果用stak[top]更新了i,因......
  • [洛谷P3503][POI2010][BZOI2086]Blocks
    先看数据范围,n≤1e7,k≤1e9,暴力显然行不通,只能考虑单调栈;首先题目中说每一个数都要大于k,那么我们可以在初始化时就将每一个数都减去k,将问题转化为从正数中取出数加到负数里;然后维护一个前缀和,来判断一个区间是否符合要求;显然,当sum[j]-sum[i]≥0时,区间[i+1,j]符合题意,......
  • Blocks(单调栈)
    题干中说每次选择一个大于k的数,还要选他左右两个数其中之一加上一,最后问你最长的每个数不小于K的子序列。这些都是障眼法,其实就是问你最长的平均值大于或等于K的最长子序列,这样就明朗了。接下来就是找子序列的问题,因为要求的是区间最大平均值,所以不能再以单个数的值为依据来决......
  • blocks——题解
    题目描述解析对于这道题,他要求大于k的数进行操作,所以直接让每个数减k,然后用前缀和维护一下与0比较就可以了,因为一段区间和的平均值大于k的话,那么这就是一个合法区间,即为操作后的这个区间和大于0,我们可以用一个单调递减栈去维护,先把比0小的推入栈中,因为要求最大区间,所以边界......
  • 尝试通过Codeblocks编译Codeblocks
    最近工作安排上的空余时间比较多.尝试了下通过Codeblocks去编译(Self-host)Codeblocks还传了个Gitee(code-blocks-mint),不知道后面会不会继续对其进行修改——主要最近习惯了使用qml这种脚本化的界面实现方式,看见widget跟页面标签就一阵头大;另外,Codeblocks的代码虽然相对屎......
  • 页面中的blockShow组件展示,可进行相关的样式修改,一般月饼图搭配使用,具体根据实际来
    <template><!--这是新版的相对应的颜色列表的UI--><divclass="bllockListShow"><divclass="pieList"v-for="(item,index)indataArr":key="index"@click="clickUptown(index,item)"......
  • KubeBlocks 研发轶事之 addon 抽象
    作者介绍张云杨,前阿里云数据库产品负责人,2016-2019年任阿里云数据库产品总监,负责RDS、PolarDB、Redis、MongoDB等核心产品。目前作者就职于云猿生数据,主要负责云原生数据控制面KubeBlocks和ServerlessMySQL产品。欢迎云计算或数据库行业从业者加微信交流。作者微信:realzyy......