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]幸运数字的更多相关文章

  1. BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]

    4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...

  2. [SCOI2016]幸运数字 树链剖分,线性基

    [SCOI2016]幸运数字 LG传送门 为了快乐,我们用树剖写这题. 强行树剖,线段树上每个结点维护一个线性基,每次查询暴力合并. 瞎分析一波复杂度:树剖两点之间\(\log n\)条重链,每条重链 ...

  3. bzoj 4568: [Scoi2016]幸运数字

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 848  Solved: 336[Submit][Status ...

  4. [洛谷P3292] [SCOI2016]幸运数字

    洛谷题目链接:[SCOI2016]幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城 ...

  5. 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)

    4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...

  6. [BZOJ4568][Scoi2016]幸运数字 倍增+线性基

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1791  Solved: 685[Submit][Statu ...

  7. [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2131  Solved: 865[Submit][Statu ...

  8. 【BZOJ4568】[Scoi2016]幸运数字 倍增+线性基

    [BZOJ4568][Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念 ...

  9. bzoj4568: [Scoi2016]幸运数字(LCA+线性基)

    4568: [Scoi2016]幸运数字 题目:传送门 题解: 好题!!! 之前就看过,当时说是要用线性基...就没学 填坑填坑: %%%线性基 && 神犇 主要还是对于线性基的运用和 ...

随机推荐

  1. luogu 3375 KMP模板题

    #include<bits/stdc++.h> using namespace std; ,M = ; int next[N]; void getNext(char s[]) //找nex ...

  2. 剑指offer--8.调整数组顺序使奇数位于偶数前面

    习惯了简单 ------------------------------------------------- 时间限制:1秒 空间限制:32768K 热度指数:422906 本题知识点: 数组 题目 ...

  3. THUPC2018 城市地铁规划

    $n$ 个点,你可以随意连成一棵树,一个点的贡献为 $F(度数) \space mod \space 59393$ ,$F$ 为给定多项式函数,不超过 $10$ 次 求这 $n$ 个点的最大贡献,和最 ...

  4. wpf中将string格式的颜色转换成color类型

    wpf中Brushes有很多对应的颜色,先盗张图,每个颜色对于的名称和ARGB值有了,问题是有时候我们取到的颜色是ARGB值,而且是string类型的,该怎么转换成color呢,只有转换成color之 ...

  5. TP上传图片

    //更新 更新中的话,一定要写那一个if判断 public function update(){ $model = M('link'); $upload = new \Think\Upload();/ ...

  6. nodejs express mysql

  7. GMchess Linux下的中国象棋游戏

    gmchess,一款Linux下的中国象棋程序

  8. LOJ 10189 仓库建设 ——斜率优化dp

    题目:https://loj.ac/problem/10189 #include<iostream> #include<cstdio> #include<cstring& ...

  9. Pix mesa 自动化测试

    最近在准备PIX的认证, 需要进行mesa测试. 但是Mesa的标准测试工具中没有针对PIX的TestCase, 只是提到NIST的web测试.路径为:http://pixpdqtests.nist. ...

  10. OpenCV绘图函数

    OpenCV几个绘图函数 矩形 rectangle(Mat& img,Point pt1, Point pt2, const Scalar&color, int thickness=1 ...