鏈接:https://www.nowcoder.com/questionTerminal/35fac8d69f314e958a150c141894ef6a
來源:牛客網
小Q在週末的時候和他的小夥伴來到大城市逛街,一條步行街上有很多高樓,共有n座高樓排成一行。
小Q從第一棟一直走到了最後一棟,小Q從來都沒有見到這麼多的樓,所以他想知道他在每棟樓的位置處能看到多少棟樓呢?(當前面的樓的高度大於等於後面的樓時,後面的樓將被擋住)
輸入描述:
輸入第一行將包含一個數字n,代表樓的棟數,接下來的一行將包含n個數字wi(1<=i<=n),代表每一棟樓的高度。
1<=n<=100000;
1<=wi<=100000;
輸出描述:
輸出一行,包含空格分割的n個數字vi,分別代表小Q在第i棟樓時能看到的樓的數量。
示例1
輸入
6 5 3 8 3 2 5
輸出
3 3 5 4 4 4
說明
當小Q處於位置3時,他可以向前看到位置2,1處的樓,向後看到位置4,6處的樓,加上第3棟樓,共可看到5棟樓。當小Q處於位置4時,他可以向前看到位置3處的樓,向後看到位置5,6處的樓,加上第4棟樓,共可看到4棟樓。
思路:一開始想到動態規劃,當前看到個數=左邊+自己+右邊;
左邊 = 前一個是否比自己高?1:前一個能看到的-1;
右邊 = 後一個是否比自己高?1:後一個能看到的-1;
思路是錯的,5555,因爲前一個能看的包括自己的左右,會和後一個能看的重合!
因此調整思路:
左邊能看到的:從前一個到第一個位置的倒序遞增(正序遞減)
右邊能看到的:從後一個到最後一個位置的正序遞增(倒序遞減)
就是↖自己↗
因此在左邊遇到a[i]大於a[i-1]要跳過a[i-1],右邊遇到a[i]大於a[i+1]要跳過a[i+1],像冒泡排序交換的次數
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
vector<int> a, b;
stack<int> st1, st2;
int main() {
int n, x[100001];
cin >> n;
int ans = 0;
for (int i = 0; i < n; i++) cin >> x[i];
for (int i = 0, j = n - 1; i < n, j >= 0; i++, j--) {
a.push_back(st1.size());
b.push_back(st2.size());
while (!st1.empty() && st1.top() <= x[i]) st1.pop();
while (!st2.empty() && st2.top() <= x[j]) st2.pop();
st1.push(x[i]);
st2.push(x[j]);
}
reverse(b.begin(), b.end());
for (int i = 0; i < n; i++) cout << b[i] + a[i] + 1<< " ";
return 0;
}