Luogu 3292 [SCOI2016]幸运数字
BZOJ 4568。
感觉很板。
前置技能:线性基。 放一篇感觉讲的比较丰富的博客: 戳这里。
首先要求在一个序列中任意选点使得异或和最大,当然是想到线性基了。
把问题转换到树上,如果每次询问的序列是两点之间的路径,也就是说我们只要提取出树上一条路径的线性基就可以了吧。
发现线性基满足可以快速合并这个性质,如果要合并的话只要把一个暴力插到另一个里面去就行了,这样是两个$log$,我们还可以启发式合并,把小的插到大的里面去,这样会更快。
所以我们发现可以链剖或者倍增来维护这个东西,我这么懒,当然是倍增了。
注意倍增的时候是点形成的集合而不是边形成的集合。
再提两句:
1、线性基并不满足区间可减性,所以大力可持久化应该是不行的。
2、点分治可以减少一个$log$,再用$tarjan$求一求$lca$会更快。
时间复杂度$O(nlog^3n)$。
Code:
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = ;
const int B = ;
const int Lg = ; int n, qn, tot = , head[N], dep[N], fa[N][Lg];
ll a[N]; struct Edge {
int to, nxt;
} e[N << ]; inline void add(int from, int to) {
e[++tot].to = to;
e[tot].nxt = head[from];
head[from] = tot;
} template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} struct Lp {
ll p[B]; int cnt; inline void init() {
cnt = ;
memset(p, 0LL, sizeof(p));
} inline void ins(ll val) {
for(int i = ; i >= ; i--) {
if((val >> i) & ) {
if(!p[i]) {
p[i] = val;
++cnt;
break;
}
val ^= p[i];
}
}
} inline ll getMax() {
ll res = 0LL;
for(int i = ; i >= ; i--)
if((res ^ p[i]) > res) res ^= p[i];
return res;
} } s[N][Lg]; inline Lp merge(Lp u, Lp v) {
Lp res; res.init();
if(u.cnt > v.cnt) {
res = u;
for(int i = ; i >= ; i--) {
if(!v.p[i]) continue;
res.ins(v.p[i]);
}
} else {
res = v;
for(int i = ; i >= ; i--) {
if(!u.p[i]) continue;
res.ins(u.p[i]);
}
}
return res;
} inline void swap(int &x, int &y) {
int t = x; x = y; y = t;
} void dfs(int x, int fat, int depth) {
fa[x][] = fat, dep[x] = depth;
s[x][].init();
if(fat) s[x][].ins(a[fat]);
for(int i = ; i <= ; i++) {
fa[x][i] = fa[fa[x][i - ]][i - ];
s[x][i] = merge(s[x][i - ], s[fa[x][i - ]][i - ]);
}
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs(y, x, depth + );
}
} inline Lp getLp(int x, int y) {
Lp res; res.init();
res.ins(a[x]), res.ins(a[y]);
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i--)
if(dep[fa[x][i]] >= dep[y]) {
res = merge(res, s[x][i]);
x = fa[x][i];
}
if(x == y) return res;
for(int i = ; i >= ; i--)
if(fa[x][i] != fa[y][i]) {
res = merge(res, s[x][i]), res = merge(res, s[y][i]);
x = fa[x][i], y = fa[y][i];
}
res = merge(res, s[x][]), res = merge(res, s[y][]);
return res;
} inline void solve(int x, int y) {
Lp res = getLp(x, y);
printf("%lld\n", res.getMax());
} int main() {
read(n), read(qn);
for(int i = ; i <= n; i++) read(a[i]);
for(int x, y, i = ; i < n; i++) {
read(x), read(y);
add(x, y), add(y, x);
} dfs(, , ); for(int x, y; qn--; ) {
read(x), read(y);
solve(x, y);
} return ;
}
唔,Linear Basis居然被我写成了Lp……无话可说
Luogu 3292 [SCOI2016]幸运数字的更多相关文章
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
		
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
 - [SCOI2016]幸运数字 树链剖分,线性基
		
[SCOI2016]幸运数字 LG传送门 为了快乐,我们用树剖写这题. 强行树剖,线段树上每个结点维护一个线性基,每次查询暴力合并. 瞎分析一波复杂度:树剖两点之间\(\log n\)条重链,每条重链 ...
 - bzoj 4568: [Scoi2016]幸运数字
		
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 848 Solved: 336[Submit][Status ...
 - [洛谷P3292] [SCOI2016]幸运数字
		
洛谷题目链接:[SCOI2016]幸运数字 题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城 ...
 - 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
		
4568: [Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形 ...
 - [BZOJ4568][Scoi2016]幸运数字  倍增+线性基
		
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1791 Solved: 685[Submit][Statu ...
 - [BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)
		
4568: [Scoi2016]幸运数字 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 2131 Solved: 865[Submit][Statu ...
 - 【BZOJ4568】[Scoi2016]幸运数字 倍增+线性基
		
[BZOJ4568][Scoi2016]幸运数字 Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念 ...
 - bzoj4568: [Scoi2016]幸运数字(LCA+线性基)
		
4568: [Scoi2016]幸运数字 题目:传送门 题解: 好题!!! 之前就看过,当时说是要用线性基...就没学 填坑填坑: %%%线性基 && 神犇 主要还是对于线性基的运用和 ...
 
随机推荐
- @angular/cli项目构建--animations
			
使用方法一(文件形式定义): animations.ts import { animate, AnimationEntryMetadata, state, style, transition, tri ...
 - KVM-环境安装
			
1.操作系统安装 本文采用Centos6.4X64操作系统,也可以采用RHEL/CentOS6.x. (1)查看系统版本.内核版本 ##查看系统版本 [root@KVM ~]# cat /etc/re ...
 - 树莓派视频监控 —— 使用 mjpg
			
下载到树莓派本地: $ wget https://github.com/jacksonliam/mjpg-streamer/archive/master.zip $ unzip master.zip ...
 - Reinforcement Learning Q-learning 算法学习-1
 - nodejs 设置跨域访问
			
app.use(logger('dev')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); a ...
 - jacksi(比较实用的工具批处理)
			
批处理类别: 国产软件 批处理语言: 简体中文 授权方式: 免费软件 运行环境: Windows平台 警告:运行BAT源码是一种危险的动作,如果你不熟悉,请不要尝试! 这里分享的是用bat写的比较实用 ...
 - 如何测试远端TCP和UDP端口是否开放
			
项目遇到问题时首先排查网络是否正常是一个重要的方面.遇到很多次,同事找我解决问题,最后发现却是IP或端口不通的问题.然而就是这么个简单的问题,对方却花费了甚至一天的时间排查原因. 现在大部分项目都是用 ...
 - bzoj 2655 calc——拉格朗日插值
			
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2655 先考虑DP.dp[ i ][ j ]表示值域为 i .选 j 个值的答案,则 dp[ ...
 - ORACLE增加用户
			
create user 账号 identified by "密码"; grant connect to 账号; grant resource to 账号; --把dba 权限给in ...
 - 分布式锁之一:zookeeper分布式锁1
			
zookeeper集群的每个节点的数据都是一致的, 那么我们可以通过这些节点来作为锁的标志. 首先给锁设置一下API, 至少要包含, lock(锁住), unlock(解锁), isLocked(是否 ...