51nod p1175 区间中第K大的数

1175 区间中第K大的数

基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题

一个长度为N的整数序列,编号0 - N - 1。进行Q次查询,查询编号i至j的所有数中,第K大的数是多少。

例如: 1 7 6 3 1。i = 1, j = 3,k = 2,对应的数为7 6 3,第2大的数为6。

Input

第1行:1个数N,表示序列的长度。(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应序列中的元素。(0 <= S[i] <= 10^9)
第N + 2行:1个数Q,表示查询的数量。(2 <= Q <= 50000)
第N + 3 - N + Q + 2行:每行3个数,对应查询的起始编号i和结束编号j,以及k。(0 <= i <= j <= N - 1,1 <= k <= j - i + 1)

Output

共Q行,对应每一个查询区间中第K大的数。

Input示例

5
1
7
6
3
1
3
0 1 1
1 3 2
3 4 2

Output示例

7
6
1

区间第k大,主席树写一发,使用java写的,顺便复习吐槽---java真是慢,一定要离散化,c++随便写都过而且没有sort,没有map,只有hashmap,真逊啊。。。。

  1 package p1175;
  2
  3 import java.io.*;
  4 import java.util.*;
  5
  6 import javax.management.Query;
  7
  8 public class Main
  9 {
 10     public static class Node
 11     {
 12         int sum;
 13         Node lc, rc;
 14         public Node(Node t)
 15         {
 16             if(t == null)
 17             {
 18                 lc = rc = null;
 19                 sum = 0;
 20             }
 21             else
 22             {
 23                 lc = t.lc;
 24                 rc = t.rc;
 25                 sum = t.sum;
 26             }
 27         }
 28     }
 29
 30     static final int N = 50010;
 31
 32     public static void main(String[] args) throws IOException
 33     {
 34         // TODO Auto-generated method stub
 35         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
 36         BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
 37         int n = getInt(reader);
 38         int[] arr = new int[n], store = new int[n];
 39         for(int i = 0; i < n; i++) store[i] = arr[i] = getInt(reader);
 40         mergeSort(store, 0, n - 1);
 41         int len = 1;
 42         for(int i = 1; i < n; i++)
 43             if(store[i] != store[i - 1]) store[len++] = store[i];
 44         HashMap<Integer, Integer> myMap = new HashMap<Integer, Integer>();
 45         for(int i = 0; i < len; i++)
 46             myMap.put(store[i], i);
 47         for(int i = 0; i < n; i++)
 48             arr[i] = myMap.get(arr[i]);
 49
 50
 51         Node[] root = new Node[n + 1];
 52         Node last = null;
 53         for(int i = 0; i < n; i++)
 54         {
 55             root[i] = new Node(last);
 56             buildTree(root[i], arr[i], 0, len);
 57             last = root[i];
 58         }
 59
 60         for(int m = getInt(reader); m > 0; m--)
 61         {
 62             int l = getInt(reader), r = getInt(reader), k = getInt(reader);
 63             int ans = queryKth(l > 0 ? root[l - 1] : null, root[r], k, 0, len);
 64             writer.write(store[ans] + "\r\n");
 65             writer.flush();
 66         }
 67     }
 68
 69     public static int querySum(Node t)
 70     {
 71         if(t == null) return 0;
 72         return t.sum;
 73     }
 74
 75     public static int queryKth(Node l, Node r, int kth, int left, int right)
 76     {
 77         if(left == right) return left;
 78         int mid = (left + right) >> 1, ret = -1;
 79         int lCnt = l == null ? 0 : querySum(l.rc), rCnt = r == null ? 0 : querySum(r.rc);
 80         if(rCnt - lCnt >= kth) ret = queryKth(l == null ? null : l.rc, r == null ? null : r.rc, kth, mid + 1, right);
 81         else ret = queryKth(l == null ? null : l.lc, r == null ? null : r.lc, kth - (rCnt - lCnt), left, mid);
 82         return ret;
 83     }
 84
 85     public static void buildTree(Node x, int val, int left, int right)
 86     {
 87         if(left < right)
 88         {
 89             int mid = (left + right) >> 1;
 90             if(val <= mid)
 91             {
 92                 x.lc = new Node(x.lc);
 93                 buildTree(x.lc, val, left, mid);
 94             }
 95             else
 96             {
 97                 x.rc = new Node(x.rc);
 98                 buildTree(x.rc, val, mid + 1, right);
 99             }
100         }
101         x.sum++;
102     }
103
104     static int[] tmp = new int[N];
105     public static void mergeSort(int[] arr, int l, int r)
106     {
107         if(l >= r) return;
108         int mid = (l + r) >> 1;
109         mergeSort(arr, l, mid);
110         mergeSort(arr, mid + 1, r);
111         int itL = l, itR = mid + 1, now = l;
112         while(itL <= mid && itR <= r)
113         {
114             if(arr[itL] < arr[itR]) tmp[now++] = arr[itL++];
115             else tmp[now++] = arr[itR++];
116         }
117         while(itL <= mid) tmp[now++] = arr[itL++];
118         while(itR <= r) tmp[now++] = arr[itR++];
119         for(int i = l; i <= r; i++) arr[i] = tmp[i];
120     }
121
122     public static int getInt(BufferedReader reader) throws IOException
123     {
124         char ch = ‘ ‘;
125         for( ; !(ch >= ‘0‘ && ch <= ‘9‘); ch = (char) reader.read()) ;
126         int ret = 0;
127         for( ; ch >= ‘0‘ && ch <= ‘9‘; ch = (char) reader.read())
128             ret = ret * 10 + ch - ‘0‘;
129         return ret;
130     }
131
132 }

时间: 2024-12-28 16:35:01

51nod p1175 区间中第K大的数的相关文章

51nod 1105 第K大的数

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * B[0],A[0] * B[1] ......A[1] * B[0],A[1] * B[1]......A[n - 1] * B[n - 1](数组A同数组B的组合).求数组C中第K大的数. 例如:A:1 2 3,B:2 3 4.A与B组合成的C包括2 3 4 4 6 8 6 9 12共9个数. Input 第1行:2个数N和K,中间用

51 nod 1105 第K大的数

1105 第K大的数 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * B[0],A[0] * B[1] ......A[1] * B[0],A[1] * B[1]......A[n - 1] * B[n - 1](数组A同数组B的组合).求数组C中第K大的数. 例如:A:1 2 3,B:2 3 4.A与B组合成的C包括2 3 4 4 6 8 6 9 12共9个数. I

统计前k大的数x

我终于敲上了题目--记起来啦! 描述 给定一个数组,统计前k大的数并且把这k个数从大到小输出. 输入 第一行包含一个整数n,表示数组的大小.n < 100000. 第二行包含n个整数,表示数组的元素,整数之间以一个空格分开.每个整数的绝对值不超过100000000. 第三行包含一个整数k.k < n. 输出 从大到小输出前k大的数,每个数一行. 样例输入 10 4 5 6 9 8 7 1 2 3 0 5 样例输出 9 8 7 6 5 //AC自动机x #include<iostream&

找出整数中第k大的数

一  问题描述: 找出m个整数中第k(0<k<m+1)大的整数. 二  举例: 假设有12个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2, -9],请找出第5大的数(容易知道是0). 三   算法思路:        一种基于快排思想的算法可以在O(n)复杂度内找到第k大的数,首先要知道partition这个函数,它可以调整一个序列 使小于key的元素都排在key左边,大于key的元素都排在key右边,key可以在这个序列中任意选择,一般选择给定序 列

