【謎一樣的牛】題解
阿新 • • 發佈:2020-08-23
題目描述
題目描述
有n頭奶牛,已知它們的身高為 1~n 且各不相同,但不知道每頭奶牛的具體身高。
現在這n頭奶牛站成一列,已知第i頭牛前面有Ai頭牛比它低,求每頭奶牛的身高。
輸入格式
第1行:輸入整數n。
第2..n行:每行輸入一個整數Ai,第i行表示第i頭牛前面有Ai頭牛比它低。 (注意:因為第1頭牛前面沒有牛,所以並沒有將它列出)
輸出格式
輸出包含n行,每行輸出一個整數表示牛的身高。
第i行輸出第i頭牛的身高。
樣例輸入
5
1
2
1
0
樣例輸出
2
4
5
3
1
分析
首先,這道題我們採用倒推的思想。
由於題目告訴我們,所有牛的身高是 1 ~ n, 所以我先用一個優先佇列(等會說為什麼)來儲存所有還沒有確定是哪頭牛身高的值,初始當然是把所有值存進去。
我們設當前序列的最後一頭牛的前面有 x 頭比他矮。那麼當他的身高是 y 時, 那麼他前面比他矮的牛一定是現在序列中所有身高比 y 小的所有(因為他在最後)(顯而易見吧),那麼我們想要他前面有 x 頭牛比他矮,我們就需要他是當前序列之中 x + 1 小的值(優先佇列就是為了找最小)。我們在找出這個值之後,我們就把他從優先佇列之中彈出(因為他已經在這個位置,因為是從後往前面找,所以他在這裡就不會影響他的前面一個值了,就把他彈出
程式碼
#include <cstdio> #include <queue> #include <iostream> using namespace std; const int MAXN = 1e5 + 5; queue <int> q2; priority_queue <int, vector <int>, greater<int> > q; int a[MAXN]; int ans[MAXN]; void read(int &x) { x = 0; int f = 1; char s = getchar(); while (s > '9' || s < '0') { if (s == '-') f = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + (s - '0'); s = getchar(); } x *= f; } int main () { int n; read(n); q.push(1); for (int i = 2; i <= n; i++) { read (a[i]); q.push(i); } for (int i = n; i >= 2; i--) { // printf ("+%d+ ", a[i]); while (a[i]--) { q2.push(q.top()); q.pop(); } ans[i] = q.top(); q.pop(); while (!q2.empty()) { q.push(q2.front()); q2.pop(); } } printf ("%d\n", q.top()); for (int i = 2; i <= n; i++) { printf ("%d\n", ans[i]); } return 0; }
當然大家也看到了,這個程式碼的時間複雜度是很高的,所以我們呢就只拿到了 86分,所以就想到了優化。
如下:
#include <cstdio> #include <queue> #include <iostream> using namespace std; const int MAXN = 1e5 + 5; deque <int> q2; deque <int> q; int a[MAXN]; int ans[MAXN]; void read(int &x) { x = 0; int f = 1; char s = getchar(); while (s > '9' || s < '0') { if (s == '-') f = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + (s - '0'); s = getchar(); } x *= f; } int main () { int n; read(n); q.push_back(1); for (int i = 2; i <= n; i++) { read (a[i]); q.push_back(i); } for (int i = n; i >= 2; i--) { // printf ("+%d+ ", a[i]); while (a[i]--) { q2.push_back(q.front()); q.pop_front(); } ans[i] = q.front(); q.pop_front(); while (!q2.empty()) { q.push_front(q2.back()); q2.pop_back(); } } printf ("%d\n", q.front()); for (int i = 2; i <= n; i++) { printf ("%d\n", ans[i]); } return 0; }
這樣大大優化了時間複雜度,大概為 245 ms 左右,就可以過了。