D1. Xor-Subsequence (easy version)
D1. Xor-Subsequence (easy version)
It is the easy version of the problem. The only difference is that in this version $a_i \le 200$.
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$.
解题思路
如果我们选择了一个合法的序列,$(a_{i_1} \, , \, i_1), \, (a_{i_2} \, , \, i_2), \, \ldots, \, (a_{i_m} \, , \, i_m)$,那么必然有 $a_{i_1} \oplus i_2 < a_{i_2} \oplus i_1, \, \ldots a_{i_{m-1}} \oplus i_m < a_{i_{m}} \oplus i_{m-1}$。
定义状态 $f(i)$ 表示选择 $(a_i, i)$ 作为最后一项的所有序列中长度的最大值,根据序列前一个元素是哪个进行状态划分,有状态转移方程$$f(i) = \max\limits_{\begin{array}{c} 0 \leq j < i \\ a_j \oplus i < a_i \oplus j \end{array}}\left\{ f(j) \right\} + 1$$
很明显如果直接暴力枚举 $j$ 那么时间复杂度是 $O(n^2)$ 的。观察式子 $a_j \oplus i < a_i \oplus j$,此时已经有 $i > j$ 了,意味着 $a_j \oplus i$ 要变小或 $a_i \oplus j$ 变大。注意到 $a_i$ 最大只有 $200$,在二进制下只有最低 $8$ 位是有效的,即 $a_j$ 只对 $i$ 的最低 $8$ 位有影响,同理 $a_i$ 只对 $j$ 的最低 $8$ 位有影响。考虑 $i$ 和 $j$ 除了最低 $8$ 位之外的位,即 $\left\lfloor \frac{i}{2^8} \right\rfloor$ 和 $\left\lfloor \frac{j}{2^8} \right\rfloor$,如果 $\left\lfloor \frac{j}{2^8} \right\rfloor < \left\lfloor \frac{i}{2^8} \right\rfloor$,那么无论 $a_i$ 和 $a_j$ 的值是多少,必然有 $a_j \oplus i > a_i \oplus j$,所以 $j$ 的下界就是 $\left\lfloor \frac{i}{2^8} \right\rfloor \times 2^8$,也就是把 $i$ 的最低 $8$ 位都置 $0$,这样 $j$ 和 $i$ 在除了最低 $8$ 位之外的位都一样。为此 $j$ 的枚举范围应该是 $j \in \left[ \left\lfloor \tfrac{i}{2^8} \right\rfloor \times 2^8, \, i - 1 \right]$,区间大小最大只有 $2^8$。
AC 代码如下,时间复杂度为 $O(2^8 \cdot n)$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
int a[N];
int f[N];
void solve() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", a + i);
}
int ret = 0;
for (int i = 0; i < n; i++) {
f[i] = 1;
for (int j = i >> 8 << 8; j < i; j++) {
if ((a[j] ^ i) < (a[i] ^ j)) f[i] = max(f[i], f[j] + 1);
}
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
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17865151.html