记录 CCF CSP 中的一些入门题 (第二题)
20220302-2 CCF CSP
出行计划
这道题的核心是求出当前出行时间时符合条件的所有计划和;
因此可以考虑通过预处理差分数组提前得到各个时间点所有情况的交集.
#include <iostream> #include <vector> using namespace std; typedef pair<int, int> PII; const int N = 1e6 + 10; int n, m, k, q; int go[N], delay[N], sub[N]; // 定义sub数组作为差分数组 vector<PII> bor; void insert(int sub[], int l, int r) { sub[l] += 1, sub[r + 1] -= 1; //求差分操作 } int main() { cin >> n >> m >> k; // 把每一个出行计划的前后时间边界存入border数组;
// 判断一下, 如果最早时间小于0, 则存入0 for (int i = 1; i <= n; i ++ ) { scanf("%d%d", &go[i], &delay[i]); go[i] - delay[i] + 1 < 0 ? bor.push_back({0, go[i]}) : bor.push_back({go[i] - delay[i] + 1, go[i]}); } // 将需要预处理的边界数据加入sub数组中 for (int i = 0; i < n; i ++ ) insert(sub, bor[i].first, bor[i].second); // 求前缀和得到区间交集情况 for (int i = 0; i < N; i ++ ) sub[i] += sub[i - 1]; // 依次读入询问, 输出对应出行时间的交集数量 while (cin >> q) printf("%d\n", sub[q + k]); return 0; }
成功通过

202104-1
灰度直方图
#include <iostream> using namespace std; const int N = 300; int n, l, map[N]; int main() { cin >> n >> n >> l; while (cin >> n) map[n] ++; for (int i = 0; i < l; i ++ ) cout << map[i] << ' '; return 0; }

附一张加速后
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
 
202012-2
期末预测之最佳阈值
#include <iostream> #include <algorithm> #include <unordered_map> using namespace std; typedef pair<int, int> PII; const int N = 4e5 + 10; #define x first #define y second int n, mx, s[N]; PII c[N]; unordered_map<int, int> h(N); int main() { cin >> n; for (int i = 1; i <= n; i ++ ) scanf("%d%d", &c[i].x, &c[i].y); sort(c + 1, c + n + 1); for (int i = 1; i <= n; i ++ ) if (!h[c[i].x]) h[c[i].x] = i; for (int i = 1; i <= n; i ++ ) s[i] += s[i - 1] + c[i].y; for (auto t : h) if (t.y - s[t.y - 1] - s[t.y - 1] > h[mx] - s[h[mx] - 1] - s[h[mx] - 1]) mx = t.x; cout << mx; return 0; }

202009-2
风险人群筛查
#include <iostream> using namespace std; const int N = 1010; int n, k, t, x1, y1, x2, y2, st, th; int l[N], r[N]; int main() { cin >> n >> k >> t >> x1 >> y1 >> x2 >> y2; while (n -- ) { for (int i = 0; i < t; i ++ ) scanf("%d%d", &l[i], &r[i]); int cnt = 0; bool stay = false, through = false; for (int i = 0; i < t; i ++ ) if (l[i] >= x1 && r[i] >= y1 && l[i] <= x2 && r[i] <= y2) { if (++ cnt == k) stay = true; through = true; } else cnt = 0; if (stay) st ++; if (through) th ++; } cout << th << endl << st; return 0; }

202006-2
稀疏矩阵
用stl自带的map
#include <iostream> #include <unordered_map> using namespace std; typedef long long LL; const int N = 2e6; int n, a, b; LL res; unordered_map<int, int> h(N); int main() { ios::sync_with_stdio(false); cin.tie(NULL); cin >> n >> a >> b; while (cin >> a >> b) { if (h[a]) res += (LL)h[a] * (LL)b; else h[a] += b; } cout << res << endl; return 0; }

尝试手写了哈希表,发现效率提高不少
#include <iostream> #include <cstring> using namespace std; typedef long long LL; typedef pair<int, int> PII; const int N = 2777777, null = 0x3f3f3f3f; int n, a, b; LL res; PII h[N]; int find(int x) { int t = (x % N + N) % N; while (h[t].first != null && h[t].first != x) { t ++; if (t == N) t = 0; } return t; } int main() { ios::sync_with_stdio(false); cin.tie(NULL); memset(h, 0x3f, sizeof h); cin >> n >> a >> b; while (cin >> a >> b) { if (h[find(a)].first == a) res += (LL)h[find(a)].second * (LL)b; else h[find(a)] = {a, b}; } cout << res << endl; return 0; }

