在POJ2104中,由于会给定序列的区间,而且是多次查询,所以像快速排序加二分这种分治算法的时间效率就不算很高了,然后自己尝试用二叉搜索树保存数据,粗略的写了个java代码:
import java.util.Arrays;
import java.util.Scanner;
/**
*
* @author Sot_fzh
*/
public class Poj2104 {
static class Point {
int x;
int left = -1;
int right = -1;
}
static Point[] p;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
int count = scan.nextInt();
int[] a = new int[num];
int[] b = new int[num];
p = new Point[num];
for (int i = 0; i < num; i++) {
a[i] = b[i] = scan.nextInt();
}
Arrays.sort(b);
for (int i = 0; i < num; i++) {
p[i] = new Point();
p[i].x = b[i];
}
int head = creTree(b, 0, num - 1);
while (count-- != 0) {
int low = scan.nextInt() - 1;
int high = scan.nextInt() - 1;
int k = scan.nextInt();
int h = head;
while (true) {
int down = 0, up = 0;
for (int i = low; i <= high; i++) {
if (a[i] < p[h].x) {
down++;
}
if (a[i] > p[h].x) {
up++;
}
}
if (down >= k) { //证明在左子树
h = p[h].left;
} else if (down < k) { //证明不在左子树
if (down==k-1&&up+down+1==high-low+1) { //如果大于中值点数+小于中值点的数+1==总共数
System.out.println(p[h].x);
break;
}
h = p[h].right;
}
}
}
}
public static int creTree(int[] b, int low, int high) {
int mid = (low + high) / 2;
if (low <= mid - 1) {
p[mid].left = creTree(b, low, mid - 1);
}
if (high >= mid + 1) {
p[mid].right = creTree(b, mid + 1, high);
}
return mid;
}
public static void printP(int head) { //先序遍历
System.out.print(p[head].x + " ");
if (p[head].left != -1) {
printP(p[head].left);
}
if (p[head].right != -1) {
printP(p[head].right);
}
}
public static void printM(int head) { //中序遍历
if (p[head].left != -1) {
printM(p[head].left);
}
System.out.print(p[head].x + " ");
if (p[head].right != -1) {
printM(p[head].right);
}
}
}
由于自己长期怕麻烦又习惯使用java编写程序,经典的树形数据结构其实自己还很少用代码来实现,以上代码又是tle。。
但是无意中发现这道题目可以这样做:
设置节点,保存序列时把每个数的原始下标也保存下来,然后进行排序,之后从小到大依次检验节点的下标是否在给定区间中,若存在k--,否则下一个,当k减到0时,证明Kth已经找到。这里根据节点保存的原始下标来检验是否包含在给定区间中,这一点比较巧妙,因为用一个比较大小来代替一个for循环了。
以下代码AC
import java.util.Arrays;
import java.util.Scanner;
/**
*
* @author Sot_fzh
*/
public class My2104 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int len = scan.nextInt();
int num = scan.nextInt();
Point[] pa = new Point[len];
for (int i = 0; i < len; i++) {
pa[i] = new Point(i, scan.nextInt());
}
Arrays.sort(pa);
while (num-- != 0) {
int left = scan.nextInt() - 1;
int right = scan.nextInt() - 1;
int k = scan.nextInt();
for (int i = 0; i < len; i++) { //从小到达遍历排序数组
if (pa[i].i >= left && pa[i].i <= right) {
k--;
}
if (k == 0) {
System.out.println(pa[i].num);
break;
}
}
}
}
static class Point implements Comparable{
int i, num;
public Point(int i, int num) {
this.i = i;
this.num = num;
}
@Override
public int compareTo(Object o) {
return num-((Point)o).num;
}
}
}