当前位置:   article > 正文

超级马里奥_csdn超级马里奥

csdn超级马里奥

一 问题描述

马里奥是世界著名的水管工。他的“魁梧”形象和惊人的跳跃能力深深地留在在我们的记忆中。现在这位可怜的公主再次陷入困境,马里奥需要拯救他的情人。我们把通往老板城堡的道路视为一条线(长度为n) ,在每个整数点 i 上都有一块高度位 hi 的砖。现在的问题是,如果他能跳的最大高度是 H ,那么 Mario 在区间[L,R]中可以跳过多少砖块。

二 输入和输出

1 输入

第一行是整数 T,即测试数据的数量。

对于每个测试数据:

第一行包含两个整数 n,m,n 是 道路的长度,m 是查询的数量。

下一行包含 n 个整数,每个转的高度。

接下来的 m 行,每行包含三个整数 L,R,H 

2 输出

对于每种情况,每行输出“Case X:”(X 是从 1 开始的案例编号),后跟 m 行,每行包含一个整数。第 i 个整数是 Mario 可以为第 i 个查询命中的转块数。

三 输入和输出样例

1 输入样例

1

10 10

0 5 2 7 5 4 3 8 7 7

2 8 6

3 5 0

1 3 1

1 9 4

0 1 0

3 5 5

5 5 1

4 6 3

1 5 7

5 7 3

2 输出样例

Case 1:

4

0

0

3

1

2

0

1

5

1

四 分析和设计

1 分析

本问题包括区间查询。区间查询比较特殊,查询小于等于 H 的数有多少个。

可以采用分块的方法解决。

2 设计

a 分块

划分块,每块非递减排序。

b 查询

查询区间[l,r]有多少个数小于等于 h。

如果该区间属于同一块,则暴力累加块内有多少个数小于等于 h。

如果该区间包含多块,则累加中间每一块小于等于 h 的数,然后暴力累加左端和右端有多少个数小于等于h。

lower_bound()和upper bound()都是利用二分查找的方法在一个排好序的数组中进行查找的。需要引入头文件:algorithm.

五 代码

  1. package com.platform.modules.alg.alglib.hdu4417;
  2. import java.util.Arrays;
  3. import static java.lang.Math.sqrt;
  4. public class Hdu4417 {
  5. public final int maxn = 100000;
  6. int L[] = new int[maxn];
  7. int R[] = new int[maxn];
  8. int belong[] = new int[maxn];
  9. int a[] = new int[maxn];
  10. int temp[] = new int[maxn];
  11. int n;
  12. int m;
  13. public String output = "";
  14. void build() {
  15. int t = (int) sqrt(n);
  16. int num = n / t;
  17. if (n % num != 0) num++;
  18. for (int i = 1; i <= num; i++) {
  19. L[i] = (i - 1) * t + 1;
  20. R[i] = i * t;
  21. }
  22. R[num] = n;
  23. for (int i = 1; i <= n; i++)
  24. belong[i] = (i - 1) / t + 1;
  25. for (int i = 1; i <= num; i++) {
  26. // 每块排序
  27. Arrays.sort(temp, L[i], 1 + R[i]);
  28. }
  29. }
  30. int query(int l, int r, int h) {
  31. int ans = 0;
  32. if (belong[l] == belong[r]) {
  33. for (int i = l; i <= r; i++)
  34. if (a[i] <= h) ans++;
  35. } else {
  36. for (int i = l; i <= R[belong[l]]; i++)//左端
  37. if (a[i] <= h) ans++;
  38. for (int i = belong[l] + 1; i < belong[r]; i++)//中间
  39. ans += upperBound(temp, L[i], R[i] + 1, h) - L[i];
  40. for (int i = L[belong[r]]; i <= r; i++)//右端
  41. if (a[i] <= h) ans++;
  42. }
  43. return ans;
  44. }
  45. /**
  46. * @param arr 数组
  47. * @param value 待比较的值
  48. * @param left 左端点下标
  49. * @param right 右端点下标
  50. * @return 第一个大于value的数的坐标
  51. */
  52. int upperBound(int[] arr, int left, int right, int value) {
  53. int l = left, r = right - 1;
  54. while (l <= r) {
  55. int m = (l + r) / 2;
  56. if (arr[m] <= value) {
  57. l = m + 1;
  58. } else { // arr[m] > value
  59. r = m - 1;
  60. }
  61. }
  62. return l;
  63. }
  64. public String cal(String input) {
  65. String[] line = input.split("\n");
  66. String[] num = line[0].split(" ");
  67. n = Integer.parseInt(num[0]);
  68. m = Integer.parseInt(num[1]);
  69. String[] keys = line[1].split(" ");
  70. for (int i = 1; i <= n; i++) {
  71. a[i] = Integer.parseInt(keys[i - 1]);
  72. temp[i] = a[i];
  73. }
  74. build();
  75. int j = 0;
  76. while (m-- > 0) {
  77. int l, r, h;
  78. String[] command = line[2 + j].split(" ");
  79. j++;
  80. l = Integer.parseInt(command[0]);
  81. r = Integer.parseInt(command[1]);
  82. h = Integer.parseInt(command[2]);
  83. output += query(++l, ++r, h) + "\n";
  84. }
  85. return output;
  86. }
  87. }

六 测试

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/109300?site
推荐阅读
相关标签
  

闽ICP备14008679号