HDU 4006 The kth great number 堆/优先级队列/线段树
来源:互联网 发布:软考初级程序员难吗 编辑:程序博客网 时间:2024/06/06 00:50
题意:先输入两个整数 n, k。然后有 n 行输入, I 代表写下一个数字, Q代表询问在所有写下的数字中第 k 大的数数多少?
题解:因为当写下的数少于 k 个是不存在询问的情况。所以可以建一个堆,然后没写下一个数字,若它比堆中的最小数字还小,则堆不做改变。若它比堆中的最小数字要大,那么将堆中的最小数字去掉,并加入刚写入的数字。
具体写了三种方法:
方法一:最小堆
#include <algorithm>#include <iostream>using namespace std;struct min_Heap { int array[1000002], size; void siftDown ( int start ) //下滑调整,若子女的值小于父节点的值,则子节点上浮,之后继续向下层比较 { int i = start, j = i * 2; int temp = array[start]; while ( j <= size ) { if ( j < size && array[j] > array[j+1] ) ++j; if ( temp <= array[j] ) break; else { swap(array[i],array[j]); i = j; j = j * 2; } } } void siftUp ( int start ) //上滑调整,若子女的值小于父节点的值则互相交换 { int j = start, i = j / 2; int temp = array[j]; while ( j >= 1 ) { if ( temp >= array[i] ) break; else { swap(array[i],array[j]); j = i; i = i / 2; } } } void build_minHeap () //建堆 { int current = size / 2; while ( current >= 1 ) { siftDown ( current ); current--; } }} minHeap; int main(){char oper[3];int n, k, num;while ( scanf("%d%d",&n,&k) != EOF ){minHeap.size = 0;for ( int i = 1; i <= n; i++ ){scanf("%s",oper);if ( oper[0] == 'I' ){scanf("%d",&num);if ( minHeap.size < k ){minHeap.size++;minHeap.array[minHeap.size] = num;if ( minHeap.size == k ) minHeap.build_minHeap ();}else if ( num > minHeap.array[1] ){minHeap.array[1] = num;minHeap.siftDown ( 1 );}}elseprintf("%d\n",minHeap.array[1]);}}return 0;}
方法二:优先级队列。其实和上面一种方法没有本质区别
#include <queue>#include <iostream>using namespace std;int main(){char oper[3];int n, k, num;while ( scanf("%d%d",&n,&k) != EOF ){priority_queue< int,vector<int>,greater<int> > que;for ( int i = 1; i <= n; i++ ){scanf("%s",oper);if ( oper[0] == 'I' ){scanf("%d",&num);if ( que.size() < k )que.push(num);else{if ( num > que.top() ){que.pop();que.push(num);}}}elseprintf("%d\n",que.top() );}}return 0;}
方法三:线段树实现。线段树的实现效率虽然比以上两种略差,但是实用性很强。更容易拓展。
#include <algorithm>#include <iostream>using namespace std;#define L(u) ( u << 1 )#define R(u) ( u << 1 | 1 )#define N 1000001struct item{int l, r, v;} node[N*3];void build ( int u, int l, int r ){node[u].l = l;node[u].r = r;node[u].v = 0;if ( l == r ) return;int mid = ( l + r ) >> 1;build ( L(u), l, mid );build ( R(u), mid+1, r);}void update ( int u, int pos ){node[u].v++;if ( node[u].l == pos && node[u].r == pos )return;int mid = ( node[u].l + node[u].r ) >> 1;if ( pos <= mid )update ( L(u), pos );elseupdate ( R(u), pos );}int query ( int u, int k ){if ( node[u].l == node[u].r )return node[u].l;if ( k <= node[L(u)].v )return query ( L(u), k );elsereturn query ( R(u), k - node[L(u)].v );}int main(){char oper[3];int n, k, num, cnt;while ( scanf("%d%d",&n,&k) != EOF ){cnt = 0;build ( 1, 1, 1000000 );for ( int i = 1; i <= n; i++ ){scanf("%s",oper);if ( oper[0] == 'I' ){scanf("%d",&num);cnt++; /* cnt 统计一共写下的数字 */update ( 1, num );}else printf("%d\n", query(1,cnt-k+1) ); /* 注意是 cnt-k+1 */}}return 0;}
- HDU 4006 The kth great number 堆/优先级队列/线段树
- hdu 4006 The kth great number(线段树 || 优先队列)
- hdu 4006 The kth great number 优先级队列
- HDU 4006 The kth great number(优先队列、堆实现)
- HDU 4006 The kth great number (堆实现优先队列)
- HDU 4006 The kth great number 【队列】
- hdu 4006 The kth great number 线段树/优先队列/set
- HDU ACM 4006 The kth great number 线段树?优先队列?
- hdu 4006 The kth great number 线段树
- HDU 4006 The kth great number【线段树二分】
- hdoj 4006The kth great number(优先级队列)
- hdu 4006 The kth great number (优先队列+STB+最小堆)
- hdu 4006 The kth great number(使用优先队列)
- HDU 4006 The kth great number(优先队列)
- HDU 4006 The kth great number(优先队列)
- hdu 4006 The kth great number(优先队列)
- hdu 4006 The kth great number 优先队列
- HDU-#4006 The kth great number(优先队列)
- 堆表和索引组织表区别
- 友元函数
- String处理: 获得URL的最后一个字符串
- 读excel(一)
- 遮挡tabbar,navigation的方法
- HDU 4006 The kth great number 堆/优先级队列/线段树
- android ntfs 多分区自动mount
- Mandelbrot集彩色单图程序源代码
- C++中delete, new以及new [], delete[]操作符内幕
- 我开通了csdn的新博客
- AA记账簿 使用说明
- 模拟带图片的select简单插件
- 用link方式安装eclipse插件
- tomcat遇到最大线程数的问题