\(A>B\),总是有二进制下从高到低的前\(k\)位相等,第\(k+1\)位\(A\)是\(1\),\(B\)是\(0\)
本题中\(A=a_i\oplus j\),\(B=a_j\oplus i\),这里有一个很奇妙的性质(手玩或者打表也可以发现):
\(a_i\oplus j\)和\(a_j\oplus i\)的前\(k\)位相等,等价于\(a_i\oplus i\)和\(a_j\oplus j\)的前\(k\)位相等
然后这题就可以做了,只要对\(a_i\oplus i\)在之前建立的字典树中从高位枚举,出现分支再进行讨论即可(\(a_i\)和\(i\)的当前位我们知道了,所以\(a_i\oplus j>a_j\oplus i\)成立只要按\(a_j\)和\(j\)的当前位分类讨论即可)
总结:位运算,异或性质,字典树上dp
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define fr first
#define se second
#define et0 exit(0);
#define rep(i, a, b) for(int i = (int)(a); i <= (int)(b); i ++)
#define rrep(i, a, b) for(int i = (int)(a); i >= (int)(b); i --)
#define IO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef unsigned long long ULL;
const int INF = 0X3f3f3f3f, N = 3e5 + 10, MOD = 1e9 + 7;
const double eps = 1e-7, pi = acos(-1);
int idx;
int a[N];
int tr[N * 40][2], dp[N * 40][2];
void insert(int x, int y) {
int p = 0;
rrep (i, 30, 0) {
int u = x >> i & 1, v = y >> i & 1;
if (!tr[p][u ^ v]) tr[p][u ^ v] = ++idx;
p = tr[p][u ^ v];
}
}
int query(int x, int y) {
int p = 0, q = 0, mx = 0;
rrep (i, 30, 0) {
int u = x >> i & 1, v = y >> i & 1;
q = tr[p][!(u ^ v)], p = tr[p][u ^ v];
if (q) mx = max(mx, dp[q][v]);
if (!p) break;
}
return mx + 1;
}
void update(int x, int y, int mx) {
int p = 0;
rrep (i, 30, 0) {
int u = x >> i & 1, v = y >> i & 1;
p = tr[p][u ^ v];
dp[p][u] = max(dp[p][u], mx);
}
}
void work() {
int n;
cin >> n;
rep (i, 0, n - 1) cin >> a[i];
int res = 0;
rep (i, 0, n - 1) {
int mx = query(a[i], i);
res = max(res, mx);
insert(a[i], i);
update(a[i], i, mx);
}
cout << res << endl;
rep (i, 0, idx) tr[i][0] = tr[i][1] = dp[i][0] = dp[i][1] = 0;
idx = 0;
}
signed main() {
IO
int test = 1;
cin >> test;
while (test--) {
work();
}
return 0;
}
标签:Xor,int,hard,tr,Codeforces,oplus,mx,dp,define
From: https://www.cnblogs.com/xhy666/p/16607009.html