题目描述
题目描述
有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
", q.top());
for (int i = 2; i <= n; i++) {
printf ("%d
", 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
", q.front());
for (int i = 2; i <= n; i++) {
printf ("%d
", ans[i]);
}
return 0;
}
这样大大优化了时间复杂度,大概为 245 ms 左右,就可以过了。