G - Max of Medians Editorial by en_translator
We do binary search for the answer.
We define functions \(f\), \(g\), \(f_d\), and \(g_d\) as follows:
Let \(f(C,x)\) be the maximum \(k\) such that we can rearrange the sequence \(C\) to make all of \(C_1 \oplus C_2, C_3 \oplus C_4, \ldots, C_{2k-1} \oplus C_{2k}\) greater than or equal to \(x\).
Let \(g(C,D,x)\) be the maximum \(k\) such that we can rearrange the sequences \(C\) and \(D\) to make all of \(C_1 \oplus D_1, C_2 \oplus D_2, \ldots, C_k \oplus D_k\) greater than or equal to \(k\).
Let \(f_d(C,x) \coloneqq f(C',x')\), where \(C'\) is the sequence obtained by replacing each element \(i\) of \(C\) with \(i \bmod 2^{d+1}\), and \(x' \coloneqq x \bmod 2^{d+1}\).
Let \(g_d(C,D,x) \coloneqq g(C', D', x')\), where \(C'\) is the sequence obtained by replacing each element \(i\) of \(C\) with \(i \bmod 2^{d+1}\), \(D'\) by replacing each element \(i\) of \(D\) with \(i \bmod 2^{d+1}\), and \(x' \coloneqq x \bmod 2^{d+1}\).
Intuitively, \(f_d\) and \(g_d\) care only about \(2^{d+1}\)s and greater places.
It is sufficient to determine if \(f(A,x) \geq \lfloor \frac{N+1}{2} \rfloor\).
Since \(f(A,x) = f_{29}(A,x)\), we seek for \( f_{29}(A,x)\).
In fact, the values of \(f_d(C,x)\) and \(g_d(C,D,x)\) can be found recursively from the values of \(f_{d-1}\) and \(g_{d-1}\) at several points. We will describe this recursion in detail. For a sequence \(X\), we denote by \(|X|\) its length.
1. Finding \(f_d(C,x)\)
For simplicity, we assume that \(x\) and each element of \(C\) is between \(0\) (inclusive) and \(2^{d+1}\) (exclusive).
For \(d \geq 0\), let \(C^{(0)}\) and \(C^{(1)}\) be the sequences consisting of the elements of \(C\) whose \(2^d\) places are \(0\) and \(1\), respectively.
1-1. if \(d = -1\)
\(f_d(C,x) = \lfloor \frac{|C|}{2} \rfloor\) (which is the base case of the recursion).
1-2. if \(d \geq 0\) and the \(2^d\)s place of \(x\) is \(0\)
By symmetry, we can assume that \(|C^{(0)}| \leq |C^{(1)}|\). The XOR of an element of \(C^{(0)}\) and another of \(C^{(1)}\) is always \(2^d\) or greater; since \(2^d > x\), it is also \(x\) or greater. Thus, \(f_d(C,x) = |C^{(0)}| + \min (\lfloor \frac {(|C^{(1)}| - |C^{(0)}|)}{2} \rfloor, f_{d-1}(C^{(1)}, x)\). (This is valid because we can pair an element of \(C^{(0)}\) and another of \(C^{(1)}\) greedily).
1-3. if \(d \geq 0\) and the \(2^d\)s place of \(x\) is \(1\)
The XOR of an element of \(C^{(0)}\) and another of \(C^{(1)}\) is always strictly less than \(2^d\); since \(2^d \leq x\), it is also strictly less than \(x\). Thus, \(f_d(C,x) = g_{d-1}(C^{(0)}, C^{(1)}, x)\).
2. Finding \(g_d(C,D,x)\)
It can be found in almost the same way as \(f_d(C,D,x)\).
For simplicity, we assume that \(x\) and each element of \(C\) and \(D\) is between \(0\) (inclusive) and \(2^{d+1}\) (exclusive).
For \(d \geq 0\), let \(C^{(0)}\) and \(C^{(1)}\) be the sequences consisting of the elements of \(C\) whose \(2^d\) places are \(0\) and \(1\), respectively; let \(D^{(0)}\) and \(D^{(1)}\) be the sequences consisting of the elements of \(D\) whose \(2^d\) places are \(0\) and \(1\), respectively.
2-1. if \(d=-1\)
\(g_d(C,D,x) = \min(|C|,|D|)\) (which is the base case of the recursion).
2-2. if \(d \geq 0\) and the \(2^d\)s place of \(x\) is \(0\)
By symmetry, we can assume that \(|C^{(0)}| \leq |D^{(1)}|\). The XOR of an element of \(C^{(0)}\) and another of \(D^{(1)}\), and the XOR of an element of \(C^{(1)}\) and another of \(D^{(0)}\), is always \(2^d\) or greater; by \(2^d > x\), it is also \(x\) or greater.
2-2-1. if \(|C^{(1)}| \leq |D^{(0)}|\)
\(g_d(C,D,x) = |C^{(0)}| + |C^{(1)}|\) (which can be easily evaluated from lower and upper).
2-2-2. if \(|C^{(1)}| > |D^{(0)}|\)
\(g_d(C,D,x) = |C^{(0)}| + |D^{(0)}| + \min(|C^{(1)}| - |D^{(0)}|, |D^{(1)}| - |C^{(0)}|, g_{d-1}(C^{(1)}, D^{(1)}, x))\). (This is true because we can greedily pair an element of \(C^{(0)}\) and another of \(D^{(1)}\), and an element of \(D^{(0)}\) and another of \(C^{(1)}\).)
2-3. if \(d \geq 0\) and the \(2^d\)s place of \(x\) is \(1\)
The XOR of an element of \(C^{(0)}\) and another of \(D^{(1)}\), and the XOR of an element of \(C^{(1)}\) and another of \(D^{(0)}\), is always strictly less than \(2^d\); by \(2^d \leq x\), it is also strictly less than \(x\). Thus, \(g_d(C,D,x) = g_{d-1}(C^{(0)}, D^{(1)}, x) + g_{d-1}(C^{(1)}, D^{(0)}, x)\).
Hence, the sought value is found by computing this recursion. For each \(d\), we evaluate \(O(N)\) points, so the decision problem is solved in an \(O(N \log \max A_i)\) time, and the entire problem is solved in a total of \(O(N (\log \max A_i) ^ 2)\) time. Observing the recursion equation, we can actually see that \(f(A,x) = \lfloor \frac {g(A,A,x)}{2} \rfloor\), so the answer can be found without using \(f\) and \(f_d\).
The following is a sample code. Note that the variable names may differ from the editorial, and in the recursion, instead of explicitly taking a sequence, we sort \(A\) and receive it in the form of \(A[l:r]\). To find the appropriate \(m\) to divide \(C = A[l:r]\) into \(|C^{(0)}| = A[l:m]\) and \(|C^{(1)}| = A[m:r]\), a precalculation using the sliding window trick is performed (but we have confirmed that we can always do a binary search in every recursion).
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 200010;
vector<vector<int>> v(30, vector<int>(N));
int g(vector<int> &a, int xl, int xr, int yl, int yr, int x, int d) {
if (xl == xr || yl == yr) return 0;
if (d == -1) return min(xr - xl, yr - yl);
int xm = v[d][xl], ym = v[d][yl];
int x1 = xm - xl, x2 = xr - xm, y1 = ym - yl, y2 = yr - ym;
if (x >> d & 1) {
int c1 = g(a, xl, xm, ym, yr, x, d - 1);
int c2 = g(a, xm, xr, yl, ym, x, d - 1);
return c1 + c2;
}
else {
bool f1 = x1 <= y2;
bool f2 = x2 <= y1;
if (f1 && f2) return x1 + x2;
else if (!f1 && !f2) return y1 + y2;
else if (f1 && !f2) {
int r = min({ g(a, xm, xr, ym, yr, x, d - 1), y2 - x1, x2 - y1 });
return r + x1 + y1;
}
else if (!f1 && f2) {
int r = min({ g(a, xl, xm, yl, ym, x, d - 1), x1 - y2, y1 - x2 });
return r + x2 + y2;
}
}
}
int f(vector<int> &a, int l, int r, int x, int d) {
if (l == r) return 0;
if (d == -1) return (r - l) / 2;
int m = v[d][l];
int x1 = m - l, x2 = r - m;
if (x >> d & 1) return g(a, l, m, m, r, x, d - 1);
else {
if (x1 <= x2) return min((x2 - x1) / 2, f(a, m, r, x, d - 1)) + x1;
else return min((x1 - x2) / 2, f(a, l, m, x, d - 1)) + x2;
}
}
int main() {
int n;
cin >> n;
vector<int> a(2 * n);
for (int i = 0; i < 2 * n; i++) cin >> a[i];
sort(a.begin(), a.end());
a.push_back(7 << 28);
int ans = 0;
for (int i = 0; i < 30; i++) {
int f = 0;
int z = 1 << (i + 1);
int nxt = a[0] / z * z + z / 2;
int mx = a[0] / z * z + z;
int tmp = -1;
for (int j = 0; j < 2 * n + 1; j++) {
if (a[j] >= nxt && tmp == -1) tmp = j;
if (a[j] >= mx) {
for (int k = f; k < j; k++) v[i][k] = tmp;
f = j;
nxt = a[j] / z * z + z / 2;
mx = a[j] / z * z + z / 2;
tmp = -1;
}
if (a[j] >= nxt && tmp == -1) tmp = j;
}
}
for (int b = 29; b >= 0; b--) {
int tmp = ans | (1 << b);
int cnt = f(a, 0, 2 * n, tmp, 29);
if (cnt >= (n + 1) / 2) ans |= 1 << b;
}
cout << ans << '\n';
}
posted:
last update: