当前位置: 首页 > news >正文

洛谷 P3292 [SCOI2016] 幸运数字 题解 - L

link

Description

给定一棵 \(n\) 个节点的树,每个节点有一个正整数权值 \(w_i\)

进行 \(q\) 次询问,每次询问给出两个节点 \(x, y\),从 \(x\)\(y\) 路径上的所有节点的权值中选出若干个数(可以不选),使得它们的异或和最大,输出这个最大值。

\(1 \le n \le 2 \times 10^4\)\(1 \le m \le 2 \times 10^5\)\(1 \le w_i \le 2^{60}\)

Solution

异或和最大,容易想到线性基。

线性基是根据序列生成的具有如下特殊性质的一个集合:

  • 在该集合中任选一些数的异或和,等于原序列中任选一些数的异或和;
  • 满足上述条件的极小集合。

因此线性基有如下附加性质:

  • 原序列中的任何数,都等于线性基中任选一些数的异或和;
  • 线性基中不存在一组数,使得它们的异或和为 \(0\)
  • 线性基中不存在两组取值集合,使得它们的异或值相等。

(思考:为什么?)

于是我们可以写出线性基的封装结构:

struct LB {int bss[MaxBit + 5];LB() { memset(bss, 0, sizeof(bss)); }void insert(int x) {for (int j = MaxBit; ~j; j--) {if (!(x & (1ll << j))) continue;if (bss[j]) x ^= bss[j];else { bss[j] = x; break; }}}void unite(LB y) {for (int j = MaxBit; ~j; j--) {if (y.bss[j]) insert(y.bss[j]);}}int query() {int res = 0;for (int j = MaxBit; ~j; j--) {if ((res ^ bss[j]) > res) res ^= bss[j];}return res;}
};
  • bss 数组

    线性基集合。bss[j] 表示最高位为 j 的基。

  • insert 方法

    向线性基中插入一个数。

    原理:不断地用既有的线性基去攻击它,直到它剩下一些不可消除的数。这些数于是成为新的线性基。

  • unite 方法

    合并两个线性基。

    基于暴力合并,因此单次时间复杂度为 \(O(\log^2 V)\)

  • query 方法

    查询线性基中,异或和的最大值。

考虑将树上问题转换为链上问题,注意到树上两点间路径最多仅能转化为两条链,因此对这两条链分别处理。用树上倍增预处理每个节点往上走 \(2^j\) 步的路径上所有节点权值的线性基。查询时,将 \(u \leftrightarrow v\) 的路径拆分成 \(u \leftrightarrow \text{LCA}(u, v)\)\(v \leftrightarrow \text{LCA}(u, v)\),将这些段的线性基合并,最后求最大异或和。

写法注意:以 LCA 模板为基础,边倍增边更新线性基。

代码:

