优先队列专题

1、UVALive 3135  Argus

  题意:有若干注册信息,每个id每经过一个周期返回一个id信息。求前k个返回信息的id。如果两个信息返回的时间点相同,则小的那个先返回。

  思路:优先队列简单应用。

 1 #include<iostream>
 2 #include<queue>
 3 #include<map>
 4 #include<cstdio>
 5 using namespace std;
 6 char s[10];
 7 struct nd
 8 {
 9     int id;
10     int v;
11     nd(int ii=0,int vv=0):id(ii),v(vv){ }
12     friend bool operator<(const nd&a, const nd&b)
13     {
14         if (a.v == b.v) return a.id > b.id;
15         else return a.v > b.v;
16     }
17 };
18 int main()
19 {
20     priority_queue<nd>q;
21     map<int, int>mp;
22     while (~scanf("%s", s))
23     {
24         if (s[0] == '#')break;
25         int id, period;
26         scanf("%d%d", &id, &period);
27         q.push(nd(id, period));
28         mp[id] = period;
29     }
30     int cnt;
31     scanf("%d", &cnt);
32     while (cnt--)
33     {
34         nd u = q.top();
35         q.pop();
36         printf("%d\n", u.id);
37         q.push(nd(u.id, u.v + mp[u.id]));
38     }
39     return 0;
40 }
View Code

 2、uva 11997 K Smallest Sums

  题意:给出k个数组,每个数组有k个元素,现在可以从每个数组各选一个数组成和,共有k^k个。求其前k小的数。

  思路:优先队列+多路归并。

 1 #include<iostream>
 2 #include<queue>
 3 #include<functional>
 4 #include<algorithm>
 5 #include<cstdio>
 6 using namespace std;
 7 int num[800][800];
 8 struct pos
 9 {
10     int sum;
11     int id;
12     pos(int ss=0,int ii=0):sum(ss),id(ii){ }
13     friend bool operator<(const pos&a, const pos&b)
14     {
15         return a.sum > b.sum;
16     }
17 };
18 int main()
19 {
20     int k;
21     while (~scanf("%d", &k))
22     {
23         for (int i = 0; i < k; i++)
24         {
25             for (int j = 0; j < k; j++)
26             {
27                 scanf("%d", &num[i][j]);
28             }
29             sort(num[i], num[i] + k);
30         }
31         //多路归并
32         for (int i = 1; i < k; i++)
33         {
34             priority_queue<pos>q;
35             for (int j = 0; j < k; j++) q.push(pos(num[0][j] + num[i][0], 0));
36             for (int j = 0; j < k; j++)
37             {
38                 pos u = q.top();
39                 q.pop();
40                 num[0][j] = u.sum;
41                 if (u.id + 1 < k) q.push(pos(u.sum - num[i][u.id] + num[i][u.id + 1], u.id + 1));
42             }
43         }
44         for (int i = 0; i < k; i++)
45         {
46             if (i) printf(" ");
47             printf("%d", num[0][i]);
48         }
49         printf("\n");
50     }
51     return 0;
52 }
View Code

 3、uva 11136 Hoax or what

  题意:每天员工都会向箱子里放他们的业绩单,每天结束的时候,老板从中挑出最高和最低的两份,并奖励高业绩的人数目为业绩之差的奖金。问老板要给出多少奖金。

  思路:

①两个优先队列。注意一个优先队列的元素可能在另一个优先队列里已经pop。

 1 #include<iostream>
 2 #include<queue>
 3 #include<functional>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn = 1000100;
 7 int numq1[maxn];
 8 int numq2[maxn];
 9 int main()
10 {
11     int n;
12     while (~scanf("%d", &n))
13     {
14         if (n == 0) break;
15         priority_queue<int, vector<int>, greater<int> >q1;
16         priority_queue<int, vector<int>, less<int> >q2;
17         memset(numq1, 0, sizeof(numq1));
18         memset(numq2, 0, sizeof(numq2));
19 
20         long long sum = 0;
21         for (int i = 0; i < n; i++)
22         {
23             int m;
24             scanf("%d", &m);
25             for (int j = 0; j < m; j++)
26             {
27                 int v;
28                 scanf("%d", &v);
29                 q1.push(v);
30                 q2.push(v);
31             }
32             int u = q1.top(), v = q2.top();
33             while (numq2[u])
34             {//如果已经在另一个优先队列pop
35                 numq2[u]--;
36                 q1.pop();
37                 u = q1.top();
38             }
39             while (numq1[v])
40             {//如果已经在另一个优先队列pop
41                 numq1[v]--;
42                 q2.pop();
43                 v = q2.top();
44             }
45             sum += v - u;
46             q1.pop(), q2.pop();
47             numq1[u]++, numq2[v]++;
48         }
49         printf("%lld\n", sum);
50     }
51     return 0;
52 }
View Code

可重集multiset

 1 #include<iostream>
 2 #include<set>
 3 using namespace std;
 4 int main()
 5 {
 6     int n;
 7     while (~scanf("%d", &n) && n)
 8     {
 9         long long sum = 0;
10         multiset<int>mt;
11         for (int i = 0; i < n; i++)
12         {
13             int k;
14             scanf("%d", &k);
15             for (int j = 0; j < k; j++)
16             {
17                 int v;
18                 scanf("%d", &v);
19                 mt.insert(v);
20             }
21             sum += *(--mt.end()) - *(mt.begin());
22             mt.erase(mt.begin());
23             mt.erase(--mt.end());
24         }
25         printf("%lld\n", sum);
26     }
27     return 0;
28 }
View Code

 

转载于:https://www.cnblogs.com/ivan-count/p/7427508.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值