Skip to content

Commit 98ecb17

Browse files
committed
USACO 2021 + CSES problems
1 parent 0a1bf7f commit 98ecb17

File tree

4 files changed

+278
-0
lines changed

4 files changed

+278
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <bits/stdc++.h>
2+
using namespace std;
3+
4+
vector<int> graph[100001];
5+
int visited[100001], odd[100001], timer = 1;
6+
vector<pair<int, int>> ans;
7+
8+
void dfs(int node, int parent = 0) {
9+
visited[node] = timer++;
10+
for (int i : graph[node]) if (i != parent) {
11+
if (!visited[i]) {
12+
dfs(i, node);
13+
if (odd[i]) {
14+
ans.push_back({i, node});
15+
odd[i] = 0;
16+
} else {
17+
ans.push_back({node, i});
18+
odd[node] ^= 1;
19+
}
20+
} else if (visited[node] > visited[i]) {
21+
ans.push_back({node, i});
22+
odd[node] ^= 1;
23+
}
24+
}
25+
}
26+
27+
int main() {
28+
cin.tie(0)->sync_with_stdio(0);
29+
int n, m;
30+
scanf("%d %d", &n, &m);
31+
while (m--) {
32+
int u, v;
33+
scanf("%d %d", &u, &v);
34+
graph[u].push_back(v);
35+
graph[v].push_back(u);
36+
}
37+
for (int i = 1; i <= n; i++) if (!visited[i]) dfs(i);
38+
if (accumulate(odd + 1, odd + n + 1, 0)) printf("IMPOSSIBLE");
39+
else for (pair<int, int> i : ans) printf("%d %d\n", i.first, i.second);
40+
return 0;
41+
}

CSES/(7) Mathematics/2185.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <bits/stdc++.h>
2+
typedef long long ll;
3+
using namespace std;
4+
5+
ll a[20];
6+
7+
int main() {
8+
cin.tie(0)->sync_with_stdio(0);
9+
ll n;
10+
int k;
11+
cin >> n >> k;
12+
for (int i = 0; i < k; i++) cin >> a[i];
13+
ll ans = 0;
14+
for (int mask = 1; mask < (1 << k); mask++) {
15+
int mult = 1 - 2 * (__builtin_popcount(mask) & 1);
16+
ll tmp = n;
17+
for (int i = 0; i < k; i++) if (mask & (1 << i)) tmp /= a[i];
18+
ans += mult * tmp;
19+
}
20+
cout << abs(ans);
21+
return 0;
22+
}