201912-2
回收站选址
#include <iostream> #include <algorithm> #include <map> using namespace std; typedef pair<int, int> PII; const int N = 1010; int n, a, b, c[5]; map<PII, int> h; vector<PII> cor; int main() { cin >> n; while (cin >> a >> b) { cor.push_back({a, b}); h[{a, b}] ++; } for (auto& x : cor) { bool flag = true; int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; for (int i = 0; i < 4; i ++ ) { a = x.first + dx[i], b = x.second + dy[i]; if (!h[{a, b}]) flag = false; } if (flag) { int cnt = 0; int ddx[4] = {-1, 1, 1, -1}, ddy[4] = {1, 1, -1, -1}; for (int i = 0; i < 4; i ++ ) { a = x.first + ddx[i], b = x.second + ddy[i]; if (h[{a, b}]) cnt ++; } c[cnt] ++; } } for (int x : c) cout << x << endl; return 0; }

201909-2
小明种苹果(续)
#include <iostream> using namespace std; const int N = 1010; int n, m, t, d, e; bool D[N]; int be(int x) // behind { return x + 1 > n ? 1 : x + 1; } int main() { cin >> n; for (int i = 1; i <= n; i ++ ) { int a, now = 0; cin >> m >> a; now += a; while ( -- m) { cin >> a; if (a <= 0) now += a; else if (a < now) { D[i] = true; now = a; } } t += now; } for (auto x : D) if (x) d ++; for (int i = 1; i <= n; i ++ ) if (D[i] && D[be(i)] && D[be(be(i))]) e ++; printf("%d %d %d", t, d, e); return 0; }

201903-2
二十四点
#include <iostream> #include <stack> #include <unordered_map> using namespace std; int n; string s; stack<int> num; stack<char> op; void eval() { int x; auto b = num.top(); num.pop(); auto a = num.top(); num.pop(); auto c = op.top(); op.pop(); if (c == '+') x = a + b; if (c == '-') x = a - b; if (c == 'x') x = a * b; if (c == '/') x = a / b; num.push(x); } int main() { unordered_map<char, int> pr = {{'+', 1 }, {'-', 1}, {'x', 2}, {'/', 2}}; cin >> n; while (n -- ) { cin >> s; for (auto i : s) if (isdigit(i)) num.push(i - '0'); else { if (op.size() && pr[op.top()] >= pr[i]) eval(); op.push(i); } while (op.size()) eval(); if (num.top() == 24) puts("Yes"); else puts("No"); num.pop(); } return 0; }

201812-2
小明放学
#include <iostream> using namespace std; const int N = 1e5 + 10; long long r, y, g, n, res; int k[N], t[N]; void change(int x, long long ttt) { int tt = ttt % (r + g + y); if (k[x] == 1) { if (t[x] - tt > 0) t[x] -= tt; else if (t[x] + g - tt > 0) k[x] = 3, t[x] = t[x] + g - tt; else if (t[x] + g + y - tt > 0) k[x] = 2, t[x] = t[x] + g + y - tt; else t[x] = t[x] + g + y + r - tt; } else if (k[x] == 2) { if (t[x] - tt > 0) t[x] -= tt; else if (t[x] + r - tt > 0) k[x] = 1, t[x] = t[x] + r - tt; else if (t[x] + r + g - tt > 0) k[x] = 3, t[x] = t[x] + r + g - tt; else t[x] = t[x] + g + y + r - tt; } else if (k[x] == 3) { if (t[x] - tt > 0) t[x] -= tt; else if (t[x] + y - tt > 0) k[x] = 2, t[x] = t[x] + y - tt; else if (t[x] + y + r - tt > 0) k[x] = 1, t[x] = t[x] + y + r - tt; else t[x] = t[x] + g + y + r - tt; } } int main() { cin >> r >> y >> g >> n; for (int i = 1; i <= n; i ++ ) scanf("%d%d", &k[i], &t[i]); for (int i = 1; i <= n; i ++ ) { if (k[i] == 0 || k[i] == 1) res += t[i]; else if (k[i] == 2) res += r + t[i]; if (i < n) change(i + 1, res); } cout << res; }

