Skip to content

Commit b7b260b

Browse files
authoredFeb 18, 2024
Merge pull request #4314 from stefdasca/master
Updating and adding information for several Romanian or regional contests involving Romania
2 parents 606b609 + dd71371 commit b7b260b

File tree

5 files changed

+222
-9
lines changed

5 files changed

+222
-9
lines changed
 

‎content/1_General/Olympiads.mdx

+17-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ links.
8888
- [oj.uz](https://oj.uz/problems/source)
8989
- All problems from 2014-2019.
9090

91+
### [Romanian NOI](https://sepi.ro/) (Romanian)
92+
93+
- [Kilonova](https://kilonova.ro/problem_lists/524)
94+
- Every national olympiad problem from 2002 onwards.
95+
- [Kilonova](https://kilonova.ro/problem_lists/225)
96+
- Every Romanian IOI TST problem from early 2000s onwards.
97+
- [Kilonova](https://kilonova.ro/problem_lists/689)
98+
- Every Romanian EJOI/JBOI junior TST problem from 2008 onwards.
99+
100+
### [IIOT](https://iio.team/)
101+
102+
- [Kilonova](https://kilonova.ro/problem_lists/128)
103+
- Most Romanian problems from 2019 onwards.
104+
- [olinfo.it](https://training.olinfo.it/#/tasks/1?tag=ois)
105+
- Most Italian problems from 2016 onwards.
106+
91107
<!--
92108
<Warning>
93109

@@ -114,7 +130,7 @@ Solutions from POI problems are unfortunately only available in Polish.
114130
### Other
115131

116132
- [Italy](https://training.olinfo.it/#/overview)
117-
- [International Informatics Olympiad in Teams](http://ioit.altervista.org/2018-teams-and-contests-.html)
133+
- [International Informatics Olympiad in Teams](https://iio.team/)
118134
- [Balkan Olympiad in Informatics](https://boi2019.epy.gr/)
119135
- [InfO(1) Cup](http://info1cup.com/)
120136

‎content/4_Gold/Stacks.problems.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,15 @@
164164
}
165165
},
166166
{
167-
"uniqueId": "infoarena-ssdj",
167+
"uniqueId": "kilonova-ssdj",
168168
"name": "ssdj",
169-
"url": "https://infoarena.ro/problema/ssdj",
170-
"source": "InfoArena",
169+
"url": "https://kilonova.ro/problems/1976",
170+
"source": "Kilonova",
171171
"difficulty": "Very Hard",
172172
"isStarred": false,
173173
"tags": ["Stack"],
174174
"solutionMetadata": {
175-
"kind": "none"
175+
"kind": "internal"
176176
}
177177
},
178178
{

‎content/6_Advanced/DP_SOS.problems.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@
5252
}
5353
},
5454
{
55-
"uniqueId": "infoarena-xortransform",
55+
"uniqueId": "kilonova-xortransform",
5656
"name": "xortransform",
57-
"url": "https://infoarena.ro/problema/xortransform",
58-
"source": "InfoArena",
57+
"url": "https://kilonova.ro/problems/1832",
58+
"source": "kilonova",
5959
"difficulty": "Hard",
6060
"isStarred": true,
6161
"tags": ["Bitmasks", "DP", "NT"],
6262
"solutionMetadata": {
63-
"kind": "none"
63+
"kind": "internal"
6464
}
6565
},
6666
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
id: kilonova-xortransform
3+
source: Romania IOI selection test 2018
4+
title: xortransform
5+
author: Stefan Dascalescu
6+
---
7+
8+
[Official Analysis (in Romanian)](https://github.com/roalgo-discord/Romanian-Olympiad-Solutions/blob/main/Baraj%20%2B%20Lot%20Seniori%20(IOI%20team%20selection%20tests)/2018/Lot%202/descriere_xortransform.pdf)
9+
10+
## Explanation
11+
12+
After running the brute force solution, one can observe that the period of how matrix looks like is the smallest power of two such that it's greater than both $n$ and $m$.
13+
14+
Also, we can reduce the problem to finding the xor-sum of the elements in positions such that the number of roads from $(0, 0)$ to $(i, j)$ in $k$ steps is odd, where $k$ is the number of transformations done.
15+
16+
This is equal to $C(k, i) \cdot C(k, j)$, where $C(n, k)$ is $n$ choose $k$. Also, if $C(n, k)$ is odd, then $n \& k = k$ (this can also be observed by brute-force).
17+
18+
Also, if $C(n, i)$ and $C(n, j)$ are odd, then $C(n, i|j)$ is odd as well, so we can reduce the problem to SOS DP, where $SOS[i]$ = xorsum of elements which are in positions included by $i$.
19+
20+
For each bit of the period, $SOS[i] = SOS[i - 2^{position}] \oplus SOS[i]$, if $i$ has the bit on position equal to $1$.
21+
22+
For other approaches, you can also check out the user solutions on [Infoarena](https://infoarena.ro/monitor?task=xortransform), just make sure to press that popup you receive after you first click on a solution. Take note that the version used is slightly different from the actual version, as this problem was given as an interactive problem and Infoarena couldn't support interactive problems at the time.
23+
24+
## Implementation for infoarena version
25+
26+
**Time Complexity:** $\mathcal{O}(N \cdot M \cdot \log N)$
27+
28+
<LanguageSection>
29+
<CPPSection>
30+
31+
```cpp
32+
#include <bits/stdc++.h>
33+
using namespace std;
34+
35+
int main() {
36+
ifstream f("xortransform.in");
37+
int n, m, q;
38+
f >> n >> m >> q;
39+
vector<int> sos(n * m * 2 + 1);
40+
for (int i = 0; i < n; i++) {
41+
for (int j = 0; j < m; j++) {
42+
int nr;
43+
f >> nr;
44+
sos[i | j] ^= nr;
45+
}
46+
}
47+
48+
int mx = 1;
49+
int stp = 1;
50+
while (mx < n || mx < m) {
51+
mx <<= 1;
52+
stp++;
53+
}
54+
for (int i = 0; i < stp; i++) {
55+
for (int j = 0; j < mx; j++) {
56+
if (j & (1 << i)) { sos[j] ^= sos[j - (1 << i)]; }
57+
}
58+
}
59+
60+
int prev_ans = 0;
61+
ofstream g("xortransform.out");
62+
for (int i = 0; i < q; i++) {
63+
int nr;
64+
f >> nr;
65+
nr ^= prev_ans;
66+
nr &= (mx - 1);
67+
prev_ans = sos[nr];
68+
g << prev_ans << '\n';
69+
}
70+
}
71+
```
72+
73+
</CPPSection>
74+
</LanguageSection>

‎solutions/gold/kilonova-ssdj.mdx

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
id: kilonova-ssdj
3+
source: Romania IOI selection test 2014
4+
title: ssdj
5+
author: Stefan Dascalescu
6+
---
7+
8+
[Official Analysis (in Romanian)](https://github.com/roalgo-discord/Romanian-Olympiad-Solutions/blob/main/Baraj%20%2B%20Lot%20Seniori%20(IOI%20team%20selection%20tests)/2014/Lot%201/sol-ssdj.pdf)
9+
10+
## Explanation
11+
12+
Let's start from a more simple case, when the grid will only contain letters `a` and `b`. Let's associate for each letter a value corresponding to its position in the alphabet (for now, `a` equals $0$ and `b` equals $1$). Now we will have to find the number of submatrices such that we have ones in the top left and bottom right corners we have $1$ and we have $0$ everywhere else.
13+
14+
Let's construct another grid of size $n \times n$ where $b(i, j)$ stores the number of consecutive $0$ on the column $j$ above the position $(i, j)$.
15+
16+
Now for each line from $2$ to $n$, for a given position $(i, j)$ which is equal to $1$ (we will consider this the bottom-right corner), we will move from right to left on that line to find the values equal to $1$ placed at coordinates $(i, k)$ where $k < j$ such that $b(i, k) > 0$ and $b(i, k)$ strictly smaller than all values $b(i, p)$ with $p$ between $k+1$ and $j$.
17+
18+
The complexity of this approach is $\mathcal{O}(n^2)$.
19+
20+
Now we need to generalize for the entire grid, which has all lowercase letters of the alphabet. At each step, we fix a letter, let's call it $ch$.
21+
22+
For that letter, we will now create a grid where the positions corresponding to all the letters which are smaller than $ch$ will be equal to $0$, all letters equal to $ch$ will be equal to $1$ and all letters greater than $ch$ will be equal to $2$.
23+
24+
Just like we did it for the binary grid, we will count how many submatrices have values equal to $0$ except for the two corners aforementioned. In order to avoid overcounting, we will only count the submatrices such that they contain $1$ in at least a corner. Now, when we process a position $(i, j)$ we will do as such: if on that position we have $1$, we will count the number of previous position which correspond to both $1$ and $2$, and if on the same position we have $2$, we will only count the previous positions that are equal to $1$.
25+
26+
The complexity of this approach is still $\mathcal{O}(n^2)$ for each letter, which gives us an overall complexity of $\mathcal{O}(sigma \times n^2)$, where $sigma = 26$ is the length of the alphabet.
27+
28+
For other approaches, you can also check out the user solutions on [Infoarena](https://infoarena.ro/monitor?task=ssdj), just make sure to press that popup you receive after you first click on a solution.
29+
30+
## Implementation
31+
32+
**Time Complexity:** $\mathcal{O}(26 \cdot N^2)$
33+
34+
<LanguageSection>
35+
<CPPSection>
36+
37+
```cpp
38+
#include <bits/stdc++.h>
39+
using namespace std;
40+
41+
int main() {
42+
ifstream f("ssdj.in");
43+
44+
int n;
45+
f >> n;
46+
47+
long long ans = 0;
48+
vector<vector<char>> mat(n + 1, vector<char>(n + 1));
49+
vector<vector<int>> lst(n + 2, vector<int>(n + 2));
50+
vector<vector<int>> lst2(n + 2, vector<int>(n + 2));
51+
vector<int> d(n + 2);
52+
53+
for (int i = 1; i <= n; i++) {
54+
for (int j = 1; j <= n; j++) { f >> mat[i][j]; }
55+
}
56+
for (int i = 1; i <= n; i++) { lst2[n + 1][i] = n + 2; }
57+
for (char i = 'z'; i >= 'a'; i--) {
58+
for (int row = 1; row <= n; row++) {
59+
int stackSize = 0;
60+
for (int col = 1; col <= n; col++) {
61+
if (mat[row][col] >= i) {
62+
lst[row][col] = row;
63+
} else {
64+
lst[row][col] = lst[row - 1][col];
65+
}
66+
while (stackSize &&
67+
lst[row - 1][col] >= lst[row][d[stackSize]]) {
68+
--stackSize;
69+
}
70+
if (mat[row][col] == i) {
71+
ans += stackSize;
72+
if (stackSize && d[1] == col) { --stackSize; }
73+
}
74+
while (stackSize && lst[row][col] >= lst[row][d[stackSize]]) {
75+
--stackSize;
76+
}
77+
if (lst[row][col] <= (row - 1) && lst[row][col] != 0) {
78+
d[++stackSize] = col;
79+
}
80+
}
81+
}
82+
83+
for (int row = n; row >= 1; row--) {
84+
int stackSize = 0;
85+
int hm = 0;
86+
for (int col = n; col >= 1; col--) {
87+
if (mat[row][col] >= i) {
88+
lst2[row][col] = row;
89+
} else {
90+
lst2[row][col] = lst2[row + 1][col];
91+
}
92+
while (stackSize &&
93+
lst2[row + 1][col] <= lst2[row][d[stackSize]]) {
94+
if (mat[lst2[row][d[stackSize]]][d[stackSize]] == i) {
95+
hm--;
96+
}
97+
stackSize--;
98+
}
99+
if (mat[row][col] == i) {
100+
ans += stackSize;
101+
ans -= hm;
102+
if (stackSize && d[stackSize] == col) { ans--; }
103+
}
104+
while (stackSize && lst2[row][col] <= lst2[row][d[stackSize]]) {
105+
if (mat[lst2[row][d[stackSize]]][d[stackSize]] == i) {
106+
hm--;
107+
}
108+
stackSize--;
109+
}
110+
if (lst2[row][col] >= (row + 1) && lst2[row][col] != (n + 2)) {
111+
if (mat[lst2[row][col]][col] == i) { hm++; }
112+
d[++stackSize] = col;
113+
}
114+
}
115+
}
116+
}
117+
118+
ofstream("ssdj.out") << ans << endl;
119+
}
120+
```
121+
122+
</CPPSection>
123+
</LanguageSection>

0 commit comments

Comments
 (0)