π§© AtCoder Beginner Contest 375
π§© AtCoder Beginner Contest 375
# Info & Summary
- Date:
2024-10-12
- Completion Status: A β / B β / C β / D β / E β / F β / G β
- Problem Type:
Problem | Type(s) | Data Structure / Algo | π₯ Key Insight / Mark |
---|---|---|---|
D | Prefix & Suffix | Prefix Sum & Suffix Sum | βπ₯ |
E | DP | DP / Grouped DP | π§ π οΈ |
F | Shortest Distance | Floyd-Warshall | π§ π |
G | Shortest Distance | Dijkstraβs algorithm | π |
Details
Emoji | Label | Meaning |
---|---|---|
β | Important | Problem is strategically useful or has reusable patterns |
π₯ | Must master | Classic problem or technique that appears often and is worth mastering |
β οΈ | Reattempt | You attempted but failed; worth reviewing and solving again |
π§ | New to me | Introduced a new idea, technique, or pattern you hadnβt seen before |
π οΈ | Template | You built or improved a code template from solving this problem |
π | Too hard now | Beyond current ability to understand/solve; revisit after more practice |
π A - Seats

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
string S;
cin >> N >> S;
int ans = 0;
for (int i = 0; i < N - 2; i++)
{
ans += S[i] == '#' && S[i + 1] == '.' && S[i + 2] == '#';
}
cout << ans << endl;
return 0;
}
π B - Traveling Takahashi Problem

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
double ans = 0;
long long x = 0, y = 0;
for (int i = 0; i < N; i++)
{
long long nx, ny;
cin >> nx >> ny;
ans += sqrt((x - nx) * (x - nx) + (y - ny) * (y - ny));
x = nx;
y = ny;
}
ans += sqrt(x * x + y * y);
cout << fixed << setprecision(20) << ans << endl;
return 0;
}
π C - Spiral Rotation

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
vector<string> grid(N);
for (int i = 0; i < N; i++)
{
cin >> grid[i];
}
vector<string> ans(N, string(N, '.'));
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
int x = i, y = j;
int t = min({i + 1, j + 1, N - i, N - j});
t %= 4;
while (t--)
{
tie(x, y) = pair(N - 1 - y, x);
}
ans[i][j] = grid[x][y];
}
}
for (int i = 0; i < N; i++)
{
cout << ans[i] << endl;
}
return 0;
}
π D - ABA

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string S;
cin >> S;
int n = S.size();
vector<vector<long long>> pre(n, vector<long long>(26, 0));
for (int i = 1; i < n; i++)
{
for (int j = 0; j < 26; j++)
{
pre[i][j] += pre[i - 1][j] + (S[i - 1] - 'A' == j);
}
}
vector<vector<long long>> suf(n, vector<long long>(26, 0));
for (int i = n - 2; i >= 0; i--)
{
for (int j = 0; j < 26; j++)
{
suf[i][j] += suf[i + 1][j] + (S[i + 1] - 'A' == j);
}
}
long long res = 0;
for (int i = 1; i < n - 1; i++)
{
for (int j = 0; j < 26; j++)
{
res += pre[i][j] * suf[i][j];
}
}
cout << res << endl;
return 0;
}
π E - 3 Team Division

Tips
Let be the minimum number of people who need to switch their teams so that people are assigned to each team and the strengths of teams 1
, 2
and 3
are , and , respectively (if it is impossible, let it )
Naively performing this DP does not finish within the execution time limit. However, considering the sum of strengths of people , it turns out that is uniquely determined given , and . This allows us not to maintain as the index
Tips
In short, the answer can be found with DP, where is the minimum number of people who need to switch their teams so that people are assigned to each team and the strengths of teams 1
and 2
are and
The sought answer is , where
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
vector<long long> A(N), B(N);
long long sum = 0;
for (int i = 0; i < N; i++)
{
cin >> A[i] >> B[i];
sum += B[i];
}
if (sum % 3 != 0)
{
cout << -1 << endl;
return 0;
}
// minimum switches to make team 1 have sum x and team 2 have sum y
vector<vector<long long>> dp(501, vector<long long>(501, 1e9));
// No person assigned, 0 total strength in teams 1 and 2, 0 switches
dp[0][0] = 0;
for (int i = 0; i < N; i++)
{
vector<vector<long long>> ndp(501, vector<long long>(501));
for (int x = 0; x <= 500; x++)
{
for (int y = 0; y <= 500; y++)
{
ndp[x][y] = 1e9;
// Assign to team 1
if (x >= B[i])
{
ndp[x][y] = min(ndp[x][y], dp[x - B[i]][y] + (A[i] != 1));
}
// Assign to team 2
if (y >= B[i])
{
ndp[x][y] = min(ndp[x][y], dp[x][y - B[i]] + (A[i] != 2));
}
// Assign to team 3
ndp[x][y] = min(ndp[x][y], dp[x][y] + (A[i] != 3));
}
}
dp = ndp;
}
cout << (dp[sum / 3][sum / 3] == 1e9 ? -1 : dp[sum / 3][sum / 3]) << endl;
return 0;
}
π F - Road Blocked

Tips
By processing the queries in reverse order, we now how to handle edge-adding queries instead of removal queries
If there is no edge-adding queries, one can do precalculation of Warshall-Floyd algorithm in a total of time to answer each query in time
Tips
When an edge is added between vertices and , the shortest path from vertex to vertex is always one of the following, depending on whether the new edge should be used or not:
- the original path
- the path consisting of a shortest path from to , the edge from to , and the shortest path from to , in this order
- the path consisting of a shortest path from to , the edge from to , and the shortest path from to , in this order
If we know the original all-pair shortest distances, this can be checked in time, for a total of time to update the all-pair shortest distances
// TODO
π G - Road Blocked 2

Warning
Hard Problems to Tackle Later
// TODO