| Predictor | A | B | C | D | E | F | G | |
|---|---|---|---|---|---|---|---|---|
| Proof_by_QED | 800 | 900 | 1100 | 1200 | 1400 | 1700 | 1900 | |
| Dominater069 | 800 | 800 | 800 | 900 | 1200 | 1200 | 1600 | 1600 |
| reirugan | 800 | 800 | 800 | 900 | 1500 | 1500 | 1700 | 1700 |
| macaquedev | 800 | 800 | 800 | 900 | 1600 | 900 | 1800 | — |
| Filikec | 800 | 800 | 800 | 900 | 1300 | 1500 | 1700 | 1800 |
| Edeeva | 800 | 800 | 800 | 1000 | 1300 | 1600 | 1700 | 1900 |
| yoru_sacri | 800 | 800 | 800 | 900 | 1400 | 1700 | 1900 | 1900 |
| kevlu8 | 800 | 800 | 800 | 900 | 1600 | 1400 | 1700 | — |
| AG-88301 | 800 | 800 | 800 | 800 | 1400 | 1500 | — | — |
| -firefly- | 800 | 800 | 800 | 1000 | 1300 | 1200 | 1800 | 2000 |
| SpyrosAliv | 800 | 800 | 800 | 1000 | 1200 | 3500 | 1900 | 2000 |
| temporary1 | 800 | 800 | 800 | 1000 | 1400 | 1500 | 1500 | 2000 |
Thanks to reirugan for helping write the editorials.
2094A - Триппи Троппи
Problem Credits: Proof_by_QED
This can be solved by printing the zero-th index of each string in sequence. For example, suppose your strings are $$$a$$$, $$$b$$$, and $$$c$$$. Then in C++, you can use cout << a[0] << b[0] << c[0] << '\n';, and similarly, in Python you can use print(a[0] + b[0] + c[0]). See your preferred language's syntax for how to obtain a given indexed character from a string.
t = int(input())
for _ in range(t):
inp = input()
for w in inp.split():
print(w[0],end="")
print()
2094B - Бобритто Бандито
Problem Credits: Proof_by_QED
What is the condition for $$$l'$$$ and $$$r'$$$ to be valid?
We must have $$$r' - l' = m$$$ and $$$l\leq l' \leq 0 \leq r'\leq r$$$.
The problem reduces to finding $$$l'$$$ and $$$r'$$$ such that $$$r' - l' = m$$$ and $$$l\leq l' \leq 0 \leq r'\leq r$$$. There are several different approaches; two are outlined below.
One approach which runs in $$$O(1)$$$ time is to case on whether $$$m\leq r$$$. If $$$m\leq r$$$, we can choose $$$l' = 0$$$ and $$$r' = m$$$, and then we see that $$$r' - l' = m - 0 = m$$$ and $$$l \leq 0 \leq 0 \leq m \leq r$$$ as desired. If $$$m \gt r$$$, we can choose $$$l' = r-m$$$ and $$$r' = r$$$, and then we see that $$$r' - l' = r - (r-m) = m$$$ and $$$l \leq r-m \leq 0 \leq r \leq r$$$, where $$$l \leq r-m$$$ holds because $$$r-l = n \geq m$$$.
An alternative approach which runs in $$$O(m)$$$ time is to simply simulate the process; expand in an arbitrary direction which satisfies the desired inequalities until $$$r' - l' = m$$$.
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n, m, l, r; cin >> n >> m >> l >> r;
int diff = n - m;
l = abs(l);
if (l >= diff) {
l -= diff;
diff = 0;
}
else {
diff -= l;
l = 0;
}
cout << -l << " " << r - diff << '\n';
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int t; cin >> t;
while (t--) solve();
return 0;
}
2094C - Брр Бррр Патапим
Problem Credits: cry
How can we find $$$p_i$$$ for $$$2\leq i\leq n$$$? How can we find $$$p_i$$$ for $$$n+1\leq i\leq 2n$$$?
For $$$2\leq i\leq n$$$, we can find $$$p_i$$$ by checking $$$G_{1, i-1}$$$. For $$$n+1\leq i\leq 2n$$$, we can find $$$p_i$$$ by checking $$$G_{n, i-n}$$$.
Observe that for all $$$2\leq i\leq n$$$, we can find $$$p_i$$$ by checking $$$G_{1, i-1}$$$. Then for all $$$n+1\leq i\leq 2n$$$, we can find $$$p_i$$$ by checking $$$G_{n, i-n}$$$. Now, we only have to find the value of $$$p_1$$$. However, each value from $$$1$$$ to $$$2n$$$ must appear exactly once in $$$p$$$. Thus, we can simply find the value which has not appeared yet, and choose that as $$$p_1$$$. This can be done by storing which values have been seen in a boolean array, and then finding which one remains false.
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n; cin >> n;
vector<int> ans(2*n+1, 0);
vector<bool> used(2*n+1, false);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int x; cin >> x;
ans[i + j] = x;
used[x] = true;
}
}
for (int i = 1; i <= 2 * n; i++) {
if (ans[i] != 0) cout << ans[i] << " ";
else {
for (int j = 1; j <= n * 2; j++) {
if (!used[j]) {
used[j] = true;
cout << j << " ";
break;
}
}
}
}
cout << "\n";
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int t; cin >> t;
while (t--) solve();
return 0;
}
2094D - Тунг Тунг Сахур
Problem Credits: Proof_by_QED
What would happen if $$$s_1$$$ consists of only $$$L$$$?
In this case, the answer is yes if and only if $$$|s_1| \leq |s_2| \leq 2|s_1|$$$. Now try to generalize this.
First, let us consider a simpler case of the problem: suppose that there is only $$$L$$$ in both $$$s_1$$$ and $$$s_2$$$. Then it is clear that the answer is yes if and only if $$$|s_1| \leq |s_2| \leq 2|s_1|$$$. If this holds (in particular, we also necessitate that $$$s_1$$$ and $$$s_2$$$ consist of only a single character, and the same character), we will call $$$s_2$$$ an extension of $$$s_1$$$.
Now, observe that the problem given is simply the simpler version, repeated several times alternating between $$$L$$$ and $$$R$$$. So we can partition $$$s_1$$$ into "blocks" (where we define a block to be a maximal group of contiguous identical characters). Then the answer is yes if and only if $$$s_2$$$ is the concatenation of extensions of blocks in $$$s_1$$$. For example, consider $$$s_1 = LLLLLRL$$$. We see that this consists of five $$$L$$$s, one $$$R$$$, and one $$$L$$$. So the answer is yes if and only if $$$s_2$$$ consists of between five and ten $$$L$$$s (inclusive), between one and two $$$R$$$s, and between one and two $$$L$$$ 's, concatenated in that order.
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
string a, b; cin >> a >> b;
int n = a.size();
int m = b.size();
if (m < n || m > 2 * n || a[0] != b[0]) {
cout << "NO\n";
return;
}
vector<int> aa, bb;
int cnt = 1;
for (int i = 1; i < n; i++) {
if (a[i] != a[i-1]) {
aa.push_back(cnt);
cnt = 1;
}
else cnt++;
}
aa.push_back(cnt);
cnt = 1;
for (int i = 1; i < m; i++) {
if (b[i] != b[i-1]) {
bb.push_back(cnt);
cnt = 1;
}
else cnt++;
}
bb.push_back(cnt);
if (aa.size() != bb.size()) {
cout << "NO\n";
return;
}
n = aa.size();
for (int i = 0; i < n; i++) {
if (aa[i] > bb[i] || aa[i] * 2 < bb[i]) {
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int t; cin >> t;
while (t--) solve();
return 0;
}
2094E - Бонэка Амбалабу
Problem Credits: Proof_by_QED
Consider each bit independently.
Suppose we fix $$$k$$$. How can we compute the desired sum quickly? Note that this may require preprocessing.
Here, it suffices to consider each bit independently, because addition is both commutative and associative. For $$$0\leq i \lt 30$$$, let $$$cnt_i$$$ denote the number of elements of $$$a$$$ which have the $$$i$$$-th bit set (where bits are indexed from the least significant bit being the $$$0$$$-th bit); note that these can be found in $$$O(30n)$$$ time (more generally, we need $$$O(\log\max{a_i})$$$ operations per element).
Now, suppose we choose a particular $$$k$$$. Then we can find the sum $$$(a_k\oplus a_1) + (a_k\oplus a_2) \dots + (a_k\oplus a_n)$$$ as follows: for a given bit position $$$i$$$, the number of elements $$$a_j$$$ such that $$$a_k \oplus a_j$$$ has the $$$i$$$-th bit set will be $$$cnt_i$$$ if the $$$i$$$-th bit of $$$a_k$$$ is not set, and $$$n-cnt_i$$$ if the $$$i$$$-th bit of $$$a_k$$$ is set. So we can simply add $$$cnt_i \cdot 2^i$$$ to our sum if the $$$i$$$-th bit of $$$a_k$$$ is not set, and add $$$(n-cnt_i) \cdot 2^i$$$ to our sum if the $$$i$$$-th bit of $$$a_k$$$ is set.
This allows us to compute $$$(a_k\oplus a_1) + (a_k\oplus a_2) \dots + (a_k\oplus a_n)$$$ for any $$$k$$$ in $$$O(30)$$$ time, so we can now compute this sum for all $$$k$$$ in $$$O(30n)$$$ time and output the maximum.
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n; cin >> n;
int arr[n+1];
vector<int> cnt(30, 0);
for (int i = 1; i <= n; i++) {
cin >> arr[i];
for (int j = 0; j < 30; j++) {
cnt[j] += ((arr[i] >> j) & 1);
}
}
int ans = 0;
for (int i = 1; i <= n; i++) {
int tot = 0;
for (int j = 0; j < 30; j++) {
bool f = ((arr[i] >> j) & 1);
if (f) tot += (1 << j) * (n - cnt[j]);
else tot += (1 << j) * cnt[j];
}
ans = max(ans, tot);
}
cout << ans << "\n";
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int t; cin >> t;
while (t--) solve();
return 0;
}
2094F - Трулимэро Труличина
Problem Credits: Proof_by_QED
What would happen if we tried outputting the numbers $$$1, \dots, k, 1, \dots, k, \dots$$$ in the natural reading order? For example, for $$$n=3$$$, $$$m=4$$$, and $$$k=6$$$, we would output the following:
| 1 | 2 | 3 | 4 |
| 5 | 6 | 1 | 2 |
| 3 | 4 | 5 | 6 |
In which cases does this fail?
This fails if and only if $$$m$$$ is a multiple of $$$k$$$, because we see that horizontally adjacent elements differ by $$$1\pmod k$$$ and vertically adjacent elements differ by $$$m\pmod k$$$. Now try to resolve this case.
There are many working constructions for this problem; one of them is to case on whether or not $$$m$$$ is a multiple of $$$k$$$.
Suppose $$$m$$$ is not a multiple of $$$k$$$. For example, consider the second sample, where $$$n=3$$$, $$$m=4$$$, and $$$k=6$$$. Then we can output the numbers $$$1, \dots, k, 1, \dots, k, \dots$$$ in the natural reading order, as follows:
| 1 | 2 | 3 | 4 |
| 5 | 6 | 1 | 2 |
| 3 | 4 | 5 | 6 |
and we see that any two horizontally adjacent elements differ by $$$1\pmod k$$$, whereas any two vertically adjacent elements differ by $$$m\pmod k$$$, so no two adjacent elements are the same, as desired.
Now, suppose $$$m$$$ is a multiple of $$$k$$$. For example, consider the case $$$n=4$$$, $$$m=6$$$, and $$$k=3$$$. Suppose we were to try the above strategy, then we get:
| 1 | 2 | 3 | 1 | 2 | 3 |
| 1 | 2 | 3 | 1 | 2 | 3 |
| 1 | 2 | 3 | 1 | 2 | 3 |
| 1 | 2 | 3 | 1 | 2 | 3 |
which doesn't work, since vertically adjacent elements are the same. We can fix this by cyclically shifting every other row as follows:
| 1 | 2 | 3 | 1 | 2 | 3 |
| 2 | 3 | 1 | 2 | 3 | 1 |
| 1 | 2 | 3 | 1 | 2 | 3 |
| 2 | 3 | 1 | 2 | 3 | 1 |
and we see that any two horizontally adjacent elements differ by $$$1\pmod k$$$ as before, whereas any two vertically adjacent elements also differ by $$$1\pmod k$$$, so no two adjacent elements are the same, as desired.
import sys
input = sys.stdin.readline
for _ in range(int(input())):
n,m,k = map(int,input().split())
LAST = [-1 for _ in range(m)]
for i in range(n):
shift = False
CUR = [0 for _ in range(m)]
for j in range(m):
elm = ((i * m + j) % k) + 1
if elm == LAST[j]:
shift = True
CUR[j] = elm
if shift:
CUR = [CUR[(j+1)%m] for j in range(m)]
print(*CUR)
LAST = CUR
2094G - Шимпанзини Бананини
Problem Credits: Proof_by_QED, cry
Note that reversing an array then pushing an element to the back is similar to simply pushing an element to the front. Thus, we would like to push elements to both ends of the array. What data structure supports this?
A deque is the most natural choice to use. Most languages, including C++, Java, and Python, include deques in their standard library, so you likely do not have to implement it yourself.
What other values do we need to maintain in order to keep track of score?
It suffices to keep track of the current score, the score of the array if it were backwards, the size of the array, and the sum of the array.
We can solve this using a deque. Let $$$score$$$ denote the current score, and $$$rscore$$$ denote the score of the array if it were backwards. Let $$$size$$$ denote the size of the array, and $$$sum$$$ denote the sum of the array. Then we consider how these three values change as each operation is performed.
Suppose operation 1 is performed. This is equivalent to popping the back element of the array and pushing it in the front. When you pop the back element of the array, $$$score$$$ decreases by $$$a_n \cdot size$$$. Then when you push it to the front, $$$score$$$ increases by $$$sum$$$ because $$$a_n$$$ is pushed to the first spot and every element from $$$a_1$$$ to $$$a_{n-1}$$$ moves forward one spot. Notice that $$$rscore$$$ changes in the reverse way; this is equivalent to popping the front element of the array and pushing it to the back. When you pop the front element of the array, $$$rscore$$$ decreases by $$$sum$$$, and when you push it to the back, $$$rscore$$$ increases by $$$a_n \cdot size$$$. Note that $$$size$$$ and $$$sum$$$ remain unchanged.
Suppose operation 2 is performed. Then we swap $$$score$$$ and $$$rscore$$$, and we also want to "reverse" the array. However, it is costly to entirely reverse the deque. Instead, we will set a flag to indicate that the array has been reversed (and similarly, if the flag is already set, we will unset it). If the flag is set, we simply switch the front and back ends whenever we access or modify the deque while performing operations 1 or 3.
Suppose operation 3 is performed. Then we see that $$$size$$$ increases by $$$1$$$ and $$$sum$$$ increases by $$$k$$$. Then $$$score$$$ increases by $$$k \cdot size$$$ and $$$rscore$$$ increases by $$$sum$$$ (using the new value of $$$sum$$$), by identical reasoning to that in operation 1.
Additional optimization: we don't actually have to maintain $$$rscore$$$; we can obtain it with the expression: $$$(n+1)\sum_{i=1}^na_i-score$$$. This is because $$$score + rscore = (n+1)\sum_{i=1}^na_i$$$ since the $$$i$$$-th term is counted $$$i$$$ times in $$$score$$$ and $$$n+1-i$$$ times in $$$rscore$$$.
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int norm = 0, rev = 0;
int q; cin >> q;
int tot = 0;
int n = 0;
deque<int> qNorm, qRev;
int p = 0;
while (q--) {
int s; cin >> s;
if (s == 1) {
int last = qNorm.back();
qNorm.pop_back();
qNorm.push_front(last);
norm += (tot - last);
norm -= last * n;
norm += last;
last = qRev.front();
qRev.pop_front();
qRev.push_back(last);
rev -= (tot - last);
rev += last * n;
rev -= last;
}
else if (s == 2) {
swap(rev, norm);
swap(qNorm, qRev);
}
else if (s == 3) {
n++;
int k; cin >> k;
qNorm.push_back(k);
qRev.push_front(k);
norm += k * n;
rev += tot;
rev += k;
tot += k;
}
cout << norm << "\n";
}
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int t; cin >> t;
while (t--) solve();
return 0;
}



