Skip to content

Commit 5152115

Browse files
committed
Stuff
1 parent 85ce78d commit 5152115

File tree

4 files changed

+145
-11
lines changed

4 files changed

+145
-11
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# .vscode/
1+
.vscode/

.vscode/c_cpp_properties.json

+8-10
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,18 @@
44
"name": "Win32",
55
"includePath": [
66
"${workspaceFolder}/**",
7-
"C:\\MinGW\\lib\\gcc\\mingw32\\9.2.0\\include\\c++",
8-
"C:\\MinGW\\lib\\gcc\\mingw32\\9.2.0\\include\\c++\\mingw32",
9-
"C:\\MinGW\\include"
10-
],
11-
"defines": [
12-
"_DEBUG",
13-
"UNICODE",
14-
"_UNICODE"
7+
"C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++",
8+
"C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/i686-w64-mingw32",
9+
"C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/include",
10+
"C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include",
11+
"C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/i686-w64-mingw32/include",
1512
],
13+
"defines": ["_DEBUG", "UNICODE", "_UNICODE"],
1614
"windowsSdkVersion": "10.0.18362.0",
17-
"compilerPath": "C:\\MinGW\\bin\\g++.exe",
15+
"compilerPath": "C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/g++.exe",
1816
"cStandard": "c17",
1917
"cppStandard": "c++17",
20-
"intelliSenseMode": "gcc-x64"
18+
"intelliSenseMode": "gcc-x86"
2119
}
2220
],
2321
"version": 4

IOI/IOI 17-books.cpp

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
IOI 2017 Ancient Books
3+
- The base cost will be sum(|P[i] - i|) for each i
4+
- Case S = 0:
5+
- Consider the cycles formed from the permutation
6+
- If two cycles "overlap", then Aryan can sort them simultaneously at no extra cost
7+
- We can thus "merge" overlapping cycles and discard any books that Aryan won't walk past
8+
- The extra cost will be 2 * (No. of unmerged cycles - 1)
9+
- We can extend this idea to work with S != 0
10+
- Let extend(l, r) = Given l and r, find the bounds of the merged cycle containing [l, r]
11+
- We can compute extend(l, r) in amortized linear time
12+
- Let dp[l, r] = Minimum extra cost Aryan needs given that all books in [l, r] are sorted
13+
= 0 if [l, r] == The entire range of books Aryan needs to sort
14+
2 + min(dp[extend(l - 1, r)], dp[extend(l, r + 1)]) otherwise
15+
- We can reduce the number of states we visit by noticing that if extend(l - 1, r)^x contains
16+
extend(l, r + 1) and extend(l, r + 1)^y contains extend(l - 1, r), then we know that
17+
extend(l - 1, r)^x == extend(l, r + 1)^y
18+
- This means that the extra cost is simply 2 * min(x, y), and we can find each min(x, y) for
19+
each [l, r] in amortized linear time
20+
- Complexity: O(N)
21+
*/
22+
23+
#include "books.h"
24+
25+
#include <bits/stdc++.h>
26+
typedef long long ll;
27+
using namespace std;
28+
29+
int crit_l, crit_r;
30+
int cmp[1000000], cmp_l[1000000], cmp_r[1000000];
31+
32+
void extend(int &l, int &r) {
33+
int ext_l = min(cmp_l[cmp[l]], cmp_l[cmp[r]]);
34+
int ext_r = max(cmp_r[cmp[l]], cmp_r[cmp[r]]);
35+
while (l != ext_l || r != ext_r) {
36+
if (l != ext_l) {
37+
l--;
38+
ext_l = min(ext_l, cmp_l[cmp[l]]);
39+
ext_r = max(ext_r, cmp_r[cmp[l]]);
40+
} else {
41+
r++;
42+
ext_l = min(ext_l, cmp_l[cmp[r]]);
43+
ext_r = max(ext_r, cmp_r[cmp[r]]);
44+
}
45+
}
46+
}
47+
48+
ll compute(int l, int r) {
49+
extend(l, r);
50+
if (l == crit_l && r == crit_r) return 0;
51+
if (l == crit_l) return compute(l, r + 1) + 2;
52+
if (r == crit_r) return compute(l - 1, r) + 2;
53+
54+
ll to_l = 2;
55+
int nl = l - 1, nr = r, tl = l, tr = r + 1;
56+
extend(nl, nr), extend(tl, tr);
57+
while (nl != crit_l && nr < tr) {
58+
to_l += 2;
59+
nl--;
60+
extend(nl, nr);
61+
}
62+
if (nr < tr) return to_l + compute(nl, nr);
63+
64+
ll to_r = 2;
65+
nl = l, nr = r + 1, tl = l - 1, tr = r;
66+
extend(nl, nr), extend(tl, tr);
67+
while (nl > tl) {
68+
to_r += 2;
69+
nr++;
70+
extend(nl, nr);
71+
}
72+
return min(to_l, to_r) + compute(nl, nr);
73+
}
74+
75+
ll minimum_walk(vector<int> p, int s) {
76+
int n = p.size(), cmp_cnt = 0;
77+
fill(cmp, cmp + n, -1);
78+
crit_l = s, crit_r = s;
79+
ll intra = 0;
80+
for (int i = 0; i < n; i++) {
81+
intra += abs(p[i] - i);
82+
if (cmp[i] == -1) {
83+
int curr = i;
84+
cmp_l[cmp_cnt] = cmp_r[cmp_cnt] = i;
85+
do {
86+
cmp[curr] = cmp_cnt;
87+
cmp_r[cmp_cnt] = max(cmp_r[cmp_cnt], curr);
88+
curr = p[curr];
89+
} while (curr != i);
90+
if (i != p[i]) {
91+
crit_l = min(crit_l, cmp_l[cmp_cnt]);
92+
crit_r = max(crit_r, cmp_r[cmp_cnt]);
93+
}
94+
cmp_cnt++;
95+
}
96+
}
97+
return intra + compute(s, s);
98+
}

