hdu 4006 The kth great number(线段树 || 优先队列)

2024-03-27 23:38

本文主要是介绍hdu 4006 The kth great number(线段树 || 优先队列),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4006

求一个数字序列的第K大的值。先输入两个数字n,k,接着是n行输入,I表示加入新的数字,Q是询问第k大的数字。

Sample Input
  
8 3 I 1 I 2 I 3 Q I 5 Q I 4 Q

Sample Output
  
1 2 3
练习线段树遇到这道题的,听说方法还挺多的。
线段树:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e6+5; //',INF=0x3f3f3f3f;
int ans[maxn];
struct node{int l,r,count;int mid(){  return (l+r)/2; }int length(){  return (r-l+1); }
}tree[maxn<<2];
void build(int a,int b,int root){tree[root].l=a;tree[root].r=b;tree[root].count=0;if(a==b){return ;}int m=tree[root].mid();build(a,m,2*root);build(m+1,b,2*root+1);
}
void insert(int root,int number){if(tree[root].l==tree[root].r){tree[root].count++;return ;}if(number<=tree[root].mid()) insert(2*root,number);else insert(2*root+1,number); // number-tree[2*root].count is wrongtree[root].count=tree[2*root].count+tree[2*root+1].count;
}
int query(int root,int number){if(tree[root].l==tree[root].r){return tree[root].l;}int ans;if(number<=tree[2*root].count)ans=query(2*root,number);else ans=query(2*root+1,number-tree[2*root].count);  //we need "number-tree[2*root].count"return ans;
}
int main()
{//freopen("cin.txt","r",stdin);int n,k;while(cin>>n>>k){build(1,maxn,1);char str[3];int top=0;for(int i=0;i<n;i++){scanf("%s",str);if(str[0]=='I'){int a;scanf("%d",&a);insert(1,a);top++;}else {printf("%d\n",query(1,top-k+1));}}}return 0;
}

优先队列:
第一次写好的代码怀着忐忑的心情交上去,没错,果然超时了:
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn=1e6+5;
int number[maxn];
int main()
{//freopen("cin.txt","r",stdin);int n,k;while(cin>>n>>k){priority_queue<int> que;char s[3];for(int i=0;i<n;i++){scanf("%s",s);if(s[0]=='I'){int a;scanf("%d",&a);que.push(a);}else {int j;for(j=0;j<k;j++){number[j]=que.top();que.pop();}printf("%d\n",number[j-1]);for(j=0;j<k;j++){que.push(number[j]);}}}}return 0;
}
想个办法把第二个循环去掉吧,抓住主要矛盾,忽略次要因素:
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
const int maxn=1e6+5;
int number[maxn];
int main()
{//freopen("cin.txt","r",stdin);int n,k;while(cin>>n>>k){priority_queue<int,vector<int>,greater<int> > que;  //从小到大char s[3];for(int i=0;i<n;i++){scanf("%s",s);if(s[0]=='I'){int a;scanf("%d",&a);que.push(a);if(que.size()>k)que.pop();}else {printf("%d\n",que.top());}}}return 0;
}

记住要用functional头文件,不然会Compilation Error。


这篇关于hdu 4006 The kth great number(线段树 || 优先队列)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853787

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :