Codeforces Educational Round 114

Codeforces Educational Round 114

A:Regular Bracket Sequences

Description

给定 \(n\),构造 \(n\) 个不同的长度为 \(2n\) 的匹配括号序列。

多测。

限制\(1\le t,n\le 50\)

Solution

考虑对每个 \(i\),构造长度为 \(2i\) 的括号匹配序列和长度为 \(2(n-i)\) 的括号匹配序列。对 \(i=1\sim n\),共有 \(n\) 对。

例如 \(n=3\) 时,我们可以构造如下序列:

()(()) i=1
(())() i=2
((())) i=3

实现这个比较简单,我用的是递归。

时间复杂度:\(\mathcal O(n^2t)\)

Code

void Outbracket(int deep) {
    if (deep == 0) 
        return ;
 
    cout << '(',Outbracket(deep - 1),cout << ')';
}
 
inline void solve() {
    static int n ;
 
    cin >> n;
 
    for (int i = 1; i <= n; ++i) {
        Outbracket(i),Outbracket(n - i),cout << '\n';
    }
}

B:Combinatorics Homework

Description

构造一个字符串 \(s\),满足下列限制

  • 恰好有 \(a\)A
  • 恰好有 \(b\)B
  • 恰好有 \(c\)C
  • 没有其他字母
  • 恰好有 \(m\)\(i\) 满足 \(s_i = s_{i+1}\)

多测。

限制\(1\le t\le 10^4,1\le a,b,c\le 10^8,0\le m \le 10^8\)

Solution

方便起见,我们假设 \(a\ge b\ge c\)

那么这些字母能构成的最多连续对的数目即为 \(a+b+c-3\)(每个字母构成其数目 \(-1\) 对),最少构成 \(a-b-c-1\) 对。

所以只要 \(m\) 在此范围内就可以,反之不行。

时间复杂度:\(\mathcal O(t)\)

Code

inline void solve() {
    int a,b,c,m ;
 
    cin >> a >> b >> c >> m ; 
 
    if (a < b) std::swap(a,b) ;
    if (a < c) std::swap(a,c) ;
    if (b < c) std::swap(b,c) ;
 
    if (a + b + c - 3 < m || a - b - c - 1 > m) 
        return cout << "NO\n",void() ;
    
    cout << "YES\n" ;
}

C:Slay the Dragon

Description

给定长度为 \(n\) 的序列 \(a\)\(m\) 次询问,每次询问包含两个参数 \(x,y\),你可以给序列任意位置 \(+1\),最后你需要找出一个位置 \(p\) ,满足

  • \(a_p\ge x\)
  • \(\displaystyle\sum_{i=1}^n a_i[i\not= p] \ge y\)

最小化 \(+1\) 次数,输出其次数。

询问之间互相独立。

限制\(2\le n\le2\times 10^5,1\le m\le 2\times10^5,1\le a_i,x\le 10^{12},1\le y\le 10^{18}\)

Solution

首先可以发现,如果要使其次数最小,那么要满足选出的 \(a_p\) 最接近 \(x\),然后这个时候要讨论一下。

如果最大值小于 \(x\),那么首先把最大值加到 \(x\),然后再考虑剩下的。

如果最小值大于 \(x\),那么就直接考虑剩下的。

否则把最大的小于 \(x\) 的花费算一下,把最小的大于等于 \(x\) 的花费算一下,取最小值。

时间复杂度:\(\mathcal O(n\log n -m)\)

Code

	in(n) ;

    for (int i = 1; i <= n; ++i)
        in(a[i]),sum += a[i];

    std::sort(a + 1,a + 1 + n) ;

    in(m) ;

    for (int i = 1; i <= m; ++i) 
        in(d[i].x,d[i].y) ;

    for (int i = 1; i <= m; ++i) {
        auto value = std::lower_bound(a + 1,a + 1 + n,d[i].x);
        auto x = d[i].x,y = d[i].y;

        if (!*value) {
            --value ;

            auto delta = x - *value + max(y + *value - sum,0ll) ;

            out('\n',delta) ;
            continue ;
        }

        if (!*(value - 1)) {
            auto delta = y + *value - sum ;

            out('\n',max(delta,0ll)) ;
            continue ;
        }

        auto delta_1 = x - *(value - 1) + max(y + *(value - 1) - sum,0ll) ;
        auto delta_2 =  max(y + *(value) - sum,0ll) ;

        out('\n',min(delta_1,delta_2)) ;
    } 

D:The Strongest Build

Description

给定 \(n\) 个序列,第 \(i\) 个序列 \(a_i\) 的长度为 \(c_i\),你需要从每个序列中选出一个数,组成一个 \(n\) 元组。

但是有 \(m\)\(n\) 元组禁止选,询问在合法的 \(n\) 元组里,和最大的 \(n\) 元组是什么。

限制\(1\le n\le 10,1\le c_i.\sum c_i\le 2\times 10^5,0\le m\le 10^5,a_{i,j}\le 10^8(1\le j\le c_i)\)

Solution

posted @ 2021-10-15 19:28  feicheng  阅读(29)  评论(0编辑  收藏  举报