[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
我们每次找到重心,处理与重心相关的路径。
处理时我们将重心到每个节点这一段的线性基存起来,然后找到所有经过重心的路径
在遍历以重心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]幸运数字的更多相关文章
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
- [SCOI2016]幸运数字 树链剖分,线性基
[SCOI2016]幸运数字 LG传送门 为了快乐,我们用树剖写这题. 强行树剖,线段树上每个结点维护一个线性基,每次查询暴力合并. 瞎分析一波复杂度:树剖两点之间\(\log n\)条重链,每条重链 ...
- bzoj 4568: [Scoi2016]幸运数字
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 848 Solved: 336[Submit][Status ...
- [洛谷P3292] [SCOI2016]幸运数字
洛谷题目链接:[SCOI2016]幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城 ...
- 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...
- [BZOJ4568][Scoi2016]幸运数字 倍增+线性基
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1791 Solved: 685[Submit][Statu ...
- [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2131 Solved: 865[Submit][Statu ...
- 【BZOJ4568】[Scoi2016]幸运数字 倍增+线性基
[BZOJ4568][Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念 ...
- bzoj4568: [Scoi2016]幸运数字(LCA+线性基)
4568: [Scoi2016]幸运数字 题目:传送门 题解: 好题!!! 之前就看过,当时说是要用线性基...就没学 填坑填坑: %%%线性基 && 神犇 主要还是对于线性基的运用和 ...
- [SCOI2016]幸运数字(线性基,倍增)
[SCOI2016]幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作 ...
随机推荐
- Bate敏捷冲刺每日报告--day4
1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285) Git链接:https://github.com/WHUSE2017/C-team 2 ...
- 《高级软件测试》11.14.安装和运行Jira
今日任务完成情况如下: 小段:研究Jira在Linux的安装教程 小费:尝试在Ubuntu下安装Jira 小高:查阅了关于Jira软件的介绍和安装教程,下载准备明天安装,并学习使用 小王:注册Jira ...
- 学大伟业 国庆Day2
期望得分:30+100+0=130 实际得分:30+100+20=150 忍者钩爪 (ninja.pas/c/cpp) [问题描述] 小Q是一名酷爱钩爪的忍者,最喜欢飞檐走壁的感觉,有一天小Q发现一个 ...
- a标签传递参数
a标签传递参数 单个参数:参数名称前面跟 ? <a href="localhost:8080/arguments?id=1">单个参数</a> 多个参数 ...
- EXT3文件系统误删除导致文件系统中的邮件丢失恢复方法
一.故障描述 由8块盘组成的RAID5, 上层是EXT3文件系统,由于误删除导致文件系统中的邮件丢失 二.镜像磁盘为防止数据恢复过程中由于误操作对原始磁盘造成二次破坏, 使用winhex软件为每块磁盘 ...
- Java基础类库简介
Java基础类库简介 一.常用的基础类库:11个jar(Java Archive,Java归档)包 作为java语言使用者,我们可以感受到java语言带来的优势(平台无关.面向对象.多线程.高效易扩展 ...
- 剑指offer-数组中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- 09_Python定义方法_Python编程之路
有关Python判断与循环的内容我们上几节已经跟大家一起学习了,这一节我们主要针对def 做一个讲解 def 定义一个方法 在项目编程中,我们往往要做很多重复的事,比如一个排序的功能(当然Python ...
- 翻译:JVM虚拟机规范1.7中的运行时常量池部分(三)
4.4.7. The CONSTANT_Utf8_info Structure The CONSTANT_Utf8_info structure is used to represent consta ...
- 归档(NSKeyedArchiver)的使用
归档的使用,是归于使用保存数据,但是一些简单的数据,如数组,字典等基本的数据类型,往往不使用在归档中,归档和plist以及UserDefaults最大的区别就在于,前者可以存放自定义的数据类型,而后两 ...