#include <bits/stdc++.h>
#define int long long
#define inf 1e18
#define debug cout << '!';
#define filein(x) freopen(#x".in", "r", stdin);
#define fileout(x) freopen(#x".out", "w", stdout);
#define file(x) filein(x) fileout(x)
// #define Fast_IO
using namespace std;
#ifdef Fast_IO
inline int read() {int x = 0, f = 1; char c = getchar();while (c < '0' or c > '9') { if (c == '-') f = -1; c = getchar(); }while (c >= '0' and c <= '9') { x = x * 10 + c - '0'; c = getchar(); }return x * f;
}
void write(int x) {if (x < 0) putchar('-'), x = -x;if (x > 9) write(x / 10);putchar(x % 10 + '0'); return;
}
#endif
const int MaxN = 2e4, MaxL = 15, MaxBit = 62;
int n, q;
int anc[MaxN + 5][MaxL + 5], dep[MaxN + 5], val[MaxN + 5];
struct LB {int bss[MaxBit + 5];LB() { memset(bss, 0, sizeof(bss)); }void insert(int x) {for (int j = MaxBit; ~j; j--) {if (!(x & (1ll << j))) continue;if (bss[j]) x ^= bss[j];else { bss[j] = x; break; }}}void unite(LB y) {for (int j = MaxBit; ~j; j--) {if (y.bss[j]) insert(y.bss[j]);}}int query() {int res = 0;for (int j = MaxBit; ~j; j--) {if ((res ^ bss[j]) > res) res ^= bss[j];}return res;}
} lb[MaxN + 5][MaxL + 5];
vector<int> g[MaxN + 5];
void DFS(int u, int fa) {lb[u][0].insert(val[u]);for (auto v: g[u]) {if (v == fa) continue;dep[v] = dep[u] + 1;anc[v][0] = u;DFS(v, u);}
}
void LCA_init() {for (int j = 1; j <= MaxL; j++) {for (int i = 1; i <= n; i++) {anc[i][j] = anc[anc[i][j - 1]][j - 1];lb[i][j] = lb[i][j - 1];lb[i][j].unite(lb[anc[i][j - 1]][j - 1]);}}
}
int LCA_query(int u, int v) {LB cur;if (dep[u] < dep[v]) swap(u, v);for (int j = MaxL; ~j; j--) {if (dep[anc[u][j]] >= dep[v]) {cur.unite(lb[u][j]);u = anc[u][j];}}if (u == v) {cur.insert(val[u]);return cur.query();}for (int j = MaxL; ~j; j--) {if (anc[u][j] != anc[v][j]) {cur.unite(lb[u][j]), cur.unite(lb[v][j]);u = anc[u][j], v = anc[v][j];}}cur.unite(lb[u][0]), cur.unite(lb[v][0]);cur.insert(val[anc[u][0]]);return cur.query();
}
signed main() {cin.tie(0) -> sync_with_stdio(0);cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> val[i];}for (int i = 1; i < n; i++) {int u, v; cin >> u >> v;g[u].push_back(v); g[v].push_back(u);}DFS(1, 0);LCA_init();while (q--) {int u, v; cin >> u >> v;cout << LCA_query(u, v) << '\n';}return 0;
}
http://www.jsqmd.com/news/827911/

相关文章:

  • Snap.Hutao胡桃工具箱:免费开源的原神桌面助手完全指南
  • 心智网络与图神经网络:从Awesome清单到脑科学AI实战
  • PCA降维后画图总感觉差点意思?试试用sklearn和matplotlib绘制带置信区间的分类图(附完整代码)
  • 基于RT-Thread与PSoC 6的智能环境监测系统设计与实现
  • Adafruit Bluefruit Playground:iOS与蓝牙开发板的物联网交互实战
  • 2026届学术党必备的六大AI学术平台解析与推荐
  • UPS不间断电源正确使用指南:从开机到维护,一文掌握核心要点
  • FPGA并行FIR滤波器设计:50MHz实时信号处理与Verilog实现
  • STM32F4 HAL库实战:手把手教你用MPU6050 DMP库获取稳定欧拉角(附避坑指南)
  • Maxwell 2D仿真进阶:从磁力线可视化到磁感应强度曲线分析
  • 在Windows上安装安卓应用的终极指南:告别模拟器,开启跨平台新体验
  • Cursor-Learner:打造个性化AI编程助手,让代码编辑器更懂你
  • 国产数据库有哪些
  • Unity实战:利用TriLib插件实现运行时动态加载外部3D模型
  • 在Windows上安装安卓应用的终极指南:APK安装器完整使用教程
  • 让经典游戏在现代Windows系统上流畅运行:DDrawCompat兼容性解决方案
  • 嵌入式开发避坑:uboot bootcmd参数配错,内核解压失败怎么办?
  • 如何用FanControl实现显卡风扇0 RPM静音?Windows电脑散热优化终极指南
  • 免费音频编辑终极指南:Audacity如何让专业音频处理变得简单
  • AI资源自动化管理:构建智能代理系统整合免费API与开源模型
  • Mac n 工具常用命令
  • CTF 入门避坑指南:新手常犯的 8 个致命错误,告别无效学习
  • UEFI开发避坑指南:WaitForEvent和CreateEvent的5个实战陷阱与正确用法
  • 玩转 Agent 02 | 告别系统孤岛,一篇看懂企业级一站式智能体工作站 HiAgent
  • 金字塔式 Python学习路径全景图解
  • 从零构建千万级IM系统:微服务架构与核心消息流转实战
  • AI自动化工具开发实战:从免费API整合到浏览器自动化
  • iOS 26.4-26.5终极越狱指南:安全解锁iPhone隐藏功能与高级定制方案
  • 城区回收黄金哪家更靠谱?暗访六家店,福正美答案最踏实 - 福正美黄金回收
  • AI规则自动化进化:让大语言模型自我约束与对齐的工程实践