题目描述

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

我们每次找到重心,处理与重心相关的路径。

处理时我们将重心到每个节点这一段的线性基存起来,然后找到所有经过重心的路径

在遍历以重心G为根的一个子树过程中,找到与这棵子树中节点u有关的询问(u,v),判断是否在之前遍历过的以重心为根的其他子树中出现过,如果出现过,我们可以将G->u和G->v的线性基合并

找到合并后的线性基中的最大值就好了。对于合并,直接暴力拆开一个线性基,一个一个插入到另一个线性基中

处理完这棵子树之后,再遍历一遍,打上访问过的标记。这样保证所有询问都只计算过一次。

注意,处理完这个重心之后,清空标记时,不要memset,直接再遍历一遍就好了,快得多。

值得注意的是,要单独考虑与G有关的询问如(G,v)

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long lol;
struct Node
{
int next,to,dis;
}edge[],edgeq[];
int num,numq,head[],headq[];
int size[],maxsize[],minsize,root,n,q;
bool vis[],judge[];
lol ans[],pw[],val[];
struct BASE
{
lol a[];
void clear()
{
for (int i=;i<=;i++)
a[i]=;
}
void insert(lol x)
{
for (int i=;i>=;i--)
{
if (x&pw[i])
{
if (a[i]==)
{a[i]=x;break;}
else x^=a[i];
}
}
}
lol getmax()
{
lol x=;
for (int i=;i>=;i--)
{
if ((x^a[i])>x)
x^=a[i];
}
return x;
}
void merge(BASE b)
{
for (int i=;i<=;i++)
insert(b.a[i]);
}
void copy(BASE b)
{
for (int i=;i<=;i++)
a[i]=b.a[i];
}
}base[];
void add(int u,int v)
{
num++;
edge[num].next=head[u];
head[u]=num;
edge[num].to=v;
}
void addq(int u,int v,int d)
{
numq++;
edgeq[numq].next=headq[u];
headq[u]=numq;
edgeq[numq].to=v;
edgeq[numq].dis=d;
}
void get_size(int x,int fa)
{
int i;
size[x]=;
maxsize[x]=;
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==&&v!=fa)
{
get_size(v,x);
size[x]+=size[v];
maxsize[x]=max(maxsize[x],size[v]);
}
}
}
void get_root(int r,int x,int fa)
{
int i;
maxsize[x]=max(maxsize[x],size[r]-size[x]);
if (maxsize[x]<minsize)
{
root=x;
minsize=maxsize[x];
}
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==&&v!=fa)
{
get_root(r,v,x);
}
}
}
void get_ans(int r,int x,int fa)
{int i;
base[x].copy(base[fa]);
base[x].insert(val[x]);
for (i=headq[x];i;i=edgeq[i].next)
{
int v=edgeq[i].to;
if (judge[v])
{
BASE tmp;
tmp.copy(base[x]);
tmp.merge(base[v]);
ans[edgeq[i].dis]=tmp.getmax();
}
else if (v==r)
{
ans[edgeq[i].dis]=base[x].getmax();
}
}
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==&&v!=fa)
{
get_ans(r,v,x);
}
}
}
void get_update(int x,int fa)
{
judge[x]=!judge[x];
for (int i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==&&v!=fa)
{
get_update(v,x);
}
}
}
void doit(int x)
{
minsize=2e9;
get_size(x,);
get_root(x,x,);
vis[root]=;
base[root].clear();
base[root].insert(val[root]);
for (int i=head[root];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==)
{
get_ans(root,v,root);
get_update(v,root);
}
}
for (int i=head[root];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==)
{
get_update(v,root);
}
}
for (int i=head[root];i;i=edge[i].next)
{
int v=edge[i].to;
if (vis[v]==)
{
doit(v);
}
}
}
int main()
{int i,u,v;
cin>>n>>q;
pw[]=;
for (i=;i<=;i++)
pw[i]=pw[i-]*;
for (i=;i<=n;i++)
{
scanf("%lld",&val[i]);
}
for (i=;i<=n-;i++)
{
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
for (i=;i<=q;i++)
{
scanf("%d%d",&u,&v);
if (u!=v)
addq(u,v,i),addq(v,u,i);
else ans[i]=val[u];
}
doit();
for (i=;i<=q;i++)
{
printf("%lld\n",ans[i]);
}
}

[SCOI2016]幸运数字的更多相关文章

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

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

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

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

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

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

  4. [洛谷P3292] [SCOI2016]幸运数字

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

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

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

  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]幸运数字 倍增+线性基

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

  9. bzoj4568: [Scoi2016]幸运数字(LCA+线性基)

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

  10. [SCOI2016]幸运数字(线性基,倍增)

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

随机推荐

  1. 2017-2018-1 Java演绎法 小组会议及交互汇总

    第一周会议 今天我们小组开展了第一次团队例会活动.我们小组将<构建之法>分为了六个部分并由六位成员先分别学习并向组长上传学习收获,这次的活动内容便是 交流前两周小组成员学习阅读<构建 ...

  2. 学号:201621123032 《Java程序设计》第11周学习总结

    1:本周学习总结 1.1.:以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2:书面作业 2.1.: 源代码阅读:多线程程序BounceThread 1.1: BallRunnable类有什 ...

  3. OVS常用命令

    添加brideg: sudo ovs-vsctl add-br br0 删除brideg: sudo ovs-vsctl del-br br0 显示bridge: sudo ovs-vsctl sho ...

  4. Scrum 冲刺 第四日

    目录 要求 项目链接 燃尽图 问题 今日任务 明日计划 成员贡献量 小组会议 要求 各个成员今日完成的任务(如果完成的任务为开发或测试任务,需给出对应的Github代码签入记录截图:如果完成的任务为调 ...

  5. JAVA_SE基础——71.Random类制作随机验证码

    public class Demo5 { public static void main(String[] args) { char[] arr={'s','b','g','h','a','c'}; ...

  6. JAVA_SE基础——63.String类的常用方法

    获取方法int length()  获取字符串的长度char charAt(int index) 获取特定位置的字符 (角标越界)int indexOf(String str) 查找子串第一次出现的索 ...

  7. JavaScript 实现二叉树

    JavaScript 实现二叉树: // JavaScript 实现二叉树 function BinaryTree () { var Node = function (key) { this.key ...

  8. SpringBoot入门:Spring Data JPA 和 JPA(理论)

    参考链接: Spring Data JPA - Reference Documentation Spring Data JPA--参考文档 中文版 纯洁的微笑:http://www.ityouknow ...

  9. MySql入门(2-1)windows下安装mysql的两种方式

    一.下载mysql 1.下载解压MySQL 登录oracle主页,需要用户名和口令: lshengqi@netease.com/1wsx**** 下载路径:: https://dev.mysql.co ...

  10. [八省联考2018] 劈配 mentor

    Description 一年一度的综艺节目<中国新代码>又开始了.Zayid 从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. Input 轻车熟路的Zay ...