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

    前言

    只做了 A、B、C 三题。= =,D 的 dp 没写出来,贪了好久。

    比赛链接

    A. Bad Triangle

    题目大意

    在给定 (n) 个数里选择出三个数,使得其不能组成三角形

    分析

    三角形的组成条件为任意两边和大于第三边。不妨把 (n) 个数按照升序排列(题目默认升序),然后取前面最小的两个为两个边,计算它们的和。再从第三个开始找,找到大于等于和的边就是答案。找不到就输出 (-1)

    代码

    #include <bits/stdc++.h>
    #define lowbit(x) ((x)&(-x))
    #define mem(i, a) memset(i, a, sizeof(i))
    #define sqr(x) ((x)*(x))
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    typedef long long ll;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e5 + 7;
    using namespace std;
    int arr[maxn];
    int main(void){
    #ifdef ljxtt
    freopen("data.in", "r", stdin);
    #endif
        int T; scanf("%d", &T);
        while(T--){
            int n; scanf("%d", &n);
            for(int i = 0; i < n; i++) scanf("%d", &arr[i]);
            int sum = arr[0] + arr[1];
            int inx = -1;
            for(int i = 2; i < n; i++){
                if(arr[i] >= sum){
                    inx = i;
                    break;
                }
            }
            if(inx == -1)
                puts("-1");
            else
                printf("1 2 %d
    ", inx + 1);
        }
        return 0;
    }
    

    B. Substring Removal Game

    题目大意

    A 和 B两个人玩游戏,A先行。

    游戏规则为:给一段 01 串,每次操作都可以将一段连续相同的字符去掉,所得到的分数为去掉1的个数。当字符串为空时停止游戏。

    A、B两人都按照对自己最优的策略走,问A能得到的最大的分数是多少。

    分析

    显然,去掉一段相同的 0 并没有什么卵用。所以,贪心地取连续最长的 1 即可。

    代码

    #include <bits/stdc++.h>
    #define lowbit(x) ((x)&(-x))
    #define mem(i, a) memset(i, a, sizeof(i))
    #define sqr(x) ((x)*(x))
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    typedef long long ll;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e5 + 7;
    using namespace std;
    char s[maxn];
    vector<int> arr;
    int main(void){
    #ifdef ljxtt
    freopen("data.in", "r", stdin);
    #endif
        int T; scanf("%d", &T);
        while(T--){
            scanf("%s", s);
            int len = strlen(s), cnt = 0;
            for(int i = 0; i < len; i++){
                if(s[i] == '1'){
                    cnt++;
                }else{
                    if(cnt != 0) arr.push_back(cnt);
                    cnt = 0;
                }
            }
            if(cnt != 0) arr.push_back(cnt);
            sort(arr.begin(), arr.end(), greater<int> ());
            int ans = 0;
            for(int i = 0; i < arr.size(); i += 2) ans += arr[i];
            printf("%d
    ", ans);
            arr.clear();
        }
        return 0;
    }
    

    C. Good Subarrays

    题目大意

    给定一个序列,询问有多少个区间满足:

    [sum_{i = l}^{r}a_i = r - l + 1 ]

    分析

    用前缀和表示上式为:

    [egin{aligned} S(r) - S(l - 1) &= r - l + 1 \ S(r) - r &= S(l - 1) - (l - 1)\ f(r) &= f(l - 1) end{aligned} ]

    其中 (f(x) = S(x) - x),且 (f(0) = 0)

    所以,也就是在所有的 (f(x)) 里任意取出两个相同的数字,询问方案数。

    统计一下相同数字的个数,用组合数算一下 (C_n^2) 就行了。

    代码

    #include <bits/stdc++.h>
    #define lowbit(x) ((x)&(-x))
    #define mem(i, a) memset(i, a, sizeof(i))
    #define sqr(x) ((x)*(x))
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    typedef long long ll;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e5 + 7;
    using namespace std;
    ll arr[maxn];
    map<ll, int> ma;
    int main(void){
    #ifdef ljxtt
    freopen("data.in", "r", stdin);
    #endif
        int T; scanf("%d", &T);
        while(T--){
            int n; scanf("%d", &n);
            for(int i = 1; i <= n; i++) scanf("%1lld", &arr[i]);
            for(int i = 1; i <= n; i++) arr[i] += arr[i - 1];
            for(int i = 1; i <= n; i++) arr[i] -= i;
            for(int i = 0; i <= n; i++) ma[arr[i]]++;
            ll ans = 0;
            for(auto it: ma){
                if(it.second > 1) ans += 1ll * it.second * (it.second - 1) / 2; 
            }
            printf("%lld
    ", ans);
            ma.clear();
        }
        return 0;
    }
    

    D. Colored Rectangles

    题目大意

    给定 R、G、B对的红色、绿色、蓝色的木棒,对应颜色的第 i 对的长度为 ri,gi,bi。你可以进行如下操作:

    在两种不同的颜色里各选出一对,使得它们组成一个长方形,并将矩形的面积加入到答案里。

    题目要求使得最后的答案最大。

    分析

    这种题目要么贪心,要么dp。

    很显然有个贪心的想法,就是把三种木棒混合在一起,按长度排序。然后从大到小枚举木棍,再在剩下的木棍里选出颜色不同但最大的木棍组成矩形,加入到答案里。枚举一遍就是答案。但这样有一个问题就是下面这样一个样例:

    1 1 2
    1
    1
    1 1
    

    上面这个样例就有可能使得 R 和 G 配对,然后剩下的两个 B 没办法配对。最优的答案是 R 和 B 配对,G 和 B 配对。所以上面这个贪心不成立。

    所以我们考虑一下dp。先把三种不同的木棍按长度降序排列,定义 (dp[i][j][k]) 为 R、G、B分别用了 i,j,k 个木棍所取得的最大答案,那么就有转移方程为:

    [egin{array} \ dp[i][j][k] = max(&dp[i - 1][j - 1][k] + R[i] imes G[i], \ &dp[i - 1][j][k - 1] + R[i] imes B[i], \&dp[i][j - 1][k - 1] + G[i] imes B[i]) end{array} ]

    初值为 (dp[0][0][0] = 0)

    代码

    #include <bits/stdc++.h>
    #define lowbit(x) ((x)&(-x))
    #define mem(i, a) memset(i, a, sizeof(i))
    #define sqr(x) ((x)*(x))
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    typedef long long ll;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 2e2 + 7;
    using namespace std;
    ll dp[maxn][maxn][maxn];
    int arr[3][maxn];
    int main(void){
    #ifdef ljxtt
    freopen("data.in", "r", stdin);
    #endif
        int num[3]; for(int i = 0; i < 3; i++) scanf("%d", &num[i]);
        for(int i = 0; i < 3; i++){
            for(int j = 0; j < num[i]; j++)
                scanf("%d", &arr[i][j]);
            sort(arr[i], arr[i] + num[i], greater<int> ());
        }
        ll ans = 0;
        for(int i = 0; i <= num[0]; i++)
            for(int j = 0; j <= num[1]; j++)
                for(int k = 0; k <= num[2]; k++){
                    dp[i + 1][j + 1][k] = max(dp[i + 1][j + 1][k], dp[i][j][k] + 1ll * arr[0][i] * arr[1][j]);
                    dp[i + 1][j][k + 1] = max(dp[i + 1][j][k + 1], dp[i][j][k] + 1ll * arr[0][i] * arr[2][k]);
                    dp[i][j + 1][k + 1] = max(dp[i][j + 1][k + 1], dp[i][j][k] + 1ll * arr[1][j] * arr[2][k]);
                    ans = max(ans, dp[i][j][k]);
                }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    基于vue2.0 +vuex+ element-ui后台管理系统:包括本地开发调试详细步骤
    require.js实现js模块化编程(二):RequireJS Optimizer
    require.js实现js模块化编程(一)
    树型权限管理插件:jQuery Tree Multiselect详细使用指南
    表格组件神器:bootstrap table详细使用指南
    后台管理系统中的重点知识大全
    Ajax最详细的参数解析和场景应用
    npm常用命令小结
    详解javascript,ES5标准中新增的几种高效Object操作方法
    git入门学习(二):新建分支/上传代码/删除分支
  • 原文地址:https://www.cnblogs.com/ljxtt/p/13508269.html
Copyright © 2011-2022 走看看