201809-2
买菜
#include <iostream> using namespace std; const int N = 1e6 + 10; int n, x, y, res, map[N]; int main() { cin >> n; while (cin >> x >> y) map[x] += 1, map[y] -= 1; for (int i = 1; i < N; i ++ ) { map[i] += map[i - 1]; if (map[i] == 2) res ++; } cout << res; return 0; }

201803-2
碰撞的小球
#include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef pair<int, int> PII; int n, l, t; vector<PII> ball; int main() { cin >> n >> l >> t; while (cin >> n) ball.push_back({n, 1}); while (t -- ) { for (auto& a : ball) a.first += a.second; for (int j = 0; j < ball.size(); j ++ ) { if (ball[j].first == l || !ball[j].first) ball[j].second = - ball[j].second; for (int k = j + 1; k < ball.size(); k ++ ) if (ball[j].first == ball[k].first) swap(ball[j].second, ball[k].second); } } for (auto x : ball) cout << x.first << ' '; return 0; }

201712-2
游戏
#include <iostream> #include <queue> using namespace std; int n, k, x; queue<int> q; int main() { cin >> n >> k; for (int i = 1; i <= n; i ++ ) q.push(i); while (q.size() - 1) { x ++; int pre = q.front(); q.pop(); if (x % k != 0 && x % 10 != k) q.push(pre); } cout << q.front(); return 0; }

201709-2
公共钥匙盒
#include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef pair<int,int> PII; const int N = 1e5 + 10; int n, k, a, b, c, key[N]; vector<PII> gt, pt; void put(int x) //放钥匙 { for (int i = 1; i <= n; i ++ ) if (!key[i]) { key[i] = x; break; } } void get(int x) //取钥匙 { for (int i = 1; i <= n; i ++ ) if (key[i] == x) { key[i] = 0; break; } } int main() { cin >> n >> k; for (int i = 1; i <= n; i ++ ) key[i] = i; for (int i = 1; i <= k; i ++ ) { cin >> a >> b >> c; gt.push_back({b, a}); //依次推入取的时间和钥匙编号 pt.push_back({b + c, a}); //依次推入放的时间和钥匙编号 } sort(gt.begin(), gt.end()); //按照时间先后排序 sort(pt.begin(), pt.end()); int i = 0, j = 0; while (i < gt.size() && j < pt.size()) { while (i < gt.size() && gt[i].first < pt[j].first) get(gt[i].second), i ++; while (j < pt.size() && gt[i].first >= pt[j].first) put(pt[j].second), j ++; //加等号是因为时间相同需要优先存放钥匙 } while (j < pt.size()) put(pt[j].second), j ++; //将未放完的钥匙全部放回去 for (int i = 1; i <= n; i ++ ) cout << key[i] << ' '; return 0; }

201703-2
学生排队
#include <iostream> using namespace std; const int N = 1010; int n, m, q[N]; void insert(int a, int b) { int x = a; for (int i = 1; i <= n; i ++ ) if (q[i] == a) { a = i; break; } if (b > 0) for (int i = a; i < a + b; i ++ ) q[i] = q[i + 1]; else for (int i = a - 1; i >= a + b; i -- ) q[i + 1] = q[i]; q[a + b] = x; } int main() { cin >> n >> m; for (int i = 1; i <= n; i ++ ) q[i] = i; while (m -- ) { int a, b; scanf("%d%d", &a, &b); insert(a, b); } for (int i = 1; i <= n; i ++ ) printf("%d ", q[i]); }

