题目描述

A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5 和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中可以保留的最大幸运值是多少。

输入

第一行包含 2 个正整数 n ,q,分别表示城市的数量和旅行者数量。第二行包含 n 个非负整数,其中第 i 个整数 Gi 表示 i 号城市的幸运值。随后 n-1 行,每行包含两个正整数 x ,y,表示 x 号城市和 y 号城市之间有一条道路相连。随后 q 行,每行包含两个正整数 x ,y,表示这名旅行者的旅行计划是从 x 号城市到 y 号城市。N<=20000,Q<=200000,Gi<=2^60

输出

输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。

样例输入

4 2
11 5 7 9
1 2
1 3
1 4
2 3
1 4

样例输出

14
11


题解

自己yy出的树上倍增+高斯消元动态维护线性基

求最大异或和,显然需要使用线性基。那么对于每组询问,拿出路径上的线性基即可。

采用树上倍增的方法,设$f[i][x]$为x的$2^i$祖先,$a[i][x]$为x(包括)到$f[i][x]$(不包括)的路径上的点的线性基。

那么需要做的就是合并线性基。这里将小的暴力插入到大的中。对于插入的一个数,如果不能用原来的线性基把它消掉,那么就添加该数,并使用插入排序维护线性基单调递减。

最后贪心求解即可。

复杂度为感人的$O(q\log n\log^2g)$,实际跑了20s--

另外本题维护线性基如果使用vector则会MLE,所以必须使用数组。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 20010
using namespace std;
typedef long long ll;
struct data
{
ll v[64];
int tot;
data() {memset(v , 0 , sizeof(v)) , tot = 0;}
void insert(ll x)
{
int i;
for(i = 0 ; i < tot ; i ++ )
if((x ^ v[i]) < x)
x ^= v[i];
if(x)
{
v[++tot] = x;
for(i = tot ; i ; i -- )
{
if(v[i] > v[i - 1]) swap(v[i] , v[i - 1]);
else break;
}
}
}
ll query()
{
ll ans = 0;
int i;
for(i = 0 ; i < tot ; i ++ )
if((ans ^ v[i]) > ans)
ans ^= v[i];
return ans;
}
}a[15][N];
ll w[N];
int head[N] , to[N << 1] , next[N << 1] , cnt , fa[15][N] , deep[N] , log[N];
void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void merge(data a , data b , data *c)
{
if(a.tot > b.tot) swap(a , b);
c->tot = b.tot;
int i;
for(i = 0 ; i < b.tot ; i ++ ) c->v[i] = b.v[i];
for(i = 0 ; i < a.tot ; i ++ ) c->insert(a.v[i]);
}
void dfs(int x)
{
int i;
a[0][x].v[a[0][x].tot ++ ] = w[x];
for(i = 1 ; (1 << i) <= deep[x] ; i ++ )
fa[i][x] = fa[i - 1][fa[i - 1][x]] , merge(a[i - 1][x] , a[i - 1][fa[i - 1][x]] , &a[i][x]);
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[0][x])
fa[0][to[i]] = x , deep[to[i]] = deep[x] + 1 , dfs(to[i]);
}
ll solve(int x , int y)
{
data tmp;
int i;
if(deep[x] < deep[y]) swap(x , y);
for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
if(deep[x] - (1 << i) >= deep[y])
merge(tmp , a[i][x] , &tmp) , x = fa[i][x];
for(i = log[deep[x]] ; ~i ; i -- )
if(deep[x] >= (1 << i) && fa[i][x] != fa[i][y])
merge(tmp , a[i][x] , &tmp) , merge(tmp , a[i][y] , &tmp) , x = fa[i][x] , y = fa[i][y];
if(x != y) merge(tmp , a[0][x] , &tmp) , merge(tmp , a[0][y] , &tmp) , x = fa[0][x];
tmp.insert(w[x]);
return tmp.query();
}
int main()
{
int n , m , i , x , y;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ ) scanf("%lld" , &w[i]);
for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x);
for(i = 2 ; i <= n ; i ++ ) log[i] = log[i >> 1] + 1;
deep[1] = 1 , dfs(1);
while(m -- ) scanf("%d%d" , &x , &y) , printf("%lld\n" , solve(x , y));
return 0;
}

