zoukankan      html  css  js  c++  java
  • 【谜一样的牛】题解

    题目描述


    题目描述
    有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 左右,就可以过了。

  • 相关阅读:
    ACM——完数
    基于图片的信息隐藏与显示
    ACM——数的计数
    ACM——A + B Problem (2)
    ACM——简单排序
    ACM——回文
    ACM——圆柱体的表面积
    ACM——进制转换
    ACM——线性表操作
    this的理解
  • 原文地址:https://www.cnblogs.com/cqbzyanglin/p/13550655.html
Copyright © 2011-2022 走看看