USACO/USACO 21-paint.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
USACO 2021 Paint by Letters
3+
- http://usaco.org/current/data/sol_prob3_platinum_jan21.html
4+
- Very cool problem; whoever made it deserves a medal ;)
5+
- Complexity: O(NM + Q(N + M))
6+
*/
7+
8+
#include <bits/stdc++.h>
9+
using namespace std;
10+
11+
int n, m, q;
12+
char grid[2001][2001];
13+
pair<int, int> cmp[2002][2002], d[4]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
14+
int s_pref[2002][2002], v_pref[2002][2002], h_pref[2002][2002];
15+
bool deleted[2002][2002];
16+
17+
bool inside(int x, int y, int nx, int ny) {
18+
if (!(~nx && ~ny && nx <= n + 1 && ny <= m + 1)) return false;
19+
if (nx == x + 1) return grid[x][y] != grid[x][y - 1];
20+
if (nx == x - 1) return grid[nx][y] != grid[nx][y - 1];
21+
if (ny == y + 1) return grid[x][y] != grid[x - 1][y];
22+
return grid[x][ny] != grid[x - 1][ny];
23+
}
24+
25+
void dfs(int x, int y) {
26+
for (int i = 0; i < 4; i++) {
27+
int nx = x + d[i].first, ny = y + d[i].second;
28+
if (inside(x, y, nx, ny)) {
29+
if (nx == x + 1) v_pref[x][y] = 1;
30+
else if (nx == x - 1) v_pref[nx][y] = 1;
31+
else if (ny == y + 1) h_pref[x][y] = 1;
32+
else h_pref[x][ny] = 1;
33+
34+
if (!cmp[nx][ny].first) {
35+
cmp[nx][ny] = cmp[x][y];
36+
dfs(nx, ny);
37+
}
38+
}
39+
}
40+
}
41+
42+
bool bad(int x, int y, int x1, int y1, int x2, int y2) {
43+
int a = cmp[x][y].first, b = cmp[x][y].second;
44+
if (a > x1 && a <= x2 && b > y1 && b <= y2 && !deleted[a][b]) {
45+
deleted[a][b] = true;
46+
return true;
47+
}
48+
return false;
49+
}
50+
51+
void reset(int x, int y) {
52+
int a = cmp[x][y].first, b = cmp[x][y].second;
53+
deleted[a][b] = false;
54+
}
55+
56+
int main() {
57+
cin.tie(0)->sync_with_stdio(0);
58+
cin >> n >> m >> q;
59+
for (int i = 1; i <= n; i++)
60+
for (int j = 1; j <= m; j++)
61+
cin >> grid[i][j];
62+
for (int i = 1; i <= n + 1; i++)
63+
for (int j = 1; j <= m + 1; j++)
64+
if (!cmp[i][j].first) {
65+
s_pref[i][j] = 1;
66+
cmp[i][j] = {i, j};
67+
dfs(i, j);
68+
}
69+
for (int i = 1; i <= n + 1; i++)
70+
for (int j = 1; j <= m + 1; j++) {
71+
s_pref[i][j] += s_pref[i - 1][j] + s_pref[i][j - 1] - s_pref[i - 1][j - 1];
72+
v_pref[i][j] += v_pref[i - 1][j] + v_pref[i][j - 1] - v_pref[i - 1][j - 1];
73+
h_pref[i][j] += h_pref[i - 1][j] + h_pref[i][j - 1] - h_pref[i - 1][j - 1];
74+
}
75+
while (q--) {
76+
int x1, x2, y1, y2;
77+
cin >> x1 >> y1 >> x2 >> y2;
78+
int E = v_pref[x2][y2] - v_pref[x2][y1] - v_pref[x1 - 1][y2] + v_pref[x1 - 1][y1] +
79+
h_pref[x2][y2] - h_pref[x2][y1 - 1] - h_pref[x1][y2] + h_pref[x1][y1 - 1];
80+
int V = (x2 - x1) * (y2 - y1);
81+
int C = s_pref[x2][y2] - s_pref[x2][y1] - s_pref[x1][y2] + s_pref[x1][y1];
82+
for (int i = x1; i <= x2 + 1; i++) {
83+
if (bad(i, y2 + 1, x1, y1, x2, y2)) C--;
84+
if (bad(i, y1, x1, y1, x2, y2)) C--;
85+
}
86+
for (int i = y1; i <= y2 + 1; i++) {
87+
if (bad(x2 + 1, i, x1, y1, x2, y2)) C--;
88+
if (bad(x1, i, x1, y1, x2, y2)) C--;
89+
}
90+
for (int i = x1; i <= x2 + 1; i++) {
91+
reset(i, y2 + 1);
92+
reset(i, y1);
93+
}
94+
for (int i = y1; i <= y2 + 1; i++) {
95+
reset(x2 + 1, i);
96+
reset(x1, i);
97+
}
98+
cout << E - V + C + 1 << '\n';
99+
}
100+
return 0;
101+
}

