赞
踩
马里奥是世界著名的水管工。他的“魁梧”形象和惊人的跳跃能力深深地留在在我们的记忆中。现在这位可怜的公主再次陷入困境,马里奥需要拯救他的情人。我们把通往老板城堡的道路视为一条线(长度为n) ,在每个整数点 i 上都有一块高度位 hi 的砖。现在的问题是,如果他能跳的最大高度是 H ,那么 Mario 在区间[L,R]中可以跳过多少砖块。
第一行是整数 T,即测试数据的数量。
对于每个测试数据:
第一行包含两个整数 n,m,n 是 道路的长度,m 是查询的数量。
下一行包含 n 个整数,每个转的高度。
接下来的 m 行,每行包含三个整数 L,R,H
对于每种情况,每行输出“Case X:”(X 是从 1 开始的案例编号),后跟 m 行,每行包含一个整数。第 i 个整数是 Mario 可以为第 i 个查询命中的转块数。
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
Case 1:
4
0
0
3
1
2
0
1
5
1
本问题包括区间查询。区间查询比较特殊,查询小于等于 H 的数有多少个。
可以采用分块的方法解决。
a 分块
划分块,每块非递减排序。
b 查询
查询区间[l,r]有多少个数小于等于 h。
如果该区间属于同一块,则暴力累加块内有多少个数小于等于 h。
如果该区间包含多块,则累加中间每一块小于等于 h 的数,然后暴力累加左端和右端有多少个数小于等于h。
lower_bound()和upper bound()都是利用二分查找的方法在一个排好序的数组中进行查找的。需要引入头文件:algorithm.
- package com.platform.modules.alg.alglib.hdu4417;
-
- import java.util.Arrays;
-
- import static java.lang.Math.sqrt;
-
- public class Hdu4417 {
- public final int maxn = 100000;
- int L[] = new int[maxn];
- int R[] = new int[maxn];
- int belong[] = new int[maxn];
- int a[] = new int[maxn];
- int temp[] = new int[maxn];
- int n;
- int m;
-
- public String output = "";
-
- void build() {
- int t = (int) sqrt(n);
- int num = n / t;
- if (n % num != 0) num++;
- for (int i = 1; i <= num; i++) {
- L[i] = (i - 1) * t + 1;
- R[i] = i * t;
- }
- R[num] = n;
- for (int i = 1; i <= n; i++)
- belong[i] = (i - 1) / t + 1;
- for (int i = 1; i <= num; i++) {
- // 每块排序
- Arrays.sort(temp, L[i], 1 + R[i]);
- }
- }
-
- int query(int l, int r, int h) {
- int ans = 0;
- if (belong[l] == belong[r]) {
- for (int i = l; i <= r; i++)
- if (a[i] <= h) ans++;
- } else {
- for (int i = l; i <= R[belong[l]]; i++)//左端
- if (a[i] <= h) ans++;
- for (int i = belong[l] + 1; i < belong[r]; i++)//中间
- ans += upperBound(temp, L[i], R[i] + 1, h) - L[i];
- for (int i = L[belong[r]]; i <= r; i++)//右端
- if (a[i] <= h) ans++;
- }
- return ans;
- }
-
- /**
- * @param arr 数组
- * @param value 待比较的值
- * @param left 左端点下标
- * @param right 右端点下标
- * @return 第一个大于value的数的坐标
- */
- int upperBound(int[] arr, int left, int right, int value) {
- int l = left, r = right - 1;
- while (l <= r) {
- int m = (l + r) / 2;
- if (arr[m] <= value) {
- l = m + 1;
- } else { // arr[m] > value
- r = m - 1;
- }
- }
- return l;
- }
-
- public String cal(String input) {
- String[] line = input.split("\n");
- String[] num = line[0].split(" ");
- n = Integer.parseInt(num[0]);
- m = Integer.parseInt(num[1]);
- String[] keys = line[1].split(" ");
-
-
- for (int i = 1; i <= n; i++) {
- a[i] = Integer.parseInt(keys[i - 1]);
- temp[i] = a[i];
- }
- build();
- int j = 0;
- while (m-- > 0) {
- int l, r, h;
- String[] command = line[2 + j].split(" ");
- j++;
- l = Integer.parseInt(command[0]);
- r = Integer.parseInt(command[1]);
- h = Integer.parseInt(command[2]);
- output += query(++l, ++r, h) + "\n";
- }
- return output;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。