Luogu 3292 [SCOI2016]幸运数字
BZOJ 4568。
感觉很板。
前置技能:线性基。 放一篇感觉讲的比较丰富的博客: 戳这里。
首先要求在一个序列中任意选点使得异或和最大,当然是想到线性基了。
把问题转换到树上,如果每次询问的序列是两点之间的路径,也就是说我们只要提取出树上一条路径的线性基就可以了吧。
发现线性基满足可以快速合并这个性质,如果要合并的话只要把一个暴力插到另一个里面去就行了,这样是两个$log$,我们还可以启发式合并,把小的插到大的里面去,这样会更快。
所以我们发现可以链剖或者倍增来维护这个东西,我这么懒,当然是倍增了。
注意倍增的时候是点形成的集合而不是边形成的集合。
再提两句:
1、线性基并不满足区间可减性,所以大力可持久化应该是不行的。
2、点分治可以减少一个$log$,再用$tarjan$求一求$lca$会更快。
时间复杂度$O(nlog^3n)$。
Code:
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = ;
const int B = ;
const int Lg = ; int n, qn, tot = , head[N], dep[N], fa[N][Lg];
ll a[N]; struct Edge {
int to, nxt;
} e[N << ]; inline void add(int from, int to) {
e[++tot].to = to;
e[tot].nxt = head[from];
head[from] = tot;
} template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} struct Lp {
ll p[B]; int cnt; inline void init() {
cnt = ;
memset(p, 0LL, sizeof(p));
} inline void ins(ll val) {
for(int i = ; i >= ; i--) {
if((val >> i) & ) {
if(!p[i]) {
p[i] = val;
++cnt;
break;
}
val ^= p[i];
}
}
} inline ll getMax() {
ll res = 0LL;
for(int i = ; i >= ; i--)
if((res ^ p[i]) > res) res ^= p[i];
return res;
} } s[N][Lg]; inline Lp merge(Lp u, Lp v) {
Lp res; res.init();
if(u.cnt > v.cnt) {
res = u;
for(int i = ; i >= ; i--) {
if(!v.p[i]) continue;
res.ins(v.p[i]);
}
} else {
res = v;
for(int i = ; i >= ; i--) {
if(!u.p[i]) continue;
res.ins(u.p[i]);
}
}
return res;
} inline void swap(int &x, int &y) {
int t = x; x = y; y = t;
} void dfs(int x, int fat, int depth) {
fa[x][] = fat, dep[x] = depth;
s[x][].init();
if(fat) s[x][].ins(a[fat]);
for(int i = ; i <= ; i++) {
fa[x][i] = fa[fa[x][i - ]][i - ];
s[x][i] = merge(s[x][i - ], s[fa[x][i - ]][i - ]);
}
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs(y, x, depth + );
}
} inline Lp getLp(int x, int y) {
Lp res; res.init();
res.ins(a[x]), res.ins(a[y]);
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[y]) {
res = merge(res, s[x][i]);
x = fa[x][i];
}
if(x == y) return res;
for(int i = ; i >= ; i--)
if(fa[x][i] != fa[y][i]) {
res = merge(res, s[x][i]), res = merge(res, s[y][i]);
x = fa[x][i], y = fa[y][i];
}
res = merge(res, s[x][]), res = merge(res, s[y][]);
return res;
} inline void solve(int x, int y) {
Lp res = getLp(x, y);
printf("%lld\n", res.getMax());
} int main() {
read(n), read(qn);
for(int i = ; i <= n; i++) read(a[i]);
for(int x, y, i = ; i < n; i++) {
read(x), read(y);
add(x, y), add(y, x);
} dfs(, , ); for(int x, y; qn--; ) {
read(x), read(y);
solve(x, y);
} return ;
}
唔,Linear Basis居然被我写成了Lp……无话可说
Luogu 3292 [SCOI2016]幸运数字的更多相关文章
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
- [SCOI2016]幸运数字 树链剖分,线性基
[SCOI2016]幸运数字 LG传送门 为了快乐,我们用树剖写这题. 强行树剖,线段树上每个结点维护一个线性基,每次查询暴力合并. 瞎分析一波复杂度:树剖两点之间\(\log n\)条重链,每条重链 ...
- bzoj 4568: [Scoi2016]幸运数字
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 848 Solved: 336[Submit][Status ...
- [洛谷P3292] [SCOI2016]幸运数字
洛谷题目链接:[SCOI2016]幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城 ...
- 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...
- [BZOJ4568][Scoi2016]幸运数字 倍增+线性基
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1791 Solved: 685[Submit][Statu ...
- [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2131 Solved: 865[Submit][Statu ...
- 【BZOJ4568】[Scoi2016]幸运数字 倍增+线性基
[BZOJ4568][Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念 ...
- bzoj4568: [Scoi2016]幸运数字(LCA+线性基)
4568: [Scoi2016]幸运数字 题目:传送门 题解: 好题!!! 之前就看过,当时说是要用线性基...就没学 填坑填坑: %%%线性基 && 神犇 主要还是对于线性基的运用和 ...
随机推荐
- Linux-Crontab服务
1.安装并检查Crontab服务 检查cron服务: 检查Crontab工具是否安装:crontab -l 检查crond服务是否启动:service crond status 安装cron: yum ...
- 简单常用sql查询
[self.db executeUpdate:sql, record.recordID]; CREATE TABLE scene_record(id TEXT PRIMARY KEY, record_ ...
- MyISAM引擎的特点及优化方法
1.什么是MyISAM引擎?MyISAM引擎是MySQL关系数据库管理系统的默认存储引擎(MySQL5.5.5以前),这种MySQL的表存储结构从旧的ISAM代码扩展出许多有用的功能.在存储的时候,每 ...
- ACM学习历程—SNNUOJ1213 加油站问题(动态规划 || 数学)
题目链接:http://219.244.176.199/JudgeOnline/problem.php?id=1213 这是这次微软实习面试的一道题,当时只相出了一个2n的做法,面试官让我优化成n的做 ...
- celery 停止执行中 task
目录 原因 解决过程 原因 因为最近项目需求中需要提供对异步执行任务终止的功能,所以在寻找停止celery task任务的方法.这种需求以前没有碰到过,所以,只能求助于百度和google,但是找遍了资 ...
- nodejs 接口跨域
//设置跨域访问 //设置跨域访问 app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Orig ...
- ASP.NET MVC5中View显示Html
@Html.Raw(Model.Name) @(new HtmlString(Model.Name));
- 获得Oracke中刚插入的ID ---> GetInsertedID()
(1)首先 需要创建序列: CREATE SEQUENCE SE_TD_POWER MINVALUE 1 NOMAXVALUE START WITH 1 INCREMENT BY 1 NOCYCLE ...
- python 三元表达式、列表推导式、生成器表达式
一 三元表达式.列表推导式.生成器表达式 一 三元表达式 name=input('姓名>>: ') res='mm' if name == 'hahah' else 'NB' print( ...
- spring MVC 异常处理整理
一.异常结构 1.异常由外到内如下: web服务器处理异常--->web应用里面web.xml处理异常--->Spring框架处理异常---->控制器注释处理异常--->控制器 ...