2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)

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

B - The Feast and the Bus

题意:有n个人,每个人分别属于某个队伍,共有k个队伍。要租车,要求至多两个队伍坐同一次车,不能有多于三个队伍在同一次车上。同一个队伍的人不能分开。设车的容量为s,要开的次数为r,花费为s*r,求最小的花费。

题解:想了一个n+k^2的题解?统计好每个人的队伍的siz之后按照siz排序,显然要两个队伍坐同一次车的,是siz最小的连续一段的偶数个队伍。因为换个siz大的队伍进来只会徒增车的容量。且这些拼车的队伍肯定是首尾拼接。看了下复杂度刚好够。

int n, k;
int siz[8005];

void test_case() {
    scanf("%d%d", &n, &k);
    while(n--) {
        int x;
        scanf("%d", &x);
        ++siz[x];
    }
    sort(siz + 1, siz + 1 + k);
    ll ans = 1ll * siz[k] * k;
    for(int i = 2; i <= k; i += 2) {
        int maxsiz = siz[k];
        for(int j = 1; j <= i / 2; ++j)
            maxsiz = max(maxsiz, siz[j] + siz[i + 1 - j]);
        ans = min(ans, 1ll * maxsiz * (i / 2 + k - i));
    }
    printf("%lld\n", ans);
}

收获:为什么最小的一定是首尾拼接呢?可以从1+4=2+3看出一点端倪。设a1<=a2<=a3<=a4,且a2=a1+d2,a3=a1+d3,a4=a1+d4则max(a1+a4,a2+a3)=
max(2a1+d4,2a1+d2+d3)=2a1+max(d4,d2+d3)。其他的几种组合:max(d3,d2+d4)显然d2+d4>=d2+d3且d2+d4>=d4。max(d2,d3+d4)同理。

J - The Parade

题意:有n种数字,第i种数字有ci个。要求分为恰好k行,每行的数字的个数相等,且同一行的数字两两之间的差不超过1。求最多选出多少个数字。

题解:很显然是满足单调性的(能选出多的数字,就全部砍掉一部分,就变成少的数字)。二分答案,然后根据“同一行的数字两两之间的差不超过1”来check。

int n;
ll k;
ll cnt[30005], sum;

bool check(ll x) {
    if(x == 0)
        return true;
    ll pre = 0, r = 0;
    for(int i = 1; i <= n; ++i) {
        ll cur = pre + cnt[i];
        if(cur >= x) {
            r += cur / x;
            pre = cur % x;
        } else
            pre = cnt[i];
    }
    return r >= k;
}

ll bs() {
    ll L = 0, R = sum / k;
    while(1) {
        ll M = (L + R) / 2;
        if(L == M) {
            if(check(R))
                return R * k;
            else
                return L * k;
        }
        if(check(M))
            L = M;
        else
            R = M - 1;
    }
}

void test_case() {
    scanf("%d%lld", &n, &k);
    sum = 0;
    for(int i = 1; i <= n; ++i) {
        scanf("%lld", &cnt[i]);
        sum += cnt[i];
    }
    printf("%lld\n", bs());
}

反思:除以一个可以为零的数之前都要先特判。或者当初定二分的上下界都要定为正数。然后不存在的时候就输出0。

K - Addition Robot

题意:维护一个数据结构。这个数据结构本身存有一个01串。操作1:[L,R],把[L,R]中的串翻转。操作2:(L,R,A,B):遍历[L,R]中的串,遇到一个0,执行:A=A+B,遇到一个1,执行B=B+A。输出每次操作2后的A和B。

题解:看起来就很线段树。

posted @ 2020-02-17 17:33  KisekiPurin2019  阅读(409)  评论(0编辑  收藏  举报