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 ...
随机推荐
- 程序员过关斩将--redis做消息队列,香吗?
Redis消息队列 在程序员这个圈子打拼了太多年,见过太多的程序员使用redis,其中一部分喜欢把redis做缓存(cache)使用,其中最典型的当属存储用户session,除此之外,把redis作为 ...
- 【python-leetcode713-双指针】乘积小于k的子数组
问题描述: 给定一个正整数数组 nums. 找出该数组内乘积小于 k 的连续的子数组的个数. 示例 1: 输入: nums = [10,5,2,6], k = 100输出: 8解释: 8个乘积小于10 ...
- java 自学简单框架(反射+注解)
1.先定义一个学生类 2.再定义一个teacher类(这个是为了练习多个注解,自己练习可以 不写这个) 3.再定义个一个学生老师类(这个是为了最终调用上面的那个学生类做准备) 4.下面开始真正的写框架 ...
- docker容器互联,实现目录、服务共享
一.需求 docker使服务之间实现容器隔离,比如Javaweb项目前端.后端.数据库.数据库后台,分别把它们部署在不同的容器里面,实现隔离.但服务和服务之间也有互访的需求,这就涉及到容器网络和容器互 ...
- vux-- Vue.js 移动端 UI 组件库
1.使用 安装或更新: npm install vux --save npm install vux-loader --save 如果没有安装less: npm install less less-l ...
- Python学习小记(2)---[list, iterator, and, or, zip, dict.keys]
1.List行为 可以用 alist[:] 相当于 alist.copy() ,可以创建一个 alist 的 shallo copy,但是直接对 alist[:] 操作却会直接操作 alist 对象 ...
- 如何利用Azure DevOps快速实现自动化构建、测试、打包及部署
前两天有朋友问我,微软的Azure好用吗,适不适合国人的使用习惯,我就跟他讲了下,Azue很好用,这也是为什么微软云营收一直涨涨涨的原因,基本可以再1个小时内实现自动化构建.打包以及部署到Azure服 ...
- ELK学习005:Kibana 安装与运行
下载安装Kibana 1. 下载地址:https://www.elastic.co/cn/downloads/kibana 2. 解压下载的压缩包 [root@localhost ~]# tar -z ...
- 关于使用kms时遇到的there is nothing to do here
我讲一下我自己的解决方法 ------------------------------------ 这个错误还是很明显的,没事干,如果不是kms的锅的话,那么就是字面上的问题了 ----------- ...
- 限制input输入框只能输入 数字
<input type="text" oninput = "value=value.replace(/[^\d]/g,'')">