P3292 [SCOI2016]幸运数字

题目链接

题意分析

一句话题意 : 树上一条链中挑选出某些数 异或和最大

我们可以考虑维护一个树上倍增线性基

然后倍增的时候 维护一个线性基合并就可以了

写起来还是比较容易的

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 200008
#define IL inline
#define M 66
#define D double
#define ull unsigned long long
#define R register
using namespace std;
template<typename T>IL void read(T &_)
{
    T __=0,___=1;char ____=getchar();
    while(!isdigit(____)) {if(____=='-') ___=0;____=getchar();}
    while(isdigit(____)) {__=(__<<1)+(__<<3)+____-'0';____=getchar();}
    _=___ ? __:-__;
}
/*-------------OI使我快乐-------------*/
int n,m,tot;
int to[N<<1],nex[N<<1],head[N];
int dep[N],fath[N][20];
ll num[N],ans[M],key[N][20][M];
IL void add(int x,int y)
{to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
IL void insert(ll *x,ll y)
{
	for(R int i=61;i>=0;--i)
	{
		ll now=(1ll<<i);
		if(now&y)
		{
			if(!x[i]) {x[i]=y;break;}
			y^=x[i];
		}
	}
}
IL void merge(ll *cdy,ll *wzy)
{
	for(R int i=61;i>=0;--i) if(cdy[i]) insert(wzy,cdy[i]);
}
IL ll qury_ans()
{
	ll res=0;
	for(R int i=61;i>=0;--i)
	if((res^ans[i])>res) res^=ans[i];
	return res;
}
IL void dfs(int now,int fat)
{
	fath[now][0]=fat;dep[now]=dep[fat]+1;
	insert(key[now][0],num[now]);
	for(R int i=1;(1<<i)<=dep[now];++i)
	{//倍增 + 合并线性基
		fath[now][i]=fath[fath[now][i-1]][i-1];
		merge(key[now][i-1],key[now][i]);
		merge(key[fath[now][i-1]][i-1],key[now][i]);
	}
	for(R int i=head[now];i;i=nex[i])
	{
		int v=to[i];
		if(v==fat) continue;
		dfs(v,now);
	}
}
IL ll qury_LCA(int nowx,int nowy)
{//倍增 + 维护答案线性基
	memset(ans,0,sizeof ans);
	if(dep[nowx]<dep[nowy]) swap(nowx,nowy);
	for(R int i=19;i>=0;--i)
	{
		if(dep[fath[nowx][i]]>=dep[nowy])
		{
			merge(key[nowx][i],ans);
			nowx=fath[nowx][i];
		}
	}
	if(nowx==nowy)
	{
		insert(ans,num[nowx]);
//		insert(ans,num[nowx]);
//		insert(ans,num[fath[nowx][0]]);
		return qury_ans();
	} 
	for(R int i=19;i>=0;--i)
	{
		if(fath[nowx][i]!=fath[nowy][i])
		{
			merge(key[nowx][i],ans);
			merge(key[nowy][i],ans);
			nowx=fath[nowx][i];nowy=fath[nowy][i];
		}
	}
	insert(ans,num[nowx]);
	insert(ans,num[nowy]);
	insert(ans,num[fath[nowx][0]]);
//	insert(ans,num[nowx]);
//	insert(ans,num[fath[nowx][0]]);	
//	insert(ans,num[nowy]);
//	insert(ans,num[fath[nowy][0]]);	
	return qury_ans();
}
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	read(n);read(m);
	for(R int i=1;i<=n;++i) read(num[i]);
	for(R int i=1,x,y;i<n;++i)
	{
		read(x);read(y);
		add(x,y);add(y,x);
	}
	dfs(1,0);
	while(m--)
	{
		int x,y;
		read(x);read(y);
		printf("%lld\n",qury_LCA(x,y));
	}
//	fclose(stdin);
//	fclose(stdout);
    return 0;
}

posted @ 2019-04-20 15:37  tcswuzb  阅读(223)  评论(0)    收藏  举报