Educational Codeforces Round 114 (Rated for Div. 2) (A ~ F)全题解
整理的算法模板合集: ACM模板
点我看算法全家桶系列!!!
实际上是一个全新的精炼模板整合计划
Educational Codeforces Round 114 (Rated for Div. 2)
比赛链接:https://codeforces.com/contest/1574/
前四题过于简单()
后两题有点要命()
A. Regular Bracket Sequences
Problem
Solution
只要求输出 nnn 对合法括号,我们移动一下其中一个右括号即可。
Code
// Problem: A. Regular Bracket Sequences
// Contest: Codeforces - Educational Codeforces Round 114 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1574/problem/A
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 1e5 + 6, INF = 0x3f3f3f3f;
int n, m, s, t;
ll ans;
int a[maxn];void solve()
{cin >> n;for(int i = 1; i <= n; ++ i) {int cnt1 = n, cnt2 = n;for (int j = 1; j <= 2 * n; ++ j) {if(j == i + 1) {cnt2 -- ;putchar(')');}else {if(cnt1) {cnt1 -- ;putchar('(');}else if(cnt2) {cnt2 -- ;putchar(')');}}} puts("");}
}int main()
{cin >> t;while(t -- ) {solve();}return 0;
}
B. Combinatorics Homework
Problem
Solution
设 sum=a+b+csum=a+b+csum=a+b+c
最多的对数显然就是按照顺序放置,一共有 r=sum−3r = sum-3r=sum−3 对。
最少的对数,我们使用数量较小的两个字母 hack=sum−max{a,b,c}hack=sum-\max\{a,b,c\}hack=sum−max{a,b,c},去将数量最多的字母隔开,一共可以隔开 2×hack+12\times hack+12×hack+1 个相同字母,剩下的必须连在一起,那么最少对数就是 l=sum−2×hack−1l = sum-2 \times hack-1l=sum−2×hack−1
判断 mmm 是否在区间内即可。
Code
// Problem: B. Combinatorics Homework
// Contest: Codeforces - Educational Codeforces Round 114 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1574/problem/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 1e5 + 6, INF = 0x3f3f3f3f;
int n, m, s, t;
ll ans;
int a, b, c;void solve()
{cin >> a >> b >> c >> n;int hack = a + b + c - max({a, b, c});int l = a + b + c - 2 * hack - 1;int r = a + b + c - 3;if(l <= n && n <= r)puts("YES");else puts("NO");
}int main()
{cin >> t;while(t -- ) {solve();}return 0;
}
C. Slay the Dragon
Problem
Solution
排序后直接 lower_bound
找到大于等于 xxx 的英雄 pospospos 让他去杀 dragon 即可。
由于我们拥有强化的功能,所以需要判断一下让 pospospos 去杀以及让 pos−1pos-1pos−1 强化之后去杀,谁更便宜即可。
Code
// Problem: C. Slay the Dragon
// Contest: Codeforces - Educational Codeforces Round 114 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1574/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define int long long
using ll = long long;
const int maxn = 3e5 + 6, INF = 2e18;
int n, m, s, t;
ll ans;
int a[maxn];void solve()
{cin >> n;int sum = 0;int maxx = -INF;for (int i = 1; i <= n; ++ i) scanf("%lld", &a[i]), sum += a[i];sort(a + 1, a + 1 + n);cin >> m;while(m -- ) {int x, y;scanf("%lld%lld", &x, &y);ll ans = INF;int pos = lower_bound(a + 1, a + 1 + n, x) - a; if(pos != n + 1) {int kill = a[pos];int rem = sum - kill;int res = max(0ll, y - rem);ans = min(ans, res);}if(pos != 1) {int kill = a[pos - 1];int rem = sum - kill;int res = max(0ll, y - (sum - a[pos - 1])) + x - a[pos - 1];ans = min(ans, res);}cout << ans << endl;}
}signed main()
{// cin >> t;t = 1;while(t -- ) {solve();}return 0;
}
D. The Strongest Build
Problem
Solution
首先考虑如何判断某种选择方案是否被 ban,显然可以直接使用 hash 表 map
O(1)O(1)O(1) 查询即可。我们将数组用 vector
存入,直接使用 map
判断是否存在这种 vector
即可。
由于输入的 aija_{ij}aij 是递增的,考虑暴力搜索,我们可以从最外层选择 cic_ici ,即 max{ci},i∈[1,n]\max\{c_i\},i\in [1,n]max{ci},i∈[1,n] 开始往里 bfsbfsbfs 搜索即可,每次各减一步,一旦找到没有被 ban 的即为最大值。
我们在 bfs 搜索时,我们先判断最优解是否被 ban,若被 ban ,判断最优解的下一层也即某一个 i --
,判断此时是否被 ban 。但是我们发现 ban 掉的方案 m≤105m\le 10^5m≤105,其实我们直接对所有的被 ban 的选择方案,仅判断他们的下一层即可。
对于限选方案 3 2 3
仅判断它的下一层: 2 2 3, 3 1 3, 3 2 2
即可。
此时时间复杂度为 O(nm)=1×106O(nm)=1\times 10^6O(nm)=1×106
因为从最优解开始,只有最优解以及其下一层的方案均被 ban 掉,才需要看下下一层,那么下一层在被 ban 的列表里也将会判断它的下一层。因此仅判断被 ban 的方案的下一层一定能找到可选的最优值。
Code
// Problem: D. The Strongest Build
// Contest: Codeforces - Educational Codeforces Round 114 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1574/problem/D
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define int long long
using ll = long long;
const int maxn = 2e5 + 6, INF = 0x3f3f3f3f, base = 13331, mod1 = 998244353, mod2 = 1e9 + 7;
int n, m, s, t;
vector <int> a[10], ans, b[maxn];
map <vector <int> , int> mp;void solve()
{cin >> n;for (int i = 0; i < n; ++ i) {int c;scanf("%lld", &c);ans.emplace_back(c - 1);for (int j = 0; j < c; ++ j) {int x;scanf("%lld", &x);a[i].emplace_back(x);}}cin >> m;for (int i = 0; i < m; ++ i) { for (int j = 0; j < n; ++ j) {int x;scanf("%lld", &x);x -- ;b[i].emplace_back(x);}mp[b[i]] = 1;} if(mp.find(ans) == mp.end()) {for (auto it : ans)cout << it + 1 << ' ';puts("");return ;}int res = 0;for (int i = 0; i < m; ++ i) {int sum = 0;for (int j = 0; j < n; ++ j)sum += a[j][b[i][j]];for (int j = 0; j < n; ++ j) {sum -= a[j][b[i][j]];if(b[i][j] == 0) continue;b[i][j] -- ;sum += a[j][b[i][j]];if(mp.find(b[i]) == mp.end()) if(sum > res) ans = b[i], res = sum;sum -= a[j][b[i][j]];b[i][j] ++ ;sum += a[j][b[i][j]];}}for (auto it : ans)cout << it + 1 << ' ';puts("");
}signed main()
{// cin >> t;t = 1;while(t -- ) {solve();}return 0;
}
E. Coloring
Problem
Solution
官方题解:
为了更好地理解,我们将矩阵替换为 000 和 111 ,并使用带有黑白单元格的矩阵。
首先,让我们考虑如果有两个相邻的相同颜色的水平单元格
例如单元格 (5,5)(5,5)(5,5) 和 (5,6)(5,6)(5,6) 是黑色的矩阵,那么单元格 (4,5),(4,6),(6,5)(4,5),(4,6),(6,5)(4,5),(4,6),(6,5) 和 (6,6)(6,6)(6,6) 必须有相反的颜色(白色);
单元格 (3,5),(3,6),(7,5)(3,5),(3,6),(7,5)(3,5),(3,6),(7,5) 和 (7,6)(7,6)(7,6) 必须是相同的颜色(黑色)等等。 因此,两个相邻的水平单元格生成宽度为 222 的垂直条带。 两个相邻的垂直单元格产生宽度为 222 的水平条带。 如果同时存在水平条带和垂直条带,那么答案是 000,因为它们相互矛盾。也就是说对于一个合法矩阵要么都是垂直条带,要么都是水平条带。
如果在同一行中有两个相同颜色的单元格,并且它们之间的单元格数量是偶数(例如 (2,2)(2,2)(2,2) 和 (2,7)(2,7)(2,7) 之间有四个单元格),那么就有一个垂直的条形图(因为它们之间总是有两个相邻的单元格,它们之间的颜色是相同的)。对于水平条带同样适用。
现在让我们考虑如果有垂直的条带,矩阵是什么样子的。 它看起来像一个 n×mn×mn×m 大小的棋盘,但有些垂直条带的颜色是颠倒的。 如果有水平条带,答案同样正确。
我们如何能快速判断在同一行中有两个相同颜色的细胞,它们之间的细胞数是否为偶数?我们可以在棋盘给矩阵涂上棋盘图案。其中一个细胞在棋盘上有相同颜色的细胞,另一个细胞在棋盘上有相反颜色的细胞。
我们维护下面的信息计算答案即可:
- 每个彩色细胞的颜色;
- 包含相同颜色单元格且单元格之间有偶数个单元格的行和列;
- 包含至少一个彩色单元格的行数和列数(用于计算漂亮矩阵的数目)。
Code
官方题解代码:
#include <bits/stdc++.h>using namespace std;const int MOD = 998244353;
const int N = 1'000'009;int sum (int a, int b) {int res = a + b;if (res < 0) res += MOD;if (res >= MOD) res -= MOD;return res;
}int n, m, k;
map <pair <int, int>, char> c;
int cntr[N][2], cntc[N][2];
int cntx[2];
set <int> badr, badc;
set<int> ur, uc;
int p2[N];void upd2(int pos, int col, int add, int cnt[N][2], set <int> &bad, set<int> &u) {cnt[pos][col] += add;assert(cnt[pos][col] >= 0);if (cnt[pos][0] > 0 && cnt[pos][1] > 0){if (!bad.count(pos))bad.insert(pos);} else {if (bad.count(pos))bad.erase(pos);}if (cnt[pos][0] > 0 || cnt[pos][1] > 0){if (!u.count(pos))u.insert(pos);} else {if (u.count(pos))u.erase(pos);}
}void upd(int x, int y, int t) {int col = (x & 1) ^ (y & 1);if (c.count({x, y})) {int ncol = col ^ c[{x, y}];--cntx[ncol];upd2(x, ncol, -1, cntr, badr, ur);upd2(y, ncol, -1, cntc, badc, uc);c.erase({x, y});}if (t == -1)return;int ncol = col ^ t;++cntx[ncol];upd2(x, ncol, 1, cntr, badr, ur);upd2(y, ncol, 1, cntc, badc, uc);c[{x, y}] = t;
}int main(){p2[0] = 1;for (int i = 1; i < N; ++i)p2[i] = sum(p2[i - 1], p2[i - 1]);scanf("%d%d%d", &n, &m, &k);for (int i = 0; i < k; ++i) {int x, y, t;scanf("%d %d %d", &x, &y, &t);--x, --y;upd(x, y, t);int res = 0;if(badr.size() > 0 && badc.size() > 0) {res = 0;} else if (badr.size() > 0) {assert(m - uc.size() >= 0);res = p2[m - uc.size()];} else if (badc.size() > 0) {assert(n - ur.size() >= 0);res = p2[n - ur.size()];} else {if (ur.size() == 0 && uc.size() == 0)res = sum(sum(p2[n], p2[m]), -2);else {assert(m - uc.size() >= 0);res = sum(res, p2[m - uc.size()]);assert(n - ur.size() >= 0);res = sum(res, p2[n - ur.size()]);if (cntx[0] == 0 || cntx[1] == 0) {assert(cntx[0] != 0 || cntx[1] != 0);res = sum(res, -1);}}}printf("%d\n", res);}return 0;
}
F. Occurrences
Problem
Solution
动态规划做法:
https://codeforces.com/blog/entry/95188
生成函数做法:
设 aia_iai 为长度为 iii 的有效子数组的个数。
设 aia_iai 的生成函数 A(x)=∑i=1∞aixi\displaystyle A(x)=\sum\limits_{i=1}^{\infin}a_ix^iA(x)=i=1∑∞aixi
设生成函数 B(x)B(x)B(x) 是构成整个序列 aaa 的方案数,显然构造出长度为 mmm 的序列 aaa 的方案数为: [xm]B(x)[x^m]B(x)[xm]B(x)
有:
B=1+A+A×A+A×A×A+⋯=∑i=0∞Ai=11−A(x)\displaystyle B=1+A+A\times A+A\times A\times A+\cdots=\sum\limits_{i=0}^{\infin}A^i=\cfrac{1}{1-A(x)}B=1+A+A×A+A×A×A+⋯=i=0∑∞Ai=1−A(x)1
多项式求逆计算 11−A(x)\cfrac{1}{1-A(x)}1−A(x)1 即可。
Code
Educational Codeforces Round 114 (Rated for Div. 2) (A ~ F)全题解相关推荐
- Educational Codeforces Round 114 (Rated for Div. 2) D. The Strongest Build 暴力 + bfs
传送门 文章目录 题意: 思路: 题意: 你有nnn个装备槽,每个槽里面有cic_ici个力量加成,对于每个槽只能选一个力量加成,现在给你mmm个力量组合[b1,b2,...,bn][b_1,b_2 ...
- Educational Codeforces Round 114 (Rated for Div. 2)C. Slay the Dragon
题目链接:Problem - 1574C - Codeforces Recently, Petya learned about a new game "Slay the Dragon&quo ...
- Educational Codeforces Round 114 (Rated for Div. 2) 个人题解
中秋节快乐! A. Regular Bracket Sequences 题意 输出nnn个不同的长度为2n2n2n的合法括号序列. 分析 先输出一个"()()()-"序列. 然后依 ...
- 1574D The Strongest Build (Educational Codeforces Round 114 (Rated for Div. 2))
题意 给定n个从小到大的数组,从每个数组中选出一个下标构成一个序列,但是有m种序列被ban了,要求选出的序列对应的数字和最大且没有被ban. 思路 因为有m个序列被ban了,那么最坏的情况可以假设为最 ...
- Educational Codeforces Round 106 (Rated for Div. 2)(A ~ E)题解(每日训练 Day.16 )
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 Educational Codeforces Round 106 (Rated for Div. ...
- Educational Codeforces Round 37 (Rated for Div. 2) 1
Educational Codeforces Round 37 (Rated for Div. 2) A.Water The Garden 题意:Max想给花园浇水.花园可被视为长度为n的花园床,花园 ...
- Educational Codeforces Round 90 (Rated for Div. 2)(A, B, C, D, E)
Educational Codeforces Round 90 (Rated for Div. 2) Donut Shops 思路 分三种情况: a==c/ba == c / ba==c/b这个时候两 ...
- Educational Codeforces Round 89 (Rated for Div. 2)(A, B, C, D)
Educational Codeforces Round 89 (Rated for Div. 2) A. Shovels and Swords 思路 题意非常简单,就是得到最多的物品嘛,我们假定a, ...
- Educational Codeforces Round 72 (Rated for Div. 2) D. Coloring Edges dfs树/拓扑找环
传送门 文章目录 题意: 思路: 题意: 给你一张图,你需要给这个图的边染色,保证如果有环那么这个环内边的颜色不全相同,输出染色方案和用的颜色个数. n,m≤5e3n,m\le5e3n,m≤5e3 思 ...
最新文章
- 项目管理利器taiga快速安装
- PostgreSQL在何处处理 sql查询之二十一
- 【项目管理】Scrum内容整理
- python常见数据存储 csv txt pickle
- python的应用范围有哪些_Python主要应用场景有哪些?
- SpringBoot的@SpringBootApplication注解和其他几个注解
- 获取linux详细信息,Linux 获取网口详细信息
- 近期在做或要做的实验
- c++ 封装的zookeeper库
- python 装饰器,登录小练习
- response返回中文乱码
- Cisco 3550交换机IOS备份(真实设备演示)
- 注塑模具设计师要懂得的四个概念
- hbuilderx gitee操作教程
- CAD2018安装计算机黑屏,简单几步解决cad2019在win10上打不开的问题
- 手写JDBC的几个步骤(针对MySQL8.0以上的mysql数据库)
- SMDS:交换式多兆位数据服务--网络大典
- 马斯克的脑机接口,一块树莓派就能做出来?
- 软件新产品开发失败原因分析
- Qt QEvent 介绍