可是冰墩墩一墩难求啊
题目描述
北京冬奥会吉祥物冰墩墩,成为冬奥名副其实的顶流。无论是线上还是线下,实力演绎着“一墩难求”。小明排队无聊之际,想出了一个问题:已知某一时刻有
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(1≤n≤5∗105),表示排队人数。
第二行包含
n
n
n个正整数,第
i
i
i个数为
a
i
(
1
≤
a
i
≤
1
0
9
)
a_i(1\le a_i\le10^9)
ai(1≤ai≤109),表示第
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
j−i.正确的做法是采用单调递减的单调栈优化,单调栈本身的作用是快速求出作边或者右边第一个大于等于自己的数,由于此题单调栈需要维护的是序列下标而不是序列值本身。答案上限可达
1
0
11
10^{11}
1011,需采用long long
数据类型,复杂度为
O
(
n
)
O(n)
O(n)