Codeforces Round #377 (Div. 2)

Posted kisekipurin2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #377 (Div. 2)相关的知识,希望对你有一定的参考价值。

题目链接:https://codeforces.com/contest/732

A - Buy a Shovel

题意:有无穷枚10元硬币和1枚r元硬币,且r是[1,9]。每个物品的单价是x元,求最少买多少件不用找钱。

题解:记得区分用r元和不用r元两种情况,分别对应模10的余数为r或者为0。现在枚举不超过10个就可以出结果。

B - Cormen --- The Best Friend Of a Man

题意:宠物狗每连续两天都需要总共走至少k步,注意对于[0,1]和[n,n+1]没有这个要求。给出一个数列表示第几天走几步,增加最少的步使得[1,2],[2,3]...[n-1,n]都满足每连续两天都需要总共走至少k步。

题解:贪心往右边的一天放。注意最后一天。

C - Sanatorium

题意:某人在食堂待了连续的一段时间,而每一天都依次吃早餐b、晚餐d、宵夜s,而他有可能会漏掉其中的一些餐。已知三种餐吃的次数,求最少漏了多少餐。

题解:可以分多种情况讨论,得到一个贪心:

假设他是从b开始吃,最后一餐吃b,则b会比另外两种多1。

假设他是从b开始吃,最后一餐吃d,则b和d会比s多1。

假设……

最后会发现一个规律,要把最少的两种都配到最多比最多的一种少1,而和他们的顺序无关(三种是完全对称的)。

*D - Exams

挺有意思的一道题。

题意:一段连续的日子,每个日子可能会有恰好一门课的Exam,或者没有任何Exam。问这段日子是否可以成功通过所有课的考试。注意每门课可能有多次Exam,只需要选一门完成。要是不参加当天的考试,则可以用来复习。第j门课在考试前需要aj天复习,问最短的通过所有考试的时间,或说明无解。

题解:一开始还在想怎么用堆(延迟决策贪心)来贪心,但是显然有个二分的算法,二分天数x,则每门课肯定选x及其之前的最后一次考试来考,这个可以O(n)得到,然后必定是贪心,到了选择的一门课的时候就要尽可能分配已有的复习资源给它,不够分配则GG。

int n, m;
int d[100005];
int a[100005];

pii lst[100005];

bool check(int len) {
    for(int i = 1; i <= m; ++i)
        lst[i] = {0, a[i]};
    for(int i = 1; i <= len; ++i)
        lst[d[i]].first = i;
    for(int i = 1; i <= m; ++i) {
        if(lst[i].first == 0)
            return 0;
    }
    sort(lst + 1, lst + 1 + m);
    int cnt0 = lst[1].first - 1;
    for(int i = 1; i <= m; ++i) {
        if(cnt0 < lst[i].second)
            return 0;
        else {
            if(i == m)
                return 1;
            cnt0 -= lst[i].second;
            cnt0 += (lst[i + 1].first - lst[i].first - 1);
        }
    }
    return 0;
}

int LB;
int bs() {
    int L = LB, R = n;
    while(1) {
        int M = (L + R) >> 1;
        if(L == M) {
            if(check(L))
                return L;
            if(check(R))
                return R;
            return -1;
        }
        if(check(M))
            R = M;
        else
            L = M + 1;
    }
}

bool vis[100005];

void test_case() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &d[i]);
    int cnt = 0;
    LB = -1;
    for(int i = 1; i <= n; ++i) {
        if(!vis[d[i]]) {
            vis[d[i]] = 1;
            ++cnt;
            if(cnt == m) {
                LB = i;
                break;
            }
        }
    }
    if(LB == -1) {
        puts("-1");
        return;
    }
    for(int i = 1; i <= m; ++i)
        scanf("%d", &a[i]);
    printf("%d
", bs());
}

以上是关于Codeforces Round #377 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #377 (Div. 2)F - Tourist Reform

Codeforces Round #377 (Div. 2) B. Cormen — The Best Friend Of a Man(贪心)

Codeforces Round #222 (Div. 1) (ABCDE)

Codeforces Round #436 E. Fire(背包dp+输出路径)

[ACM]Codeforces Round #534 (Div. 2)

codeforces - 377A 题解