Educational Codeforces Round 114 (Rated for Div. 2) 题解

Posted 人形自走Bug生成器

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 114 (Rated for Div. 2) 题解相关的知识,希望对你有一定的参考价值。

旅行传送门

A. Regular Bracket Sequences

题意:给你一个整数 \\(n\\) ,构造并打印长度为 \\(2n\\)\\(n\\) 个不同的合法括号序列。

题目分析:模拟,不妨设最初的括号序列为 \\(\\underbrace{(((}_{n} \\cdots \\underbrace{)))}_{n}\\) ,每次从中取出一对合法括号放外边即可。

AC代码

#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); i++)
#define down(i, x, y) for (register int i = (x); i >= (y); i--)

char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == \'-\')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = x * 10 + ch - \'0\';
        ch = getchar();
    }
    return x * f;
}

void solve()
{
    int n = read();
    down(k, n, 1)
    {
        rep(i, 1, k) printf("(");
        rep(i, 1, k) printf(")");
        rep(j, 1, n - k) printf("()");
        puts("");
    }
}

int main(int argc, char const *argv[])
{
    int T = read();
    while (T--)
        solve();
    return 0;
}

B. Combinatorics Homework

题意:给你四个整数值 \\(a\\)\\(b\\)\\(c\\)\\(m\\)

判断是否存在包含以下内容的字符串:

  • \\(a\\) 个字母 \\(A\\)
  • \\(b\\) 个字母 \\(B\\)
  • \\(c\\) 个字母 \\(C\\)
  • 正好含有 \\(m\\) 对相邻的相等字母(即 \\(s[i] = s[i+1]\\) )。

题目分析:不妨假设 \\(a \\leq b \\leq c\\) ,先考虑相邻相等字母的上下限:

  • 上限:\\(\\underbrace{AAA}_{a} \\cdots \\underbrace{BBBB}_{b} \\cdots \\underbrace{CCCCC}_{c}\\) ,即 \\((a-1)+(b-1)+(c-1)\\)
  • 下限:\\(\\underbrace{CACA}_{a个C} \\cdots \\underbrace{CBCBCB}_{b个C} \\cdots CCCCC\\) ,即 \\(c - (a+b) - 1\\)

可以证明,若 \\(min \\leq m \\leq max\\) ,则这样的序列一定存在。

  • \\(min +1\\)\\(\\underbrace{ACACA \\cdots CA}_{a-1个C} \\underbrace{CBCBCB}_{b个C} \\cdots CCCCC+C\\)
  • \\(min +2\\)\\(\\underbrace{CACA \\cdots CAA}_{a-1个C} \\underbrace{CBCBCB}_{b个C} \\cdots CCCCC+C\\)

\\(min\\) 的基础上每多出一对邻相等字母,就把字符串的头字母放到该字母最后一次出现的位置之后。

AC代码

#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); i++)
#define down(i, x, y) for (register int i = (x); i >= (y); i--)

char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == \'-\')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = x * 10 + ch - \'0\';
        ch = getchar();
    }
    return x * f;
}

bool solve()
{
    int a = read(), b = read(), c = read(), m = read();
    if (c < a)
        std::swap(a, c);
    if (c < b)
        std::swap(b, c);
    int mx = a + b + c - 3, mn = std::max(c - (a + b) - 1, 0);
    return (mn <= m && m <= mx) ? true : false;
}

int main(int argc, char const *argv[])
{
    int T = read();
    while (T--)
        puts(solve() ? "YES" : "NO");
    return 0;
}

C. Slay the Dragon

题意很久很久以前,巨龙突然出现

你有一支含 \\(n\\) 位勇者的小队,现在有 \\(m\\) 条恶龙,第 \\(i\\) 条的防御为 \\(x_i\\) ,攻击力为 \\(y_i\\) 。对每条龙,你可以选出一名能力值 \\(a_i \\geq x_i\\) 的勇者诛戮恶龙,其余勇者留下来防守,且防守的勇者们能力值总和 \\(sum \\geq y_i\\)

同时,你可以花费 \\(1\\)\\(cost\\) 将任意勇者的能力值提升 \\(1\\) 点,此操作可以进行任意次。

问击败第 \\(i\\) 条龙的最小花费是多少(对战每条龙时所有勇者的能力值重置)。

题目分析:采取贪心策略,找到序列中首次出现的 \\(\\geq\\)\\(\\leq x_i\\) 的值 \\(a_i\\) ,然后计算相应花费输出较小的即可。

AC代码

#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i <= (y); i++)
#define down(i, x, y) for (register int i = (x); i >= (y); i--)
using ll = long long;
using namespace std;

char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == \'-\')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = x * 10 + ch - \'0\';
        ch = getchar();
    }
    return x * f;
}

inline bool cmp(ll a, ll b) { return a > b; }

int main(int argc, char const *argv[])
{
    int n = read();
    ll sum = 0;
    vector<ll> a(n + 1), b(n + 1);
    rep(i, 1, n) sum += (a[i] = b[i] = read());
    sort(a.begin() + 1, a.begin() + n + 1);
    sort(b.begin() + 1, b.begin() + n + 1, cmp);
    int m = read();
    while (m--)
    {
        ll x = read(), y = read();
        int pos1 = lower_bound(a.begin() + 1, a.begin() + n + 1, x) - a.begin();
        int pos2 = lower_bound(b.begin() + 1, b.begin() + n + 1, x, greater<ll>()) - b.begin();
        if (pos1 > n)
            pos1 = n;
        if (pos2 > n)
            pos2 = n;
        ll ans1 = 0, ans2 = 0;
        if (x > a[pos1])
            ans1 += x - a[pos1];
        if (y > sum - a[pos1])
            ans1 += y - (sum - a[pos1]);
        if (x > b[pos2])
            ans2 += x - b[pos2];
        if (y > sum - b[pos2])
            ans2 += y - (sum - b[pos2]);
        printf("%lld\\n", min(ans1, ans2));
    }
    return 0;
}

