A Mountaineer 最详细的解题报告

题目来源:A Mountaineer (不知道该链接是否可以直接访问,所以将题目复制下来了)

题目如下:

D - A Mountaineer



Time limit : 2sec / Stack limit : 256MB / Memory limit : 256MB

Problem

Dave is a mountaineer. He is now climbing a range of mountains.

On this mountains, there are N huts located on a straight lining from east to west..

The huts are numbered sequentially from 1 to N. The west most hut is 1, the east most hut is N. The i-th hut is located at an elevation of hi meters.

Dave wants to know how many huts he can look down and see from each hut.

He can see the j-th hut from the i-th hut if all huts between the i-th hut and the j-th hut including the j-th one are located at equal or lower elevation than hi.

Note that the i-th hut itself is not included in the hut he can see from the i-th hut.


Input

The input will be given in the following format from the Standard Input.

N
h1
h2
:
hN
  • On the first line, you will be given N(1≦N≦105), the number of huts.
  • Then N lines follow, each of which contains hi(1≦hi≦105) the elevation of the i-th hut.

Achievements and Points

Your answer will be checked for two levels.

  • When you pass every test case which satisfies 1≦N≦3,000, you will be awarded 30 points.
  • In addition, if you pass all the rest test cases which satisfy 1≦N≦105, you will be awarded 70 more points, summed up to 100points.

Output

On the i-th line, output the number of huts Dave can see from the i-th hut. Make sure to insert a line break at the end of the output.


Input Example 1

3
1
2
3

Output Example 1

0
1
2

From each hut he can see every huts on the west.


Input Example 2

5
1
2
3
2
1

Output Example 2

0
1
4
1
0

From the 1st and 5th hut he can‘t see any other huts.

From the 2nd hut he can only see the 1st hut.

From the 4th hut he can only see the 5th hut.

From the 3rd hut he can see every other huts.


Input Example 3

5
3
2
1
2
3

Output Example 3

4
2
0
2
4

Note that he can see the huts on the equal elevation.


Input Example 4

8
4
3
2
3
4
3
2
1

Output Example 4

7
2
0
2
7
2
1
0

由于题目比较简单,所以就不翻译了。

算法一解题思路(时间复杂度O(n^2))

假设输入序列为 a1,a2,...,ai-1,ai,ai+1,...,an,如果要求ai所能看见的huts个数,则需要依次统计ai左边和右边小于ai的个数和。

具体算法(java版,TLE)

 1 import java.util.Scanner;
 2
 3 public class Main {
 4
 5     public static void main(String[] args) {
 6         Scanner scanner = new Scanner(System.in);
 7         int n = scanner.nextInt();
 8         int[] array = new int[n];
 9         for (int i = 0; i < n; i++) {
10             array[i] = scanner.nextInt();
11         }
12         for (int i = 0; i < n; i++) {
13             int value = array[i];
14             int count = 0;
15             int j = i - 1;
16             int k = i + 1;
17             while (j >= 0 && array[j] <= value) {
18                 count++;
19                 j--;
20             }
21             while (k < n && array[k] <= value) {
22                 count++;
23                 k++;
24             }
25             System.out.println(count);
26         }
27     }
28 }

算法二解题思路(时间复杂度O(n))

分析一下算法一为什么会比较慢,其主要原因是会有大量重复的计算。假设我们已经知道ai-1左边小于ai-1的huts个数m了,如果ai大于ai-1,则ai左边huts的个数一定大于等于m+1,我们不妨将下标从ai-1向左移动m位,然后再比较ai与n=ai-m-1所对应的值,如果ai对应的值大于等于n对应的值,依次计算。然后用同样的方法计算右边的值,最后将左边和右边的值相加就可以得到正确结果。

具体算法(java版,直接AC)

 1 import java.util.Scanner;
 2
 3 public class Main {
 4
 5     public static void main(String[] args) {
 6         Scanner scanner = new Scanner(System.in);
 7         int n = scanner.nextInt();
 8         int[] array = new int[n];
 9         for (int i = 0; i < n; i++) {
10             array[i] = scanner.nextInt();
11         }
12         int[] ansLeft = new int[n];
13         int[] ansRight = new int[n];
14         for (int i = 0; i < n; i++) {
15             int value = array[i];
16             if (i > 0) {
17                 int k = i - 1;
18                 if (value < array[k]) {
19                     ansLeft[i] = 0;
20                 } else {
21                     while (k >= 0 && array[k] <= value) {
22                         ansLeft[i] += ansLeft[k] + 1;
23                         k = k - ansLeft[k] - 1;
24                     }
25                 }
26             }
27         }
28         for (int i = n - 1; i >= 0; i--) {
29             int value = array[i];
30             if (i < n - 1) {
31                 int k = i + 1;
32                 if (value < array[k]) {
33                     ansRight[i] = 0;
34                 } else {
35                     while (k < n && array[k] <= value) {
36                         ansRight[i] += ansRight[k] + 1;
37                         k = k + ansRight[k] + 1;
38                     }
39                 }
40             }
41         }
42         for (int i = 0; i < n; i++) {
43             System.out.println(ansLeft[i] + ansRight[i]);
44         }
45     }
46 }

