加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

The kth great number(第k大数模板题:优先队列或树状数组或SBT

发布时间:2020-12-14 02:46:12 所属栏目:大数据 来源:网络整理
导读:Link:http://acm.hdu.edu.cn/showproblem.php?pid=4006 The kth great number Time Limit: 2000/1000 MS (Java/Others)????Memory Limit: 65768/65768 K (Java/Others) Total Submission(s): 7134????Accepted Submission(s): 2916 Problem Description Xia


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


The kth great number

Time Limit: 2000/1000 MS (Java/Others)????Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 7134????Accepted Submission(s): 2916


Problem Description
Xiao Ming and Xiao Bao are playing a simple Numbers game. In a round Xiao Ming can choose to write down a number,or ask Xiao Bao what the kth great number is. Because the number written by Xiao Ming is too much,Xiao Bao is feeling giddy. Now,try to help Xiao Bao.
?

Input
There are several test cases. For each test case,the first line of input contains two positive integer n,k. Then n lines follow. If Xiao Ming choose to write down a number,there will be an " I" followed by a number that Xiao Ming will write down. If Xiao Ming choose to ask Xiao Bao,there will be a "Q",then you need to output the kth great number.?
?

Output
The output consists of one integer representing the largest number of islands that all lie on one line.?
?

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

Sample Output
      
      
1 2 3
Hint
Xiao Ming won't ask Xiao Bao the kth great number when the number of the written number is smaller than k. (1=<k<=n<=1000000).
?

Source
The 36th ACM/ICPC Asia Regional Dalian Site —— Online Contest
?

Recommend
lcy???|???We have carefully selected several similar problems for you:?? 4003? 4007? 4004? 4008? 4005?
?

Statistic?|? Submit?|? Discuss?|? Note


题意:题目会给出n个数,求第k大的数.

输入:第一行输入两个整数n 和 k

接下来有n行数据,输入的数据分为两种.

输入I 和 一个数字x?? 表示写入数字x

输入Q 表示进行一次询问 询问当前第k大的数是多少并输出这个数.

?

?开始使用sort进行排序,提交后会超时.

后来改用优先队列.

声明一个结构体

struct Node
{
    int x;
    friend bool operator < (Node a,Node b)
    {
        return a.x > b.x;
    }

};

主要用于重载小于号,让小的优先.
输入时先输入k个数,输入k个数后再输入时需要判断输入的数与队头的大小关系.

输入数小于队头则不进队.

输入数大于队头则进队,弹出队头.

保证优先队列中只有k的元素.

而队头是k个元素中最小的元素.

即第k大元素



AC ?code:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<cmath>
using namespace std;
struct node{
	int v;
	friend bool operator < (node a,node b)
	{
		return a.v>b.v;
	}
};

int main()
{
    int n,k;
    
    while(scanf("%d%d",&n,&k)!=EOF)
    {
    	int cnt=0;
    	priority_queue<node>pq;
    	while(n--)
    	{
    		char c;
    		cin>>c;
    		if(c=='I')
			{
				
				if(cnt<k)
				{
					node t;
			    	scanf("%d",&t.v);
					pq.push(t);
					cnt++;
				}
				else
				{
					node t;
			    	scanf("%d",&t.v);
					if(pq.top().v<t.v)
					{
						pq.pop();
						pq.push(t);
					}
				}	
			}
			else
			{
				if(c=='Q')
				{
					printf("%dn",pq.top().v);
				}
			
			}
		}
	}
	return 0;
 } 


以下树状数组代码参考:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
const int N=1000005;
int cal[N],ptr[N];
struct TNode {
	char c[5];
	int m;
}node[N];
int n,m;
int lowbit(int x) {return x&-x;}
int getsum(int x) {
	int s=0;
	for(;x>0;s+=cal[x],x-=lowbit(x));
	return s;
}
void update(int x,int value) {
	for(;x<m;cal[x]+=value,x+=lowbit(x));
}
//数组中一共有m个数
int seach(int value) {
	int l=1,r=m-1,mid;
	while(l<=r) 
	{
		mid=(l+r)>>1;
		int t=ptr[mid];
		if(t==value) return mid;
		else if(t>value)
			r=mid-1;
		else l=mid+1;
	}
	return -1;
}
int find(int k) {
	int cnt=0,sum=0;
	for (int i=20;i>=0;i--) {
		sum+=(1<<i);
		if(sum>=m||cnt+cal[sum]>=k)
			sum-=(1<<i);
		else cnt+=cal[sum];
	}
	return sum+1;
}
int main() {
	int i,j,k,t;
	char le[5];
	while(~scanf("%d%d",&k))
	{
		memset(cal,sizeof(cal));
		for(i=1,m=1;i<=n;i++)
		{
			scanf("%s",node[i].c);
			if(node[i].c[0]=='I')
			{
				scanf("%d",&node[i].m);
				ptr[m++]=node[i].m;
			}
		}
		//相当于离散化处理
		sort(ptr+1,ptr+m);
		//去重
		for(i=2,j=1;i<m;i++)
		{
			if(ptr[i]!=ptr[j])
				ptr[++j]=ptr[i];
		}
		m=j+1;
		for(i=1,j=0;i<=n;i++) 
		{
			if(node[i].c[0]=='I') 
			{
				t=seach(node[i].m);
				update(t,1); j++;
			}
			else 
			{
				t=find(j+1-k);
				printf("%dn",ptr[t]);
			}
		}
	}
	return 0;
}


附上别人其他做法(来自:http://blog.sina.com.cn/s/blog_732dd9320100trmj.html):

SBT解法:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<vector>
using namespace
?std;
const
?int
?N=1000005;
struct
?TNode?{
????int
?left,right,size,key;
????void
?init() {
????????left=0;?right=0;?size=1;
????}
}
node[N];
int
?n,m,tot,root;
void
?leftrorate(int?&t) {//左旋
????int?k=node[t].right;
????node[t].right=node[k].left;
????node[k].left=t;
????node[k].size=node[t].size;
????node[t].size=node[node[t].left].size+node[node[t].right].size+1;
????t=k;
}

void
?rightrorate(int?&t) {//右旋
????int?k=node[t].left;
????node[t].left=node[k].right;
????node[k].right=t;
????node[k].size=node[t].size;
????node[t].size=node[node[t].left].size+node[node[t].right].size+1;
????t=k;
}

void
?maintain(int?&t,bool?flag) {//维护
????if(!flag) {
????????if
(
node[node[node[t].left].left].size>node[node[t].right].size)
????????????rightrorate(t);
????????else if
(
node[node[node[t].left].right].size>node[node[t].right].size) {
????????????leftrorate(node[t].left);
????????????rightrorate(t);
????????}

????????else return
?;
????}

????else
?{
????????if
(
node[node[node[t].right].right].size>node[node[t].left].size)
????????????leftrorate(t);
????????else if
(
node[node[node[t].right].left].size>node[node[t].left].size) {
????????????rightrorate(node[t].right);
????????????leftrorate(t);
????????}

????????else return
?;
????}

????maintain(node[t].left,0);
????maintain(node[t].right,1);
????maintain(t,0);
????maintain(t,1);
}

void
?insert(int?&t,int?value) {//插入
????if(!t) {
????????t=++tot;
????????node[t].init();
????????node[t].key=value;
????}

????else
?{

????????node[t].size++;
????????if
(
value<node[t].key)?insert(node[t].left,value);
????????else
?insert(node[t].right,value);
????????maintain(t,value>=node[t].key);
????}
}

int
?find(int?t,int?k) {//查找第k小的数
????if(k<=node[node[t].left].size)?return?find(node[t].left,k);
????else if
(
k>node[node[t].left].size+1)
????????return
?find(node[t].right,k-node[node[t].left].size-1);
????else return
?node[t].key;
}

int
?main() {
????int
?k,end;
????char
?le[5];
????while
(~
scanf("%d%d",&n,&end)) {
????????root=tot=0;
????????for
(
k=0;k<n;k++) {
????????????scanf("%s",le);
????????????switch
(
le[0]) {
????????????case
?'I':scanf("%d",&m);
????????????????insert(root,m);?break;

????????????default?:
????????????????printf("%dn",find(root,tot+1-end));
????????????}
????????}
????}

????return
?0;
}

树状数组解法:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
using namespace
?std;
const
?int
?N=1000005;
int
?cal[N],ptr[N];
struct
?TNode?{
????char
?c[5];
????int
?m;
}
node[N];
int
?n,m;
int
?lowbit(int?x) {return?x&-x;}
int
?getsum(int?x) {
????int
?s=0;
????for
(;
x>0;s+=cal[x],x-=lowbit(x));
????return
?s;
}

void
?update(int?x,int?value) {
????for
(;
x<m;cal[x]+=value,x+=lowbit(x));
}

int
?seach(int?value) {
????int
?l=1,r=m-1,mid;
????while
(
l<=r) {
????????mid=(l+r)>>1;
????????int
?t=ptr[mid];
????????if
(
t==value)?return?mid;
????????else if
(
t>value)?r=mid-1;
????????else
?l=mid+1;
????}

????return
?-
1;
}

int
?find(int?k) {
????int
?cnt=0,sum=0;
????for
?(int
?i=20;i>=0;i--) {
????????sum+=(1<<i);
????????if
(
sum>=m||cnt+cal[sum]>=k)
????????????sum-=(1<<i);
????????else
?cnt+=cal[sum];
????}

????return
?sum+1;
}

int
?main() {
????int
?i,j,k,t;
????char
?le[5];
????while
(~
scanf("%d%d",&k)) {
????????memset(cal,0,sizeof(cal));
????????for
(
i=1,m=1;i<=n;i++) {
????????????scanf("%s",node[i].c);
????????????if
(
node[i].c[0]=='I') {
????????????????scanf("%d",&node[i].m);
????????????????ptr[m++]=node[i].m;
????????????}
????????}

????????sort(ptr+1,ptr+m);
????????for
(
i=2,j=1;i<m;i++) {
????????????if
(
ptr[i]!=ptr[j])?ptr[++j]=ptr[i];
????????}

????????m=j+1;
????????for
(
i=1,j=0;i<=n;i++) {
????????????if
(
node[i].c[0]=='I') {
????????????????t=seach(node[i].m);
????????????????update(t,1);?j++;
????????????}

????????????else
?{

????????????????t=find(j+1-k);
????????????????printf("%dn",ptr[t]);
????????????}
????????}
????}

????return
?0; }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读