Educational Codeforces Round 93 (Rated for Div. 2) A、B、C、D题解

1398 A. Bad Triangle

题意:给一个数组有n个数,问是否能找出三个数,使得以三个数为边长的边无法构成一个三角形。

思路:因为题目输入已经是有序的,所以直接用最小的两个和最大的数进行判断即可。只要v[0]+v[1]<=v[n-1]就存在。

/**
 * Created by jiangxiaoju on 2020/8/14 22:31.
 */
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp(a, b) make_pair(a, b)
#define mid ((l + r) >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
 
typedef long long ll;
typedef pair<ll, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<double, double> pdd;
typedef pair<double, int> pdi;
typedef pair<ll, double> pld;
typedef pair<double, ll> pdl;
typedef pair<ll, ll> pll;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
 
template<class T>
bool isPrime(T x) {
    if (x <= 1)
        return false;
    if (x == 2)
        return true;
    if (x % 2 == 0)
        return false;
    T m = sqrt(x);
    for (T i = 3; i <= m; i += 2) {
        if (x % i == 0)
            return false;
    }
    return true;
}
 
template<class T>
T gcd(T m, T n) { return m % n == 0 ? n : gcd(n, m % n); }
 
 
ll qpow(ll x, ll y) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x;
        x = x * x;
        y >>= 1;
    }
    return res;
}
 
template<class T>
ll qpow(ll x, ll y, T mod) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return res;
}
 
int main() {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<long long> v(n);
        for (auto &val:v) {
            cin >> val;
        }
        int i;
        int flag = 1;
        if (v[0] + v[1] <= v[n - 1]) {
            cout << 1 << ' ' << 2 << ' ' << n << endl;
            flag = 0;
        }
        if (flag)cout << -1 << endl;
    }
    return 0;
}

1398 B. Substring Removal Game

题意:有一个只包含0和1的字符串,Alice和Bob轮流对字符串进行删除操作。每次可以删除至少一个相同连续的字符。他们最后的得分是删除字符1的次数。问Alice最后最多可以得多少分。(玩家都是采取最有操作)

思路:既然要尽可能的多删除1,那么每次删除的时候肯定是优先选择连续的1进行删除。所以只要记录每段连续1的长度,然后排个序,进行累加即可。

/**
 * Created by jiangxiaoju on 2020/8/14 22:31.
 */
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp(a, b) make_pair(a, b)
#define mid ((l + r) >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
 
typedef long long ll;
typedef pair<ll, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<double, double> pdd;
typedef pair<double, int> pdi;
typedef pair<ll, double> pld;
typedef pair<double, ll> pdl;
typedef pair<ll, ll> pll;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
 
template<class T>
bool isPrime(T x) {
    if (x <= 1)
        return false;
    if (x == 2)
        return true;
    if (x % 2 == 0)
        return false;
    T m = sqrt(x);
    for (T i = 3; i <= m; i += 2) {
        if (x % i == 0)
            return false;
    }
    return true;
}
 
template<class T>
T gcd(T m, T n) { return m % n == 0 ? n : gcd(n, m % n); }
 
 
ll qpow(ll x, ll y) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x;
        x = x * x;
        y >>= 1;
    }
    return res;
}
 
template<class T>
ll qpow(ll x, ll y, T mod) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return res;
}
 
int main() {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        string str;
        cin >> str;
        int ans1 = 0;
        int ans2 = 0;
        vector<int> v;
        int i;
        int cnt = 1;
        for (i = 0; i < str.size(); i++) {
            if (str[i] == '1') {
                cnt = 0;
                while (i < str.size() && str[i] == '1') {
                    i++;
                    cnt++;
                }
                v.push_back(cnt);
            }
        }
        sort(v.begin(),v.end(),greater<int>());
        for(i=0;i<v.size();i+=2){
            ans1+=v[i];
        }
        cout << ans1 << endl;
    }
    return 0;
}

1398 C. Good Subarrays

题意:有一个数组,数组中每个元素只包含0-9这10中数字。问有多少个子数组满足子数组和等于该子数组长度。

思路:对数组中每个元素都-1。这样就可以把求子数组和等于该子数组长度转换成 有多少个子数组和为0。根据前缀和的性值 如果 sum[i]==sum[j] (i>j)的话,那么[j+1,i]这个区间中的和肯定是为0的。任意两个相等的前缀和之间都可以有一个区间和为0。所以假设前缀和为A的共有B个。那么区间和为0的个数为(B-1)*B/2。

/**
 * Created by jiangxiaoju on 2020/8/14 22:57.
 */
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp(a, b) make_pair(a, b)
#define mid ((l + r) >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
 
typedef long long ll;
typedef pair<ll, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<double, double> pdd;
typedef pair<double, int> pdi;
typedef pair<ll, double> pld;
typedef pair<double, ll> pdl;
typedef pair<ll, ll> pll;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
 
template<class T>
bool isPrime(T x) {
    if (x <= 1)
        return false;
    if (x == 2)
        return true;
    if (x % 2 == 0)
        return false;
    T m = sqrt(x);
    for (T i = 3; i <= m; i += 2) {
        if (x % i == 0)
            return false;
    }
    return true;
}
 
