The Preliminary Contest for ICPC Asia Xuzhou 2019 E XKC's basketball team [单调栈上二分]

也许更好的阅读体验

D e s c r i p t i o n \mathcal{Description} Description

给n个数,与一个数m,求 a i a_i ai右边最后一个至少比 a i a_i ai m m m的数与这个数之间有多少个数
2 n 5 1 0 5 , 0 m 1 0 9 2\leq n\leq 5*10^5,0\leq m\leq 10^9 2n5105,0m109

S o l u t i o n \mathcal{Solution} Solution

这道题看了下其他题解都是用线段树写的
虽然线段树是一个很显然的方法,但是代码冗长并且常数较大 (可能是我不喜欢数据结构)
如果把数据范围开大 3 , 4 3,4 3,4倍就妥妥的 T T T
这里提供一个单调栈的打法
从后往前考虑每个位置
我们把每个答案为 1 -1 1的位置的数用一个递增的单调栈维护起来
每次到一个位置就二分这个单调栈,找到第一个比它大至少 m m m的位置,然后答案就是它们的距离减 1 1 1
为什么只有 1 -1 1的位置要放到单调栈里面呢
因为有比它大至少 m m m的位置,所以这个位置永远不会是最优的

C o d e \mathcal{Code} Code

/******************************* Author:Morning_Glory LANG:C++ Created Time:2019年09月16日 星期一 20时46分27秒 *******************************/
#include <cstdio>
#include <fstream>
using namespace std;
const int maxn = 1000006;
int n,m,mx=-1,loc,t;
int h[maxn],ans[maxn],q[maxn];
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;++i)	scanf("%d",&h[i]);
	ans[n]=-1,q[++t]=n;
	for (int i=n-1;i>=1;--i){
		int g=h[i]+m;
		if (h[q[t]]<g){
			ans[i]=-1;
			if (h[q[t]]<h[i])	q[++t]=i;
		}
		else{
			int l=1,r=t;
			while (l<r){
				int mid=(l+r)>>1;
				if (h[q[mid]]>=g)	r=mid;
				else	l=mid+1;
			}
			ans[i]=q[l]-i-1;
		}
	}
	for (int i=1;i<=n-1;++i)	printf("%d ",ans[i]);
	printf("-1\n");
	return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧

全部评论

相关推荐

12-20 11:21
复旦大学 Java
点赞 评论 收藏
分享
想干测开的tomca...:这份简历是“大一新生硬凹资深后端”的典型反面教材,槽点离谱到能让面试官直接笑出声: ### 1. 「年龄+入学时间」和项目复杂度完全脱节,可信度直接归0 你2024年7月才入学(现在刚读了1年多),19岁的大一新生,能把Vue3+Spring Boot+ShardingSphere+K8s+AI这些技术全塞进两个项目里?别说实际开发,光把这些技术的文档看完都得半年——这不是“能力强”,是“把招聘JD里的技术词全抄过来造假”,明摆着没碰过实际代码
点赞 评论 收藏
分享
不知道怎么取名字_:两个方向 1.简历针对性准备下 2.面试前也需要准备的 主要还是要看各个公司需求,看公司行业和岗位描述,那里面已经写了对技术的需求,一份简历,不可能和所有嵌入式岗位都匹配的
投递北京经纬恒润科技股份有限公司等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务