BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)
题目链接 BZOJ 4568
考虑树链剖分+线段树维护每一段区域的异或线性基
对于每个询问,求出该点集的异或线性基。然后求一下这个线性基里面能异或出的最大值即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define ls i << 1
#define rs i << 1 | 1
#define lson i << 1, L, mid
#define rson i << 1 | 1, mid + 1, R typedef long long LL; const int N = 2e4 + 10; struct lb{
LL d[70];
int cnt;
void clear(){
memset(d, 0, sizeof d);
cnt = 0;
}
bool ins(LL val){
dec(i, 62, 0) if (val & (1LL << i)){
if (!d[i]){ d[i] = val; break; }
val ^= d[i];
}
return val > 0;
}
LL qmax(){
LL ret = 0;
dec(i, 62, 0) if ((ret ^ d[i]) > ret) ret ^= d[i];
return ret;
}
LL qmin(){
rep(i, 0, 62) if (d[i]) return d[i];
return 0;
}
}; lb t[N << 3]; int f[N], fp[N], son[N], deep[N], father[N], sz[N], top[N];
int q, tot, n;
LL a[N];
vector <int> v[N]; lb merge(const lb &n1, const lb &n2){
lb ret = n1;
dec(i, 60, 0) if (n2.d[i]) ret.ins(n2.d[i]);
return ret;
} void dfs1(int x, int fa, int dep){
deep[x] = dep;
father[x] = fa;
son[x] = 0;
sz[x] = 1;
int ct = (int)v[x].size();
rep(i, 0, ct - 1){
int u = v[x][i];
if (u == fa) continue;
dfs1(u, x, dep + 1);
sz[x] += sz[u];
if (sz[son[x]] < sz[u]) son[x] = u;
}
} void dfs2(int x, int tp){
top[x] = tp;
f[x] = ++tot;
fp[f[x]] = x;
if (son[x]) dfs2(son[x], tp);
int ct = (int)v[x].size();
rep(i, 0, ct - 1){
int u = v[x][i];
if (u == father[x] || u == son[x]) continue;
dfs2(u, u);
}
} void build(int i, int L, int R){
if (L == R){
t[i].ins(a[fp[L]]);
return;
} int mid = (L + R) >> 1;
build(lson);
build(rson);
t[i] = merge(t[ls], t[rs]);
} lb query(int i, int L, int R, int l, int r){
if (L == l && R == r) return t[i];
int mid = (L + R) >> 1;
if (r <= mid) return query(lson, l, r);
else if (l > mid) return query(rson, l, r);
else return merge(query(lson, l, mid), query(rson, mid + 1, r));
} lb work(int x, int y){
lb ret;
ret.clear();
int f1 = top[x], f2 = top[y];
for (; f1 != f2; ){
if (deep[f1] < deep[f2]) swap(f1, f2), swap(x, y);
ret = merge(ret, query(1, 1, n, f[f1], f[x]));
x = father[f1], f1 = top[x];
} if (x == y) return merge(ret, query(1, 1, n, f[x], f[y]));
if (deep[x] > deep[y]) swap(x, y);
return merge(ret, query(1, 1, n, f[x], f[y]));
} int main(){ scanf("%d%d", &n, &q);
rep(i, 1, n) scanf("%lld", a + i); rep(i, 2, n){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
} dfs1(1, 0, 0);
dfs2(1, 1);
build(1, 1, n); while (q--){
int x, y;
scanf("%d%d", &x, &y);
lb cnt = work(x, y);
printf("%lld\n", cnt.qmax());
} return 0;
}
BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)的更多相关文章
- [SCOI2016]幸运数字 树链剖分,线性基
[SCOI2016]幸运数字 LG传送门 为了快乐,我们用树剖写这题. 强行树剖,线段树上每个结点维护一个线性基,每次查询暴力合并. 瞎分析一波复杂度:树剖两点之间\(\log n\)条重链,每条重链 ...
- 【BZOJ-4568】幸运数字 树链剖分 + 线性基合并
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 238 Solved: 113[Submit][Status ...
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
- bzoj 4568: [Scoi2016]幸运数字
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 848 Solved: 336[Submit][Status ...
- bzoj 4568: [Scoi2016]幸运数字【树链剖分+线段树+线性基】
一眼做法,好处是好想好写坏处是常数大,容易被卡(bzoj loj 洛谷开O2 能AC,不开有90分-- 大概就是树剖之后维护线段树,在线段树的每个节点上上维护一个线性基,暴力\( 60^2 \)的合并 ...
- BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增
[题目分析] 考虑异或的最大值,维护线性基就可以了. 但是有多次的询问,树剖或者倍增都可以. 想了想树剖动辄数百行的代码. 算了,我还是写倍增吧. 注:被位运算和大于号的优先级坑了一次,QaQ [代码 ...
- BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)
传送门 解题思路 异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的. 代码 #include<iostr ...
- 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...
- bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 876 Solved: 446[Submit][Status][ ...
随机推荐
- laravel5 使用try catch
在laravel5中使用以下代码并没有捕获异常 try{ var_dump($val); }catch (Exception $e){ var_dump($e); } Laravel 5 时代控制器 ...
- List<Object>删除某一个Object
1.直接删除: List<LineShop> tlineprices = new ArrayList<>(); tlineprices.remove(0); 2.使用遍历删除 ...
- 20181210(os,os.path,subprocess,configparser,shutil)
1.os模块 os表示操作系统,该模块主要处理与操作系统相关的操作.最常用的是文件操作:打开,读取,删除,复制,重命名. 重点掌握增删改查的函数操作. import os# 获取当前执行文件所在文件夹 ...
- CodeForces - 948C Producing Snow(优先队列)
题意: n天. 每天你会堆一堆雪,体积为 v[i].每天都有一个温度 t[i] 所有之前堆过的雪在第 i 天体积都会减少 t[i] . 输出每天融化了的雪的体积. 这个题的正解我怎么想都很难理解,但是 ...
- luogu3389 【模板】高斯消元法
#include <algorithm> #include <iostream> #include <cstdio> #include <cmath> ...
- python学习-- 理解'*','*args','**','**kwargs'
刚开始学习Python的时候,对有关args,kwargs,和*的使用感到很困惑.相信对此感到疑惑的人也有很多.我打算通过这个帖子来排解这个疑惑(希望能减少疑惑). 让我们通过以下5步来理解: 1. ...
- 数据库导入Exel,输入到浏览器
db.php <?php require dirname(__FILE__)."/dbconfig.php";//引入配置文件 class db{ public $conn= ...
- [uiautomator篇][1] 官网译文
http://www.jianshu.com/p/7718860ec657 2016.07.25 20:59 字数 3675 Android UIAutomator浅谈 --------------- ...
- A Few Laughing Men
A Few Laughing Men CodeChef - LAUGHMEN Balaji is a great person to hang out with. He tells really am ...
- pat 1037
如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 —— 就如海格告诉哈利的:“十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西可,很容易.”现在,给定 ...