priority_queue的应用

来源:互联网 发布:网络购物管辖法院 编辑:程序博客网 时间:2024/05/21 05:58
 

                                          (一)

The kth great number

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65768/65768K (Java/Other)
Total Submission(s) : 15   Accepted Submission(s) : 5
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 3I 1I 2I 3QI 5QI 4Q
 

Sample Output
123
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).

 

 

题目的意思是要求已经加入队列的数的第k大的数是多少,可以用优先队列来解决

在队列中只保存k个数,这k个数按大小顺序排列,最前面的是“最优”,即是这k个数中最小的(便是第k大)。对于新加入的数,只需要和priority_queue队列中的top比较,

如果比top小,那这个数就无意义,不压入队列;如果比这个数大,之前的“最优解”已经不是第k大的数了,所以把它踢出,压入这个新元素,然后priority_queue就会自动再排列,top又变成“最优解”。

 

#include <queue>   #include <iostream>   #include<cstdio>using namespace std;    int main()  {  //freopen("input.txt","r",stdin);    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);                      }                  }              }              else                  printf("%d\n",que.top() );          }      }      return 0;  }  


 

 

Fence Repair

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 8   Accepted Submission(s) : 2
Problem Description

Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needsN (1 ≤N ≤ 20,000) planks of wood, each having some integer lengthLi (1 ≤Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into theN planks (i.e., whose length is the sum of the lengthsLi). FJ is ignoring the "kerf", the extra length lost to sawdust when a sawcut is made; you should ignore it, too.

FJ sadly realizes that he doesn't own a saw with which to cut the wood, so he mosies over to Farmer Don's Farm with this long board and politely asks if he may borrow a saw.

Farmer Don, a closet capitalist, doesn't lend FJ a saw but instead offers to charge Farmer John for each of theN-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.

Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create theN planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.

 


 

Input
Line 1: One integer N, the number of planks
Lines 2..N+1: Each line contains a single integer describing the length of a needed plank
 


 

Output
Line 1: One integer: the minimum amount of money he must spend to makeN-1 cuts
 


 

Sample Input
3858
 


 

Sample Output
34

 

 

题目要求把一个木块切成N块,一共且N-1次, 每次切的花费为要切的那块木板的长度(例如,要在一块长10米的木块切一刀,分为两个5米的木块,那么就是花费10元)

要使花费最少,那么就要使每一刀切的那个木块长度能够最小,因此可以将切木板的过程反过来看, 把N个长度各异的木块拼成一整块木块, 每次把两个木块连接成一块,

为了使花费最小,要让每次连接的这两块木块是所有木块中最小的那两块。 连接好的两块就变成了一块,再次放入队列中。 因此可用到最优队列,每次都能保证得到所

需要的顺序的队列。

/*将切木板的过程反过来看,也就是将所有切好了的木板每次拿两块拼接起来(每次拼接后的长度就是费用),最终便会拼接成原来的完整的木板。*/#include<iostream>#include<cstdio>#include<queue>#include<vector>using namespace std;int main(){    int n,i;__int64 x;    priority_queue<__int64,vector<__int64>,greater<__int64> > q;        scanf("%d",&n);    while(n--){        scanf("%I64d",&x);        q.push(x);    }    __int64 sum=0;    while( q.size()!=1 ){__int64 a,b;        a = q.top();        q.pop();        b = q.top();        q.pop();        q.push(a+b);sum+=a+b;    }    printf("%I64d\n",sum);    return 0;}