Educational Codeforces Round 93 (Rated for Div. 2)

传送门

A. Bad Triangle

题意:
给出一个不降的序列 \(a\), 要求判断是否能在其中找出三个下标递增且不能组成三角形的数,
能则输出三个下标,否则输出 \(-1\)

题解:
贪心思考怎样最容易凑不出三角形,选择前两个和最后一个即可,此时若凑出了三角形就输出 \(-1\)

Code

#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define SZ(a) (int)((a).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair <int, int> Pii;
typedef pair <ll, int> Pli;
typedef unsigned long long ull;
const double eps = 1e-8;
const int mod = (int)(1e9) + 7;
const int inf = 0x7fffffff;
const int N = (int)(5e4) + 7;
 
int _, n, a[N];
 
int main() {
 
    // freopen("in.in", "r", stdin);
    for (scanf("%d", &_); _; --_) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        if (a[1] + a[2] <= a[n]) printf("1 2 %d\n", n);
        else puts("-1");
    }
 
    return 0;
}

B. Substring Removal Game

题意:
给出一个 \(01\) 串,从 Alice 开始,和 Bob 轮流操作,
每次操作可以移除任意长度连续且元素都相等的子串,
最后得分是自己移除所有子串中 \(1\) 的个数总和,
每人都会以选择最优的策略,求 Alice 的得分。

题解:
既然都是最优策略,每人肯定都只会优先移除连续的 \(1\),
所以把连续的 \(1\) 按个数记录到数组里,从大到小排序,再从第一个开始跳着选即是 Alice 的答案。

Code

#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define SZ(a) (int)((a).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair <int, int> Pii;
typedef pair <ll, int> Pli;
typedef unsigned long long ull;
const double eps = 1e-8;
const int mod = (int)(1e9) + 7;
const int inf = 0x7fffffff;
const int N = (int)(2e5) + 7;
 
int _, n;
char s[N];
int one[N], cnt;
 
int main() {
 
    // freopen("in.in", "r", stdin);
    for (scanf("%d", &_); _; --_) {
        cnt = 0;
        scanf("%s", s + 1);
        n = strlen(s + 1);
        for (int i = 1; i <= n; ++i) {
            if (s[i] == '1') {
                if (s[i - 1] != '1') one[++cnt] = 1;
                else ++one[cnt];
            }
        }   
        sort(one + 1, one + 1 + cnt, greater<int>());
        int res = 0;
        for (int i = 1; i <= cnt; i += 2) res += one[i];
        printf("%d\n", res);
    }
 
    return 0;
}

C. Good Subarrays

题意:
给出一个由 \([0, 9]\) 的数字构成的数字串 \(a\),给出好子串的定义:

  • 对于连续子串 \(a_l, a_{l + 1} \dots a_{r - 1}, a_r\),
    满足 \(\sum_{i = l}^r a_i = r - l + 1\)

求该序列中有多少好串。

题解:
对于这种可以整体扫一遍的区间计数问题,

一种常见的分类就是首先外层的 \(O(n)\) 枚举 \(i\), 再 \(O(1) 或 O(nlogn)\) 计算出以 \(i\) 为有端点的指定区间个数。

我的思路是首先求一遍前缀和 \(pre\), 将题意转化为求满足 \(1 \leq l < r \leq n\)\(pre_r - pre_{l - 1} = r - l + 1\)\((l, r)\) 对数。

将上式移项得 \(pre_r - r = pre_{l - 1} - (l - 1)\), \(1 \leq l < r \leq n\)

\(pre_r - r = pre_l - l\), \(0 \leq l < r \leq n\)

此时可令 \(pre_i = pre_i - i, 1 \leq i \leq n\),最后在遍历统计时用 map 记录前 \(i - 1\) 个元素中与第 \(i\) 相等的个数即可。

Code

#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define SZ(a) (int)((a).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair <int, int> Pii;
typedef pair <ll, int> Pli;
typedef unsigned long long ull;
const double eps = 1e-8;
const int mod = (int)(1e9) + 7;
const int inf = 0x7fffffff;
const int N = (int)(2e5) + 7;
 
char s[N];
int _, n, a[N], pre[N];
map <int, ll> pm;
 
int main() {
 
    // freopen("in.in", "r", stdin);
    for (scanf("%d", &_); _; --_) {
        pm.clear();
        scanf("%d%s", &n, s + 1);
        for (int i = 1; i <= n; ++i) a[i] = (s[i] ^ 48);
        for (int i = 1; i <= n; ++i) pre[i] = pre[i - 1] + a[i];            
        for (int i = 1; i <= n; ++i) pre[i] -= i;
        // for (int i = 1; i <= n; ++i) printf("%d%c", pre[i], " \n"[i == n]);
        ll res = 0;
        pm[0] = 1;
        for (int i = 1; i <= n; ++i) {
            res += pm[pre[i]];
            ++pm[pre[i]];
        }
        printf("%lld\n", res);
    }
 
    return 0;
}

你可能感兴趣的:(Educational Codeforces Round 93 (Rated for Div. 2))