[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 个非负整数,表示这名旅行者可以保留的最大幸运值。

输入输出样例

输入样例#1:

4 2

11 5 7 9

1 2

1 3

1 4

2 3

1 4

输出样例#1:

14

11

很神的题目,思路还是比较好想的,倍增套上线性基,但是代码还是不怎么好写,而且貌似我的常数比较大。倍增预处理的时候暴力合并线性基,倍增找lca的时候也暴力合并即可。

#include<bits/stdc++.h>
#define lll long long
using namespace std;
lll read(){
lll x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
const lll N=20010;
lll n,q,x,y,cnt,qwe;
lll head[N],c[63][21][N],f[21][N],ans[63],deep[N],a[N];
struct node{
lll to,next;
}edge[2*N];
void add(lll x,lll y){
cnt++;edge[cnt].to=y;edge[cnt].next=head[x];head[x]=cnt;
}
void insert(lll opt,lll k,lll v){
for(lll i=61;i>=0;i--){
if(!(v>>i))continue;
if(!c[i][opt][k]){c[i][opt][k]=v;break;}
v^=c[i][opt][k];if(!v)break;
}
}
void dfs(lll k,lll fa){
for(lll i=head[k];i;i=edge[i].next){
lll v=edge[i].to;if(v==fa)continue;
deep[v]=deep[k]+1;f[0][v]=k;insert(0,v,a[k]);
dfs(v,k);
}
}
void merge(lll k,lll opt,lll v1,lll v2){
for(lll i=61;i>=0;i--)c[i][opt][k]=c[i][opt-1][v1];
for(lll i=61;i>=0;i--){
if(c[i][opt-1][v2])insert(opt,k,c[i][opt-1][v2]);
}
}
void init(){
for(lll i=1;i<=19;i++){
for(lll j=1;j<=n;j++){
f[i][j]=f[i-1][f[i-1][j]];
merge(j,i,j,f[i-1][j]);
}
}
}
void update(lll opt,lll k){
for(lll j=61;j>=0;j--){
if(c[j][opt][k]){
lll v=c[j][opt][k];
for(lll i=61;i>=0;i--){
if(!(v>>i))continue;
if(!ans[i]){ans[i]=v;break;}
v^=ans[i];if(!v)break;
}
}
}
}
void LCA(lll x,lll y){
memset(ans,0,sizeof(ans));
lll v=a[x];
for(lll i=61;i>=0;i--){
if(!(v>>i))continue;
if(!ans[i]){ans[i]=v;break;}
v^=ans[i];if(!v)break;
}
v=a[y];
for(lll i=61;i>=0;i--){
if(!(v>>i))continue;
if(!ans[i]){ans[i]=v;break;}
v^=ans[i];if(!v)break;
}
if(deep[x]<deep[y])swap(x,y);
for(lll i=19;i>=0;i--){
if(deep[f[i][x]]>=deep[y]){
update(i,x);
x=f[i][x];
}
}
if(x==y)return;
for(lll i=19;i>=0;i--){
if(f[i][x]!=f[i][y]){
update(i,x);update(i,y);
x=f[i][x];y=f[i][y];
}
}
//cout<<f[0][x]<<endl;
update(0,x);return;
}
int main(){
n=read();q=read();
for(lll i=1;i<=n;i++)a[i]=read();
for(lll i=1;i<n;i++){
x=read();y=read();
add(x,y);add(y,x);
}
deep[1]=1;dfs(1,0);init();
while(q--){
x=read();y=read();
LCA(x,y);qwe=0;
for(lll i=61;i>=0;i--){
if(qwe<(qwe^ans[i]))qwe^=ans[i];
}printf("%lld\n",qwe);
}
}

[SCOI2016]幸运数字(线性基,倍增)的更多相关文章

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

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

  2. 洛谷P3292 [SCOI2016]幸运数字 线性基+倍增

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

  3. P3292 [SCOI2016]幸运数字 [线性基+倍增]

    线性基+倍增 // by Isaunoya #include <bits/stdc++.h> using namespace std; #define rep(i, x, y) for ( ...

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

    题意 题目链接 Sol 线性基是可以合并的 倍增维护一下 然后就做完了?? 喵喵喵? // luogu-judger-enable-o2 #include<bits/stdc++.h> # ...

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

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

  6. P3292 [SCOI2016]幸运数字 线性基

    正解:线性基+倍增 解题报告: 先放下传送门QAQ 然后这题,其实没什么太大的技术含量,,,?就几个知识点套在一起,除了代码长以外没任何意义,主要因为想复习下线性基的题目所以还是写下,,, 随便写下思 ...

  7. 洛谷P3292 [SCOI2016] 幸运数字 [线性基,倍增]

    题目传送门 幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的 ...

  8. bzoj4568 [Scoi2016]幸运数字 线性基+树链剖分

    A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游览 A ...

  9. [SCOI2016]幸运数字 线性基

    题面 题面 题解 题面意思非常明确:求树上一条链的最大异或和. 我们用倍增的思想. 将这条链分成2部分:x ---> lca , lca ---> y 分别求出这2个部分的线性基,然后合并 ...

  10. BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)

    题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...

随机推荐

  1. [pipenv]Warning: Python 3.7 was not found on your system…

    前置条件: 切换到pipfile文件所在目录gotest_official 问题描述: 使用pipenv install创建虚拟环境,报错 wangju@wangju-HP--G4:~/Desktop ...

  2. IP冲突如何把冲突的IP挤下去

    把冲突IP挤下去的方法: ①进入网络和共享中心>本地连接>禁用. ②进入网络和共享中心>更改适配器设置>双击被禁用的连接,自动重新连接即可.

  3. JS实战篇

    实现选项卡的选择: 效果图如下: 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8& ...

  4. 剑指Offer总结——用两个栈实现队列

    class Solution { public: void push(int node) { stack2.push(node); } int pop() { if(stack1.empty()){ ...

  5. USACO1.6 回文质数 Prime Palindromes

    题目传送门 题目的提示已经非常明显了,可以先生成回文数再判断质数,因为生成回文数的复杂度较小.判断质数用了之前学到的那种做法. 其实可以用一些比较优秀的筛质数的方法,再判断回文数. /* ID: St ...

  6. adobe Keychain mac

    Keychain password access This question has been Answered. janec2070563 May 8, 2018 11:07 AM I consta ...

  7. 在redis里面使用lua

    Redis从2.6版本开始引入对Lua脚本的支持,通过在服务器中嵌入Lua环境,Redis客户端可以使用Lua脚本,直接在服务端原子的执行多个Redis命令. lua脚本的好处: 减少网络开销.可以将 ...

  8. set的常见用法

    set的使用 set是什么 set是一个内部有序且不含重复元素的容器 用处 *使得元素自动有序 *去除重复元素 set的引入 # include <set> using namespace ...

  9. php中文网--JavaScript

    PHP中文网:http://www.php.cn/course/18.html 常用的两个客户端输出方法 document.write("你好呀js"); 描述:在网页的<b ...

  10. selenium与页面交互之二:webelement类的属性

    webelement类的属性如下: element.size()   获取元素的大小 element.tag_name() 获取元素的HTML标签名称 element.text()   获取元素的文本 ...