校OJ:可是冰墩墩一墩难求啊

可是冰墩墩一墩难求啊

题目描述
北京冬奥会吉祥物冰墩墩,成为冬奥名副其实的顶流。无论是线上还是线下,实力演绎着“一墩难求”。小明排队无聊之际,想出了一个问题:已知某一时刻有 n n n个人从左到右排成一队,其中第 i i i个人的身高为 a i a_i ai,假设对于第 i i i个人来说,他能看到 k i k_i ki个人的头顶(所有人都只能向右看,且每个人只能看见比他矮的人的头顶,比自己高的人会挡住视野)。求 ∑ i = 1 n k i \sum _{i=1} ^n k_i i=1nki

例如 n = 4 n=4 n=4,且队伍从左到右身高依次为10,3,7,1:

  • 第1个人身高为10,他可以看到身高为3,7,1的人的头顶,则 k 1 = 3 k_1=3 k1=3
  • 第2个人身高为3,虽然第4个人的身高为1且小于3,但身高为7的第3个人会挡住视野,所以仍然是一个人的头顶也看不见,则 k 2 = 0 k_2=0 k2=0
  • 第3个人身高为7,他可以看到身高为1的人的头顶,则 k 3 = 1 k_3=1 k3=1
  • 第4个人站在队伍最右边,一个头顶也看不见,则 k 4 = 0 k_4=0 k4=0
    ∑ i = 1 n k i = 3 + 0 + 1 + 0 = 4 \sum _{i=1} ^n k_i=3+0+1+0=4 i=1nki=3+0+1+0=4

输入
第一行包含一个正整数 n ( 1 ≤ n ≤ 5 ∗ 1 0 5 ) n(1\le n\le5*10^5) n(1n5105),表示排队人数。
第二行包含 n n n个正整数,第 i i i个数为 a i ( 1 ≤ a i ≤ 1 0 9 ) a_i(1\le a_i\le10^9) ai(1ai109),表示第 i i i个人的身高。
输出
一行一个整数表示 ∑ i = 1 n k i \sum _{i=1} ^n k_i i=1nki,含义如上所示
样例输入

4
10 3 7 1

样例输出

4

提示

比自己高的或者一样高的都会挡住视野

AC代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
stack<int> s;
int n;
ll ans;
int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) {
		int h;
		scanf("%d", &h);
		while(!s.empty() && s.top() <= h) s.pop();
		ans += s.size();
		s.push(h);
	}
	printf("%lld", ans);
	return 0;
}

代码分析

题目含义为对于每一个下标 i i i 找到右边第一个大于等于自己的下标 j j j,则 i i i 对于答案的贡献为 j − i j-i ji.正确的做法是采用单调递减的单调栈优化,单调栈本身的作用是快速求出作边或者右边第一个大于等于自己的数,由于此题单调栈需要维护的是序列下标而不是序列值本身。答案上限可达 1 0 11 10^{11} 1011,需采用long long数据类型,复杂度为 O ( n ) O(n) O(n)

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值