题目描述

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. Mysql的内连接,外链接,交叉链接

    内连接:只连接匹配的行  inner join select A.*,B.* from A,B where A.id = B.parent_id 外链接包括左外链接,右外链接,全外链接 左外链接:包含 ...

  2. Beta第四天

    听说

  3. fflush(stdin)与fflush(stdout)

    1.fflush(stdin): 作用:清理标准输入流,把多余的未被保存的数据丢掉.. 如: int main() { int num; char str[10]; cin>>num; c ...

  4. Spring-Data-JPA整合MySQL和配置

    一.简介 (1).MySQL是一个关系型数据库系统,是如今互联网公司最常用的数据库和最广泛的数据库.为服务端数据库,能承受高并发的访问量. (2).Spring-Data-Jpa是在JPA规范下提供的 ...

  5. 十、Python练习----基础搭建飞机大战

    只是简单的学习了pygame,实现飞机的摧毁还需要多张图片的切换,和sprite(碰撞精灵),还有多种音效的添加(如背景音乐.摧毁特效).以后再深入学习我只是练习一下python. 一.搭建界面(基于 ...

  6. Xen Server虚拟机数据恢复的方法和数据恢复过程

    在服务器运行过程中如果出现意外情况突然断电很容易引起服务器故障,服务器中的硬件设备损坏可以修复或者购买,但是服务器中的数据一旦发生故障丢失,对于企业来说将是不可估量的损失.那么服务器数据一旦丢失就除了 ...

  7. Angular.js 1++快速上手

    AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Goole所收购.是一款优秀的前端JS框架.AngularJS有着诸多特性,最为核心的是:MVC,撗块化,自动化双向数据绑 ...

  8. 2018年东北农业大学春季校赛-wyh的吃鸡

    BFS: 1. 从起点开始BFS,遇到X点则return: 2. vis[px][py][0]代表经过pxpy这点前还没有找到车: vis[px][py][1]代表经过pxpy这点前已经找到车: 3. ...

  9. token 验证

    组件: https://jwt.io/#libraries-io

  10. Python内置函数(34)——map

    英文文档: map(function, iterable, ...) Return an iterator that applies function to every item of iterabl ...