145. 超市 AcWing

原题链接

考察:并查集+贪心或堆排序+贪心

因为最近在做并查集专题所以直接考虑用并查集写,但是看题目完全没有想到用并查集的方式,以前写的并查集题目关系的传递性都很明显,但是这道题本蒟蒻完全没看出来

思路:

       用并查集维护天数,贪心策略是能多晚卖出就多晚卖出,起初每个天数都在它自己的集合里,当我们决定要卖出此商品时(设过期天数为d),那么第d个位置就被占用了,我们需要让d这个位置指向在它前面第一个空闲的位置.因为是和它前面的链接,所以直接链接d与d-1即可.当所指的位置到0,那么说明这个商品不能被卖出,利用路径压缩可以把时间复杂度压到O(1)

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 typedef pair<int,int> pii;
 5 const int N = 10010;
 6 int p[N];
 7 pii goods[N];
 8 struct cmp{//按价值排序
 9     bool operator()(pii x,pii y){
10          return x.first>y.first;
11     }
12 };
13 int find(int x)
14 {
15     if(x!=p[x]) p[x] = find(p[x]);
16     return p[x];
17 }
18 int main()
19 {
20     int t;
21     while(scanf("%d",&t)!=EOF){
22         fill(p,p+N,0); int ans = 0;
23         for(int i=1;i<=t;i++) scanf("%d%d",&goods[i].first,&goods[i].second);
24         for(int i=1;i<=N-10;i++) p[i] = i;
25         sort(goods+1,goods+t+1,cmp());
26         for(int i=1;i<=t;i++){
27             int px = find(goods[i].second);
28             if(px){
29                 ans+=goods[i].first;
30                 p[px] = find(px-1);
31             }
32         }
33         printf("%d\n",ans);
34     }
35     return 0;
36 }

 

每天在orz算法竞赛进阶指南....

2021.2.20 二刷与本题差不多的题 Doing Homework again HDU - 1789

还是不会,md醉了.

        主要是贪心策略的选择.这里不采用并查集方法.将作业按日期排序,用一个堆维护.堆大小要么比当前作业天数小,要么与天数相同.如果相同去掉价值最小的即可.

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <queue>
 6 using namespace std;
 7 const int N = 1010;
 8 typedef pair<int,int> PII;
 9 PII work[N];
10 int main()
11 {
12     int T;
13     scanf("%d",&T);
14     while(T--)
15     {
16         int n,ans = 0;
17         scanf("%d",&n);
18         priority_queue<int,vector<int>,greater<int> > q;
19         for(int i=1;i<=n;i++) scanf("%d",&work[i].first);
20         for(int i=1;i<=n;i++) scanf("%d",&work[i].second);
21         sort(work+1,work+n+1);
22         for(int i=1;i<=n;i++)
23         {
24             if(work[i].first>q.size()) q.push(work[i].second);
25             else{
26                 if(q.top()<work[i].second)
27                 {
28                     ans+=q.top();
29                     q.pop(); q.push(work[i].second);
30                 }else ans+=work[i].second; 
31             }
32         }
33         printf("%d\n",ans);
34     }
35     return 0;
36 }
堆排序

 2021.3.7 三刷 并查集的方法还是没有学会,直接连接该天的前一天,就算前一天被占用了,会找到前面没有被占的天

posted @ 2021-01-03 22:04  acmloser  阅读(76)  评论(0编辑  收藏  举报