题目链接  BZOJ 4568

考虑树链剖分+线段树维护每一段区域的异或线性基

对于每个询问,求出该点集的异或线性基。然后求一下这个线性基里面能异或出的最大值即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define ls i << 1
#define rs i << 1 | 1
#define lson i << 1, L, mid
#define rson i << 1 | 1, mid + 1, R typedef long long LL; const int N = 2e4 + 10; struct lb{
LL d[70];
int cnt;
void clear(){
memset(d, 0, sizeof d);
cnt = 0;
}
bool ins(LL val){
dec(i, 62, 0) if (val & (1LL << i)){
if (!d[i]){ d[i] = val; break; }
val ^= d[i];
}
return val > 0;
}
LL qmax(){
LL ret = 0;
dec(i, 62, 0) if ((ret ^ d[i]) > ret) ret ^= d[i];
return ret;
}
LL qmin(){
rep(i, 0, 62) if (d[i]) return d[i];
return 0;
}
}; lb t[N << 3]; int f[N], fp[N], son[N], deep[N], father[N], sz[N], top[N];
int q, tot, n;
LL a[N];
vector <int> v[N]; lb merge(const lb &n1, const lb &n2){
lb ret = n1;
dec(i, 60, 0) if (n2.d[i]) ret.ins(n2.d[i]);
return ret;
} void dfs1(int x, int fa, int dep){
deep[x] = dep;
father[x] = fa;
son[x] = 0;
sz[x] = 1;
int ct = (int)v[x].size();
rep(i, 0, ct - 1){
int u = v[x][i];
if (u == fa) continue;
dfs1(u, x, dep + 1);
sz[x] += sz[u];
if (sz[son[x]] < sz[u]) son[x] = u;
}
} void dfs2(int x, int tp){
top[x] = tp;
f[x] = ++tot;
fp[f[x]] = x;
if (son[x]) dfs2(son[x], tp);
int ct = (int)v[x].size();
rep(i, 0, ct - 1){
int u = v[x][i];
if (u == father[x] || u == son[x]) continue;
dfs2(u, u);
}
} void build(int i, int L, int R){
if (L == R){
t[i].ins(a[fp[L]]);
return;
} int mid = (L + R) >> 1;
build(lson);
build(rson);
t[i] = merge(t[ls], t[rs]);
} lb query(int i, int L, int R, int l, int r){
if (L == l && R == r) return t[i];
int mid = (L + R) >> 1;
if (r <= mid) return query(lson, l, r);
else if (l > mid) return query(rson, l, r);
else return merge(query(lson, l, mid), query(rson, mid + 1, r));
} lb work(int x, int y){
lb ret;
ret.clear();
int f1 = top[x], f2 = top[y];
for (; f1 != f2; ){
if (deep[f1] < deep[f2]) swap(f1, f2), swap(x, y);
ret = merge(ret, query(1, 1, n, f[f1], f[x]));
x = father[f1], f1 = top[x];
} if (x == y) return merge(ret, query(1, 1, n, f[x], f[y]));
if (deep[x] > deep[y]) swap(x, y);
return merge(ret, query(1, 1, n, f[x], f[y]));
} int main(){ scanf("%d%d", &n, &q);
rep(i, 1, n) scanf("%lld", a + i); rep(i, 2, n){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
} dfs1(1, 0, 0);
dfs2(1, 1);
build(1, 1, n); while (q--){
int x, y;
scanf("%d%d", &x, &y);
lb cnt = work(x, y);
printf("%lld\n", cnt.qmax());
} return 0;
}

  

BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)的更多相关文章

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

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

  2. 【BZOJ-4568】幸运数字 树链剖分 + 线性基合并

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

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

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

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

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

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

    一眼做法,好处是好想好写坏处是常数大,容易被卡(bzoj loj 洛谷开O2 能AC,不开有90分-- 大概就是树剖之后维护线段树,在线段树的每个节点上上维护一个线性基,暴力\( 60^2 \)的合并 ...

  6. BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增

    [题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...

  7. BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...

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

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

  9. bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][ ...

随机推荐

  1. 【整理】虚拟机和主机ping不通解决办法,虚拟机ping不通外网的解决方法

     检查几个方面: 1.检查虚拟网卡有没有被禁用2.检查虚拟机与物理机是否在一个VMNet中3.检查虚拟机的IP地址与物理机对应的VMNet是否在一个网段4.检查虚拟机与物理机的防火墙是否允许PING, ...

  2. stm32之Cortex系统定时器(SysTick)

    转载自:http://www.21ic.com/app/mcu/201811/781135.htm   SysTick时钟,俗称“嘀嗒定时器”,它能按设定的时间产生一次中断.控制工程代码中随处可见形如 ...

  3. aoj-0118 property distribution(搜索)

    Time limit1000 ms Memory limit131072 kB タナカ氏が HW アールの果樹園を残して亡くなりました.果樹園は東西南北方向に H × Wの区画に分けられ.区画ごとにリ ...

  4. The Best Path HDU - 5883 欧拉通路

    图(无向图或有向图)中恰好通过所有边一次且经过所有顶点的的通路成为欧拉通路,图中恰好通过所有边一次且经过所有顶点的回路称为欧拉回路,具有欧拉回路的图称为欧拉图,具有欧拉通路而无欧拉回路的图称为半欧拉图 ...

  5. PTA 7-1 银行业务队列简单模拟

    用链表实现队列操作,代码如下: #include <iostream> #include <cstdio> #include <algorithm> #includ ...

  6. HDU 5111 Alexandra and Two Trees 树链剖分 + 主席树

    题意: 给出两棵树,每棵树的节点都有一个权值. 同一棵树上的节点的权值互不相同,不同树上节点的权值可以相同. 要求回答如下询问: \(u_1 \, v_1 \, u_2 \, v_2\):询问第一棵树 ...

  7. Hive中集合类型

    Hive中集合类型 创建表,集合是以 - 分割的 数据文件 加载数据 查询数据 查询数组中第一个字段 再建一个表,使用map 查看数据文件 加载数据 查询数据 查询键值 创建表,struct类型 查看 ...

  8. Python 前端的第三方库

    sweetalert sweeralert:地址 这个使用很简单,需要在在他们的,css和js文件. 酷炫的结果    datatables datatables:地址 已https://datata ...

  9. 如何用treap写luogu P3391

    treap大法好!!! splay什么的都是异端 --XZZ 先%FHQ为敬 (fhq)treap也是可以搞区间翻转的 每次把它成(1~L-1)(L~R)(R+1~n)三块然后打标记拼回去 对于有标记 ...

  10. 【NOIP2017】 列队

    线段树博客先开个点随笔.... 这意味着啥呢? 今天绝对要把这道题写出来并且更掉这篇blog!!!! ~ upd:懂了哈哈哈哈哈哈哈 先贴代码 回家+讲解 ---------------------- ...