树上查两点间最大异或和
树倍增,每个点维护向上2^k个点的线性基,然后在查lca的时候合并
关于点权维护倍增略蛋疼-_-
合并线性基的时候就直接把一个线性基里的插到另一个里
复杂度O(m log n log^2INF)
合并的时候加点优化可以降掉一个logINF
接下来bb一些有关线性基和最大异或和的东西……
首先线性基是一个拟阵,遗传性显然,交换性可以把大的里边找一个小的里没有的位,小的里因为别的位有1所以一定不能表示出这一位,所以还是线性基,所以有交换性
然后找最大异或和就是,线性基保证每个数都不会被消掉,并且从高位到低位贪心,高位能放一定放高位,取max的意思就是判断之前有没有这一位
#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<iomanip> #include<vector> #include<stack> #include<queue> #include<map> #include<set> #include<bitset> using namespace std; #define MAXN 20010 #define MAXM 17 #define ll long long #define INF 1000000000 #define MOD 1000000007 #define eps 1e-8 struct vec{ int to; int fro; }; struct bas{ ll b[65]; bas(){ memset(b,0,sizeof(b)); } inline void ins(ll x){ int i; ll t=x; for(i=61;~i;i--){ if(x&(1ll<<i)){ if(!b[i]){ b[i]=x; break; }else{ x^=b[i]; } } } } bas(ll x){ memset(b,0,sizeof(b)); ins(x); } friend bas operator +(bas x,bas y){ int i; //cout<<"@"<<endl;; for(i=61;~i;i--){ if(y.b[i]){ //cout<<i<<'#'<<y.b[i]<<endl; x.ins(y.b[i]); } } return x; } ll val(){ ll re=0; int i; for(i=61;~i;i--){ re=max(re,re^b[i]); } return re; } }; vec mp[MAXN*2]; int tai[MAXN],cnt; int n,m; ll v[MAXN]; int fa[MAXN][MAXM]; bas b[MAXN][MAXM]; int dep[MAXN]; inline void be(int x,int y){ mp[++cnt].to=y; mp[cnt].fro=tai[x]; tai[x]=cnt; } inline void bde(int x,int y){ be(x,y); be(y,x); } void pre(int x,int f){ int i,j,t,y; dep[x]=dep[fa[x][1]]+1; if(!f){ b[x][0]=bas(v[x]); fa[x][0]=x; } for(i=tai[x];i;i=mp[i].fro){ y=mp[i].to; if(y!=f){ b[y][0]=bas(v[y]); fa[y][0]=y; for(j=1,t=x;t;j++){ fa[y][j]=t; t=fa[t][j]; } if(fa[y][1]){ b[y][1]=b[y][0]+b[fa[y][1]][0]; } for(j=2;fa[y][j];j++){ b[y][j]=b[y][j-1]+b[fa[y][j-1]][j-1]; } pre(y,x); } } } bas ask(int x,int y){ bas re; int i; re.ins(v[x]); re.ins(v[y]); if(dep[x]<dep[y]){ swap(x,y); } for(i=16;i;i--){ if(dep[fa[x][i]]>=dep[y]){ re=re+b[x][i]; x=fa[x][i]; } } for(i=16;i;i--){ if(fa[x][i]!=fa[y][i]){ re=re+b[x][i]; re=re+b[y][i]; x=fa[x][i]; y=fa[y][i]; } } if(x!=y){ re=re+b[x][1]; } return re; } bas bask(int x,int y){ int i; bas re; if(dep[x]<dep[y]){ swap(x,y); } re.ins(v[x]); re.ins(v[y]); while(dep[x]>dep[y]){ x=fa[x][1]; re.ins(v[x]); } while(x!=y){ x=fa[x][1]; y=fa[y][1]; re.ins(v[x]); re.ins(v[y]); } return re; } int main(){ int i,x,y,z; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%lld",&v[i]); } for(i=1;i<n;i++){ scanf("%d%d",&x,&y); bde(x,y); } pre(1,0); for(i=1;i<=m;i++){ scanf("%d%d",&x,&y); printf("%lld\n",ask(x,y).val()); } return 0; } /* 10 1 1 2 4 8 16 32 64 128 256 512 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 1 10 10027007 */