洛谷P3292 [SCOI2016] 幸运数字 [线性基,倍增]
幸运数字
题目描述
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
分析:
树上线性基的模板。
显然我们的做法应该是把树上路径的每个点构造成线性基然后求异或最大值。但问题在于我们如何快速构造出任意一条路径的线性基。
这里采用倍增的思想。
我们开一个三维数组$p[i][j][k]$表示从$i$跳$2^j$时路径上的线性基。在预处理倍增的时候,我们只要把两段$2^(j-1)$的线性基合并就能得到$2^j$的线性基。查询$lca$的时候用同样的方法就能得到一条路径上的线性基。
代码略长,不太好看。
Code:
//It is made by HolseLee on 13th Sep 2018
//Luogu.org P3292
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std; typedef long long ll;
const int N=2e4+;
int n,m,head[N],cnte,f[N][],dep[N];
ll p[N][][],ans[];
struct Edge{
int to,nxt;
Edge() {}
Edge(int _x,int _y): to(_x),nxt(_y) {}
}e[N<<]; inline ll read()
{
char ch=getchar(); ll num=; bool flag=false;
while( ch<'' || ch>'' ) {
if( ch=='-' ) flag=true; ch=getchar();
}
while( ch>='' && ch<='' ) {
num=num*+ch-''; ch=getchar();
}
return flag ? -num : num ;
} inline void add(int x,int y)
{
e[++cnte]=Edge(y,head[x]);
head[x]=cnte;
} void dfs(int u,int las)
{
f[u][]=las; dep[u]=dep[las]+;
for(int i=head[u]; i; i=e[i].nxt) {
if( e[i].to==las ) continue;
dfs(e[i].to,u);
}
} inline void liner(ll *x,ll y)
{
for(int i=; i>=; --i) {
if( (y>>i)& ) {
if( !x[i] ) {
x[i]=y; break;
} else {
y^=x[i];
}
}
}
} inline void merge(ll *x,ll *y)
{
for(int i=; i>=; --i) {
if( y[i] ) liner(x,y[i]);
}
} void ready()
{
for(int j=; j<=; ++j)
for(int i=; i<=n; ++i) {
f[i][j]=f[f[i][j-]][j-];
memcpy(p[i][j],p[i][j-],sizeof(p[i][j-]));
merge(p[i][j],p[f[i][j-]][j-]);
}
} inline void lca(int x,int y)
{
if( dep[x]<dep[y] ) swap(x,y);
for(int i=; i>=; --i)
if( dep[f[x][i]]>=dep[y] )
merge(ans,p[x][i]), x=f[x][i];
if( x==y ) {
merge(ans,p[x][]); return;
}
for(int i=; i>=; --i)
if( f[x][i]!=f[y][i] ) {
merge(ans,p[x][i]), merge(ans,p[y][i]);
x=f[x][i], y=f[y][i];
}
merge(ans,p[x][]), merge(ans,p[y][]);
merge(ans,p[f[x][]][]);
} int main()
{
n=read(); m=read();
for(int i=; i<=n; ++i) {
liner(p[i][],read());
}
int x,y;
for(int i=; i<n; ++i) {
x=read(), y=read();
add(x,y); add(y,x);
}
dfs(,); ready();
ll ret;
for(int i=; i<=m; ++i) {
x=read(), y=read();
ret=;
memset(ans,,sizeof(ans));
lca(x,y);
for(int i=; i>=; --i) {
ret=Max(ret,ret^ans[i]);
}
printf("%lld\n",ret);
}
return ;
}
洛谷P3292 [SCOI2016] 幸运数字 [线性基,倍增]的更多相关文章
- 洛谷P3292 [SCOI2016]幸运数字 线性基+倍增
P3292 [SCOI2016]幸运数字 传送门 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在 ...
- P3292 [SCOI2016]幸运数字 [线性基+倍增]
线性基+倍增 // by Isaunoya #include <bits/stdc++.h> using namespace std; #define rep(i, x, y) for ( ...
- [洛谷P3292] [SCOI2016]幸运数字
洛谷题目链接:[SCOI2016]幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城 ...
- P3292 [SCOI2016]幸运数字 线性基
正解:线性基+倍增 解题报告: 先放下传送门QAQ 然后这题,其实没什么太大的技术含量,,,?就几个知识点套在一起,除了代码长以外没任何意义,主要因为想复习下线性基的题目所以还是写下,,, 随便写下思 ...
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
- 洛谷P3292 [SCOI2016]幸运数字(倍增+线性基)
传送门 不知道线性基是什么东西的可以看看蒟蒻的总结 第一眼:这不会是个倍增LCA暴力合并线性基吧…… 打了一发……A了? 所以这真的是个暴力倍增LCA合并线性基么…… ps:据某大佬说其实可以离线之后 ...
- BZOJ4568: [Scoi2016]幸运数字(线性基 倍增)
题意 题目链接 Sol 线性基是可以合并的 倍增维护一下 然后就做完了?? 喵喵喵? // luogu-judger-enable-o2 #include<bits/stdc++.h> # ...
- BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增
[题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...
- bzoj4568 [Scoi2016]幸运数字 线性基+树链剖分
A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游览 A ...
随机推荐
- OpenCV---图像直方图
一:直方图的直接使用 from matplotlib import pyplot as plt def plot_demo(image): print(image.ravel()) plt.hist( ...
- jQuery中deferred的对象使用
什么是deferred对象 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作.其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是 ...
- svnserver配置详解
svnserve是SVN自带的一个轻型服务器,客户端通过使用以svn://或svn+ssh://为前缀的URL来访问svnserve服务器,实现远程访问SVN版本库. svnserve可以通过配置文件 ...
- 【BZOJ】1176: [Balkan2007]Mokia
[题意]n*n的矩阵,初始值为0(题面有误),m次操作,增加一个格子的权值,或查询子矩阵和.n<=2*10^6.(m应该较题面所述偏大). [算法]CDQ分治(算法知识见数据结构) [题解]三维 ...
- h5 canvas动画,不知道谁写的
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- tf.reduce_sum()_tf.reduce_mean()_tf.reduce_max()
根据官方文档: reduce_sum应该理解为压缩求和,用于降维 tf.reduce_sum(input_tensor,axis=None,keepdims=None,name=None,reduct ...
- Java的继承和多态
看了博客园里面的一个文章,关于java的继承和多态: class A ...{ public String show(D obj)...{ return ("A and D"); ...
- Linux系统调用、新增系统调用方法【转】
转自:http://blog.chinaunix.net/uid-25374603-id-3401045.html 说明: 系统调用是内核和应用程序间的接口,应用程序要访问硬件设备和其他操作系统资源, ...
- 64_p6
polkit-kde-5.10.1-1.fc26.x86_64.rpm 12-Jun-2017 13:45 84854 polkit-libs-0.113-8.fc26.i686.rpm 13-Apr ...
- 使用navicat for sqlserver 把excel中的数据导入到sqlserver数据库
以前记得使用excel向mysql中导入过数据,今天使用excel向sqlserver2005导入了数据,在此把做法记录一下 第一步:准备excel数据,在这个excel中有3个sheet,每个she ...