洛谷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 ...
随机推荐
- KeyDown,KeyPress和KeyUp详解(转)
1.按键的类型 Windows窗体将键盘输入标识为由按位Keys枚举表示的虚拟键代码.使用Keys枚举,可以综合一系列按键以生成单个值,这些值与WM_KEYDOWN和WM_SYSKEYDOWNWind ...
- web启动@Autowired不能自动注入
使用struts2,下面为action代码 Java代码 package com.edar.web.platform; import org.apache.struts2.convention.ann ...
- [Ahoi2008]Meet 紧急集合
1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec Memory Limit: 162 MBhttp://www.lydsy.com/JudgeOnline/p ...
- ClassNotFoundException:com.sun.xml.bind.v2.ContextFactory
项目中引入hive-jdbc-1.2.1-standalone.jar包之后,报错如下: Caused by: javax.xml.bind.JAXBException: Provider com.s ...
- 怎样用javascript关闭本窗口
大家都知道window.close()是用来关闭窗口的,而且ie和firefox都是支持的. 为了实现用户对浏览器的绝对控制,ie中用close关闭非open打开的窗口时回弹出一个对话框询问用户,怎么 ...
- python学习笔记(十五)之集合
集合:对应数学中的集合类型.集合中的元素是唯一,且无序的. 创建集合 方法一:使用{},注意python会自动删除重复元素 >>> number = {1,2,3,4,3,2,1} ...
- docker之安装和基本使用(一)
前言 开始折腾docker. 主要概念 容器:独立运行的一个或一组应用,与其他应用完全独立. 镜像:用于创建 Docker容器的模板. 仓库:用于收纳镜像文件,可以理解为代码控制中的代码仓库 注意: ...
- dpkg的用法 (转)
dpkg是一个Debian的一个命令行工具,它可以用来安装.删除.构建和管理Debian的软件包. 下面是它的一些命令解释: 1)安装软件 命令行:dpkg -i <.deb file name ...
- Nginx实现404页面的几种方法【转】
一个网站项目,肯定是避免不了404页面的,通常使用Nginx作为Web服务器时,有以下集中配置方式,一起来看看. 第一种:Nginx自己的错误页面 Nginx访问一个静态的html 页面,当这个页面没 ...
- mac下 mysql / nginx 问题总汇
"ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)&q ...