4568: [Scoi2016]幸运数字

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 238  Solved: 113
[Submit][Status][Discuss]

Description

A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5 和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中可以保留的最大幸运值是多少。

Input

第一行包含 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

Output

输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。

Sample Input

4 2
11 5 7 9
1 2
1 3
1 4
2 3
1 4

Sample Output

14
11

HINT

Source

Solution

树上线性基

感觉可以有多重做法(1)树链剖分+线性基合并(2)LCA+倍增+线性基合并(3)点分治+线性基合并

后两个是$logn$级的,第一种是$log^{2}n$级的,自己一开始算错了复杂度,于是开心的写了(1),不过BZOJ开到60s时限,所以还是可以水过的

大体上就是树链剖分一下,线段树维护区间线性基,两个叶节点的线性基合并起来就是根的线性基,具体的合并,就是直接暴力把一个插入到另一个里面

然后查询的时候正常的查询就好了.

LCA+倍增的做法就是倍增预处理出$2^{j}$步的线性基,预处理和查询的时候,同样都是暴力合并线性基

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstring>
using namespace std;
long long read()
{
long long x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 20010
int n,q; long long val[maxn];
struct EdgeNode{int next,to;}edge[maxn<<];
int head[maxn],cnt;
void add(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void insert(int u,int v) {add(u,v); add(v,u);}
//==============================================================================================
int size[maxn],deep[maxn],fa[maxn],son[maxn],pl[maxn],sz,pr[maxn],top[maxn];long long pre[maxn];
void dfs_1(int now)
{
size[now]=;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now])
{
deep[edge[i].to]=deep[now]+;
fa[edge[i].to]=now;
dfs_1(edge[i].to);
if (size[edge[i].to]>size[son[now]]) son[now]=edge[i].to;
size[now]+=size[edge[i].to];
}
}
void dfs_2(int now,int chain)
{
pl[now]=++sz; pre[sz]=val[now]; top[now]=chain;
if (son[now]) dfs_2(son[now],chain);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=fa[now] && edge[i].to!=son[now])
dfs_2(edge[i].to,edge[i].to);
pr[now]=sz;
}
//==============================================================================================
struct XXJ{long long a[];}Ans;
struct TreeNode{int l,r;XXJ X;}tree[maxn<<];
void Merge(XXJ &x,XXJ &y,XXJ &z)
{
XXJ tmp;
for (int i=; i>=; i--) tmp.a[i]=y.a[i];
for (int i=; i>=; i--)
if (z.a[i])
{
long long tp=z.a[i];
for (int i=; i>=; i--)
if (tp&(1LL<<i))
if (!tmp.a[i]) {tmp.a[i]=tp; break;}
else tp^=tmp.a[i];
}
for (int i=; i>=; i--) x.a[i]=tmp.a[i];
}
void BuildTree(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r;
if (l==r)
{
memset(tree[now].X.a,0LL,sizeof(tree[now].X.a));
long long tp=pre[l];
for (int i=; i>=; i--)
if (tp&(1LL<<i))
if (!tree[now].X.a[i]) {tree[now].X.a[i]=tp; break;}
else tp^=tree[now].X.a[i];
return;
}
int mid=(l+r)>>;
BuildTree(now<<,l,mid); BuildTree(now<<|,mid+,r);
Merge(tree[now].X,tree[now<<].X,tree[now<<|].X);
}
void Query(int now,int L,int R)
{
if (L<=tree[now].l && R>=tree[now].r) {Merge(Ans,Ans,tree[now].X); return;}
int mid=(tree[now].l+tree[now].r)>>;
if (L<=mid) Query(now<<,L,R);
if (R>mid) Query(now<<|,L,R);
}
//==============================================================================================
void Solve_Query(int x,int y)
{
while (top[x]!=top[y])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
Query(,pl[top[x]],pl[x]);
x=fa[top[x]];
}
if (deep[x]>deep[y]) swap(x,y);
Query(,pl[x],pl[y]);
}
//==============================================================================================
int main()
{
n=read();q=read();
for (int i=; i<=n; i++) val[i]=read();
for (int u,v,i=; i<=n-; i++) u=read(),v=read(),insert(u,v);
dfs_1(); dfs_2(,); BuildTree(,,n);
while (q--)
{
int x=read(),y=read(); long long ans=;
memset(Ans.a,0LL,sizeof(Ans.a));
Solve_Query(x,y);
for (int i=; i>=; i--) if ((ans^Ans.a[i])>ans) ans^=Ans.a[i];
printf("%lld\n",ans);
}
return ;
}

