HDU 4006 The kth great number 优先队列、平衡树模板题(SBT)

The kth great number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)

【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).

 

【题意】

给出一系列操作:

1.记录一个数;2.求第k小的数

 

【分析】

解法一、

题目每次询问的只是其中的一个数,这种情况下用一个堆来维护所有数的集合即可。

而且本题的k是一个固定值,因此只需要一个小根堆即可;若k不是一个固定值,则需要一个小根堆配合大根堆共同完成。

 

堆可以用STL中的优先队列来代替。

创建一个小根堆并向其加入数据,若堆中的数量大于k则弹出堆顶元素,始终保持整个堆中只有k个元素。遇到询问时,读取堆顶元素。

 1 /* ***********************************************
 2 MYID    : Chen Fan
 3 LANG    : G++
 4 PROG    : HDU4006
 5 ************************************************ */
 6 
 7 #include <iostream>
 8 #include <cstdio>
 9 #include <cstring>
10 #include <algorithm>
11 #include <queue>
12 
13 using namespace std;
14 
15 struct cmp
16 {
17     bool operator()(int x,int y)
18     {
19         return x>y;
20     }
21 };
22 
23 int main()
24 {
25     //freopen("1.txt","r",stdin);
26     //freopen("std.txt","w",stdout);
27 
28     int n,k;
29 
30     while(scanf("%d%d",&n,&k)==2)
31     {
32         priority_queue<int,vector<int>,cmp>q;
33         char c;
34         for (int i=1;i<=n;i++)
35         {
36             c=getchar();
37             while(c!='I'&&c!='Q')
38             {
39                 c=getchar();
40             }
41             if (c=='I')
42             {
43                 int now;
44                 scanf("%d",&now);
45                 q.push(now);
46                 if (q.size()>k) q.pop();
47             } else
48             {
49                 printf("%d\n",q.top());
50             }
51         }
52     }
53 
54     return 0;
55 }
View Code

 

法二、

本题可作为平衡树模板题,虽然因为有点大材小用内存占用比较大,而且时间上并没有太大优势。

动态维护一棵平衡树,求k大值。

以下采用Size Balanced Tree完成:

  1 /* ***********************************************
  2 MYID    : Chen Fan
  3 LANG    : G++
  4 PROG    : HDU4006_SBT
  5 ************************************************ */
  6 
  7 #include <iostream>
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <algorithm>
 11 
 12 using namespace std;
 13 
 14 #define MAXN 1000010
 15 
 16 typedef struct sbtnod
 17 {
 18     int key,left,right,size;
 19 } sbtnode;
 20 int sbttail,sbt;
 21 
 22 sbtnode tree[MAXN];
 23 
 24 void rrotate(int& t)
 25 {
 26     int k=tree[t].left;
 27     if (!k) return ;
 28     tree[t].left=tree[k].right;
 29     tree[k].right=t;
 30     tree[k].size=tree[t].size;
 31     tree[t].size=tree[tree[t].left].size+tree[tree[t].right].size+1;
 32     t=k;
 33 }
 34 
 35 void lrotate(int& t)
 36 {
 37     int k=tree[t].right;
 38     if (!k) return ;
 39     tree[t].right=tree[k].left;
 40     tree[k].left=t;
 41     tree[k].size=tree[t].size;
 42     tree[t].size=tree[tree[t].left].size+tree[tree[t].right].size+1;
 43     t=k;
 44 }
 45 
 46 void maintain(int& t,bool flag)
 47 {
 48     if (!t) return ;
 49     if (!flag)
 50         if (tree[tree[tree[t].left].left].size>tree[tree[t].right].size) rrotate(t);
 51         else if (tree[tree[tree[t].left].right].size>tree[tree[t].right].size) 
 52         {
 53             lrotate(tree[t].left);
 54             rrotate(t);
 55         } else return ;
 56     else
 57         if (tree[tree[tree[t].right].right].size>tree[tree[t].left].size) lrotate(t);
 58         else if (tree[tree[tree[t].right].left].size>tree[tree[t].left].size)
 59         {
 60             rrotate(tree[t].right);
 61             lrotate(t);
 62         } else return ;
 63     
 64     maintain(tree[t].left,false);
 65     maintain(tree[t].right,true);
 66     maintain(t,false);
 67     maintain(t,true);
 68 }
 69 
 70 void insert(int& t,int v)
 71 {
 72     if (!t)
 73     {
 74         sbttail++;
 75         tree[sbttail].key=v;
 76         tree[sbttail].size=1;
 77         t=sbttail;
 78     } else 
 79     {
 80         tree[t].size++;
 81         if (v<tree[t].key) insert(tree[t].left,v);
 82         else insert(tree[t].right,v);
 83         maintain(t,v>=tree[t].key);
 84     }
 85 }
 86 
 87 int del(int& t,int v)
 88 {
 89     int ret;
 90     tree[t].size--;
 91     if (v==tree[t].key||(v<tree[t].key&&tree[t].left==0)||(v>tree[t].key&&tree[t].right==0))
 92     {
 93         ret=tree[t].key;
 94         if (tree[t].left==0||tree[t].right==0) t=tree[t].left+tree[t].right;//
 95         else tree[t].key=del(tree[t].left,tree[t].key+1);
 96     } else 
 97     {
 98         if (v<tree[t].key) ret=del(tree[t].left,v);
 99         else ret=del(tree[t].right,v);
100     }
101     return ret;
102 }
103 
104 int select(int t,int k)
105 {
106     if (k==tree[tree[t].left].size+1) return t;
107     if (k<=tree[tree[t].left].size) return select(tree[t].left,k);
108     else return select(tree[t].right,k-1-tree[tree[t].left].size);
109 }
110 
111 int main()
112 {
113     //freopen("1.txt","r",stdin);
114     //freopen("st.txt","w",stdout);
115 
116     int n,k;
117     while(scanf("%d%d",&n,&k)==2)
118     {
119         memset(tree,0,sizeof(tree));
120         sbttail=0;
121         sbt=0;
122 
123         char c;
124         for (int i=1;i<=n;i++)
125         {
126             c=getchar();
127             while(c!='I'&&c!='Q')
128             {
129                 c=getchar();
130             }
131             int now;
132             if (c=='I')
133             {
134                 scanf("%d",&now);
135                 insert(sbt,now);
136             } else 
137             {
138                 now=select(sbt,sbttail-k+1);
139                 printf("%d\n",tree[now].key);
140             }
141         }
142     }
143 
144     return 0;
145 }
View Code

 

 

 

 

posted @ 2015-03-08 20:27  辰帆  阅读(254)  评论(0编辑  收藏  举报