您的位置:首页 > 其它

#1133 : 二分·二分查找之k小数(优先队列或SBT或排序)

2015-09-20 20:40 459 查看
Link:http://hihocoder.com/problemset/problem/1133


#1133 : 二分·二分查找之k小数

时间限制:10000ms
单点时限:1000ms
内存限制:256MB


描述

在上一回里我们知道Nettle在玩《艦これ》,Nettle的镇守府有很多船位,但船位再多也是有限的。Nettle通过捞船又出了一艘稀有的船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了。所以Nettle不得不把其中一艘船拆掉来让位给新的船。Nettle思考了很久,决定随机选择一个k,然后拆掉稀有度第k小的船。 已知每一艘船都有自己的稀有度,Nettle现在把所有船的稀有度值告诉你,希望你能帮他找出目标船。

提示:非有序数组的二分查找之二


输入

第1行:2个整数N,k。N表示数组长度,

第2行:N个整数,表示a[1..N],保证不会出现重复的数,1≤a[i]≤2,000,000,000。


输出

第1行:一个整数t,表示t在数组中是第k小的数,若K不在数组中,输出-1。

样例输入
10 4
1732 4176 2602 6176 1303 6207 3125 1 1011 6600


样例输出
1732


EmacsNormalVim

方法一:优先队列

AC code1:

#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;
    //freopen("D:\\in.txt","r",stdin);
    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("%d\n",pq.top().v);
	}
	return 0;
 }


方法二:SBT

AC code2:

#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
;
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() {
	//freopen("D:\\in.txt","r",stdin);
    int k,end;
    char le[5];
    while(~scanf("%d%d",&n,&end)) {
        root=tot=0;
        for(k=0;k<n;k++) {
            //scanf("%s",le);
            le[0]='I'; 
            switch(le[0]) {
            case 'I':scanf("%d",&m);
                insert(root,m); break;
            default :
                printf("%d\n",find(root,tot+1-end));
            }
        }
        printf("%d\n",find(root,end));
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: