zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 93 (Rated for Div. 2)

    比赛链接

    A. Bad Triangle

    题意:

    给一组非降序列(a),问这组序列是否存在三个数使得这三个数无法构成三角形。

    思路:

    因为序列是排好序的,根据三角形任意两边之和大于第三边,判断第(1,2,n)条边能否构成三角形就好了。

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define INF 1000000005
    typedef long long ll;
    
    const int maxn = 50005;
    using namespace std;
    
    int a[maxn], T, n;
    
    int main() {
        scanf("%d", &T);
        while (T--) {
            scanf("%d", &n);
            for (int i = 0; i < n; i++)
                scanf("%d", a + i);
            if (a[0] + a[1] <= a[n - 1]) {
                printf("1 2 %d
    ", n);
            }
            else if (a[n - 1] - a[0] >= a[1]) {
                printf("1 2 %d
    ", n);
            }
            else {
                printf("-1
    ");
            }
        }
        return 0;
    }
    

    B. Substring Removal Game

    题意:

    给定一组(01)串,每次可以选择一段连续的(0)串或者(1)串。(Alice)(Bob)在进行这场游戏,(Alice)先手。每个人都有分数,分数等于这个人选过所有数字的和。(Alice)(Bob)都希望自己的分数尽可能高。问(Alice)的分数最高是多少?

    思路:

    两个玩家每次都一定选择最长的一串(1)。因为如果有一个玩家选择了一串(0),那么另一个玩家就能一次选择更多的(1),犯不着给对手方便。如果一个玩家一次只选择一串(1)的一段,那么这一段剩下的(1)就有可能在将来归对手所有,不如一次直接全选。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <queue>
    
    const int maxn = 128;
    
    using namespace std;
    
    char s[maxn];
    int n, T, cur, cnt, ans;
    priority_queue<int> q;
    
    inline void init() {
        cur = 0;
        ans = 0;
        cnt = 0;
        while (!q.empty()) q.pop();
    }
    
    int main() {
        scanf("%d", &T);
        while (T--) {
            init();
            scanf("%s", s);
            n = strlen(s);
    
            while (cur < n) {
                while (s[cur] == '0' && cur < n) cur++;
                cnt = 0;
                while (s[cur] == '1' && cur < n) {
                    cnt++;
                    cur++;
                }
                q.push(cnt);
            }
    
            bool flag = false;
            while (!q.empty()) {
                int u = q.top();
                q.pop();
    
                if (!flag)
                    ans += u;
                flag = !flag;
            }
    
            printf("%d
    ", ans);
        }
        return 0;
    }
    

    C. Good Subarrays

    比赛的时候没想出来,所以是补题的时候补的。(其实比赛的时候想得差不多了QAQ,没特别考虑(sum_i - i = 0)的情况,所以代码不对QAQ)

    题意:

    给定(n)和一串(n)个数字,如果存在一段连续的(sumlimits_{i=l}^{r}a_i=r - l + 1),那么我们称这一段子串为good subarray。问一共有多少good subarrays。

    思路:

    先做一遍前缀和,得到所有的(sum_i)。这样,我们要求的就变成了(sum_r - sum_{l - 1} = r - l + 1)

    移项,得(sum_r - r = sum_{l-1} - (l - 1))

    所以,我们求出所有的(sum_i - i),然后(ans = ans + num_{sum_i - i}, num_{sum_i - i} = num_{sum_i - i} + 1)

    其中,(num_{sum_i - i})是之前(sum_i - i)出现的次数。

    这里要特别注意一下(sum_i - i = 0)的情况,是因为,(sum_i - i = 0)第一次出现的时候,从(1)(i)求和本身就是一个good subarray。所以要把(num_0)初始化为(1)

    代码:

    代码中的(sum)是直接利用(a)数组存的。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    typedef long long ll;
    
    using namespace std;
    const int maxn = 100005;
    
    int T, n;
    ll a[maxn];
    ll ans = 0;
    map<ll, ll> p;
    
    inline void read(ll *a) {
        int len = 0;
        char ch = getchar();
        while (ch < '0' || ch > '9') ch = getchar();
        while (ch >= '0' && ch <= '9') {
            a[++len] = ch - '0';
            a[len] += a[len - 1];
            ans += p[a[len] - len];
            p[a[len] - len]++;
            ch = getchar();
        }
    }
    
    inline void init() {
        p.clear();
        a[0] = 0;
        ans = 0;
    }
    
    int main() {
        scanf("%d", &T);
        while (T--) {
            init();
            scanf("%d", &n);
            p[0] = 1;
            read(a);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    D. Colored Rectangles

    题意:

    你有(RGB)三种颜色的木棍。告诉你每种颜色的木棍有几。问你用这些木棍凑出来所有矩形面积之和最大是多少。凑矩形必须满足如下条件:

    1. 对边颜色相同
    2. 邻边颜色不同
    3. 一条边只能用一根木棍

    思路:

    用木棍凑面积我们很容易想到一种贪心策略,就是每次取最长的两组木棍凑成矩形。所以我们对每一组木棍长度由大到小排序后跑DP。用(f_{i,j,k})表示使用了(i)根红木棍,(j)根绿木棍,(k)根蓝木棍凑出来所有矩形的最大面积之和。那么,我们有如下状态转移方程:

    [f_{i,j,k} = operatorname{max}(f_{i-1,j-1,k} + R_i imes G_j, f_{i - 1, j, k - 1} + R_i imes B_k, f_{i, j - 1, k - 1} + G_j imes B_k) ]

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <map>
    #include <queue>
    typedef long long ll;
    
    using namespace std;
    
    ll color[3], f[205][205][205];
    ll q[3][205];
    
    bool cmp(const ll &a, const ll &b) {
        return a > b;
    }
    
    int main() {
        for (int i = 0; i < 3; i++)
            scanf("%lld", color + i);
        for (int i = 0; i < 3; i++) {
            for (int j = 1; j <= color[i]; j++) {
                scanf("%lld", &q[i][j]);
            }
        }
    
        for (int i = 0; i < 3; i++)
            sort(q[i] + 1, q[i] + color[i] + 1, cmp);
            
        ll ans = 0;
        for (int i = 0; i <= color[0]; i++) {
            for (int j = 0; j <= color[1]; j++) {
                for (int k = 0; k <= color[2]; k++) {
                    if ((i + j + k) & 1) continue;
                    if (!(i + j + k)) continue;
                    if (i >= 1 && j >= 1) f[i][j][k] = max(f[i][j][k], f[i - 1][j - 1][k] + q[0][i] * q[1][j]);
                    if (i >= 1 && k >= 1) f[i][j][k] = max(f[i][j][k], f[i - 1][j][k - 1] + q[0][i] * q[2][k]);
                    if (j >= 1 && k >= 1) f[i][j][k] = max(f[i][j][k], f[i][j - 1][k - 1] + q[1][j] * q[2][k]);
    
                    ans = max(ans, f[i][j][k]);
                }
            }
        }
    
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    Qt串口的使用记录
    CImage灰度化
    (记录)MSYS2+MINGW32编译ffmpeg过程
    Blas 基本函数功能
    blas中dgemm_的用法
    选择、插入、冒泡排序
    简单的页面
    中国大学排名
    爬bing 主页
    读书报告
  • 原文地址:https://www.cnblogs.com/icysky/p/13508035.html
Copyright © 2011-2022 走看看