【bzoj4568】[Scoi2016]幸运数字 树上倍增+高斯消元动态维护线性基的更多相关文章

  1. 【bzoj4184】shallot 线段树+高斯消元动态维护线性基

    题目描述 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且 让小葱从自己手中的小 ...

  2. HDU3949:XOR(高斯消元)(线性基)

    传送门 题意 给出n个数,任意个数任意数异或构成一个集合,询问第k大个数 分析 这题需要用到线性基,下面是一些资料 1.高斯消元&线性基&Matirx_Tree定理 笔记 2.关于线性 ...

  3. bzoj2115 [Wc2011] Xor——高斯消元 & 异或线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2115 异或两次同一段路径的权值,就相当于没有走这段路径: 由此可以得到启发,对于不同的走法, ...

  4. 2019.03.25 bzoj4568: [Scoi2016]幸运数字(倍增+线性基)

    传送门 题意:给你一棵带点权的树,多次询问路径的最大异或和. 思路: 线性基上树?? 倍增维护一下就完了. 时间复杂度O(nlog3n)O(nlog^3n)O(nlog3n) 代码: #include ...

  5. BZOJ 4004: [JLOI2015]装备购买 [高斯消元同余 线性基]

    和前两(一)题一样,不过不是异或方程组了..... 然后bzoj的新数据是用来卡精度的吧..... 所有只好在模意义下做啦 只是巨慢无比 #include <iostream> #incl ...

  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]幸运数字(LCA+线性基)

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

  9. BZOJ4568 [Scoi2016]幸运数字 【点分治 + 线性基】

    题目链接 BZOJ4568 题解 选任意个数异或和最大,使用线性基 线性基插入\(O(logn)\),合并\(O(log^2n)\) 我们要求树上两点间异或和最大值,由于合并是\(O(log^2n)\ ...

随机推荐

  1. 使 windows 无需输入开机密码自动进入系统

    步骤 运行netplwiz: 勾去图中所示复选框,确定后输入密码.

  2. SAP CRM Survey调查问卷的存储模型

    数据库表CRM_SVY_DB_SVS,通过如下的函数CRM_SVY_DB_SVS_CREATE插入: 可以通过指定的创建者和创建时间很容易查找到特定的Survey: 调查问卷的答案明细以XML的格式存 ...

  3. ABAP vs Java, 蛙泳 vs 自由泳

    去年7月定下的一年之内学会自由泳的目标终于实现了,特来还愿. ABAP和Java, 蛙泳和自由泳.前面的组合是Jerry用来挣钱养家的技术,后者是Jerry花了大量业余时间和金钱苦练的技能.或许有的朋 ...

  4. ABAP function group和Tomcat library重复加载问题

    ABAP ABAP help文档里对**LOAD-OF-PROGRAM"的关键字是这样描述的: This event keyword defines the program construc ...

  5. 有关mybatis的动态sql

    一般地,实现动态SQL都是在xml中使用等标签实现的. 我们在这里使用SQL构造器的方式, 即由abstract sql写出sql的过程, 当然感觉本质上还是一个StringBuilder, 来手动生 ...

  6. [C++讨论课] 课堂记录(一)

    今天第一次参加c++讨论课,记录下了各组同学的展示的问题或者解决方法,也有一些知识点上的内容,供以后复习参考. 1.常量指针和指针常量问题 常量指针:指向常量的指针,例如const int *p =  ...

  7. python_79_模块定义导入优化

    ''' 1.定义 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件 (文件名:test.py,对应的模块名:test. import ...

  8. 【转】树莓派3代3.5寸触摸屏驱动的安装(通过ssh安装)

    这是用到的配件的树莓派3代 烧录好系统后,启动的树莓派,我的树莓派已经在一开始通过路由器和局域网,登陆了ssh,设置好了开机就能自动连接到电脑的360wifi,所以无论到哪 里,只要自己的笔记本电脑还 ...

  9. 用户输入和while循环

    函数input()的工作原理 message=input('Tell me something,and I will repeat it back to you:') print(message) 编 ...

  10. Python re module (regular expressions)

    regular expressions (RE) 简介 re模块是python中处理正在表达式的一个模块 r"""Support for regular expressi ...