Skip to content

Commit 1649ca9

Browse files
Add files via upload
1 parent ad80596 commit 1649ca9

File tree

4 files changed

+210
-0
lines changed

4 files changed

+210
-0
lines changed

COI/COCI 21-alias.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
COCI 2021 Alias
3+
- Map each word to an integer, and do Dijkstra's
4+
- Complexity: O(QN log N)
5+
*/
6+
7+
#include <bits/stdc++.h>
8+
typedef long long ll;
9+
using namespace std;
10+
11+
map<string, int> mp;
12+
vector<pair<int, ll>> graph[1000];
13+
ll visited[1000];
14+
15+
int main() {
16+
cin.tie(0)->sync_with_stdio(0);
17+
int n, m, cnt = 0;
18+
cin >> n >> m;
19+
while (m--) {
20+
string s, t;
21+
ll v;
22+
cin >> s >> t >> v;
23+
if (!mp.count(s)) mp[s] = cnt++;
24+
if (!mp.count(t)) mp[t] = cnt++;
25+
graph[mp[s]].push_back({mp[t], v});
26+
}
27+
int q;
28+
cin >> q;
29+
while (q--) {
30+
string s, t;
31+
cin >> s >> t;
32+
int src = mp[s], dest = mp[t];
33+
memset(visited, 0x3f, sizeof visited);
34+
priority_queue<pair<ll, int>> pq;
35+
visited[src] = 0;
36+
pq.push({0, src});
37+
bool found = false;
38+
while (pq.size()) {
39+
ll cost;
40+
int node;
41+
tie(cost, node) = pq.top();
42+
pq.pop();
43+
if (-cost != visited[node]) continue;
44+
if (node == dest) {
45+
found = true;
46+
cout << -cost << '\n';
47+
break;
48+
}
49+
for (pair<int, ll> i : graph[node]) if (i.second - cost < visited[i.first]) {
50+
visited[i.first] = i.second - cost;
51+
pq.push({cost - i.second, i.first});
52+
}
53+
}
54+
if (!found) cout << "Roger\n";
55+
}
56+
return 0;
57+
}

COI/COCI 21-anagramistica.cpp

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
COCI 2021 Anagramistica
3+
- Sort each word and accumulate a frequency table
4+
- dp[i][j] = Ways to choose from the first i types of words
5+
and have j similar pairs
6+
= sum(dp[i - 1][j - (k choose 2)] * (cnt[i] choose k))
7+
- Complexity: O(NK * sqrt(N))?
8+
*/
9+
10+
#include <bits/stdc++.h>
11+
typedef long long ll;
12+
using namespace std;
13+
14+
const ll MOD = 1e9 + 7;
15+
16+
ll expo(ll base, ll pow) {
17+
ll ans = 1;
18+
while (pow) {
19+
if (pow & 1) ans = ans * base % MOD;
20+
pow >>= 1;
21+
base = base * base % MOD;
22+
}
23+
return ans;
24+
}
25+
26+
ll fact[2001], chs[2001], dp[2001][2001];
27+
map<string, int> mp;
28+
int cnt[2001];
29+
30+
int main() {
31+
cin.tie(0)->sync_with_stdio(0);
32+
int n, k;
33+
cin >> n >> k;
34+
fact[0] = 1;
35+
for (int i = 1; i <= k; i++) fact[i] = fact[i - 1] * i % MOD;
36+
while (n--) {
37+
string s;
38+
cin >> s;
39+
sort(s.begin(), s.end());
40+
mp[s]++;
41+
}
42+
int m = 0;
43+
for (auto i : mp) cnt[++m] = i.second;
44+
dp[0][0] = 1;
45+
for (int i = 1; i <= m; i++) {
46+
chs[0] = 1;
47+
for (int j = 1; j <= cnt[i]; j++)
48+
chs[j] = chs[j - 1] * (cnt[i] - j + 1) % MOD * expo(j, MOD - 2) % MOD;
49+
50+
for (int j = 0; j <= k; j++) {
51+
for (int l = 0; l <= cnt[i]; l++) {
52+
if (l * (l - 1) / 2 > j) break;
53+
dp[i][j] += dp[i - 1][j - l * (l - 1) / 2] * chs[l] % MOD;
54+
if (dp[i][j] >= MOD) dp[i][j] -= MOD;
55+
}
56+
}
57+
}
58+
cout << dp[m][k];
59+
return 0;
60+
}