infoarena/infoarena matcnt.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Infoarena matcnt
3+
- Firstly, the order of the rows doesn't matter because we can permute them, so just
4+
multiply the answer by N! at the end
5+
- Consider a graph with N nodes and an edge between u and v if some row in our matrix
6+
has the 1s in columns u and v
7+
- Each node in this graph has 2 edges going to 2 different nodes
8+
- This means the graph is made up of several simple cycles of length >= 3
9+
- To count how many of these graphs there are, let dp[i] be the answer for i nodes
10+
- dp[3] = 1
11+
- dp[i + 1] += dp[i] * i If we append node (i + 1) to some cycle
12+
- dp[i + 3] += dp[i] * (i + 2 choose 2) If we create a new 3-cycle with node (i + 3)
13+
- We can thus calculate dp[N] in linear time
14+
- Complexity: O(N)
15+
*/
16+
17+
#include <bits/stdc++.h>
18+
typedef long long ll;
19+
using namespace std;
20+
21+
const ll MOD = 2e5 + 3;
22+
23+
ll dp[100004], fact = 6;
24+
25+
int main() {
26+
ifstream cin("matcnt.in");
27+
ofstream cout("matcnt.out");
28+
int n;
29+
cin >> n;
30+
dp[3] = 1;
31+
for (ll i = 3; i < n; i++) {
32+
dp[i + 1] = (dp[i + 1] + dp[i] * i) % MOD;
33+
dp[i + 3] = (dp[i + 3] + dp[i] * (i + 1) * (i + 2) / 2) % MOD;
34+
fact = fact * (i + 1) % MOD;
35+
}
36+
cout << dp[n] * fact % MOD;
37+
return 0;
38+
}

0 commit comments

Comments
 (0)