八月流水账

本文详细解析了一道关于购买酸奶的算法题目,讨论了如何在有限的条件下最大化购买不过期酸奶的数量。通过排序和标记已购买酸奶的方法,实现了O(n)的时间复杂度。并提供了两段C++代码实现,一种是直接排序扫描,另一种是优化后的逆向统计方法。

8.8

 

8.28

Kickstart Round E 2018

特别菜QAQ

UPD 2018.8.31

A. Yogurt

有n杯酸奶,每一杯酸奶的过期日期是ai ,一天最多买k杯不过期酸奶,问从第一天开始最多能买多少杯酸奶

笔试的时候 感觉还是有点紧张 匆匆想了想 感觉好像对的就交了 一直怕大数据T ,先排序,在日期x 的时候,一定只能买 ai >= x 的,然后就暴力扫,标记被买过的酸奶,就是O(n)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;

const int maxn = 1e5 + 5;
int n,k,a[maxn],vis[maxn];


int main()
{
    freopen("A-large.txt","r",stdin);
    freopen("Abig.txt","w",stdout);
    int T;
    scanf("%d",&T);
    for (int kase = 1;kase <= T;kase++)
    {
        memset(vis,0,sizeof(vis));
        scanf("%d %d",&n,&k);
        for (int i = 1;i <= n;i++) scanf("%d",&a[i]);

        sort(a + 1,a + n + 1);
        int ans = 0;
        for (int i = 1;;i++)
        {
            int cnt = 0;
            int ok = 0;
            for (int j = 1;j <= n;j++)
            {
                if (vis[j]) continue;

                if (a[j] >= i)
                {
                    cnt++;
                    if (a[j] == i) vis[j] = 1;
                    if (cnt > k) break;
                    vis[j] = 1;
                    ans++;
                    ok = 1;
                }

               // printf("i = %d j = %d ans = %d cnt = %d\n",i,j,ans,cnt);

            }
            int flag = 0;
            if (ok == 0) break;
            for (int j = 1;j <= n;j++) flag = flag + vis[j];
            if (flag == n) break;
        }

        printf("Case #%d: %d\n",kase,ans);

    }
    return 0;
}


/*

4
2 1
1 1

10
5 1
3 2 3 2 3

10
2 2
1 1

10
6 2
1 1 1 7 7 7

*/
View Code

 

看题解发现是昂神出的题目qwq ,可以省掉一个排序,因为k >= 1 所以 当 ai >=  n 的时候 ,ai 可以看做等于 n

统计在每一天过期的酸奶,倒着扫,前一天剩下的 一定可以累加 到 今天买 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 1e6 + 5;
 8 typedef long long LL;
 9 LL a[maxn];
10 int n,k;
11 
12 int main()
13 {
14     freopen("A-large-practice.txt","r",stdin);
15     freopen("Abig.txt","w",stdout);
16     int T;
17     scanf("%d",&T);
18     for (int kase = 1;kase <= T;kase++)
19     {
20         scanf("%d %d",&n,&k);
21         for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
22 
23         sort(a + 1,a + n + 1);
24         LL ans = 0LL;
25 
26         for (int i = 1;i <= n;i++) if (a[i] >= n) a[i] = n;
27 
28         int add = 0,i = n;
29         for (int day = n;day >= 1;day--)
30         {
31             int j = i;
32             while (j >= 1 && a[j] == day) j--;
33 
34             int cnt = i - j;
35             if (cnt < k)
36             {
37                 int newadd = min(add + cnt,k);
38                 ans += newadd;
39                 add -= newadd - cnt;
40             }
41             else
42             {
43 
44                 ans += k;
45                 add += cnt - k;
46             }
47 
48             //printf("i = %d j = %d cnt = %d add = %d ans = %I64d\n",i,j,cnt,add,ans);
49 
50             i = j;
51 
52         }
53 
54         printf("Case #%d: %I64d\n",kase,ans);
55 
56     }
57     return 0;
58 }
59 
60 
61 /*
62 
63 4
64 2 1
65 1 1
66 5 1
67 3 2 3 2 3
68 2 2
69 1 1
70 
71 4
72 6 2
73 1 1 1 7 7 7
74 
75 */
View Code

 

转载于:https://www.cnblogs.com/wuyuewoniu/p/9443323.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值