zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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。

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

  • 相关阅读:
    使用zinnia制作android手写输入功能(上)编译zinnia
    Raphael实例
    正则表达式 笔记
    已知弧长和弦长求半径
    Raphael参考 翻译完毕
    在chorme中查找多余的css规则
    CSS3中Transform
    手机移动端WEB资源整合
    JS判断移动设备最佳方法 并实现跳转至手机版网页
    让IE和Firefox兼容的CSS技巧集合css hack
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12322723.html
Copyright © 2011-2022 走看看