[SCOI2016] 幸运数字 题解

\(xor\) 最大值想到线性基,路径想到 \(lca\) 和树链剖分,由于没有修改用 \(lca\) 就可以。先用处理 \(fa\) 数组的方式处理倍增线性基(自然是得用线性基合并的),在求 \(lca\) 时把所有线性基全部合到一块儿就行。

考虑到本题实际上核心在于让路径上的线性基数量 \(\le O(\log n)\),所以也可以用点分治求解。三个时间复杂度应该都是 \(O(n\log^2n)\)

本代码使用倍增。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=20005,M=65;
int n,q,f[N][16],id[N];
vector<int>g[N];int dep[N];
struct lbas{
	int ps[M];
	lbas(){
		memset(ps,0,sizeof(ps));
	}inline void add(int x){
		for(int i=60;~i;i--)
			if((x>>i)&1){
				if(ps[i]) x^=ps[i];
				else{ps[i]=x;return;}
			}
	}inline void cov(lbas x){
		for(int i=0;i<61;i++) ps[i]=x.ps[i];
	}inline void merge(lbas x){
		for(int i=0;i<61;i++)
			if(x.ps[i]) add(x.ps[i]);
	}inline int maxn(){
		int re=0;
		for(int i=60;~i;i--)
			re=max(re,re^ps[i]);
		return re;
	}
}lb[N][16];
inline void dfs(int x,int fa){
	lb[x][0].add(id[x]);
	f[x][0]=fa,dep[x]=dep[fa]+1;
	for(int i=0;i<15;i++){
		f[x][i+1]=f[f[x][i]][i];
		lb[x][i+1].cov(lb[f[x][i]][i]);
		lb[x][i+1].merge(lb[x][i]);
	}for(auto y:g[x])
		if(y!=fa) dfs(y,x);
}inline int lca(int x,int y){
	lbas sum;
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=15;~i;i--)
		if(dep[x]-dep[y]>=(1<<i))
			sum.merge(lb[x][i]),x=f[x][i];
	if(x==y) return sum.add(id[x]),sum.maxn();
	for(int i=15;~i;i--){
		if(f[x][i]==f[y][i]) continue;
		sum.merge(lb[x][i]),x=f[x][i];
		sum.merge(lb[y][i]),y=f[y][i];
	}sum.add(id[f[x][0]]),sum.add(id[y]);
	return sum.add(id[x]),sum.maxn();
}signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>id[i];
	for(int i=1,x,y;i<n;i++)
		cin>>x>>y,g[x].push_back(y),g[y].push_back(x);
	dfs(1,0);
	while(q--){
		int x,y;cin>>x>>y;
		cout<<lca(x,y)<<"\n";
	}return 0;
}
posted @   长安一片月_22  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示