《数据结构与算法分析:C语言描述》读书笔记------练习1.1 求第K大的数

求一组N个数中的第k个最大者,设k=N/2. 1 import java.util.Random; 2 3 4 public class K_Max { 5 6 /** 7 * @param args 8 */ 9 //求第K大的数,保证K大于等于1,小于等于array.length/2哦 10 public static int TopK(int array[],int K) 11 { 12 int topk[] = new int [K]; 13 for(int i = 0; i<topk.

poj 2401 划分树 求区间第k大的数

题目:http://poj.org/problem?id=2104 划分树待我好好理解下再写个教程吧,觉得网上的内容一般,,, 模板题: 贴代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define CLR(a) memset(a,0,sizeof(a)) const int MAXN = 1000

hdu 4006 第K大的数(优先队列)

N次操作 I是插入一个数 Q是输出第K大的数 Sample Input8 3 //n kI 1I 2I 3QI 5QI 4Q Sample Output123 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <string> 6 # include <cmath> 7 # incl

[二分法]线性时间内在数组中找出第k大的数

#include "stdafx.h" #include "iostream" using namespace std; //参数为 数组指针,开始下标, 结束下标, 第K大数(k从0开始) int rand_par(int array[], int start, int end, int th){ if( start < 0 || end < 0 || th < 0 || end < start ){ return -1; } int le

分治法寻找第k大的数

利用快速排序的思想·去做 #include<iostream>using namespace std;int FindKthMax(int*list, int left, int right, int k);int main(){ int i,n,k; while (cin >> n){ int *a = new int[n]; for (i = 0; i < n; i++) cin >> a[i]; cin >> k; cout << F