P3292 [SCOI2016]幸运数字 [线性基+倍增]
线性基+倍增
// by Isaunoya
#include <bits/stdc++.h>
using namespace std;
#define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
#define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
using ll = long long ;
const int _ = 1 << 21;
struct I {
char fin[_], *p1 = fin, *p2 = fin;
inline char gc() {
return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
}
inline I& operator>>(int& x) {
bool sign = 1;
char c = 0;
while (c < 48) ((c = gc()) == 45) && (sign = 0);
x = (c & 15);
while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
x = sign ? x : -x;
return *this;
}
inline I& operator>>(ll& x) {
bool sign = 1;
char c = 0;
while (c < 48) ((c = gc()) == 45) && (sign = 0);
x = (c & 15);
while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
x = sign ? x : -x;
return *this;
}
} in;
struct O {
char st[100], fout[_];
signed stk = 0, top = 0;
inline void flush() {
fwrite(fout, 1, top, stdout), fflush(stdout), top = 0;
}
inline O& operator<<(ll x) {
if (top > (1 << 20)) flush();
if (x < 0) fout[top++] = 45, x = -x;
do
st[++stk] = x % 10 ^ 48, x /= 10;
while (x);
while (stk) fout[top++] = st[stk--];
return *this;
}
inline O& operator<<(char x) {
fout[top++] = x;
return *this;
}
inline O& operator<<(string s) {
if (top > (1 << 20)) flush();
for (char x : s) fout[top++] = x;
return *this;
}
} out;
#define pb emplace_back
#define fir first
#define sec second
template < class T > inline void cmax(T & x , const T & y) {
(x < y) && (x = y) ;
}
template < class T > inline void cmin(T & x , const T & y) {
(x > y) && (x = y) ;
}
int n , q ;
const int N = 2e4 + 10 ;
ll g[N] , d[N][22][65] ;
void ins(ll x , ll * p) {
for(int i = 63 ; ~ i ; i --)
if(x & (1ll << i)) {
if(! p[i]) p[i] = x ;
x ^= p[i] ;
}
}
void mergeto(ll * a , ll * b) { for(int i = 63 ; ~ i ; i --) if(a[i]) ins(a[i] , b) ; }
struct edge {int v , nxt ;} ; edge e[N << 1] ;
int cnt = 0 , head[N] ;
void add(int u , int v) { e[++ cnt] = { v , head[u] } ; head[u] = cnt ; }
int fa[N] , dep[N] , f[N][22] ;
void dfs(int u) {
for(int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].v ;
if(v ^ fa[u]) { fa[v] = u ; dep[v] = dep[u] + 1 ; dfs(v) ; }
}
}
ll ans[65] ;
inline int Lca(int x , int y) {
if(dep[x] < dep[y]) swap(x , y) ;
for(int i = 20 ; ~ i ; i --) if(dep[f[x][i]] >= dep[y]) x = f[x][i] ;
if(x == y) return x ;
for(int i = 20 ; ~ i ; i --) if(f[x][i] ^ f[y][i]) { x = f[x][i] ; y = f[y][i] ; }
return f[x][0] ;
}
inline int getdis(int lca , int y) { return dep[y] - dep[lca] + 1 ; }
inline ll query(int x , int y) {
memset(ans , 0 , sizeof(ans)) ;
int lca = Lca(x , y) , dis = getdis(lca , x) ;
for(int i = 20 ; ~ i ; i --) if(dis & (1 << i)) mergeto(d[x][i] , ans) , x = f[x][i] ;
dis = getdis(lca , y) ;
for(int i = 20 ; ~ i ; i --) if(dis & (1 << i)) mergeto(d[y][i] , ans) , y = f[y][i] ;
ll res = 0 ; for(int i = 63 ; ~ i ; i --) cmax(res , res ^ ans[i]) ;
return res ;
}
signed main() {
#ifdef _WIN64
freopen("testdata.in" , "r" , stdin) ;
#endif
in >> n >> q ;
rep(i , 1 , n) { in >> g[i] ; }
rep(i , 1 , n - 1) { int u , v ; in >> u >> v ; add(u , v) ; add(v , u) ; }
dfs(1) ; rep(i , 1 , n) f[i][0] = fa[i] ; rep(i , 1 , n) ins(g[i] , d[i][0]) ;
rep(j , 1 , 20)
rep(i , 1 , n) { f[i][j] = f[f[i][j - 1]][j - 1] ; mergeto(d[i][j - 1] , d[i][j]) ; mergeto(d[f[i][j - 1]][j - 1] , d[i][j]) ; }
while(q --) { int u , v ; in >> u >> v ; out << query(u , v) << '\n' ; }
return out.flush(), 0;
}
P3292 [SCOI2016]幸运数字 [线性基+倍增]的更多相关文章
- 洛谷P3292 [SCOI2016]幸运数字 线性基+倍增
P3292 [SCOI2016]幸运数字 传送门 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在 ...
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
- P3292 [SCOI2016]幸运数字 线性基
正解:线性基+倍增 解题报告: 先放下传送门QAQ 然后这题,其实没什么太大的技术含量,,,?就几个知识点套在一起,除了代码长以外没任何意义,主要因为想复习下线性基的题目所以还是写下,,, 随便写下思 ...
- 洛谷P3292 [SCOI2016] 幸运数字 [线性基,倍增]
题目传送门 幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的 ...
- BZOJ4568: [Scoi2016]幸运数字(线性基 倍增)
题意 题目链接 Sol 线性基是可以合并的 倍增维护一下 然后就做完了?? 喵喵喵? // luogu-judger-enable-o2 #include<bits/stdc++.h> # ...
- BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增
[题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...
- bzoj4568 [Scoi2016]幸运数字 线性基+树链剖分
A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游览 A ...
- [SCOI2016]幸运数字 线性基
题面 题面 题解 题面意思非常明确:求树上一条链的最大异或和. 我们用倍增的思想. 将这条链分成2部分:x ---> lca , lca ---> y 分别求出这2个部分的线性基,然后合并 ...
- BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)
题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...
随机推荐
- 7天用Go动手写/从零实现分布式缓存GeeCache
1 谈谈分布式缓存 第一次请求时将一些耗时操作的结果暂存,以后遇到相同的请求,直接返回暂存的数据.我想这是大部分童鞋对于缓存的理解.在计算机系统中,缓存无处不在,比如我们访问一个网页,网页和引用的 J ...
- Go语言实现:【剑指offer】数组中重复的数字
该题目来源于牛客网<剑指offer>专题. 在一个长度为n的数组里的所有数字都在0到n-1的范围内.数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组 ...
- SpringBoot2.x操作缓存的新姿势
一.介绍 spring cache 是spring3版本之后引入的一项技术,可以简化对于缓存层的操作,spring cache与springcloud stream类似,都是基于抽象层,可以任意切换其 ...
- 阿里云服务器ECS Ubuntu18.04 初次使用配置教程(图形界面安装)
最近由于工作需要,要使用服务器测试,就先自已买了个服务器,就在阿里云买了一个,先买了那个叫虚拟主机的,后来发现不是我需要的,所以退了,就先了这个ECS主机.3年.如果购买就上图了.下面直接进入正题. ...
- ubuntu下怎么配置/查看串口-minicom工具
一.安装minicom工具: 可直接使用命令sudo apt-get install minicom来完成安装 上面的截图因为检测到我已经安装过了. 二.通过minicom工具配置串口: 1.启动mi ...
- python OpenCV安装
linux系统 yum install -y libSM.x86_64 libXext.x86_64 libXrender.x86_64 pip install numpy Matplotlib pi ...
- ORB-SLAM2 论文&代码学习 —— LocalMapping 线程
转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12360913.html 本文要点: ORB-SLAM2 Local ...
- asp.net MVC项目开发之统计图echarts柱状图(一)
echarts统计图doc网址:http://echarts.baidu.com/echarts2/index.html 使用echarts,需要引用在js中,如果你已经下载echarts的js包,可 ...
- linux使用和基础操作
1.linux系统初使用 linux有图形终端和字符终端,关于linux学习以字符终端为主,即命令行操作: [root@centos7 ~]#runlevel 查看当前工作模式N 3 //3为字符终端 ...
- 用 Python 分析今年考研形势
还有5天,就到了考研初试的时间了. ! 尽管今年研招网内部,已经做了优化改善,还是抵挡不住考生们的报名热情(网站崩溃). 2017年考研人数增长至201万人, 2018年则达到238万人, 201 ...