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 ...
随机推荐
- BZOJ2326 [HNOI2011]数学作业(分块矩阵快速幂)
题意: 定义函数Concatenate (1 ..N)是将所有正整数 1, 2, …, N 顺序连接起来得到的数,如concatenate(1..5)是12345,求concatenate(1...n ...
- 题解【Luogu P6102 谔运算】
\[ \texttt{Description} \] 给出一个长度为 \(n\) 的数列 \(a\),求 \(\sum\limits_{i=1}\limits^{n}\sum\limits_{j=1} ...
- Spring ——Spring IoC容器详解(图示)
1.1 Spring IoC容器 从昨天的例子当中我们已经知道spring IoC容器的作用,它可以容纳我们所开发的各种Bean.并且我们可以从中获取各种发布在Spring IoC容器里的Bean,并 ...
- 从底层入手,解析字节码增强和Btrace应用
这篇文章聊下字节码和相关的应用. 1.机器码和字节码 机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据. 通常意义上来 ...
- OFDM Modulation Scheme
- [redis读书笔记] 第二部分 单机数据库 数据库实现
一 数据库基本实现/命令下发的实现 redis.c里,大家能看到redisCommandTable[] 的实现,列出了支持的所有命令.大部分的入参为redisClient *c,当一条REDIS命令下 ...
- 上周 GitHub 热点速览 vol.08:系统设计必看 The System Design Primer
作者:HelloGitHub-小鱼干 摘要:GitHub Trending 上周看点,老项目依旧抢眼,系统设计必看 Repo:The System Design Primer 周获 1k+ star, ...
- Hello Rust!
准备工作 Rust是系统编程语言,会经过传统的编译.链接.生成可执行文件等过程.它依赖c/cpp的编译环境,需要提前安装c/cpp开发环境,比如安装gcc及其依赖等. 安装(macOS / Linux ...
- Leetcode:110. 平衡二叉树
Leetcode:110. 平衡二叉树 Leetcode:110. 平衡二叉树 点链接就能看到原题啦~ 关于AVL的判断函数写法,请跳转:平衡二叉树的判断 废话不说直接上代码吧~主要的解析的都在上面的 ...
- codewars--js--Large Factorials--阶乘+大数阶乘
问题描述: In mathematics, the factorial of integer n is written as n!. It is equal to the product of n a ...