谢谢YJQ大大的数据,考前A题的快感

【BZOJ-4568】幸运数字 树链剖分 + 线性基合并的更多相关文章

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

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

  2. 「洛谷3292」「BZOJ4568」「SCOI2016」幸运数字【倍增LCA+线性基+合并】

    [bzoj数据下载地址]不要谢我 先讲一下窝是怎么错的... \(MLE\)是因为数组开小了.. 看到异或和最大,那么就会想到用线性基. 如果不会线性基的可以参考一下我的学习笔记:「线性基」学习笔记a ...

  3. 【CodeChef EDGEST】Edges in Spanning Trees(树链剖分+树上启发式合并)

    点此看题面 大致题意: 给你两棵\(n\)个点的树,对于第一棵树中的每条边\(e_1\),求存在多少条第二棵树中的边\(e_2\),使得第一棵树删掉\(e_1\)加上\(e_2\).第二棵树删掉\(e ...

  4. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  5. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  6. BZOJ 2243: [SDOI2011]染色 [树链剖分]

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6651  Solved: 2432[Submit][Status ...

  7. [BZOJ - 2819] Nim 【树链剖分 / DFS序】

    题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...

  8. BZOJ.4515.[SDOI2016]游戏(树链剖分 李超线段树)

    BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\ ...

  9. bzoj 4448 [Scoi2015]情报传递 (树链剖分+主席树)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4448 题面: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络 ...

随机推荐

  1. HTML5商城开发三 jquery 星星评分插件

    展示:

  2. 批量去除Teleport Pro整站下载文件冗余代码

    teleport pro tppabs标签批量删除 teleport pro tppabs标签批量删除 使 用Teleport Pro下载的网页代码中包含了很多垃圾代码,比如下载的html网页代码中会 ...

  3. Castle ActiveRecord 二级缓存使用 异常记录

    在 本公司的 IBeamMDAA 框架下,如果是配置为本机调试时,AR的查询缓存工作正常,但如果部署到服务器上,工作不正常,二级缓存配置为使用 MemoryCahcheD 服务器,二级缓存没有能够根据 ...

  4. Kafka及 .NET Core 客户端

    消息队列 Kafka 的基本知识及 .NET Core 客户端 消息队列 Kafka 的基本知识及 .NET Core 客户端   前言 最新项目中要用到消息队列来做消息的传输,之所以选着 Kafka ...

  5. sublime配置文件

    起初是为了解决 tab转四个空格问题 安装包 Sublime_Text_Build_3103_x64_CHS_Lfqy.exe 配置方法 配置脚本 { "bold_folder_labels ...

  6. SQL Server数据库代码指令简介

    这些是比较常用的命令操作,事先声明,这些命令是不区分大小写的,我按照我的课本来总结用法和知识点,无用的章节自动省略. 没有一点数据库知识基础的可以等我录制视频,不然可能看不懂,视频链接:http:// ...

  7. [转] EJB 3和Spring技术体系比较

    最近在学习EJB 3,对于SSH与EJB3,一直不太明白“即生瑜,何生亮?”,今天无意看到一篇旧文,比较系统的对比了这二种技术架构,转载于此: 原文出处:http://www.51cto.com/sp ...

  8. Cocos2d-x 3.4在AndroidStudio上编译配置

    转载请标明出处:http://www.cnblogs.com/studweijun/p/4320778.html 1.准备好以下文件 1) AndroidStudio:  https://dl.goo ...

  9. SignalR与ActiveMQ结合构建实时通信

    一.概述 本教程主要阐释了如何利用SignalR与消息队列的结合,实现不同客户端的交互 SignalR如何和消息队列交互(暂使用ActiveMQ消息队列) SignalR寄宿在web中和其他Signa ...

  10. C#中数组Array、ArrayList、泛型List<T>的比较

    在C#中数组Array,ArrayList,泛型List都能够存储一组对象,但是在开发中根本不知道用哪个性能最高,下面我们慢慢分析分析. 一.数组Array 数组是一个存储相同类型元素的固定大小的顺序 ...