USACO/USACO 21-sumdist.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
USACO 2021 Sum of Distances
3+
- The distance to a K-tuple (v[1], v[2], ..., v[K]) from (1, 1, ..., 1) is
4+
min(max(1 -> v[i] where the path is even), max(1 -> v[i] where the path is odd))
5+
- We can use a segtree/BIT + DP to compute sum(max(1 -> v[i] where the path is even) for each tuple)
6+
- First, sort the graphs by size
7+
- Let dp[i][j] be the number of i-tuples (i.e. from the first i graphs) with *even* distance j
8+
- First, compute dp[i][j] = sum(dp[i - 1][l] where l <= j)
9+
- Next, update dp[i][j] = (No. of even paths from node 1 in graph i of length < j) * dp[i - 1][j]
10+
- dp[K][j] will be the number of K-tuples with *even* distance j, so we can just iterate through dp[K]
11+
- Similar logic holds for the odd-distance tuples
12+
- What if a tuple can be reached in both even *and* odd distance though?
13+
- If that happens, then we overcount the path with length max(even[i], odd[i] for each i), so just do
14+
the above DP again but with maximums instead of evens/odds, and subtract that value from our answer
15+
- This is kinda like PIE
16+
- Complexity: O(sum(N) log sum(N))
17+
*/
18+
19+
#include <bits/stdc++.h>
20+
typedef long long ll;
21+
using namespace std;
22+
23+
const ll MOD = 1e9 + 7;
24+
25+
int k, n[50001], order[50001];
26+
vector<ll> segtree[50001];
27+
28+
ll query(int a, int b, int tree, int node, int l, int r) {
29+
if (l > b || r < a) return 0;
30+
if (l >= a && r <= b) return segtree[tree][node];
31+
int mid = (l + r) / 2;
32+
return (query(a, b, tree, node * 2, l, mid) + query(a, b, tree, node * 2 + 1, mid + 1, r)) % MOD;
33+
}
34+
35+
void update(int pos, ll val, int tree, int node, int l, int r) {
36+
if (l == r) segtree[tree][node] = (segtree[tree][node] + val) % MOD;
37+
else {
38+
int mid = (l + r) / 2;
39+
if (pos > mid) update(pos, val, tree, node * 2 + 1, mid + 1, r);
40+
else update(pos, val, tree, node * 2, l, mid);
41+
segtree[tree][node] = (segtree[tree][node * 2] + segtree[tree][node * 2 + 1]) % MOD;
42+
}
43+
}
44+
45+
void reset(int tree) { segtree[tree].clear(); segtree[tree].resize(8 * n[tree]); }
46+
47+
ll compute_sum(vector<pair<int, int>> dists) {
48+
vector<vector<int>> graphs(k);
49+
for (pair<int, int> i : dists) graphs[i.second].push_back(i.first);
50+
51+
reset(order[0]);
52+
for (int i : graphs[order[0]]) update(i, 1, order[0], 1, 0, 2 * n[order[0]] - 1);
53+
54+
for (int i = 1; i < k; i++) {
55+
reset(order[i]);
56+
vector<int> pref(2 * n[order[i]], 0);
57+
for (int j : graphs[order[i]]) {
58+
update(j, query(0, j, order[i - 1], 1, 0, 2 * n[order[i - 1]] - 1), order[i], 1, 0, 2 * n[order[i]] - 1);
59+
pref[j]++;
60+
}
61+
for (int j = 1; j < 2 * n[order[i]]; j++) {
62+
pref[j] += pref[j - 1];
63+
update(j, pref[j - 1] * query(j, j, order[i - 1], 1, 0, 2 * n[order[i - 1]] - 1) % MOD, order[i], 1, 0, 2 * n[order[i]] - 1);
64+
}
65+
}
66+
67+
ll ans = 0;
68+
for (int i = 1; i < 2 * n[order[k - 1]]; i++)
69+
ans = (ans + query(i, 2 * n[order[k - 1]] - 1, order[k - 1], 1, 0, 2 * n[order[k - 1]] - 1)) % MOD;
70+
return ans;
71+
}
72+
73+
int main() {
74+
cin.tie(0)->sync_with_stdio(0);
75+
cin >> k;
76+
vector<pair<int, int>> even, odd, mx;
77+
for (int i = 0; i < k; i++) {
78+
order[i] = i;
79+
int m;
80+
cin >> n[i] >> m;
81+
vector<vector<int>> graph(2 * n[i]);
82+
vector<int> visited(2 * n[i]);
83+
while (m--) {
84+
int u, v;
85+
cin >> u >> v;
86+
u--, v--;
87+
graph[u].push_back(n[i] + v);
88+
graph[v].push_back(n[i] + u);
89+
graph[n[i] + u].push_back(v);
90+
graph[n[i] + v].push_back(u);
91+
}
92+
// BFS to get even and odd distances
93+
visited[0] = 1;
94+
queue<int> q;
95+
q.push(0);
96+
while (q.size()) {
97+
int curr = q.front();
98+
q.pop();
99+
for (int j : graph[curr]) if (!visited[j]) {
100+
visited[j] = visited[curr] + 1;
101+
q.push(j);
102+
}
103+
}
104+
// Append to the distance lists
105+
for (int j = 0; j < n[i]; j++) {
106+
if (visited[j]) even.push_back({visited[j] - 1, i});
107+
if (visited[n[i] + j]) odd.push_back({visited[n[i] + j] - 1, i});
108+
if (visited[j] && visited[n[i] + j]) mx.push_back({max(visited[j], visited[n[i] + j]) - 1, i});
109+
}
110+
}
111+
sort(order, order + k, [](int a, int b) { return n[a] < n[b]; });
112+
cout << (compute_sum(even) + compute_sum(odd) - compute_sum(mx) + MOD) % MOD;
113+
return 0;
114+
}

0 commit comments

Comments
 (0)