template<class T>
T gcd(T m, T n) { return m % n == 0 ? n : gcd(n, m % n); }
 
 
ll qpow(ll x, ll y) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x;
        x = x * x;
        y >>= 1;
    }
    return res;
}
 
template<class T>
ll qpow(ll x, ll y, T mod) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return res;
}
 
int main() {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        vector<int> v(n + 10);
        int i;
        string str;
        cin >> str;
 
        vector<int> sum(n + 1);
        for (i = 1; i <= n; i++) {
            sum[i] = sum[i - 1] + str[i - 1] - '0' - 1;
        }
        int j;
        int cnt = 0;
        map<ll, ll> mmid;
        mmid[0] = 1;
        ll ans = 0;
        for (i = 1; i <= n; i++) {
            mmid[sum[i]]++;
        }
        for (auto[a, b]:mmid) {
            ans+=(b*(b-1)/2);
        }
        cout << ans << endl;
 
    }
    return 0;
}

1398 D. Colored Rectangles

题意:有多组R,B,G三种颜色的彩色棍。R对红色棍,第一对的长度为r1,第二对的长度为r2,…,第R对的长度为rR;G对绿色棍,第一对的长度为g1,第二对的长度为g2,…,第G对的长度为gG;B对蓝色棍,第一对长度为b1,第二对长度为b2,…,第二对长度为bB; 每次可以拿两对不同颜色的棍子组成一个矩形。每对棍子只能使用一次。问最后组成的所有矩形面积和是多少。

思路:看到这题一开始想到的是贪心。对每中颜色的棍子按长度排个序。然后每次取长度最大的不同颜色棍子进行组合,结果见代码中附带的测试数据,第一个就过不去了。所以这题很像是DP。最后用记忆化搜索莽了一发。

先对每种颜色的棍子按从小到大的顺序排个序。

定义一个dp[220][220][220],dp[r][g][b]表示每种棍子分别剩下r,g,b队时的最优解。只要棍子数量不为0。就从三种组合里面取一个最后的。r和g,r和b,b和g。

/**
 * Created by jiangxiaoju on 2020/8/14 22:57.
 */
#include <bits/stdc++.h>
 
using namespace std;
 
#define mp(a, b) make_pair(a, b)
#define mid ((l + r) >> 1)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
 
typedef long long ll;
typedef pair<ll, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<double, double> pdd;
typedef pair<double, int> pdi;
typedef pair<ll, double> pld;
typedef pair<double, ll> pdl;
typedef pair<ll, ll> pll;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
 
template<class T>
bool isPrime(T x) {
    if (x <= 1)
        return false;
    if (x == 2)
        return true;
    if (x % 2 == 0)
        return false;
    T m = sqrt(x);
    for (T i = 3; i <= m; i += 2) {
        if (x % i == 0)
            return false;
    }
    return true;
}
 
template<class T>
T gcd(T m, T n) { return m % n == 0 ? n : gcd(n, m % n); }
 
 
ll qpow(ll x, ll y) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x;
        x = x * x;
        y >>= 1;
    }
    return res;
}
 
template<class T>
ll qpow(ll x, ll y, T mod) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return res;
}
 
struct cmp {
    bool operator()(const vector<int> &v1, const vector<int> &v2) {
        if (v1.size() != v2.size())return v1.size() < v2.size();
        else {
            return v1[v1.size() - 1] < v2[v2.size() - 1];
        }
    }
};
 
ll dp[220][220][220];
 
vector<int> G, R, B;
 
ll dfs(int r, int g, int b) {
    if (dp[r][g][b] != -1) return dp[r][g][b];
    ll res = 0;
    if (((r == 0) + (g == 0) + (b == 0)) >= 2) {
        res = 0;
    }
    if (r && g) {
        res = max(res, dfs(r - 1, g - 1, b) + R[r - 1] * G[g - 1]);
    }
    if (b && g) {
        res = max(res, dfs(r, g - 1, b - 1) + B[b - 1] * G[g - 1]);
    }
    if (r && b) {
        res = max(res, dfs(r - 1, g, b - 1) + R[r - 1] * B[b - 1]);
    }
    return dp[r][g][b] = res;
}
 
int main() {
    ios::sync_with_stdio(false);
    memset(dp, -1, sizeof(dp));
    int r, g, b;
    cin >> r >> g >> b;
    R.resize(r);
    G.resize(g);
    B.resize(b);
    for (auto &val:R) {
        cin >> val;
    }
    for (auto &val:G) {
        cin >> val;
    }
    for (auto &val:B) {
        cin >> val;
    }
    sort(R.begin(), R.end());
    sort(G.begin(), G.end());
    sort(B.begin(), B.end());
 
    cout << dfs(r, g, b) << endl;
 
    return 0;
}
 
/**
 * 2 1 1
 * 5 5
 * 8
 * 9
 *
 *
 * 3 1 1
 * 1 1 1
 * 100
 * 100
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiangxiaoju

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值