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)\)