时间: 2024-08-13 07:11:51

A Mountaineer 最详细的解题报告的相关文章

hihoCoder 1037 数字三角形 最详细的解题报告

题目来源:hihoCoder 1037 数字三角形 解题思路:请好好看看 提示一.提示二.提示三 具体算法(java版,可以直接AC) import java.util.Scanner; public class Main { public static int[][] rewards; public static int[][] best; public static void main(String[] args) { Scanner scanner = new Scanner(System

hihoCoder 1051 补提交卡 最详细的解题报告

题目来源:补提交卡 解题思路:假设未提交程序的天数为:a1,a2,....,an,补交的张数为M.依次从a1,a2,....,an中去掉连续的 K 天(0<=K<=M),然后再来计算剩余数组中最长连续提交天数. 具体算法(Java版,直接AC) 1 import java.util.Scanner; 2 3 public class Main { 4 5 //计算数组中最长连续提交天数 6 public static int getMax(int[] array) { 7 int[] copy

hihoCoder 1052 基因工程 最详细的解题报告

题目来源:基因工程 解题思路:假设基因序列长度为N,则需要计算基因序列前K个和后K个相同所需要的最少改变次数sum. 假设基因序列为 ATACGTCT (即M=8),K=6:interval=M-K=2: 0  1  2  3  4  5  6  7 sq1    A  T  A C  G  T  C  T sq2    A  C G T   C  T 从上图可以看出,标有相同彩色的字符相同,sq1的下标为0的字符与sq2的下标为0的字符相同,即 sq1[0]==sq1[2],由此可以得出sq1

POJ 1057 File Mapping 最详细的解题报告

题目来源:POJ 1057 File Mapping 题目大意:像我的电脑那样显示文件夹和文件信息,其中在同一级目录内,文件夹排在文件的前面并且文件夹的顺序不变,同一级目录中文件按字母序排列.文件以‘f’开头,文件夹以‘d’开头,‘*’表示一个case的结束,‘#’表示所有输入内容结束. 解题思路:递归创建,最后递归输出.算法比较简单,我就不细说了,具体看代码: 具体算法(java版,可以直接运行) 1 import java.util.*; 2 3 public class Main { 4

A Broken Calculator 最详细的解题报告

题目来源:A Broken Calculator 题目如下(链接有可能无法访问): A Broken Calculator Time limit : 2sec / Stack limit : 256MB / Memory limit : 256MB Problem Dave's calculator is broken. His calculator halts when put more than K kinds of number. Dave wants to input an intege

POJ 1046 Color Me Less 最详细的解题报告

题目来源:POJ 1046 Color Me Less 题目大意:每一个颜色由R.G.B三部分组成,D=Math.sqrt(Math.pow((left.red - right.red), 2)+ Math.pow((left.green - right.green), 2)+ Math.pow((left.blue - right.blue), 2)) 表示两个不同颜色的之间的距离(以left和right为例,left和right分别为两种不同的颜色),现给出16组目标颜色,剩下的为待匹配的颜

POJ 1050 To the Max 最详细的解题报告

题目来源:To the Max 题目大意:给定一个N*N的矩阵,求该矩阵中的某一个矩形,该矩形内各元素之和最大,即最大子矩阵问题. 解题方法:最大子序列之和的扩展 解题步骤: 1.定义一个N*N的矩阵state,state[j][k]用来存放矩阵的某行中第j到k个元素的最大值: 2.对于行如何处理呢?我们可以将第一行中的N个元素的所有组合的最大值存放在state中,如果有哪个值小于0,清零,因为它没有做任何贡献:定计算第二行时与第一行的值(全部大于等于0)进行累加,这样就完成了第一行与第二行的累

POJ 1047 Round and Round We Go 最详细的解题报告

题目链接:Round and Round We Go 解题思路:用程序实现一个乘法功能,将给定的字符串依次做旋转,然后进行比较.由于题目比较简单,所以不做过多的详解. 具体算法(java版,可以直接AC) 1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 Scanner scanner = new Scanner(System.in); 7 Stri

POJ 1063 Flip and Shift 最详细的解题报告

题目来源:Flip and Shift 题目大意:一个椭圆形的环形容器中有黑色和白色两种盘子,问你是否可以将黑色的盘子连续的放在一起.你可以有以下两种操作: 1.顺时针旋转所有的盘子 2.顺时针旋转3个盘子 解题思路:第一种操作表明你可以对任意一个盘子执行第二种操作,所以重点在于第二种操作.仔细分析一下会发现,第二种操作其实就是将某一个盘子当前的index加2,所以我们可以先统计一下黑色盘子的个数count,然后用一个数组将所有的盘子存起来,使数组中0-count所存放的是黑色盘子(通过下标加2