BZOJ 4568: [Scoi2016]幸运数字(倍增+线性基)

传送门

解题思路

  异或最大值肯定线性基了,树上两点那么就倍增搞一搞,就维护每个点到各级祖先的线性基,时间复杂度\(O(nlog^3n)\),并不知道咋过去的。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>

using namespace std;
typedef long long LL;
const int N=20005;

template<class T> void rd(T &x){
	x=0; char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
}	

int n,q,head[N],cnt,to[N<<1],nxt[N<<1],f[N][20],dep[N];
LL w[N];

struct Base{
	LL a[62];	
	inline void insert(LL x){
		if(!x) return ;
		for(int i=60;~i;i--)
			if((1ll<<i)&x){
				if(!a[i]) {a[i]=x; break;}
				x^=a[i]; if(!x) break;
			}
	}
	inline void clear() {memset(a,0,sizeof(a));}
	inline LL query(){
		LL ret=0;
		for(int i=60;~i;i--)
			if(a[i] && (ret^a[i])>ret) ret^=a[i];
		return ret;
	}
}b[N][17],ans;

inline void add(int bg,int ed){
	to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;	
}

inline void build(Base &zz,Base B){
	for(int i=60;~i;i--) 
		if(B.a[i]) zz.insert(B.a[i]);
}	

void dfs(int x,int F){
	f[x][0]=F; b[x][0].insert(w[x]);
	for(int i=1;i<=15;i++) {
		f[x][i]=f[f[x][i-1]][i-1];
		if(f[x][i]) b[x][i]=b[x][i-1],build(b[x][i],b[f[x][i-1]][i-1]);
	}
	for(int i=head[x];i;i=nxt[i]){
		int u=to[i]; if(u==F) continue;
		dep[u]=dep[x]+1; dfs(u,x);	
	}
}

inline int LCA(int x,int y){
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=15;~i;i--) 
		if(dep[f[x][i]]>=dep[y]) x=f[x][i];
	if(x==y) return x;
	for(int i=15;~i;i--)
		if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}	

inline void solve(int x,int y){
	int lca=LCA(x,y); ans.clear();
	for(int i=15;~i;i--)
		if(dep[f[x][i]]>=dep[lca]) {
 			build(ans,b[x][i]);
			x=f[x][i];
		}	
	for(int i=15;~i;i--)
		if(dep[f[y][i]]>=dep[lca]){
			build(ans,b[y][i]);
			y=f[y][i];	
		}
	ans.insert(w[lca]);
	printf("%lld\n",ans.query());
}

int main(){
	rd(n); rd(q); int x,y;
	for(int i=1;i<=n;i++) rd(w[i]);
	for(int i=1;i<n;i++){
		rd(x); rd(y);
		add(x,y); add(y,x);	
	}
	dep[1]=1; dfs(1,0);
	while(q--){
		rd(x),rd(y);
		solve(x,y);	
	}
	return 0;
}	
posted @ 2019-01-27 16:42  Monster_Qi  阅读(174)  评论(0编辑  收藏  举报