[bzoj2086][Poi2010]Blocks_单调栈_双指针

Blocks bzoj-2086 Poi-2010

题目大意题目链接

注释:略。


想法:首先,不难发现,如果连续的一段数的平均值不小于输入的k的话,这段数是满足题意的。

所以,我们再次简化一下:将每个数都减去k,即求极大区间,使得区间和为正。

将所有数的前缀和自尾至头压进单调栈,然后左指针遍历1->n,右指针在单调栈上扫即可。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010 
using namespace std;
typedef long long ll;
ll q[N],top,n,m;
ll a[N],sum[N];
inline char nc()
{
	static char *p1,*p2,buf[100000];
	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
ll read()
{
	ll x=0; char c=nc();
	while(!isdigit(c)) c=nc();
	while(isdigit(c)) x=(x<<3)+(x<<1)+c-'0',c=nc();
	return x;
}
void dispose(ll val)
{
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		sum[i]=sum[i-1]+a[i]-val;
	}
	top=0;
	for(int i=1;i<=n;i++)
	{
		if(sum[q[top]]>sum[i]) q[++top]=i;
	}
	for(int i=n,j=top;i>=0;i--)
	{
		while(j&&sum[q[j-1]]<=sum[i]) j--;
		ans=max(ans,i-q[j]);
	}
	printf("%lld ",ans);
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
	}
	ll x;
	for(int i=1;i<=m;i++)
	{
		x=read();
		dispose(x);
	}
	puts("");
	return 0;
}

小结:%%%xqz

转载于:https://www.cnblogs.com/ShuraK/p/9424484.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值