D. The Strongest Build

题意:给你 \\(n\\) 个装备槽,每个装备槽有 \\(c\\) 件装备可以挑选,每件装备的属性值为 \\(a_{i,j}\\) ,现有 \\(m\\) 种不合法的方案数,求在此条件下使得属性值最大的组合方案。

题目分析:一开始用 \\(dfs\\) 暴搜结果 \\(MLE\\) 了。这里给出一种贪心的策略,优先用更好的装备,第 \\(i\\) 个装备槽只考虑能使方案合法的最好的第 \\(j\\) 个装备,每次从优先队列中取出当前最优方案,如果这个方案已经被 \\(ban\\) 了,就将其分成 \\(n\\) 个后继方案(一个方案的后继就是对于当前组合里的某个槽,用刚好差一档的装备换上去),但分出的后继方案可能会有重复的,因此我们选择用 \\(set\\) 去重。由于优先队列采取的是大根堆,所以这样的做法一定能得到最优解。

AC代码

#include <bits/stdc++.h>
#define rep(i, x, y) for (register int i = (x); i < (y); i++)
#define down(i, x, y) for (register int i = (x); i > (y); i--)
#define piv std::pair<int, std::vector<int>>

char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == \'-\')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        x = x * 10 + ch - \'0\';
        ch = getchar();
    }
    return x * f;
}

std::vector<int> v, g;
std::map<std::vector<int>, int> mp;
std::priority_queue<piv> q;
std::vector<std::vector<int>> f;
std::set<std::vector<int>> s;

int main(int argc, char const *argv[])
{
    int n = read(), sum = 0;
    rep(i, 0, n)
    {
        int c = read();
        v.push_back(c);
        g.clear();
        rep(j, 0, c)
        {
            int k = read();
            g.push_back(k);
        }
        f.push_back(g);
        sum += g[c - 1];
    }
    q.push(std::make_pair(sum, v));
    int m = read();
    rep(i, 0, m)
    {
        g.clear();
        rep(j, 0, n)
        {
            int k = read();
            g.push_back(k);
        }
        ++mp[g];
    }
    while (!q.empty())
    {
        piv ans = q.top();
        q.pop();
        sum = ans.first;
        g = ans.second;
        if (mp[g])
        {
            rep(i, 0, n)
            {
                if (g[i] <= 1)
                    continue;
                int cur = f[i][g[i] - 1];
                --g[i];
                int nxt = f[i][g[i] - 1];
                if (!s.count(g))
                {
                    q.push(std::make_pair(sum - cur + nxt, g));
                    s.insert(g);
                }
                ++g[i];
            }
            continue;
        }
        for (auto x : g)
            printf("%d ", x);
        puts("");
        break;
    }
    return 0;
}

// 关于dfs:它死了
// #include <bits/stdc++.h>
// #define rep(i, x, y) for (register int i = (x); i <= (y); i++)
// #define down(i, x, y) for (register int i = (x); i >= (y); i--)
// #define pii pair<int, int>
// using namespace std;

// char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
// #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
// inline int read()
// {
//     int x = 0, f = 1;
//     char ch = getchar();
//     while (!isdigit(ch))
//     {
//         if (ch == \'-\')
//             f = -1;
//         ch = getchar();
//     }
//     while (isdigit(ch))
//     {
//         x = x * 10 + ch - \'0\';
//         ch = getchar();
//     }
//     return x * f;
// }
// inline char qrc()
// {
//     char c;
//     while (!isdigit(c = getchar()))
//         ;
//     return c;
// }

// int n, ans;
// map<vector<int>, int> mp;
// vector<int> output;
// vector<pii> a[11];

// void dfs(int id, vector<int> v)
// {
//     if (v.size() == n)
//     {
//         if (mp[v])
//             return;
//         int ans = 0;
//         rep(i, 1, n)
//             ans += a[i][v[i - 1] - 1].second;
//         if (ans > ans)
//             ans = ans, output = v;
//         return;
//     }
//     for (auto x : a[id])
//     {
//         v.push_back(x.first);
//         dfs(id + 1, v);
//         v.pop_back();
//     }
// }

// int main(int argc, char const *argv[])
// {
//     n = read();
//     rep(i, 1, n)
//     {
//         int c = read();
//         rep(j, 1, c)
//         {
//             int k = read();
//             a[i].push_back(make_pair(j, k));
//         }
//     }
//     int m = read();
//     rep(i, 1, m)
//     {
//         vector<int> v;
//         rep(j, 1, n)
//         {
//             int k = read();
//             v.push_back(k);
//         }
//         ++mp[v];
//     }
//     vector<int> v;
//     dfs(1, v);
//     for (auto x : output)
//         printf("%d ", x);
//     puts("");
//     return 0;
// }

以上是关于Educational Codeforces Round 114 (Rated for Div. 2) 题解的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27