比赛速览
● A - Too Many Requests
● B - N - 1
● C - Odd One Subsequence
● D - On AtCoder Conference
● E - Hit and Away
● F - Shortest Path Query
A - Too Many Requests
输出n行,前k行输出"OK",其余输出"Too Many Requests"。
使用for循环遍历1到n,根据i与k的大小关系输出对应的字符串。
对应课程知识点
本题的循环结构对应极客程 《算法A-枚举与算法基础》 课程中的"枚举法"章节。
参考代码
#include <iostream>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
if (i <= k) {
cout << "OK" << endl;
} else {
cout << "Too Many Requests" << endl;
}
}
return 0;
}
B - N - 1
判断是否能从序列中移除一个元素,使得剩余元素和等于x。
计算序列总和,检查是否存在某个元素等于总和减去x。
对应课程知识点
本题的数组遍历与条件判断对应极客程 《算法A-枚举与算法基础》 课程中的"数组上的枚举"章节。
参考代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, x;
cin >> n >> x;
vector<int> a(n);
long long sum = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
sum += a[i];
}
bool found = false;
for (int i = 0; i < n; i++) {
if (sum - a[i] == x) {
found = true;
break;
}
}
cout << (found ? "Yes" : "No") << endl;
return 0;
}
C - Odd One Subsequence
统计恰好包含两个不同值的三元组数量。
使用哈希表统计每个数值的出现次数,对于每个出现至少2次的数值,计算选择2个该数值和1个其他数值的组合数。
对应课程知识点
本题的组合数学与哈希表应用对应极客程 《算法A-枚举与算法基础》 课程中的"桶与标记"章节。
参考代码
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n);
map<int, long long> cnt;
for (int i = 0; i < n; i++) {
cin >> a[i];
cnt[a[i]]++;
}
long long ans = 0;
for (auto &p : cnt) {
long long c = p.second;
if (c >= 2) {
ans += c * (c - 1) / 2 * (n - c);
}
}
cout << ans << endl;
return 0;
}
D - On AtCoder Conference
计算在环形池塘上,从每个起点出发遇到k个人时的总人数积分。
将环形问题转化为线性问题,通过排序和拆环成链,使用二分查找快速定位每个起点对应的停止位置。
对应课程知识点
本题的二分查找与环形处理对应极客程 《算法B-贪心法与优化》 课程中的"二分答案"章节。
参考代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n, L, k;
cin >> n >> L >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a.begin(), a.end());
vector<int> b = a;
for (int i = 0; i < n; i++) {
b.push_back(a[i] + L);
}
long long ans = 0;
for (int i = 0; i < n; i++) {
int pos = upper_bound(b.begin(), b.end(), a[i]) - b.begin();
int target_pos = pos + k - 1;
if (target_pos < b.size()) {
int next_start = (i + 1 < n) ? a[i + 1] : (a[0] + L);
ans += (long long)(next_start - a[i]) * (target_pos - i + 1);
}
}
cout << ans << endl;
return 0;
}
E - Hit and Away
对每个危险顶点,计算经过该顶点连接两个不同安全顶点的最短路径。
使用多源BFS从所有安全顶点出发,记录每个危险顶点到不同安全顶点的距离,找出最近的两个不同安全顶点。
对应课程知识点
本题的多源BFS算法对应极客程 《算法C-深搜与宽搜》 课程中的"BFS-图论基础"内容。
参考代码
#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int main() {
int n, m;
cin >> n >> m;
string s;
cin >> s;
vector<vector<int>> graph(n + 1);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
vector<int> dist(n + 1, INF);
vector<int> from_safe(n + 1, -1);
queue<int> q;
for (int i = 1; i <= n; i++) {
if (s[i - 1] == 'S') {
dist[i] = 0;
from_safe[i] = i;
q.push(i);
}
}
vector<vector<pair<int, int>>> danger_safes(n + 1);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : graph[u]) {
if (dist[v] == INF) {
dist[v] = dist[u] + 1;
from_safe[v] = from_safe[u];
q.push(v);
if (s[v - 1] == 'D') {
danger_safes[v].push_back({dist[v], from_safe[v]});
}
} else if (dist[v] == dist[u] + 1 && from_safe[v] != from_safe[u]) {
danger_safes[v].push_back({dist[v], from_safe[u]});
}
}
}
for (int i = 1; i <= n; i++) {
if (s[i - 1] == 'D') {
sort(danger_safes[i].begin(), danger_safes[i].end());
danger_safes[i].erase(unique(danger_safes[i].begin(), danger_safes[i].end()), danger_safes[i].end());
if (danger_safes[i].size() < 2) {
cout << -1 << " ";
} else {
int ans = INF;
for (int j = 0; j < danger_safes[i].size(); j++) {
for (int k = j + 1; k < danger_safes[i].size(); k++) {
if (danger_safes[i][j].second != danger_safes[i][k].second) {
ans = min(ans, danger_safes[i][j].first + danger_safes[i][k].first);
}
}
}
cout << (ans == INF ? -1 : ans) << " ";
}
}
}
cout << endl;
return 0;
}
F - Shortest Path Query
动态维护网格状态,支持翻转格子状态,查询从起点到终点的最短路径。
使用线段树维护动态DP,每个节点存储3×3的转移矩阵,支持单点修改和区间查询,快速计算最短路径。
对应课程知识点
本题的动态DP与线段树应用对应极客程 《算法D-入门级动态规划》 后续高级课程内容。
参考代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 1e9;
const int N = 100010;
struct Matrix {
int a[3][3];
Matrix() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a[i][j] = INF;
}
Matrix operator*(const Matrix& other) const {
Matrix res;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
if (a[i][k] < INF && other.a[k][j] < INF) {
res.a[i][j] = min(res.a[i][j], a[i][k] + other.a[k][j]);
}
}
}
}
return res;
}
};
class SegmentTree {
public:
SegmentTree(int n, const vector<vector<bool>>& grid) : n(n), grid(grid) {
tree.resize(4 * n);
build(1, 1, n);
}
void update(int idx, int l, int r, int pos) {
if (l == r) {
tree[idx] = buildMatrix(l);
return;
}
int mid = (l + r) / 2;
if (pos <= mid) update(idx * 2, l, mid, pos);
else update(idx * 2 + 1, mid + 1, r, pos);
tree[idx] = tree[idx * 2] * tree[idx * 2 + 1];
}
Matrix query() {
return tree[1];
}
void flip(int r, int c) {
grid[r][c] = !grid[r][c];
update(1, 1, n, c);
}
private:
int n;
vector<vector<bool>> grid;
vector<Matrix> tree;
Matrix buildMatrix(int col) {
Matrix mat;
for (int i = 0; i < 3; i++) {
if (!grid[i][col]) {
for (int j = 0; j < 3; j++) {
mat.a[i][j] = INF;
mat.a[j][i] = INF;
}
}
}
if (grid[0][col] && grid[1][col] && grid[2][col]) {
mat.a[0][0] = 1; mat.a[0][1] = 2; mat.a[0][2] = 3;
mat.a[1][0] = 2; mat.a[1][1] = 1; mat.a[1][2] = 2;
mat.a[2][0] = 3; mat.a[2][1] = 2; mat.a[2][2] = 1;
} else if (grid[0][col] && grid[1][col]) {
mat.a[0][0] = 1; mat.a[0][1] = 2;
mat.a[1][0] = 2; mat.a[1][1] = 1;
} else if (grid[1][col] && grid[2][col]) {
mat.a[1][1] = 1; mat.a[1][2] = 2;
mat.a[2][1] = 2; mat.a[2][2] = 1;
} else if (grid[0][col]) {
mat.a[0][0] = 1;
} else if (grid[1][col]) {
mat.a[1][1] = 1;
} else if (grid[2][col]) {
mat.a[2][2] = 1;
}
return mat;
}
void build(int idx, int l, int r) {
if (l == r) {
tree[idx] = buildMatrix(l);
return;
}
int mid = (l + r) / 2;
build(idx * 2, l, mid);
build(idx * 2 + 1, mid + 1, r);
tree[idx] = tree[idx * 2] * tree[idx * 2 + 1];
}
};
int main() {
int n, q;
cin >> n >> q;
vector<vector<bool>> grid(3, vector<bool>(n + 1, true));
SegmentTree seg_tree(n, grid);
while (q--) {
int r, c;
cin >> r >> c;
r--;
seg_tree.flip(r, c);
Matrix result = seg_tree.query();
if (result.a[0][2] < INF) {
cout << result.a[0][2] << endl;
} else {
cout << -1 << endl;
}
}
return 0;
}
1247

被折叠的 条评论
为什么被折叠?



