D2. Xor-Subsequence (hard version)
It is the hard version of the problem. The only difference is that in this version $a_i \le 10^9$.
You are given an array of $n$ integers $a_0, a_1, a_2, \ldots a_{n - 1}$. Bryap wants to find the longest beautiful subsequence in the array.
An array $b = [b_0, b_1, \ldots, b_{m-1}]$, where $0 \le b_0 < b_1 < \ldots < b_{m - 1} < n$, is a subsequence of length $m$ of the array $a$.
Subsequence $b = [b_0, b_1, \ldots, b_{m-1}]$ of length $m$ is called beautiful, if the following condition holds:
- For any $p$ ($0 \le p < m - 1$) holds: $a_{b_p} \oplus b_{p+1} < a_{b_{p+1}} \oplus b_p$.
Here $a \oplus b$ denotes the bitwise XOR of $a$ and $b$. For example, $2 \oplus 4 = 6$ and $3 \oplus 1=2$.
Bryap is a simple person so he only wants to know the length of the longest such subsequence. Help Bryap and find the answer to his question.
Input
The first line contains a single integer $t$ ($1 \leq t \leq 10^5$) — the number of test cases. The description of the test cases follows.
The first line of each test case contains a single integer $n$ ($2 \leq n \leq 3 \cdot 10^5$) — the length of the array.
The second line of each test case contains $n$ integers $a_0,a_1,...,a_{n-1}$ ($0 \leq a_i \leq 200$) — the elements of the array.
It is guaranteed that the sum of $n$ over all test cases does not exceed $3 \cdot 10^5$.
Output
For each test case print a single integer — the length of the longest beautiful subsequence.
Example
input
3
2
1 2
5
5 2 4 3 1
10
3 8 8 2 9 1 6 2 8 3
output
2
3
6
Note
In the first test case, we can pick the whole array as a beautiful subsequence because $1 \oplus 1 < 2 \oplus 0$.
In the second test case, we can pick elements with indexes $1$, $2$ and $4$ (in $0$-indexation). For this elements holds: $2 \oplus 2 < 4 \oplus 1$ and $4 \oplus 4 < 1 \oplus 2$.
解题思路
dp 的分析与 D1. Xor-Subsequence (easy version) 一样。观察式子 $a_j \oplus i < a_i \oplus j$,意味着 $a_j \oplus i$ 和 $a_i \oplus j$ 的二进制的前 $k-1$ 个高位相同,第 $k$ 个高位不同,且 $a_j \oplus i$ 的第 $k$ 个高位是 $0$,$a_i \oplus j$ 的第 $k$ 个高位是 $1$。只考虑前 $k-1$ 个高位,由于都相同因此有 $a_j \oplus i = a_i \oplus j$,从而有 $a_i \oplus i = a_j \oplus j$。为此可以考虑在枚举完 $a_i$ 后,把 $a_i \oplus i$ 插到 Trie 中。
为此就很容易想到对于 $a_i$,枚举 $k$ 表示前 $k-1$ 个高位相同而第 $k$ 个高位不同,那么满足条件的 $a_j$ 和 $j$ 对应到 Trie 中就是从根节点开始走 $k-1$ 步,与 $a_i \oplus i$ 路径相同的 $a_j \oplus j$。第 $k$ 步取决于 $a_i \oplus i$ 的第 $k$ 个高位,如果 $a_i \oplus i$ 的第 $k$ 个高位是 $0$ 则走 $1$ 的分支,否则走 $0$ 的分支。
为什么是这样子呢?列表格分类讨论就好了,讨论 $a_i, i, a_j, j$ 的第 $k$ 个高位的值(要满足 $a_j$ 与 $i$ 相同,$a_i$ 与 $j$ 相同),比较 $a_i \oplus i$ 与 $a_j \oplus j$。
$a_j$ | $i$ | $a_i$ | $j$ | $a_i \oplus i$ | $a_j \oplus j$ |
$0$ | $0$ | $0$ | $1$ | $0$ | $1$ |
$0$ | $0$ | $1$ | $0$ | $1$ | $0$ |
$1$ | $1$ | $0$ | $1$ | $1$ | $0$ |
$1$ | $1$ | $1$ | $0$ | $0$ | $1$ |
可以发现如果第 $k$ 个高位不同,那么对于第 $k$ 个高位必然有 $a_i \oplus i \ne a_j \oplus j$,所以应该走相反的分支。
另外 $a_i$ 与 $j$ 的第 $k$ 个高位还要不同,因此可以维护一个 $g(u,0/1)$,表示考虑所有的 $a_j, \, j \in [0,i-1]$ 中,关于 $a_j \oplus j$ 从根节点走 $k$ 步到节点 $u$,且 $j$ 的第 $k$ 个高位是 $0/1$ 的所有 $f(j)$ 的最大值。
剩余的细节请见代码。
AC 代码如下,时间复杂度为 $O(n \log{A})$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5 + 10, M = N * 30;
int a[N];
int f[N];
int tr[M][2], g[M][2], idx;
void add(int x, int y) {
int t = x ^ y, p = 0;
for (int i = 29; i >= 0; i--) {
int u = t >> i & 1;
if (!tr[p][u]) tr[p][u] = ++idx;
p = tr[p][u];
g[p][y >> i & 1] = max(g[p][y >> i & 1], f[y]);
}
}
int query(int x, int y) {
int t = x ^ y, p = 0, ret = 1;
for (int i = 29; i >= 0; i--) {
int u = t >> i & 1;
if (tr[p][!u]) ret = max(ret, g[tr[p][!u]][~x >> i & 1] + 1);
p = tr[p][u];
if (!p) break;
}
return ret;
}
void solve() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", a + i);
}
idx = 0;
for (int i = 0; i < n * 30; i++) {
tr[i][0] = tr[i][1] = g[i][0] = g[i][1] = 0;
}
int ret = 0;
for (int i = 0; i < n; i++) {
f[i] = query(a[i], i);
add(a[i], i);
ret = max(ret, f[i]);
}
printf("%d\n", ret);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Codeforces Round #815 (Div. 2) 讲解:https://www.bilibili.com/video/BV1mG4y1a7QS/
Codeforces Round #815 (Div. 2) Editorial:https://codeforces.com/blog/entry/106136
Codeforces Round #815 (Div. 2) D1 D2(字典树 + dp):https://zhuanlan.zhihu.com/p/555425330
标签:Xor,高位,int,hard,tr,ret,Subsequence,test,oplus From: https://www.cnblogs.com/onlyblues/p/17865441.html