COI/COCI 21-bold.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
COCI 2021 Bold
3+
- Just do it
4+
*/
5+
6+
#include <bits/stdc++.h>
7+
typedef long long ll;
8+
using namespace std;
9+
10+
string grid[100];
11+
12+
int main() {
13+
cin.tie(0)->sync_with_stdio(0);
14+
int n, m;
15+
cin >> n >> m;
16+
for (int i = 0; i < n; i++) cin >> grid[i];
17+
for (int i = n - 2; ~i; i--) for (int j = m - 2; ~j; j--) if (grid[i][j] == '#')
18+
grid[i][j + 1] = grid[i + 1][j] = grid[i + 1][j + 1] = '#';
19+
for (int i = 0; i < n; i++) cout << grid[i] << '\n';
20+
return 0;
21+
}

COI/COCI 21-index.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
COCI 2021 Index
3+
- Let paper i be a point (i, p[i]) in the Cartesian plane
4+
- A query is basically finding the largest M such that the number of points
5+
in the rectangle (l[j], 2e5)->(r[j], M) is at least M
6+
- We can binary search for M and use a persistent segment tree to do static
7+
2D range sum queries
8+
- Complexity: O(N log^2 N)
9+
*/
10+
11+
#include <bits/stdc++.h>
12+
using namespace std;
13+
14+
const int MX = 2e5 + 1;
15+
16+
struct Node {
17+
int l, r, cnt;
18+
Node *lc, *rc;
19+
20+
Node(int x, int c = 0): l(x), r(x), cnt(c), lc(nullptr), rc(nullptr) {}
21+
Node(Node *llc, Node *rrc) {
22+
lc = llc, rc = rrc;
23+
l = lc->l, r = rc->r;
24+
cnt = lc->cnt + rc->cnt;
25+
}
26+
};
27+
28+
Node *build(int l = 1, int r = MX) {
29+
if (l == r) return new Node(l);
30+
int mid = (l + r) >> 1;
31+
return new Node(build(l, mid), build(mid + 1, r));
32+
}
33+
34+
Node *increment(Node *node, int pos, int l = 1, int r = MX) {
35+
if (l == r) return new Node(l, node->cnt + 1);
36+
int mid = (l + r) >> 1;
37+
if (pos > mid) return new Node(node->lc, increment(node->rc, pos, mid + 1, r));
38+
return new Node(increment(node->lc, pos, l, mid), node->rc);
39+
}
40+
41+
int query(Node *node, int pos, int l = 1, int r = MX) {
42+
if (r < pos) return 0;
43+
if (l >= pos) return node->cnt;
44+
int mid = (l + r) >> 1;
45+
return query(node->lc, pos, l, mid) + query(node->rc, pos, mid + 1, r);
46+
}
47+
48+
int n, q, p[MX];
49+
Node *persist_roots[MX];
50+
51+
int main() {
52+
cin.tie(0)->sync_with_stdio(0);
53+
cin >> n >> q;
54+
for (int i = 1; i <= n; i++) cin >> p[i];
55+
persist_roots[0] = build();
56+
for (int i = 1; i <= n; i++) persist_roots[i] = increment(persist_roots[i - 1], p[i]);
57+
58+
while (q--) {
59+
int x, y;
60+
cin >> x >> y;
61+
int l = 1, r = y - x + 1;
62+
while (l != r) {
63+
int mid = (l + r + 1) >> 1;
64+
if (query(persist_roots[y], mid) - query(persist_roots[x - 1], mid) >= mid)
65+
l = mid;
66+
else
67+
r = mid - 1;
68+
}
69+
cout << l << '\n';
70+
}
71+
return 0;
72+
}

0 commit comments

Comments
 (0)