2024年3月CSP,回顾+题解。
第一次参加CSP,同时也是第一次参与真正上机的算法竞赛,得分 385/500
,有经验也有教训,故有此文浅做总结。
前置工作 首先要了解CSP支持的c++版本,考场上因为没有提前了解版本以及devcpp配置问题,导致手写iterator,浪费了很多时间和思路。
在devcpp中加入如下命令后,可使用c++14环境语法。
考试开始前可以在编辑器中提前打入模板,这样创建新项目时可以直接在模板基础上进行编程。
还有devcpp的美化问题,浅浅配置一下颜色,避免影响敲代码的心情(bushi
题解 词频统计 考点:计数
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;const int N = 105 ;int x[N], y[N];bool vis[N];inline int read () { int x = 0 , f = 1 ; char ch = getchar (); while (ch < '0' || ch > '9' ) { if (ch == '-' ) f = -1 ; ch = getchar (); } while (ch >= '0' && ch <= '9' ) { x = x * 10 + ch - 48 ; ch = getchar (); } return x * f; } int main () { int n = read (), m = read (); for (int i = 1 ; i <= n; i++){ memset (vis, 0 , sizeof vis); int l = read (); while (l--){ int t = read (); if (!vis[t]) vis[t] = true , x[t]++; y[t]++; } } for (int i = 1 ; i <= m; i++) cout << x[i] << ' ' << y[i] << '\n' ; return 0 ; }
相似度计算 考点:字符大小写转换,集合
题目本身比较简单,这里给出一个有趣的大小写转换方法。观察ASCII码,不难发现,小写字母与其对应的大写字母ASCII之差恰好为32,是space
的ASCII值,故:
若想将字符c
统一为小写:c |= ' '
若想将字符c
统一为大写:c &= ~' '
若想将字符c
小写转大写,大写转小写:c ^= ' '
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;set<string> A, B; inline int read () { int x = 0 , f = 1 ; char ch = getchar (); while (ch < '0' || ch > '9' ) { if (ch == '-' ) f = -1 ; ch = getchar (); } while (ch >= '0' && ch <= '9' ) { x = x * 10 + ch - 48 ; ch = getchar (); } return x * f; } int main () { int n = read (), m = read (); while (n--){ string s; cin >> s; for (int i = 0 ;i < s.size (); i++) s[i] |= ' ' ; A.insert (s); } while (m--){ string s; cin >> s; for (int i = 0 ;i < s.size (); i++) s[i] |= ' ' ; B.insert (s); } int same = 0 ; for (auto &v : B) if (A.find (v) != A.end ()) same++; cout << same << '\n' << A.size () + B.size () - same; return 0 ; }
化学方程式配平 考点:字符串处理,高斯消元
在处理高斯消元时,为避免浮点数的出现,这里采用了求lcm后,作线性组合行变换的方式。
(当然题目的数据范围应该也允许直接用两数乘积代替lcm)
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 #include <bits/stdc++.h> using namespace std;const int N = 50 ;int matrix[N][N];inline int read () { int x = 0 , f = 1 ; char ch = getchar (); while (ch < '0' || ch > '9' ) { if (ch == '-' ) f = -1 ; ch = getchar (); } while (ch >= '0' && ch <= '9' ) { x = x * 10 + ch - 48 ; ch = getchar (); } return x * f; } int gcd (int a, int b) { return b ? gcd (b, a % b) : a; }int lcm (int a, int b) { return a * b / gcd (a, b); }int Rank (int x1, int y1, int x2, int y2) { if (x1 > x2 || y1 > y2) return 0 ; int flag = 0 ; for (int i = x1; i <= x2; i++){ if (matrix[i][y1]) { flag = i; break ; } } if (!flag) return Rank (x1, y1 + 1 , x2, y2); swap (matrix[x1], matrix[flag]); for (int i = x1 + 1 ; i <= x2; i++){ if (matrix[i][y1] == 0 ) continue ; int LCM = lcm (matrix[x1][y1], matrix[i][y1]); int t1 = LCM / matrix[i][y1], t2 = LCM / matrix[x1][y1]; for (int j = y1; j <= y2; j++) matrix[i][j] = matrix[i][j] * t1 - matrix[x1][j] * t2; } return Rank (x1 + 1 , y1 + 1 , x2, y2) + 1 ; } void solve () { memset (matrix, 0 , sizeof matrix); map<string, int > mp; int m = read (); int r = 0 , c = 1 ; char ch; int num = 0 ; string ele; while (ch = getchar ()) { if (num && (ch < '0' || ch > '9' )) { if (!mp[ele]) mp[ele] = ++r; matrix[mp[ele]][c] = num; ele = "" , num = 0 ; if (ch == '\n' || ch == EOF) break ; if (ch == ' ' ) { c++; continue ; } } if (ch >= '0' && ch <= '9' ) num = num * 10 + ch - 48 ; else if (ch >= 'a' && ch <= 'z' ) ele += ch; } if (Rank (1 , 1 , r, c) == c) cout << 'N' << '\n' ; else cout << 'Y' << '\n' ; } int main () { int n = read (); while (n--) solve (); return 0 ; }
十滴水 考点:离散化 + 双向链表
分析:需要一个能快速锁定前驱和后继,并且支持删除操作的数据结构,故用双向链表模拟题意即可。
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <bits/stdc++.h> using namespace std;typedef pair<int , int > PII;const int N = 3e5 + 10 ;vector<int > alls; vector<PII> storage; int l[N], r[N], v[N];priority_queue<int , vector<int >, greater<int >> q; inline int read () { int x = 0 , f = 1 ; char ch = getchar (); while (ch < '0' || ch > '9' ) { if (ch == '-' ) f = -1 ; ch = getchar (); } while (ch >= '0' && ch <= '9' ) { x = x * 10 + ch - 48 ; ch = getchar (); } return x * f; } int to_find (int x) { return lower_bound (alls.begin (), alls.nd (), x) - alls.begin () + 1 ; } int main () { int c = read (), m = read (), n = read (); for (int i = 1 ; i <= m; i++) { int x = read (), w = read (); alls.emplace_back (x); storage.emplace_back (x, w); } sort (alls.begin (), alls.end ()); for (auto & u : storage) v[to_find (u.first)] = u.second; for (int i = 1 ; i <= m; i++) l[i] = i - 1 , r[i] = i + 1 ; v[0 ] = v[m + 1 ] = 666 ; while (n--) { int p = to_find (read ()); v[p]++; if (v[p] == 5 ) q.emplace (p); while (!q.empty ()) { int u = q.top (); q.pop (); r[l[u]] = r[u]; l[r[u]] = l[u]; m--; v[l[u]]++, v[r[u]]++; if (v[l[u]] == 5 ) q.emplace (l[u]); if (v[r[u]] == 5 ) q.emplace (r[u]); } cout << m << '\n' ; } return 0 ; }
文件夹合并 暂时不会,以后上传,咕咕~
成绩