201612-2
工资计算
#include <iostream> using namespace std; const int N = 2e5 + 10; int s, h[N]; int main() { cin >> s; for (int i = 0; i <= N; i += 100 ) { int A = i - 3500; double sub = 0; if (A > 0) { if (A <= 1500) sub += A * 0.03; if (1500 < A && A <= 4500) sub += (A - 1500) * 0.1 + 1500 * 0.03; if (4500 < A && A <= 9000) sub += (A - 4500) * 0.2 + 3000 * 0.1 + 1500 * 0.03; if (9000 < A && A <= 35000) sub += (A - 9000) * 0.25 + 4500 * 0.2 + 3000 * 0.1 + 1500 * 0.03; if (35000 < A && A <= 55000) sub += (A - 35000) * 0.3 + 26000 * 0.25 + 4500 * 0.2 + 3000 * 0.1 + 1500 * 0.03; if (55000 < A && A <= 80000) sub += (A - 55000) * 0.35 + 20000 * 0.3 + 26000 * 0.25 + 4500 * 0.2 + 3000 * 0.1 + 1500 * 0.03; if (A > 80000) sub += (A - 80000) * 0.45 + 25000 * 0.35 + 20000 * 0.3 + 26000 * 0.25 + 4500 * 0.2 + 3000 * 0.1 + 1500 * 0.03; } h[i - (int)sub] = i; } cout << h[s]; return 0; }

201609-2
火车购票
#include <iostream> using namespace std; const int N = 20; int n, p, t[N], st[N]; int main() { cin >> n; for (int i = 0; i < N; i ++ ) t[i] = 5; for (int i = 1; i <= n; i ++ ) { bool f = false; cin >> p; for (int j = 0; j < N; j ++ ) { if (t[j] >= p) { t[j] -= p; for (int k = 1; k <= p; k ++ ) cout << j * 5 + ++ st[j] << ' '; cout << endl; f = true; break; } } if (!f) { for (int u = 0; u < p; u ++ ) for (int j = 0; j < N; j ++ ) if (t[j] >= 1) { t[j] -= 1; for (int k = 1; k <= 1; k ++ ) cout << j * 5 + ++ st[j] << ' '; break; } cout << endl; } } return 0; }

201604-2
俄罗斯方块
#include <iostream> using namespace std; const int N = 20; int c, m, high = 4; // high表示下落方块形状的高度 int h[N][N], shape[5][5]; int main() { for (int i = 1; i <= 15; i ++ ) for (int j = 1; j <= 10; j ++ ) cin >> h[i][j]; for (int i = 1; i <= 4; i ++ ) for (int j = 1; j <= 4; j ++ ) cin >> shape[i][j]; cin >> c; for (int i = 4; i >= 1; i -- ) { bool flag = false; for (int j = 1; j <= 4; j ++ ) if (shape[i][j]) flag = true; if (!flag) high --; // 如果形状的最下面一行全为0,那就抹掉这一行 else break; } for (int k = 1; k <= 15 - high + 1; k ++ ) { bool f = true; for (int i = 1; i <= high; i ++ ) for (int j = 1; j <= 4; j ++ ) if (h[k + i - 1][c + j - 1] && shape[i][j]) f = false; // 说明这一行会发生碰撞 if (f) m = k; // 如果没有碰撞,则记录最大坐标并跳出 else break; } for (int i = 1; i <= high; i ++ ) for (int j = 1; j <= 4; j ++ ) if (shape[i][j]) h[m + i - 1][c + j - 1] ++; // 填充方块到最正确的位置上 for (int i = 1; i <= 15; i ++ ) { for (int j = 1; j <= 10; j ++ ) cout << h[i][j] << ' '; cout << endl; } return 0; }

201512-2
消除类游戏
#include <iostream> using namespace std; const int N = 50; int n, m, q[N][N], dx[2] = {0, 1}, dy[2] = {1, 0}; bool flag[N][N]; void move(int i, int j, int k) { int a = i + dx[k], b = j + dy[k], c = a + dx[k], d = b + dy[k]; if (c >= 0 && c < n && d >= 0 && d < m && q[i][j] == q[a][b] && q[i][j] == q[c][d]) // 在不越界的情况下连走两步 flag[i][j] = flag[a][b] = flag[c][d] = true; // 连续三个相同就全部标记 } int main() { cin >> n >> m; for (int i = 0; i < n; i ++ ) for (int j = 0; j < m; j ++ ) cin >> q[i][j]; for (int i = 0; i < n; i ++ ) for (int j = 0; j < m; j ++ ) for (int k = 0; k < 2; k ++ ) // 枚举,k=0和k=1分别代表往下走和往右走 move(i, j, k); for (int i = 0; i < n; i ++ ) { for (int j = 0; j < m; j ++ ) { if (flag[i][j]) cout << 0 << ' '; else cout << q[i][j] << ' '; } cout << endl; } return 0; }

