Skip to content

Commit ec2fedc

Browse files
committed
A bunch of problems
1 parent 59f35ad commit ec2fedc

14 files changed

+456
-84
lines changed

APIO/APIO 15-skyscrapers.cpp

+40-71
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,54 @@
1-
#include <iostream>
2-
#include <queue>
3-
#include <set>
4-
#include <vector>
1+
#include <bits/stdc++.h>
2+
#define FOR(i, x, y) for (int i = x; i < y; i++)
3+
typedef long long ll;
54
using namespace std;
6-
priority_queue<pair<int, int>> q1;
7-
const int MAXN = 30010;
8-
set<int> v1[MAXN];
9-
vector<pair<int, int>> g[MAXN];
10-
bool visited[MAXN];
11-
int dp[MAXN];
12-
int target;
13-
14-
int first, jump;
5+
6+
set<int> doges[30000];
7+
vector<pair<int, int>> graph[30000];
8+
int visited[30000];
9+
1510
int main() {
16-
int n, m;
11+
ios_base::sync_with_stdio(0);
12+
cin.tie(0);
13+
int n, m, src, dest;
1714
cin >> n >> m;
18-
for (int i = 0; i < m; i++) {
15+
FOR(i, 0, m) {
1916
int b, p;
2017
cin >> b >> p;
21-
if (i == 0) {
22-
first = b;
23-
jump = p;
24-
}
25-
if (i == 1) {
26-
target = b;
27-
}
28-
29-
v1[b].insert(p);
18+
if (!i) src = b;
19+
if (i == 1) dest = b;
20+
doges[b].insert(p);
3021
}
31-
for (int i = 0; i <= n; i++) {
32-
for (int x : v1[i]) {
33-
int b = i;
34-
int p = x;
35-
int count = 1;
36-
for (int j = b + p; j <= n; j += p) {
37-
if (v1[j].find(p) != v1[j].end()) {
38-
g[b].push_back(make_pair(j, count));
39-
break;
40-
}
41-
g[b].push_back(make_pair(j, count));
42-
count++;
22+
23+
FOR(i, 0, n) {
24+
for (int j : doges[i]) {
25+
for (int k = i + j, cnt = 1; k < n; k += j, cnt++) {
26+
graph[i].push_back({k, cnt});
27+
if (doges[k].find(j) != doges[k].end()) break;
4328
}
44-
count = 1;
45-
for (int j = b - p; j >= 0; j -= p) {
46-
if (v1[j].find(p) != v1[j].end()) {
47-
g[b].push_back(make_pair(j, count));
48-
break;
49-
}
50-
g[b].push_back(make_pair(j, count));
51-
count++;
29+
for (int k = i - j, cnt = 1; k >= 0; k -= j, cnt++) {
30+
graph[i].push_back({k, cnt});
31+
if (doges[k].find(j) != doges[k].end()) break;
5232
}
5333
}
5434
}
55-
q1.push(make_pair(0, first));
56-
for (int i = 0; i <= n; i++) {
57-
dp[i] = 1e9;
58-
}
59-
dp[first] = 0;
60-
61-
while (!q1.empty()) {
62-
auto hold = q1.top();
63-
int skyscraper = hold.second;
64-
int dist = -1 * hold.first;
65-
66-
q1.pop();
67-
if (skyscraper == target) {
68-
cout << dist << endl;
69-
return 0;
70-
}
71-
if (visited[skyscraper]) {
72-
continue;
73-
}
74-
visited[skyscraper] = true;
75-
for (auto x : g[skyscraper]) {
76-
int w = x.second;
77-
int to = x.first;
78-
if (dp[to] > dp[skyscraper] + w) {
79-
dp[to] = dp[skyscraper] + w;
80-
q1.push(make_pair(-1 * dp[to], to));
35+
36+
memset(visited, 0x3f, sizeof visited);
37+
priority_queue<pair<int, int>> pq;
38+
pq.push({0, src});
39+
visited[src] = 0;
40+
while (pq.size()) {
41+
int dist, node;
42+
tie(dist, node) = pq.top();
43+
pq.pop();
44+
if (node == dest) return cout << -dist, 0;
45+
for (pair<int, int> i : graph[node]) {
46+
if (i.second - dist < visited[i.first]) {
47+
visited[i.first] = i.second - dist;
48+
pq.push({dist - i.second, i.first});
8149
}
8250
}
8351
}
84-
cout << -1 << endl;
52+
cout << -1;
53+
return 0;
8554
}

CEOI/CEOI 16-match.cpp

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
CEOI 2016 Match
3+
- Let match(i, j) = Can we make a balanced bracket sequence from s[i:j]?
4+
- First, check if match(0, N - 1) and print -1 if not
5+
- Next, notice how we want to match opening brackets as late as possible
6+
- This means that given s[i:j] where match(i, j), s[i] matches with
7+
the greatest k such that match(k + 1, j) and s[k] == s[i]
8+
- Let opt[j][c] = The greatest k such that match(k + 1, j) and s[k] == c
9+
= j if s[j] == c,
10+
opt[opt[j - 1][s[j]] - 1][c] if j > 0 and opt[j - 1][s[j]] > 0
11+
-1 otherwise
12+
- Clearly, this can be precomputed in O(26N) time and memory
13+
- Now we can recursively solve for the optimal string, since we know we match
14+
s[i] with s[opt[j][s[i]]] for the substring s[i:j]
15+
- Complexity: O(26N)
16+
*/
17+
18+
#include <bits/stdc++.h>
19+
#define FOR(i, x, y) for (int i = x; i < y; i++)
20+
typedef long long ll;
21+
using namespace std;
22+
23+
string s;
24+
int n, opt[100000][26];
25+
char ans[100000];
26+
27+
string solve(int l = 0, int r = n - 1) {
28+
if (l > r) return "";
29+
return '(' + solve(l + 1, opt[r][s[l] - 'a'] - 1) + ')' + solve(opt[r][s[l] - 'a'] + 1, r);
30+
}
31+
32+
int main() {
33+
ios_base::sync_with_stdio(0);
34+
cin.tie(0);
35+
cin >> s;
36+
n = s.size();
37+
stack<char> stck;
38+
FOR(i, 0, n) {
39+
if (stck.size() && s[i] == stck.top()) stck.pop();
40+
else stck.push(s[i]);
41+
FOR(j, 0, 26) {
42+
if (j == s[i] - 'a') opt[i][j] = i;
43+
else if (i && opt[i - 1][s[i] - 'a']) opt[i][j] = opt[opt[i - 1][s[i] - 'a'] - 1][j];
44+
else opt[i][j] = -1;
45+
}
46+
}
47+
if (stck.size()) return cout << -1, 0;
48+
cout << solve();
49+
return 0;
50+
}

COI/COCI 08-periodni.cpp

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
COCI 2008 Periodni
3+
- Notice how if we move from the y row upward, we get "islands" forming
4+
- Each island is independent and is also a smaller periodic table
5+
- This suggests that since the periodic table has no "donuts", we should
6+
compress it into a rooted tree
7+
- Kinda like IOI 2012 Ideal City
8+
- The root node of a periodic table is the largest rectangle we can make from
9+
the y few rows
10+
- We can then recursively generate the rest of the tree
11+
- dp[i][j] = The number of ways to put j noble gases in node i's subtree
12+
- tmp[i][j] = dp[i][j] but we put no noble gases in node i
13+
- dp[i][j] = sum(tmp[i][k] * choose(width[i] - k, j) * choose(height[i], j) * j!)
14+
- Complexity: O(N^2 * K)
15+
*/
16+
17+
#include <bits/stdc++.h>
18+
#define FOR(i, x, y) for (int i = x; i < y; i++)
19+
typedef long long ll;
20+
using namespace std;
21+
22+
const ll MOD = 1e9 + 7;
23+
24+
int n, m = 0, k, h[500];
25+
ll fact[1000001]{1}, inv_fact[1000001]{1};
26+
ll width[500], height[500], dp[500][501], tmp[501];
27+
vector<int> graph[500];
28+
29+
ll expo(ll base, ll pow) {
30+
ll ans = 1;
31+
while (pow) {
32+
if (pow & 1) ans = ans * base % MOD;
33+
pow >>= 1;
34+
base = base * base % MOD;
35+
}
36+
return ans;
37+
}
38+
39+
ll choose(ll x, ll y) {
40+
if (x < y) return 0;
41+
return fact[x] * inv_fact[y] % MOD * inv_fact[x - y] % MOD;
42+
}
43+
44+
void construct_tree(int l = 0, int r = n - 1, int dh = 0) {
45+
int min_h = *min_element(h + l, h + r + 1);
46+
width[m] = r - l + 1;
47+
height[m] = min_h - dh;
48+
49+
int curr_idx = m++, curr_l = l;
50+
FOR(i, l, r + 1) {
51+
if (h[i] == min_h) {
52+
if (curr_l != i) {
53+
graph[curr_idx].push_back(m);
54+
construct_tree(curr_l, i - 1, min_h);
55+
}
56+
curr_l = i + 1;
57+
}
58+
}
59+
if (curr_l != r + 1) {
60+
graph[curr_idx].push_back(m);
61+
construct_tree(curr_l, r, min_h);
62+
}
63+
}
64+
65+
void dfs(int node = 0) {
66+
dp[node][0] = 1;
67+
for (int i : graph[node]) {
68+
dfs(i);
69+
memset(tmp, 0, sizeof tmp);
70+
FOR(j, 0, width[node] + 1) {
71+
FOR(k, 0, width[i] + 1) {
72+
if (j + k > width[node]) continue;
73+
(tmp[j + k] += dp[node][j] * dp[i][k]) %= MOD;
74+
}
75+
}
76+
FOR(j, 0, width[node] + 1) dp[node][j] = tmp[j];
77+
}
78+
79+
memset(tmp, 0, sizeof tmp);
80+
FOR(i, 0, width[node] + 1) {
81+
FOR(j, 0, width[node] + 1) {
82+
if (i + j > width[node]) continue;
83+
ll x = dp[node][i];
84+
ll y = choose(width[node] - i, j) * choose(height[node], j) % MOD * fact[j] % MOD;
85+
(tmp[i + j] += x * y) %= MOD;
86+
}
87+
}
88+
FOR(i, 0, width[node] + 1) dp[node][i] = tmp[i];
89+
}
90+
91+
int main() {
92+
ios_base::sync_with_stdio(0);
93+
cin.tie(0);
94+
FOR(i, 1, 1000001) {
95+
fact[i] = fact[i - 1] * i % MOD;
96+
inv_fact[i] = expo(fact[i], MOD - 2);
97+
}
98+
99+
cin >> n >> k;
100+
FOR(i, 0, n) cin >> h[i];
101+
construct_tree();
102+
dfs();
103+
cout << dp[0][k];
104+
return 0;
105+
}
File renamed without changes.

LMIO/LMIO 18-menesinis_bilietas.cpp

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
LMIO 2018 Menesinis Bilietas
3+
- DSU
4+
- Complexity: O(N)
5+
*/
6+
7+
#include <bits/stdc++.h>
8+
#define FOR(i, x, y) for (int i = x; i < y; i++)
9+
typedef long long ll;
10+
using namespace std;
11+
12+
int cmp[500001], cmp_cnt;
13+
set<int> graph[500001];
14+
15+
int find(int A) {
16+
while (A != cmp[A]) cmp[A] = cmp[cmp[A]], A = cmp[A];
17+
return A;
18+
}
19+
20+
void onion(int A, int B) {
21+
if (find(A) == find(B)) return;
22+
cmp[find(A)] = find(B);
23+
cmp_cnt--;
24+
}
25+
26+
int main() {
27+
ios_base::sync_with_stdio(0);
28+
cin.tie(0);
29+
int n, m;
30+
cin >> n >> m;
31+
iota(cmp, cmp + n + 1, 0);
32+
cmp_cnt = n;
33+
vector<pair<int, int>> bus;
34+
while (m--) {
35+
int u, v;
36+
char t;
37+
cin >> u >> v >> t;
38+
if (t == 'A') bus.push_back({u, v});
39+
else onion(u, v);
40+
}
41+
for (pair<int, int> i : bus) {
42+
if (find(i.first) == find(i.second)) continue;
43+
graph[find(i.first)].insert(find(i.second));
44+
graph[find(i.second)].insert(find(i.first));
45+
}
46+
47+
int ans = 0;
48+
FOR(i, 1, n + 1) if (graph[find(i)].size() == cmp_cnt - 1) ans++;
49+
cout << ans;
50+
return 0;
51+
}

LMIO/LMIO 18-pigus_skrydziai.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
LMIO 2018 Pigus Skrydziai
3+
- We either take all edges incident to one node or we take a triangle
4+
- Complexity: O(N log N)
5+
*/
6+
7+
#include <bits/stdc++.h>
8+
#define FOR(i, x, y) for (int i = x; i < y; i++)
9+
typedef long long ll;
10+
using namespace std;
11+
12+
ll prof[300001];
13+
vector<pair<ll, int>> graph[300001];
14+
map<pair<int, int>, ll> edges;
15+
16+
int main() {
17+
ios_base::sync_with_stdio(0);
18+
cin.tie(0);
19+
int n, m;
20+
cin >> n >> m;
21+
while (m--) {
22+
int a, b;
23+
ll v;
24+
cin >> a >> b >> v;
25+
prof[a] += v, prof[b] += v;
26+
graph[a].push_back({v, b});
27+
graph[b].push_back({v, a});
28+
edges[{a, b}] = edges[{b, a}] = v;
29+
}
30+
ll ans = *max_element(prof + 1, prof + n + 1);
31+
FOR(i, 1, n + 1) {
32+
sort(graph[i].begin(), graph[i].end(), greater<pair<ll, int>>());
33+
if (graph[i].size() > 1) {
34+
ans = max(ans, graph[i][0].first + graph[i][1].first +
35+
edges[{graph[i][0].second, graph[i][1].second}]);
36+
}
37+
}
38+
cout << ans;
39+
return 0;
40+
}

LMIO/LMIO 19-bulves.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
22
LMIO 2019 Bulves
33
- We want to transform the arrays A so that A[i] >= B[i] for each i
4-
- This means if we define the array C[i] = A[i] - B[i], then C is a
5-
non-decreasing sequence and 0 <= C[i] <= C[N]
4+
- This means if we define the array C[i] = A[i] - B[i], then C must become a
5+
non-decreasing sequence with 0 <= C[i] <= C[N]
66
- Notice how each time we move a fertilizer to an adjacent position, exactly
77
1 element of C changes and we increment the cost by 1
88
- This problem thus turns into https://codeforces.com/contest/713/problem/C and

0 commit comments

Comments
 (0)