CF840E In a Trap
这题似乎挺经典的。给类似的位运算维护提供了一个思路。
初看题,这个形式很明显是把树上路径拆分成了若干段,这个询问很奇怪。
智商不够阈值分治来凑。每个点向上预处理 \(256\) 的长度的信息,这样就只需考虑高位带来的影响了。那么需要预处理的就是 \(f_{u,k}\) 表示这条链中异或上 \(256k\) 的最大值。这个是方便用 Trie 维护的。
于是就做完了。询问直接跳链查询就行了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
namespace IO {
#define isdigit(x) (x >= '0' && x <= '9')
template<typename T>
inline void read(T &x) {
x = 0; char ch = getchar(); int f = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
if(f) x = -x;
}
template<typename T, typename... Rest>
inline void read(T &x, Rest&... rest) {
read(x), read(rest...);
}
template<typename T>
inline void write(T x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
#undef isdigit
}
using namespace IO;
const int N = 50010;
const int B = 266;
int n, q, a[N], dep[N];
vector<int> G[N];
int adj[N][B], nxt[N];
int f[N][B];
void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
for(int v : G[u]) {
if(v == fa) continue;
adj[v][0] = v;
for(int i = 1; i <= 255; ++i)
adj[v][i] = adj[u][i - 1];
nxt[v] = adj[u][255];
dfs(v, u);
}
}
struct Trie {
int tot, tr[N][2];
void clear() {
for(int i = 1; i <= tot; ++i)
tr[i][0] = tr[i][1] = 0;
tot = 1;
}
void insert(int x) {
int u = 1;
for(int i = 15; ~i; --i) {
int tp = x >> i & 1;
if(!tr[u][tp]) tr[u][tp] = ++tot;
u = tr[u][tp];
}
}
int query(int x) {
int u = 1, res = 0;
for(int i = 15; ~i; --i) {
int tp = (x >> i & 1) ^ 1;
if(tr[u][tp]) u = tr[u][tp], res |= 1 << i;
else u = tr[u][tp ^ 1];
}
return res;
}
}trie;
void solve() {
int u, v, ans = 0, k = 0;
read(u, v);
while(dep[nxt[v]] >= dep[u]) {
ans = max(ans, f[v][k]);
++k, v = nxt[v];
}
int step = k << 8;
while(v != u) {
ans = max(ans, a[v] ^ step);
v = adj[v][1], ++step;
}
ans = max(ans, a[u] ^ step);
printf("%d\n",ans);
}
int main() {
read(n, q);
for(int i = 1; i <= n; ++i)
read(a[i]);
for(int i = 1; i < n; ++i) {
int u, v;
read(u, v);
G[u].emplace_back(v);
G[v].emplace_back(u);
}
adj[1][0] = 1;
dfs(1, 0);
for(int i = 1; i <= n; ++i) {
trie.clear();
for(int j = 0; j <= 255; ++j) {
int x = adj[i][j];
if(!x) break;
trie.insert(a[x] ^ j);
}
for(int j = 0; j <= 255; ++j)
f[i][j] = trie.query(j << 8);
}
while(q--) solve();
return 0;
}
标签:ch,int,void,tr,tp,CF840E,read,Trap
From: https://www.cnblogs.com/DCH233/p/17412630.html