201509-2
日期计算
#include <iostream> using namespace std; int y, d, month = 1; int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int main() { cin >> y >> d; bool leap = (y % 4 == 0 && y % 100 || y % 400 == 0); if (leap) days[2] ++ ; while (d > days[month]) d -= days[month ++ ]; cout << month << endl << d; return 0; }

20150302-2
数字排序
#include <iostream> const int N = 1010; using namespace std; int n, p; int q[N], map[N]; int main() { cin >> n; while (cin >> p) map[p] ++ ; for (int i = 0; i < n; i ++ ) { int max = 0; for (int i = 0; i < N; i ++ ) if (map[i] > map[max]) max = i; if (!map[max]) break; cout << max << ' ' << map[max] << endl; map[max] = 0; } return 0; }

201412-2
Z字形扫描
#include<iostream> using namespace std; const int N = 510; int n, a[N][N]; int main() { cin >> n; for (int i = 1; i <= n; ++ i) for (int j = 1; j <= n; ++ j) scanf("%d", &a[i][j]); for (int i = 2; i <= n + 1; i ++ ) for (int j = 1; j < i; j ++ ) if (i % 2) printf("%d ", a[j][i - j]); else printf("%d ", a[i - j][j]); for (int i = n + 2; i <= 2 * n; i ++ ) for (int j = n; j >= i - n; j -- ) if (i % 2) printf("%d ", a[i - j][j]); else printf("%d ", a[j][i - j]); return 0; }

201409-2
画图
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 110; typedef pair<int, int> PII; int n, a, b, c, d, res; int o[N][N]; vector<PII> low, up; int main() { cin >> n; for (int i = 0; i < n; i ++ ) { cin >> a >> b >> c >> d; low.push_back({a, b}); up.push_back({c, d}); } for (int i = 0; i < 100; i ++ ) for (int j = 0; j < 100; j ++ ) for (int k = 0; k < n; k ++ ) if (i >= low[k].first && j >= low[k].second && i < up[k].first && j < up[k].second) o[i][j] ++; for (int i = 0; i < 100; i ++ ) for (int j = 0; j < 100; j ++ ) if (o[i][j]) res ++ ; cout << res; return 0; }

201403-2
窗口
#include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef pair<int, int> PII; int n, m, a, b, c, d; vector<PII> down, up; vector<int> pri; // 定义pre数组表示每个编号的优先级,pre的下标越大,里面存放的编号优先级越高 void before(vector<int> &pri, int x) // 定义before函数将对应优先级内的编号提升到最高,其余优先级依次降低 { int tmp = pri[x]; if (x == n - 1) return; for (int i = x; i < n - 1; i ++ ) pri[i] = pri[i + 1]; pri[n - 1] = tmp; } int find(vector<PII> &down, vector<PII> &up, int a, int b) // find函数寻找范围内优先级最高的窗口 { for (int i = n - 1; i >= 0; i -- ) if (a >= down[pri[i]].first && b >= down[pri[i]].second && a <= up[pri[i]].first && b <= up[pri[i]].second) { before(pri, i); // 窗口顶置 return pri[n - 1] + 1; } return 0; // 返回0说明没有点击到窗口 } int main() { cin >> n >> m; for (int i = 0; i < n; i ++ ) { cin >> a >> b >> c >> d; down.push_back({a, b}); up.push_back({c, d}); pri.push_back(i); } while (m -- ) { int a, b; cin >> a >> b; int res = find(down, up, a, b); if (res) cout << res << endl; else cout << "IGNORED" << endl; } return 0; }

201312-2
ISBN号码
#include <iostream> #include <vector> using namespace std; int s, cnt; char id; vector<char> is; int main() { while (cin >> id) is.push_back(id); for (int i = 0; i < 12; i ++ ) { if (is[i] != '-') s += (++cnt) * (is[i] - '0'); } s %= 11; if (is[12] == 'X' && s == 10) puts("Right"); else if (is[12] - '0' == s) puts("Right"); else { for (int i = 0; i < 12; i ++ ) cout << is[i]; if (s == 10) cout << 'X'; else cout << s; } return 0; }
 

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号