2153A - Circle of Apple Trees
You can't eat two apples of the same beauty value.
Is there a way to eat apples of all kinds of beauty values that appearred?
First of all, since the beauty values of the apples you eat are in strictly increasing order, any two of them have different beauty values.
So, for each beauty value, you can eat at most one apple.
In fact, it can be shown that it is always possible to eat exactly one apple of each beauty value. Let's say all the distinct beauty values are $$$v_1,v_2,\ldots,v_k\ (v_1\lt v_2\lt\ldots\lt v_k)$$$. You can eat one apple of beauty value $$$v_i$$$ during the $$$i$$$-th time you move along the full circle.
Therefore, the answer is the number of distinct numbers in beauty values. The time complexity is $$$\mathcal{O}(n)$$$.
#include <bits/stdc++.h>
using namespace std;
int t, n;
int main() {
cin >> t;
while (t--) {
cin >> n;
set<int> st;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
st.insert(x);
}
cout << (int) st.size() << '\n';
}
return 0;
}
import sys
input = lambda: sys.stdin.readline().strip()
t = int(input())
outs = []
for _ in range(t):
n = int(input())
nums = list(map(int, input().split()))
# There can be hash collisions, but n is small enough.
outs.append(len(set(nums)))
print('\n'.join(map(str, outs)))
2153B - Bitwise Reversion
Consider each bit of the numbers separately.
Different bits don't interfere with one another when you do bitwise operations. So, for each bit $$$k$$$, we can iterate over $$$2^3$$$ possibilities of $$$a_k = \mathtt{0} \text{ or } \mathtt{1}$$$, $$$b_k = \mathtt{0} \text{ or } \mathtt{1}$$$, and $$$c_k = \mathtt{0} \text{ or } \mathtt{1}$$$, and check whether it is consistent with the given numbers.
The time complexity for each test case is $$$\mathcal{O}(\log \max(x, y, z))$$$.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXL = 60;
int t;
ll x, y, z;
int main() {
cin >> t;
while (t--) {
cin >> x >> y >> z;
ll a = 0, b = 0, c = 0;
bool ans = true;
for (int l = MAXL - 1; l >= 0; l--) {
ll bit_x = x >> l & 1, bit_y = y >> l & 1, bit_z = z >> l & 1;
bool found = false;
for (ll bit_a : {0, 1}) {
for (ll bit_b : {0, 1}) {
for (ll bit_c : {0, 1}) {
if ((bit_a & bit_b) == bit_x &&
(bit_b & bit_c) == bit_y &&
(bit_a & bit_c) == bit_z) {
found = true;
a |= bit_a << l;
b |= bit_b << l;
c |= bit_c << l;
break;
}
}
if (found) {
break;
}
}
if (found) {
break;
}
}
if (!found) {
ans = false;
break;
}
}
if (!ans) {
cout << "NO\n";
} else {
assert((a & b) == x);
assert((b & c) == y);
assert((a & c) == z);
cout << "YES\n";
}
}
return 0;
}
import sys
input = lambda: sys.stdin.readline().strip()
t = int(input())
outs = []
for _ in range(t):
x, y, z = map(int, input().split())
a = x | z
b = x | y
c = y | z
outs.append('YES' if a & b == x and b & c == y and a & c == z else 'NO')
print('\n'.join(outs))
You just need to check whether $$$(a,b,c)=(x|z,x|y,y|z)$$$ is a valid solution, where $$$|$$$ denotes the bitwise OR operation. Why?
2153C - Symmetrical Polygons
Consider the line of symmetry. It intersects with the polygon at no more than $$$2$$$ sticks if we don't consider the endpoints of the sides.
Other sticks come in pairs.
Any line intersects with the polygon at no more than $$$2$$$ sticks (Here, we don't consider the endpoints of the sides when talking about intersection).
Consider the line of symmetry. The sticks not intersecting with it come in pairs of the same length.
Once we group the sticks in pairs of the same length (some sticks are not grouped), we should always use all of the pairs to construct the symmetrical convex polygon.
That is because, if we do not use all the pairs, for each unchosen pair, we can always add a copy of the stick on each side of the line of symmetry, which enlarges the perimeter. And if there exists a pair which we only use one of them as a side, it has to intersects with the line of symmetry. We can replace it with the pair on both sides of the line of symmetry and make the polygon convex with a larger perimeter.
Case 1: The line of symmetry intersects none of the sticks.
Only pairs of sticks with same length can be used. To obtain the largest perimeter, it is the most optimal to use all possible pairs.
Case 2: The line of symmetry intersects exactly one stick.
Let us call the stick that intersects the line of symmetry the odd stick. As long as the length of the odd stick is less than the total length of the pairs of sticks with identical length, we can use the odd stick. Hence, we can iterate through all possible sticks and check whether it is possible for it to be the odd stick in $$$O(1)$$$ time for each odd stick.
Case 3: The line of symmetry intersects exactly two sticks.
Let the longer of the two sticks that intersect the line of symmetry be the long odd stick, and the shorter be the short odd stick. As long as the difference in the length of the long odd stick and even odd stick is less than the total length of the pairs of sticks with identical length, we can use the long odd stick and short odd stick.
Let's say the remaining sticks in ascending order are $$$v_1,v_2,\ldots,v_k\ (v_1\lt v_2\lt\ldots\lt v_k)$$$. If the longer stick we choose is $$$v_i\ (i\gt 1)$$$, then the shorter one we choose should always be $$$v_{i-1}$$$, because it is the longest one we can choose and the difference of the two sticks chosen is minimized.
So you just need to check these pairs: $$$(v_1,v_2),(v_2,v_3),\ldots,(v_{k-1},v_k)$$$.
The time complexity is $$$\mathcal{O}(n\log n)$$$.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 200'005;
int t;
int n;
int a[MAXN];
map<int, int> cnt;
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> t;
while (t--) {
cnt.clear();
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
cnt[a[i]]++;
}
ll base = 0;
vector<int> odd, even;
for (auto [x, c] : cnt) {
base += (ll)x * (c / 2);
if (c % 2 == 1) {
odd.push_back(x);
} else if (c >= 2) {
even.push_back(x);
}
}
if (base == 0) {
cout << 0 << '\n';
continue;
}
ll ans = 0;
for (int x : odd) {
if (2 * base > x) {
ans = max(ans, 2 * base + x);
}
}
assert(is_sorted(odd.begin(), odd.end()));
for (int i = 1; i < (int)odd.size(); i++) {
if (odd[i - 1] + 2 * base > odd[i]) {
ans = max(ans, odd[i - 1] + 2 * base + odd[i]);
}
}
for (int x : even) {
if (base - x > 0) {
ans = max(ans, 2 * base);
}
}
cout << ans << '\n';
}
return 0;
}
import sys
input = lambda: sys.stdin.readline().strip()
t = int(input())
outs = []
# avoiding hash collisions, which we don't have tests in the pretests
rnd = random.getrandbits(30)
fmax = lambda x, y: x if x > y else y
for _ in range(t):
n = int(input())
nums = list(map(int, input().split()))
cnt = Counter(x ^ rnd for x in nums)
c = 0
half = 0
tmp = []
for x in cnt:
if cnt[x] > 1:
c += cnt[x] // 2
half += cnt[x] // 2 * (x ^ rnd)
if cnt[x] % 2:
tmp.append(x ^ rnd)
tmp.sort()
ans = 0 if c <= 1 else half * 2
for x in tmp:
if half * 2 > x:
ans = fmax(ans, half * 2 + x)
for i in range(1, len(tmp)):
if half * 2 > tmp[i] - tmp[i - 1]:
ans = fmax(ans, half * 2 + tmp[i - 1] + tmp[i])
outs.append(ans)
print('\n'.join(map(str, outs)))
2153D - Not Alone
Break up a nice array into "blocks" of same values.
Each block can be considered as blocks of size $$$2$$$ and $$$3$$$ concatenating together.
We can divide the nice circular array in blocks, where each block consists of equal values.
The final circular array can be divided into blocks with size of at least $$$2$$$.
And, since $$$2=2,3=3,4=2+2$$$, each block can be divided into sub-blocks of size $$$2$$$ and $$$3$$$:
- If the block is of size $$$3k-1\ (k\gt 0)$$$, then $$$3k-1=1\cdot 2+(k-1)\cdot 3$$$.
- If the block is of size $$$3k\ (k\gt 0)$$$, then $$$3k=0\cdot 2+k\cdot 3$$$.
- If the block is of size $$$3k+1\ (k\gt 0)$$$, then $$$3k+1=2\cdot 2+(k-1)\cdot 3$$$.
With this observation, we can modify the condition of a nice circular array as follows:
A circular array is nice if we can split it into contiguous blocks of length 2 or length 3, such that each block has equal value, and each element belongs to exactly one block.
Let us first try to solve the easier problem where the array is not circular. Let $$$\text{dp}[i]$$$ be the minimum number of operations to make $$$[a_1,a_2,\ldots,a_i]$$$ nice. Then, by considering whether the last block containing $$$a_i$$$ is of length $$$2$$$ or length $$$3$$$, we can come up with the transition:
where $$$\text{cost}$$$ denotes the minimum number of operations to make the elements equal.
To solve the original problem where the array is circular, we can use the standard technique of splitting the circular array by cutting the circle between $$$(i, i + 1)$$$ for each $$$1\le i\le n$$$. This will take $$$\mathcal{O}(n^2)$$$ time. However, since the length of the blocks do not exceed $$$3$$$, we only need to try three splitting points $$$(1, 2)$$$, $$$(2, 3)$$$, and $$$(3, 4)$$$.
The time complexity is $$$\mathcal{O}(n)$$$.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll LINF = 1000000000000000005;
const int MAXN = 500005;
int t;
int n;
int a[MAXN];
ll dp[MAXN];
ll cost(int x, int y) { return abs(x - y); }
ll cost(int x, int y, int z) {
if (x > y) {
swap(x, y);
}
if (y > z) {
swap(y, z);
}
if (x > y) {
swap(x, y);
}
return z - x;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
ll ans = LINF;
for (int cyc = 0; cyc < 4; cyc++) {
dp[0] = 0;
dp[1] = LINF;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 2] + cost(a[i - 1], a[i]);
if (i >= 3) {
dp[i] =
min(dp[i], dp[i - 3] + cost(a[i - 2], a[i - 1], a[i]));
}
}
ans = min(ans, dp[n]);
// cyclic shift anti-clockwise
for (int i = 2; i <= n; i++) {
swap(a[i], a[i - 1]);
}
}
cout << ans << '\n';
}
return 0;
}
import sys
input = lambda: sys.stdin.readline().strip()
t = int(input())
outs = []
fmin = lambda x, y: x if x < y else y
inf = 10 ** 15
for _ in range(t):
n = int(input())
nums = list(map(int, input().split()))
ans = inf
for _ in range(3):
nums = nums[-1:] + nums[:-1]
dp = [inf] * (n + 1)
dp[0] = 0
for i in range(2, n + 1):
dp[i] = fmin(dp[i - 2] + max(nums[i-2:i]) - min(nums[i-2:i]),
dp[i - 3] + max(nums[i-3:i]) - min(nums[i-3:i]) if i >= 3 else inf)
ans = fmin(ans, dp[n])
outs.append(ans)
print('\n'.join(map(str, outs)))
2153E - Zero Trailing Factorial
Why is the answer always smaller than $$$10^{100}$$$ ?
There are only a few $$$k$$$-s that are worth choosing.
$$$f_m(x, n)$$$ is equal to $$$0$$$ for a lot of the $$$x$$$.
Let $$$p_0$$$ be the largest prime that is not greater than $$$n$$$. Then, $$$f_m(x, n) = 0$$$ for all $$$x \lt p_0$$$.
$$$v_{p_0}(x!) = 0$$$ for all $$$x \lt p_0$$$, and $$$v_{p_0}(n!) \gt 0$$$. Hence, $$$w_{p_0}(x, n) = \min(v_{p_0}(x!), v_{p_0}(n!)) = 0$$$.
Let $$$\mathrm{PrimeGap}(M)$$$ be the maximum difference between a number $$$x\ (2\leq x\leq M)$$$ and the largest prime number no larger than it. We only need to compute $$$\mathrm{PrimeGap}(n) \le \mathrm{PrimeGap}(10^7) = 152$$$ values of $$$f_m(x, n)$$$. As this is reasonably small, we will now try to calculate the value of each $$$f_m(x, n)$$$ for all possible $$$x \ge p_0$$$.
First, we state a simple but useful lemma: for all $$$k\ge 2$$$, $$$v_k(a!) \le v_k(b!)$$$ if $$$a\le b$$$.
$$$a!$$$ divides $$$b!$$$ if $$$a\le b$$$. Hence, if $$$k^i$$$ divides $$$a!$$$, it also divides $$$b!$$$.
To find out some more about $$$w_k(a,b)$$$, let's factor $$$k$$$ as $$$k=p_1^{v_1}p_2^{v_2}\ldots p_t^{v_t}$$$ where $$$p_1,p_2,\ldots,p_t$$$ are disctinct primes and $$$v_1,v_2,\ldots,v_t$$$ are positive integers.
Then, $$$w_k(a,b)\geq\min\limits_i w_{p_i^{v_i}}(a,b)$$$.
Without loss of generality, let $$$a\le b$$$. Consider the array $$$c=[v_{p_1^{v_1}}(a!),v_{p_2^{v_2}}(a!),\ldots,v_{p_t^{v_t}}(a!)]$$$, $$$d=[v_{p_1^{v_1}}(b!),v_{p_2^{v_2}}(b!),\ldots,v_{p_t^{v_t}}(b!)]$$$. Then $$$c_i\leq d_i$$$, for all $$$1\leq i\leq n$$$, since $$$v_{p_i^{v_i}}(a!)\leq v_{p_i^{v_i}}(b!)$$$ from the earlier lemma.
By definition, $$$v_k(a!) = \min(c)$$$, $$$v_k(b!) = \min(d)$$$, and
(the second case is due to the lemma $$$v_k(a!)\le v_k(b!)$$$).
- If $$$v_k(a!) = v_k(b!)$$$, then $$$w_k(a,b)=10^{100}$$$. The inequality already holds.
- Otherwise, $$$v_k(a!) \neq v_k(b!)$$$, i.e., $$$\min(c)\neq\min(d)$$$. Since $$$c_i\leq d_i$$$ for all $$$i$$$, $$$\min(c) \lt \min(d)$$$. Let $$$i'$$$ be the index such that $$$c_i' = \min(c)$$$. Then, $$$c_{i'} = \min(c) \lt \min(d) \le d_{i'}$$$. Hence, $$$w_{p_{i'}^{v_i'}}(a, b) = c_{i'} = w_k(a, b)$$$.
Since $$$f_m(a, b)$$$ considers the minimum of $$$w_k(a, b)$$$ over all $$$2\le k\le m$$$, we only need to consider $$$k$$$ that are primes, or powers of primes. Formally, we only need to consider integers of the form $$$p^v$$$ where $$$p$$$ is a prime number and $$$v$$$ is a positive integer.
Furthermore, we only need to consider numbers of the form $$$p^v$$$ where $$$p$$$ is a prime number and $$$p$$$ divides at least one of the numbers in $$$[p_0, n]$$$.
For each $$$x$$$ in $$$[p_0,n]$$$, $$$x!=(p_0-1)!p_0(p_0+1)\ldots x$$$, which means $$$v_p(x!)=v_p((p_0-1)!)$$$. So it always holds that $$$v_p(x!)=v_p(n!)$$$, which also implies that $$$v_{p^k}(x!)=v_{p^k}(n!)$$$.
There are $$$\mathcal{O}(\mathrm{PrimeGap}(n)\log_2 n)$$$ primes $$$p$$$ that divide at least one of the numbers in $$$[p_0, n]$$$. We can calculate the value of $$$v_p(x!)$$$ and $$$v_p(n!)$$$ in $$$\mathcal{O}(\log_2 n)$$$ using the given formula. For each prime $$$p$$$, there are at most $$$\mathcal{O}(\log_2 m)$$$ prime powers $$$p^v \le m$$$, and $$$v_{p^k}(x!)$$$ and $$$v_{p^k}(n!)$$$ can both be calculated in $$$\mathcal{O}(1)$$$ time after computing $$$v_p(x!)$$$ and $$$v_p(n!)$$$ in the previous step. Hence, a single $$$f_m(x, n)$$$ can be computed in $$$\mathcal{O}(\mathrm{PrimeGap}(n)\log_2 n(\log_2 n + \log_2 m))$$$ time.
The total time complexity if $$$\mathcal{O}(t\cdot \mathrm{PrimeGap}(n)^2\log_2 n(\log_2 n + \log_2 m))$$$. Even though this seems very big, the constant is very small, so it passess comfortably.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 10000005;
const int INF = 1000000005;
bool is_prime[MAXN];
inline int calc_v(int p, int x) {
int res = 0;
ll pw_p = p;
while (pw_p <= x) {
res += x / pw_p;
pw_p *= p;
}
return res;
}
int t;
int n, m;
vector<int> small_primes;
int main() {
#ifndef DEBUG
ios::sync_with_stdio(0), cin.tie(0);
#endif
for (int i = 2; i < MAXN; i++) {
is_prime[i] = true;
}
for (int p = 2; (ll)p * p < MAXN; p++) {
if (!is_prime[p]) {
continue;
}
small_primes.push_back(p);
for (int i = p * p; i < MAXN; i += p) {
is_prime[i] = false;
}
}
cin >> t;
while (t--) {
cin >> n >> m;
// find largest prime q <= n. Requires at most 142 iterations (due to
// prime gap)
int q = n;
while (!is_prime[q]) {
q--;
}
// precompute the useful big primes
vector<int> useful_p;
for (int f = 1; (ll)f * f <= n; f++) {
// p_bnd is the largest possible value such that floor(n / p_bnd) =
// f n / p_bnd >= f p_bnd <= n / f
int p_bnd = n / f;
int p = p_bnd;
while (!is_prime[p]) {
p--;
}
useful_p.push_back(p);
}
ll ans = 0;
// for all x < q, f_m(x, n) = 0. try all x >= q
for (int x = q; x < n; x++) {
int res = INF;
for (int p : useful_p) {
int vx = calc_v(p, x), vn = calc_v(p, n);
if (vx != vn) {
res = min(res, vx);
}
}
for (int p : small_primes) {
if ((ll)p * p > m) {
break;
}
int base_vx = calc_v(p, x), base_vn = calc_v(p, n);
for (ll exp = 1, pw_p = p; pw_p <= m; exp++, pw_p *= p) {
int vx = base_vx / exp, vn = base_vn / exp;
if (vx != vn) {
res = min(res, vx);
}
}
}
ans += res;
}
cout << ans << '\n';
}
return 0;
}
import sys
input = lambda: sys.stdin.readline().strip()
M = 10 ** 7
pr = [1] * (M + 1)
for i in range(2, M + 1):
if pr[i] == 1:
for j in range(i, M + 1, i):
pr[j] = i
t = int(input())
outs = []
fmin = lambda x, y: x if x < y else y
inf = 10 ** 9
for _ in range(t):
n, m = map(int(input().split()))
vis = set()
for i in range(n, 0, -1):
x = i
while x > 1:
vis.add(pr[x])
x //= pr[x]
if pr[i] == i: break
ans = 0
def f(val, p):
c = 0
while val:
val //= p
c += val
return c
for i in range(n - 1, 0, -1):
res = inf
for v in vis:
cur = v
c = 1
v1 = f(i, v)
v2 = f(n, v)
while cur <= m:
if v1 // c != v2 // c:
res = fmin(res, v1 // c)
cur *= v
c += 1
ans += res
if pr[i] == i: break
outs.append(ans)
print('\n'.join(map(str, outs)))
2153F - Odd Queries on Odd Array
What does the condition "there do not exist four indices $$$1\leq i\lt j\lt k\lt l\leq m$$$ such that $$$b_i\neq b_j$$$, $$$b_i=b_k$$$ and $$$b_j=b_l$$$." reminds you of?
You can construct a tree based on the array. How can you do so?
The strange condition given by the problem is that there are no subsequences in the form of $$$[x,y,x,y]\ (x\neq y)$$$.
Let us construct a tree such that its DFS order $$$^\dagger$$$ is equal to $$$a$$$. We can build the tree as follows:
- Initialize a stack containing a vertex $$$0$$$.
- Iterate over the array $$$a$$$ from index $$$i = 1$$$ to $$$i = n$$$.
- For each element $$$a[i]$$$:
- Add an edge between the vertex on top of the stack and vertex $$$i$$$. Assign vertex $$$i$$$ the value $$$a[i]$$$.
- If this is the first occurrence of $$$a[i]$$$, push $$$i$$$ onto the stack.
- If this is the last occurrence of $$$a[i]$$$, pop the top element from the stack (even if you have just pushed it).
Only the first and last occurrence of each value affects the stack. It can be proven that at the last occurence of each value, the vertex being popped from the stack will have the same value as the value of the processed vertex. This is because all elements in between the first and last occurrence of a value $$$x$$$ must be strictly contained in the range (due to the property of a cute array). Hence, all vertices that are pushed into the stack after the first occurrence of $$$x$$$ will be popped out before the last occurrence of $$$x$$$.
Due to the property of a cute array, the set of vertices with equal values forms a single connected component in the tre
Suppose that the set of vertices with equal values do not form a single connected component. Let $$$k$$$ be the value that do not form a single connected component, and let $$$u$$$ be the first occurrence of $$$a[u] = k$$$. Let $$$v$$$ be a vertex that is not connected to $$$u$$$, i.e., there exists a vertex $$$w$$$ on the simple path between $$$u$$$ and $$$v$$$ such that $$$a[w] \neq a[u]$$$.
Vertex $$$u$$$ has to be an ancestor of vertex $$$v$$$. This is because vertex $$$u$$$ will be pushed into the stack, and will remain in the stack until the last occurrence of $$$a[u]$$$, so $$$u$$$ will still be in the stack when $$$v$$$ is being processed.
Let $$$w$$$ be a vertex on the simple path between $$$u$$$ and $$$v$$$ such that $$$a[w] \neq a[u]$$$. $$$w$$$ is also an ancestor of $$$v$$$ since $$$u$$$ is an ancestor of $$$v$$$. $$$w$$$ has to be the first occurrence of $$$a[w]$$$ (for it to be pushed into the stack), and the last occurrence of $$$a[w]$$$ has to be after $$$v$$$ (otherwise it would be popped from the stack before $$$v$$$). This means that $$$[a[u], a[w], a[v], a[w]]$$$ exists as a subsequence of array $$$a$$$, which contradicts the condition of a cute array as $$$a[u] = a[v]$$$.
Since there can only be one vertex in the stack for each value, all vertices of the same value have the same parent.
To answer the queries, we decompose the range $$$l$$$ to $$$r$$$ into three parts by considering the lowest common ancestor (LCA) of vertex $$$l$$$ and vertex $$$r$$$:
- From $$$l$$$ to LCA:
- If $$$l$$$ has the same value as LCA, you can leave it to the second part.
- Otherwise, let $$$l'$$$ be the child vertex of LCA which is an ancestor of $$$l$$$, and $$$\text{last}_{l'}$$$ be the vertex with the largest index in the subtree of $$$l'$$$. The values that appear in the subtree of $$$l'$$$ never occur in other parts of the tree. Hence, the answer for the subarray $$$a_{l\ldots \text{last}_{l'}}$$$ is equals to the answer for the suffix $$$a_{l\ldots n}$$$ minus the answer for the suffix $$$a_{\text{last}_{l'} + 1\ldots n}$$$. By precomputing the answer for each suffix of the entire array $$$a$$$, we can find the answer for subarray $$$a_{l\ldots \text{last}_{l'}}$$$ in $$$\mathcal{O}(1)$$$ time.
- At LCA:
- Let $$$r'$$$ be the child vertex of the LCA which is an ancestor of $$$r$$$. We want to compute the answer for the subarray $$$a_{\text{last}_{l'} + 1\ldots r'-1}$$$.
- This can be done by considering the children of the LCA between $$$l'$$$ and $$$r'$$$, then summing up the answer for the subtrees of those children.
- For subtrees that are a single vertex, they have the same value as the LCA. We can count the occurrence of the value between vertex $$$l'$$$ and $$$r'$$$ in $$$\mathcal{O}(1)$$$ time after precomputing prefix sums.
- For other subtrees, the answer for their corresponding subarray is independent of the rest of the array. Hence, we can precompute the answer for the subtree of each vertex with a simple DFS. Then, we can sum up the answer for the subtrees of all children between $$$l'$$$ and $$$r'$$$ using perfix sums.
- From LCA to $$$r$$$:
- This is handled in the same way as the first part, except that we need to precompute the answer for each prefix of the entire array instead of the suffix.
The time complexity is $$$\mathcal{O}(n+q\log n)$$$.
$$$^\dagger$$$ The DFS order of a tree is found by calling the following dfs function on the tree.
dfs_order = []
def dfs(v):
dfs_order.append(v)
# children[v] is the set of children of vertex v
for child in children[v]:
dfs(child)
dfs(0)
import sys
import bisect
input = lambda: sys.stdin.readline().strip()
t = int(input())
outs = []
fmax = lambda x, y: x if x > y else y
for _ in range(t):
n, q = map(int, input().split())
nums = [0] + list(map(int, input().split()))
first_pos = [0] * (n + 1)
last_pos = [0] * (n + 1)
for i in range(n + 1):
last_pos[nums[i]] = i
for i in range(n, -1, -1):
first_pos[nums[i]] = i
path = [[] for _ in range(n + 1)]
nth_parent = [[-1] * (n + 1) for _ in range(20)]
depth = [0] * (n + 1)
stk = [0]
for i in range(1, n + 1):
path[stk[-1]].append(i)
nth_parent[0][i] = stk[-1]
depth[i] = depth[stk[-1]] + 1
if first_pos[nums[i]] == i:
stk.append(i)
if last_pos[nums[i]] == i:
stk.pop()
depth.append(-1)
for i in range(19):
for j in range(n + 1):
if nth_parent[i][j] != -1:
nth_parent[i + 1][j] = nth_parent[i][nth_parent[i][j]]
cnt = [0] * (n + 1)
cur = 0
pref_val = [0] * (n + 1)
for i in range(1, n + 1):
cur += -nums[i] if cnt[nums[i]] else nums[i]
cnt[nums[i]] ^= 1
pref_val[i] = cur
cnt = [0] * (n + 1)
cur = 0
suff_val = [0] * (n + 1)
for i in range(n, 0, -1):
cur += -nums[i] if cnt[nums[i]] else nums[i]
cnt[nums[i]] ^= 1
suff_val[i - 1] = cur
subtree_val = [0] * (n + 1)
subtree_max_idx = list(range(n + 1))
for i in range(n, -1, -1):
if first_pos[nums[i]] == i:
c = 1
total = 0
for j in path[i]:
total += subtree_val[j]
if nums[j] == nums[i]:
c ^= 1
subtree_max_idx[i] = fmax(subtree_max_idx[i], subtree_max_idx[j])
subtree_val[i] = total + c * nums[i]
accs = [[0] * (len(path[i]) + 2) if first_pos[nums[i]] == i else [] for i in range(n + 1)]
for i in range(n + 1):
if first_pos[nums[i]] == i:
total = 0
c = 1
accs[i][1] = total * 2 + c
for j in range(len(path[i])):
total += subtree_val[path[i][j]]
if nums[path[i][j]] == nums[i]:
c ^= 1
accs[i][j + 2] = total * 2 + c
def lca(u, v):
if depth[u] < depth[v]:
u, v = v, u
d = depth[u] - depth[v]
while d:
x = d & -d
bit = x.bit_length() - 1
u = nth_parent[bit][u]
d -= x
if u == v: return u
for i in range(19, -1, -1):
if nth_parent[i][u] != nth_parent[i][v]:
u = nth_parent[i][u]
v = nth_parent[i][v]
return nth_parent[0][u]
last = 0
ans = [0] * q
for idx in range(q):
l, r = map(int, input().split())
l = (l + last - 1) % n + 1
r = (r + last - 1) % n + 1
if l > r: l, r = r, l
ancestor = lca(l, r)
if l == r:
last = nums[l]
else:
last = 0
if l == ancestor and first_pos[nums[l]] == l:
pl = 0
elif nth_parent[0][l] == ancestor and first_pos[nums[ancestor]] == ancestor and first_pos[nums[l]] != l:
pl = bisect.bisect_left(path[ancestor], l) + 1
else:
cl = l
for i in range(19, -1, -1):
if depth[nth_parent[i][cl]] > depth[ancestor]:
cl = nth_parent[i][cl]
last += suff_val[l - 1] - suff_val[subtree_max_idx[cl]]
pl = bisect.bisect_left(path[ancestor], cl) + 2
if r == ancestor and first_pos[nums[r]] == r:
pr = 0
elif nth_parent[0][r] == ancestor and first_pos[nums[ancestor]] == ancestor and first_pos[nums[r]] != r:
pr = bisect.bisect_left(path[ancestor], r) + 1
else:
cr = r
for i in range(19, -1, -1):
if depth[nth_parent[i][cr]] > depth[ancestor]:
cr = nth_parent[i][cr]
last += pref_val[r] - pref_val[cr - 1]
pr = bisect.bisect_left(path[ancestor], cr)
xl = accs[ancestor][pl]
xr = accs[ancestor][pr + 1]
vl, cl = divmod(xl, 2)
vr, cr = divmod(xr, 2)
last += vr - vl + (cl ^ cr) * nums[ancestor]
ans[idx] = last
outs.append(' '.join(map(str, ans)))
print('\n'.join(outs))
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
namespace solution {
const int MAXL = 21;
const int MAXN = 1000005;
int n, q;
int a[MAXN];
vector<int> occ[MAXN];
ll pfx[MAXN], sfx[MAXN];
ll sm_pfx[MAXN], sm_sfx[MAXN];
inline bool is_first_occ(int i) { return occ[a[i]][0] == i; }
inline bool is_last_occ(int i) { return occ[a[i]].back() == i; }
// returns minimum j >= p such that a[j] == x, or n + 1 if does not exist
inline auto nxt_occ(int p, int x) {
return lower_bound(occ[x].begin(), occ[x].end(), p);
}
int p[MAXL][MAXN];
vector<int> adj[MAXN];
inline void add_edge(int u, int v) {
p[0][v] = u;
adj[u].push_back(v);
}
int lvl[MAXN];
void dfs(int u) {
for (int l = 1; l < MAXL; l++) {
p[l][u] = p[l - 1][p[l - 1][u]];
}
if (u) {
sm_pfx[u] += pfx[u];
auto ptr = nxt_occ(u + 1, a[u]);
sm_sfx[u] += ptr == occ[a[u]].end() ? 0 : sfx[*ptr];
}
for (int v : adj[u]) {
lvl[v] = lvl[u] + 1;
sm_pfx[v] = sm_pfx[u];
sm_sfx[v] = sm_sfx[u];
dfs(v);
}
}
tuple<int, int, int> get_lca(int a, int b) {
bool swp = false;
if (lvl[a] < lvl[b]) {
swap(a, b);
swp = true;
}
for (int l = MAXL - 1; l >= 0; l--) {
if (lvl[p[l][a]] >= lvl[b]) {
a = p[l][a];
}
}
if (a == b) {
return {a, -1, -1};
}
if (swp) {
swap(a, b);
}
for (int l = MAXL - 1; l >= 0; l--) {
if (p[l][a] != p[l][b]) {
a = p[l][a];
b = p[l][b];
}
}
return {p[0][a], a, b};
}
ll solve_same_layer(int l, int r) {
assert(p[0][l] == p[0][r]);
ll res =
(pfx[r] -
((nxt_occ(r + 1, a[l]) - occ[a[l]].begin()) % 2 == 1 ? a[l] : 0)) -
(pfx[l] -
((nxt_occ(l, a[l]) - occ[a[l]].begin() + 1) % 2 == 1 ? a[l] : 0));
if ((nxt_occ(r + 1, a[l]) - nxt_occ(l, a[l])) % 2 == 1) {
res += a[l];
}
return res;
}
void precompute() {
for (int i = 0; i <= n; i++) {
occ[i].clear();
adj[i].clear();
pfx[i] = sfx[i] = sm_pfx[i] = sm_sfx[i] = 0;
}
for (int i = 1; i <= n; i++) {
occ[a[i]].push_back(i);
}
vector<int> stk;
stk.push_back(0);
for (int i = 1; i <= n; i++) {
if (!is_first_occ(i)) {
assert(!stk.empty() && a[stk.back()] == a[i]);
stk.pop_back();
}
assert(!stk.empty());
add_edge(stk.back(), i);
if (!is_last_occ(i)) {
stk.push_back(i);
}
}
for (int u = n; u >= 0; u--) {
{
ll prv = 0;
for (int i = 0; i < (int)adj[u].size(); i++) {
int v = adj[u][i];
auto ptr = nxt_occ(v, a[v]);
pfx[v] =
prv + ((ptr - occ[a[v]].begin() + 1) % 2 == 1 ? a[v] : 0);
if (!adj[v].empty()) {
prv += pfx[adj[v].back()];
}
if (is_last_occ(v)) {
prv += occ[a[v]].size() % 2 == 1 ? a[v] : 0;
}
}
}
{
ll prv = 0;
for (int i = (int)adj[u].size() - 1; i >= 0; i--) {
int v = adj[u][i];
auto ptr = nxt_occ(v, a[v]);
if (!adj[v].empty()) {
prv += sfx[adj[v][0]];
}
sfx[v] = prv + ((occ[a[v]].end() - ptr) % 2 == 1 ? a[v] : 0);
if (is_first_occ(v)) {
prv += occ[a[v]].size() % 2 == 1 ? a[v] : 0;
}
}
}
}
dfs(0);
}
void init(int _n, int _q, vector<int> _a) {
n = _n;
q = _q;
for (int i = 1; i <= n; i++) {
a[i] = _a[i - 1];
}
precompute();
}
ll query(int l, int r) {
if (l == r) {
return a[l];
}
auto [lca, lc, rc] = get_lca(l, r);
assert(lca != r);
if (lca == l) {
ll ans = sm_pfx[r] - sm_pfx[l] + a[l];
return ans;
} else if (lc == l) {
ll ans = sm_pfx[r] - sm_pfx[rc];
ans += solve_same_layer(l, rc);
return ans;
} else {
ll ans = sfx[l] + sm_sfx[p[0][l]] - sm_sfx[lc] + sm_pfx[r] - sm_pfx[rc];
ans += solve_same_layer(*nxt_occ(lc + 1, a[lc]), rc);
return ans;
}
}
} // namespace solution
int main() {
ios::sync_with_stdio(0), cin.tie(0);
int t;
cin >> t;
while (t--) {
int n, q;
cin >> n >> q;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
solution::init(n, q, a);
ll prv_ans = 0;
while (q--) {
int l, r;
cin >> l >> r;
auto decode = [&](int x) { return (x - 1 + prv_ans) % n + 1; };
l = decode(l);
r = decode(r);
if (l > r) {
swap(l, r);
}
ll ans = solution::query(l, r);
cout << ans << ' ';
prv_ans = ans;
}
cout << '\n';
}
return 0;
}








Auto comment: topic has been updated by Little_Sheep_Yawn (previous revision, new revision, compare).
this contest made me nut.
Auto comment: topic has been updated by maomao90 (previous revision, new revision, compare).
Lightning quick editorial!!!
tutorial is broken
Nice contest and fast editorial! But surprisingly hard C :(
What a fast editorial !!
For problem B,we can calculate the sum of each bit of x, y, z. If the sum of a bit is 2, it is NO, otherwise it is YES
If x^y^z == x|y|z it is Yes. Otherwise it is No.
man explain :V:VVV:VV:V I need you wisdom, how did you get to that?
I'm wondering why it is heavily downvoted :DDD
Because people automatically assumed that you used ai. Happened with me, I also posted a different approach to problem D, used ai to articulate the solution's explanation since i am not a native English speaker, but they heavily down voted the solution.
I don't think AI will give this answer. Maybe they don't understand. Anyway don't care about them. It's not important at all. So do your best.
Thanks for the encouraging words, but it is just strange to get downvoted on an approach you found out of your own :(
how did you think of it in the first place
Well, the funnier thing is that actually I guessed it, that sum of a bit shouldn't be 2, and I haven't proved it yet.
I had a bit of a diffrent aproach. Out of the starting equation i made some other. Then i set a=x|z, b=x|y, c=y|z. After that i just checked the starting conditiones and the other equations.
why this solution works , can u please explain it
Because, if and only if there is a bit that is equals 1 in exactly two of the numbers , then this condition isn't true because: 1 ^ 1 ^ 0 = 0 but 1 | 1 | 0 = 1
How did you come up with this logic ?
create a table for bits of a,b,c and resultant bits of a&b,b&c and c&a and you will see that in all the 8 cases sum of bits of a&b,b&c and c&a is never 2, it can only be 0,1,3
same as you bro :)
if x&y == y&z == z&x it is yes else no
my idea is calculate x & y (= a & b & b & c = a & b & c), y & z ( = b & c & a & c = a & b & c) and x & z ( = a & b & a & c = a & b & c) ,if all the three result are consistent , the answer is YES
why this soultion works , can u explain?
Fast Editorial !
Nice problem Set ! But C was hard
I thought D could be solved with binary search by searching for a delta to add to the number, so ai keeps in the range [ai-delta, ai+delta], and with that I tried to delimit the blocks but couldn't find a way TT
can anyone please tell me what am I doing wrong here? 343006641
Auto comment: topic has been updated by maomao90 (previous revision, new revision, compare).
omg E WAS SO GOOD!!!
I've thought $$$O(T\cdot\operatorname{PrimeGap}(n)^2\log^2n)$$$ won't pass E and wasted 1hr+ trying to improve my solution to $$$O(T\cdot\operatorname{PrimeGap}(n)^2\log n)$$$...
The problem itself is excellent but the constraint is so tricky :/
Hmm, managed to find another solution to b, which is also a quick trick, as in the "bonus section": just check whether
(x & y) == (y & z) && (x & y) == (x & z). The solution has passed all tests :)For those, wondering why, my logic was that
a & b & cis equal tox & y(becausea & b & b & c = a & b & c) and similarly tox & zandy & z, so all these expressions must be equal to each other.Yes, same idea
Same here!
I did the same.
This is what I implemented and got all my test cases passed. This is a necessary condition but I spent 20 minutes trying to prove that it was sufficient
How did you prove it was sufficient ?
wow, people were able to solve B surprisingly fast
yeah I was very surprised too.
u could just check if z&y == y&z ==z&x and surprisingly it ACs just fine
yeah but how to think about this ? lol !!
try to observe from the given testcases and if it feels like it may work just try submitting, or atleast thats what i did
lol !!!
yeah that is what I did in
C.. got 2WAaaaahhh!!!!well this type of submission has got its risks
Try AND operating equations 1 and 2. You will get a&b&c = x&y. Just do this for 2, 3 and 1, 3. All of them should be equal.
I think treating a, b, c as sets would be a much more intuitive way to solve this problem.
Parts 1, 3, and 4 in the image need to be independent; otherwise, you will not be able to meet the requirements.
Solved F with exactly same solution but without any thinking about tree. Just got that idea randomly :)
thanks for superfast editorial
C made me lose hope
C was out of my league!!:)
I have a shorter solution for B.
I just print YES if X&Y == Y&Z == X&Z and NO otherwise. Proof : (1) It exists a and b as a & b = X (2) It exists a and b as b & c = Y So (1) AND (2) <-> a & b & b & c = a & b & c = X & Y.
So if we can find a,b,c we have X&Y == Y&Z == X&Z == a & b & c.
Sorry for my poor english and thx for this very good contest !
**I didn't participate (I was sleeping half the time), but I solved the question after contest. I saw others' solution later which were x&y == y&z == x&z but I couldn't understand it. Thanks for the explanation.
I can't understand. Can u explain more?
Here's a similar problem to today's B but harder: instead of construct from and to or, this problem do from or to and: https://mirror.codeforces.com/contest/1903/problem/B
this comment is no longer relevant.
Sir I think if he ai cheat his rank would be lot higher. also i think simulating over bits would've been a legit strat considering anybody who cared about speed could've thought of brute force. u should not accuse him of cheating becuz he's indian
We both Gave contest together yesterday, we spend almost an hour to that question but didn't get it.
we tried our best and build logic on that particular solution, but gives wrong answer. So, we use AI to update our changes
Should it be a cheating or help from AI.
At final. we use AI but I didn't submit the solution bcz we didn't understand.
C was interesting even if I couldn't solve it..
I tried an approach similar to the editorial but idk why it fails. my submission
I tried pairing all possible ones and for the single sticks i just took the longest 2. I couldn't figure out a counter case to this
Try 5 5 7 24, you can’t take 24 because it’s too long
That is why I added the polygon inequality check. Any reason why it is still wrong? My submission :342989726
Think there’s some issues with your casework, keep in mind that 1: you may not take two bad segments (maybe 1 or 0) even when more bad segments exist; and 2: the bad segment(s) you take may not be the biggest bad segments available.
As an example, I think your code returns 0 on both these cases:
5 5 7 24 —> 17
5 5 7 8 24 —> 25
Ahh, I see what you are saying, I needed to give polygon inequality preference and do casework with it. Thanks!
I understand the case where a single stick can be added but I am still confused why we need to choose 2 sticks where |long — short| < curPerimeter.
I am having a hard time visualizing this case (where 2 sticks can be added).
Take the case 5 5 7 8 24: curPerimeter is 5+5 = 10 and there are 3 extra sticks, but you can't choose 24 and 8 because 5 + 5 < 24 — 8. From a geometrical view this means that 5 5 8 can't reach both ends of 24, so we can't actually make a polygon with 5 5 8 24.
Solution is to take 5 5 7 8, you can form a trapezoid with these segments.
ohhh I get it now!
So for the case 5 5 1e9 1e9 + 1: we can take all of them since the single sticks 1e9 and 1e9+1 have a difference less that curPer (5 + 5) so we can place these 2 sticks on opposite sides
And for the case 5 5 1e9 1e9 + 10: the answer would be 0 since we can only take 5 & 5 but it would form a polygon.
Thank you so much for the help!
I am also trying the same approach as the editorial for problem C. Can you please point out what am I doing wrong? 343596059
Alternate brainless solution for F using a persistent segment tree bash:
Definitions:
Notice that an array is cute iff the set of segments $$$[l(x), r(x)]$$$ forms a laminar family (no two segments partially intersect).
When answering some query $$$[L, R]$$$, then there will be four kinds of elements $$$x$$$:
- $$$a_i = a_j = x$$$
- there lies no occurrence of $$$x$$$ in $$$[i + 1, j - 1]$$$
- there are an even number of occurrences of $$$x$$$ on $$$(j, n]$$$
, we add $$$(i, j]$$$ to $$$S_x$$$.This works in $$$O((n + q) \cdot (\log {q} + \log^2{n})$$$ time.
Code: 343034475
unordered_map made me win the battle but lose the war for C.
See this. What to use instead of unordered_map/unordered_set and make it very difficult to hack
thanks.
Answering the bonus question for B. There are a few things to note: 1) It is necessary for a to be such that a&(x|z)=(x|z). (Basically, a is a supermask of x|z) Detail: if that is not the case, then at the position where x|z is 1 but a is 0, it will give both x and z to have 0 (because of & with a), which will contradict z|x having 1(both should not be zero at that position). A similar statement could be made for b and c.
2) Suppose a is such a supermask and similar for b and c, such that all the conditions are satisfied. Then, any submask of a will also satisfy it, provided it is a valid supermask of x|z. Detail: Suppose some position where a is set to 1, and setting it to 0 will still make a supermask of x|z. Since it is a supermask of x|z (and not equal to it otherwise, setting to 0 would not be a valid supermask), it means b and c have a 0 at that position. Changing it to 0 will not alter the constraints. A similar statement could be made for b and c.
From these observations, we can choose the minimum supermasks a, b, c, i.e., (a, b, c) = (x|z, y|x, z|y) and verify. If this does not satisfy, then no other solution could satisfy.
Thank you for the lightning-fast editorial! The hints and solutions are clear and well-structured, making it easy to follow along after the contest. Problem B stands out as a thoughtful challenge on bitwise operations, emphasising reversal and bit manipulation in a clever way. This might help make it more accessible for newer participants. Overall, a solid problem set with great variety—kudos to the authors!
CLICK ON THIS IMAGE Whats the explanation for this, why people with better ranks and less rating got minus while this guy SubArU_76 got positive delta.
Codeforces gives all users some rating boost first few contests
Can anyone help me what's wrong in code for problem C 343001567
For problem B, I found out that if this condition is met, then there exists a, b, c that meets the requirements: (y & z) == (z & x) == (z & x).
so this is my code and it passed the tests:
Submission: 342983760
(task E) Hope this helps some reader to understand that this one proof is made by contradiction.
F solution using sqrt decomp
Another bonus for 2153B - Bitwise Reversion: Checking the value of
.
how?? can you explain
Why give the F such a big timelimit
because it's not a fucking div 1 sir
This round is something nice that I can solve both E and F on my own, which I really like it.
As my approaches are different from the editoral, I'll take them down.
First of all, find the biggest prime $$$P$$$ that $$$P\le n$$$. To calculate $$$f_m(i,n)(P\le i \lt n)$$$, you need to find all the "good primes", which, according to the editoral, is all the prime numbers that smaller than $$$\sqrt n$$$
However, for $$$f_m(i,n)$$$, the good primes are actually all the prime divisors of $$$i+1,i+2,...,n$$$, so just iterating from $$$n$$$ to $$$P$$$, maintaining all the good prime using prime factorization, it runs quite fast.
It's easy to avoid the same prime to occur multiple times in the good prime list without using $$$\log$$$ structure.
My submission
Under the time limit, the problem can be solve without the property that the sequence is cute, using the mysterious power of eastern data structure technique lol
Given a subarray $$$[l_0,r_0]$$$, if we know the occurance of 1~n in it, and the beauty value of the subarray, we can easily compute the beaury value of $$$[l_0-1,r_0],[l_0+1,r_0],[l_0,r_0-1],[l_0,r_0+1]$$$ with $$$\mathcal O(1)$$$
Before the query, divide the sequence into B equal parts $$$[1,p_1],[p_1+1,p_2],...,[p_{B-1}+1,n]$$$, for every query [l,r], it can be converted into the combination of $$$[p_{L}+1,p_R]$$$ and some tiny scrap elements. I should also mention that $$$p_{L}$$$ doesn't necessarily bigger than $$$l$$$, it just need to be the closest, and the same for $$$p_{R}$$$.
For the main structure $$$[p_{L}+1,p_R]$$$, we reguard it as the subarray $$$[l_0,r_0]$$$, which I have mentioned above, the occurance can be pre-calculated using the idea of prefix sum, the beauty value of the subarray can also be pre-calculated.
What's more, as the following statement holds:
The additional influence can be settled in $$$\mathcal O(B)$$$
So the whole time complexity is $$$\mathcal O(\dfrac {n^2} B+qB)$$$. Set $$$B=\sqrt n$$$, the time complexity is $$$\mathcal O(n\sqrt n)$$$.
As the space complexity is also $$$\mathcal O(n\sqrt n)$$$, we need to optimize it with a bitset.
My submission
B one line solution : if (((x | y | z) ^ (x & y & z)) & ((x & y) | (y & z) | (z & x))){no} else yes
this is my solution for B and I'm very satisfied with it :)
Can anyone please check my submission for problem C and let me know why my code is failing in test case 2
https://mirror.codeforces.com/contest/2153/submission/343057370
If you decide to select two numbers from the remaining ones, one of them does not necessarily have to be the best choice when selecting only one. If you are still confused, look at the following set of Hack:
Yay I get that that's why I tried correcting that and this time I tried running two seperate for loops first time to get a single nonsymmetric edge and the second loop to try and get two nonsymmetric edge and get the best out of two . Still I couldn't get an AC.
https://mirror.codeforces.com/contest/2153/submission/343058487
Wrong 1:
in line 49:
if(perimeter>nonsymmetrical[i] && perimeter+nonsymmetrical[i]>nonsymmetrical[i+1])why check
perimeter>nonsymmetrical[i]?Wrong 2:
If you only find one pair of edges, there must be at least one other edge; otherwise, it is impossible to form a polygon.
Hack:
Obviously, you cannot just choose "5 5".
After making these two changes, it will be accepted.
Thanks a ton man finally it got accepted!!
There is very easy and intuitive solution for B
I think its pretty self explanatory
also problem D was very nice :)
Problem C editorial
length of the long odd stick and even odd stick is less than the total length, it should beshort odd stickinsteadeven odd stick?So, no one is gonna talk about C being harrrrd
For problem B , we can notice x=a&b, y=b&c, z=c&a,
if we take x&y=a&b&b&c=a&b&c, same for y&z and z&x we got a&b&c , this means (x&y)=(y&z)=(z&x), just checking this got accepted
Little_Sheep_Yawn and maomao90, thank you for this great contest.
I want to bonus you guys another approach way for problem B
I think the editorial code is too long and my way only this 342949235 Explain:
If we read the problem carefully, we easily notice that never get 2 values out of 3 (a&b, b&c, a&c) = 1
So we only have:
0 bit = 1
3 bit = 1
If at a bit there are exactly 2 bits in (bx, by, bz) equal to 1, a,b,c is not satisfied
https://mirror.codeforces.com/contest/2153/submission/343003640
I kind of tried this way
C was too brainstorming for me, too much edge cases to find! But, really enjoyed it.
Can someone check my 342993457 of question C, cf is always wa 2, but the example is too large, and the hack examples in the comment section that I tried were all correct.
ok, I solved it because the lowerbound exceeded the int range.
what is the actual logic? my thinking is that first we will add all sticks with even or nearest small even. then we can add 2 sticks with max length which had odd frequency. and checking diferently for n==3.plz see this 343110589
An even number of edges must be selectable.
Define the sum of the even-numbered edges as
res, and then discuss three cases:first, where the axis of symmetry is at the intersection point, meaning all edges are even, in which case it is necessary to ensure there are at least two even edges;
second, where the axis passes through one edge, which can then be odd, but it must be strictly less than
res;finally, where the axis passes through two edges. My approach is to enumerate the shorter edge
xand then find the longest edge that is strictly less thanx + res.thanks a lot man
How to even think around problem D, are there any problems applying similiar ideas?
Yeah quite many. It's just basic dp. Remember what is dp, its dividing a problem to subproblem to eventually solve it. Similiraly here, when you think about long equal segment, you can think it as segments of 2 or 3 length. So you are just thinking about cost of making equal 3 or 2 consecutive elements and cost to make equal behind this segment (I'm talking about dp[i-2] and dp[i-3]). Something like that
no I don't get what is basic in this question, I tried a dp with 2 states. Something like state 1 if it is to be made equal to the element to the left of it and state 2 to the right of it. I got wa2. I don't understand how the 2 and 3 block solution is correct, would be grateful if you can give me the proof.
Problem C
Why my code is giving TLE with unoredred_map and Accepted with map ~~~~~ //this is code
include <bits/stdc++.h>
using namespace std;
define int long long
signed main() { // your code goes here ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin>>t; while(t--) { int n; cin>>n; int a[n]; unordered_map<int,int>m; vectorv; int ev=0; for(int i=0;i<n;i++) { cin>>a[i]; m[a[i]]++; }
}
~~~~~
unordered_map is hashing and its worst case search complexity is O(n) where as map is avl or binary tree(balanced) thus its worst case search complexity is O(lgn)
thnx
So there is a risk in using unordered_map,so one should always use map isn't?
honestly at my current level the answer I can give is yes use map and set instead of unordered versions. I am not sure if for more difficult questions this would work or not
Problem D is very coooool, bro
How to think of this approach, I mean I got the intuition of using DP. But how to think of this 2 block and 3 block approach Is there any other approach possible and is there any other similar question
Something that helps me find the approach . just reading the question carefully and trying to find constants factor and greedy sub-parts.
Greedy part :
Here some element always has to be paired with something else (2 — block ) nearby
if the other something is the only pair of something previous , then you need pair all 3 ( 3 — block ). ( because if you pair these 2 , then the third might be left without a pair)
I messed up coding this during the contest tho , but my approach was mostly correct
https://mirror.codeforces.com/contest/2153/submission/343125042 Can anyone tell my why my code for C is giving wrong ans.
Can someone please prove why my solution to B works, I found out that this condition is necessary and just submitted it to see if it works. I can not prove how is it sufficient. Thanks
343127275
In problem C, how do we check a polygon for degeneracy?
Every side must be less than the sum of the left sides.
Problem B:
Why was it accepted?
coz your vars are all x&z and x&y and y&z, which are all equal only if the condition specified in the question met, coz x&z from the question or any of the others will always equal something like this a &b & b & c or a & a & b & c and so, which is a & b & c, so if all of the three have the same value then a & b & c exists, and if so, then a and b and c exist
Can you please explain with an example.
Question says
a&b=x b&c=y a&c=z
and this mean
x & y = (a&b) & (b&c) = a & b & c
x & z = (a & b) & (a & c) = a & b & c
y & z = (b & c) & (a & c) = a & b & c
so the question conditions meaning that there must be some value (a & b & c) let's call it k, such that x&y = x & z = y & z = k
so if all of the three (x&y, x&z, y&z) are equal then this value k exists, and if so, then there must be a and b and c that make this value k, that's it
Example
x=3 y=4 z=6
x & y = 0
x & z = 2
y & z = 4
then as the three are not the same so the conditions of the questions will fail and this means there is no value k which means there are no values a, b and c
Summary:
a&b=x b&c=y a&c=z
means x&y=x&z=y&z=a&b&c, so try to check if they are the same as this will guarantee the existence of a&b&c which will guarantee the existence of a, b and c
Thanks a lot. Finally got it.
Bro why C is so hard
2153B — BITWISE REVERSION IF ((x&y) == (y&z) && (y&z)==(z&x)) THEN YES ELSE NO
My sol for B was I noticed that x & y = a & b & c same for x & z and y & z (from given eqs)
so I said if x&y == x&z == y&z then YES else NO, I thought everyone thought like that :)
Any proofs behind it? I noticed many guys solved it in that way, but couldn't prove it by myself.
I just proved it here: proof
Sol for C
342957538
I think it's easier to read than editorial's
343061880 why this submission is giving wrong answer on test case 4 please if someone can help debugging me ?
In Problem B , we can just check: ((x&y) == (y&z) && (x&y) == (z&x)) ? "YES" :"NO"
I still did not get the intuition for this D question(Not alone). I mean how exactly to come across this approach and are there any similar questions I can do
Why the code(pypy3.10) for F will RuntimeError on 1?
I haven't learned pypy,I just want to know how long it need.
https://mirror.codeforces.com/contest/2153/submission/343239952
sorry, i just forgot to put "import bisect" in it.
How do we check non-degeneracy in the С problem, that is, each side is less than the sum of the others
check the largest included side only
Why the heck is the code for C THAT green!?
It hurts the eye.
Also I think there was a typo here: "length of the long odd stick and even odd stick"
Regarding the sentence in question 1, I believe there is ambiguity. "Note that you are allowed to skip an apple when you first encounter it, and you can choose to eat it later on a subsequent cycle." This sentence implies that you can only skip an apple once. For example, [5,4,3,1,2], the correct answer is 5. However, if we interpret it as meaning that each apple can only be skipped once (and must be eaten the second time it is encountered), then the answer is 4, because you cannot skip 5 to eat 4 again.
Hello, I received a message about a coincidence for Problem 2153B, submission [342960539]. I want to clarify that I wrote the entire code myself during the contest. Unfortunately, two of my friends (sim_ple and Nurmuhammet) asked to see my code during the contest, and I showed it to them, believing they only wanted to understand the approach. Without my permission, they then submitted the same code. I sincerely regret this mistake — I did not realize that even showing my code could be considered a violation, and I will never do this again. Please note that I submitted before they did, and I am the original author. I fully accept responsibility for my part and kindly ask for your understanding.
Yes, I'm sorry, I didn't know that, I won't repeat it again.
https://mirror.codeforces.com/blog/entry/147352
this problem was quite hard as a beginner
There is a simpler solution to problem B using bitwise OR 343340600
yeah this one is nice and short
10s TL is too generous 343615964
Little_Sheep_Yawn Problem F tutorial, "For subtrees that are a single vertex, they have the same value as the LCA", this statement seems to be contradictory to the construction of the tree ?
Why is the minimum value obtained in Problem E not the case when $$$v_k(a!) = v_k(b!)$$$?
Has anyone passed F with a time complexity of $$$O(n \times sqrt (n))$$$. I think this complex solution can pass this question, but in fact, I received Time limit exceeded on test 6
F could be easily solved using SQRT Decomposition
Why is it true in div2C:
"As long as the difference in the length of the long odd stick and even odd stick is less than the total length of the pairs of sticks with identical length, we can use the long odd stick and short odd stick."
Is it because if we denote longer base side length as a, shorter as b, the half of the total length of sides forming pairs should be larger than difference a/2-b/2 (strictly exceed in order not to be degenerate), as segment length, connecting a and b, should be greater than 0 (sort of triangle inequality)?
In D solution, I think we won't need 4 cycles, 3 would be sufficient.
for B, x = a&b, y = b&c, z = a&c , so x&y = a&b&c, x&z = a&b&c, y&z = a&b&c, Just make them equal. Here is my implementation:363764271