BZOJ 4568 [Scoi2016]幸运数字 ——线性基 倍增
【题目分析】
考虑异或的最大值,维护线性基就可以了。
但是有多次的询问,树剖或者倍增都可以。
想了想树剖动辄数百行的代码。
算了,我还是写倍增吧。
注:被位运算和大于号的优先级坑了一次,QaQ
【代码】
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <string> #include <algorithm> #include <vector> #include <iostream> #include <queue> using namespace std; #define ll long long #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 20005 #define mlog 20 #define mxle 64 #define mxed 50005 int Getint() { int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } ll Getll() { ll x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } void Finout() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif } struct Base{ ll lb[mxle]; void add(ll x) { D(i,63,0) { if ((x>>i)&1) { if (!lb[i]) {lb[i]=x;break;} else x^=lb[i]; } } } void init(ll x){memset(lb,0,sizeof lb);add(x);} }; Base add(Base x,Base y) { Base ret=x; F(i,0,63) if (y.lb[i]) ret.add(y.lb[i]); return ret; } int f[maxn][mlog],n,q,h[mxed],to[mxed],ne[mxed],en=0,dst[maxn]; Base g[maxn][mlog]; void add(int a,int b) { to[en]=b; ne[en]=h[a]; h[a]=en++; to[en]=a; ne[en]=h[b]; h[b]=en++; } void dfs(int o) { for (int i=h[o];i>=0;i=ne[i]) if (f[o][0]!=to[i]) { f[to[i]][0]=o; dst[to[i]]=dst[o]+1; dfs(to[i]); } } ll query(Base x) { ll sum=0; D(i,63,0) if ((x.lb[i]^sum)>sum) sum^=x.lb[i]; return sum; } ll ask(int a,int b) { if (dst[a]<dst[b]) swap(a,b); Base ret;ret.init(0); int dist=dst[a]-dst[b]; D(i,mlog-1,0) if ((dist>>i)&1) { ret=add(ret,g[a][i]); a=f[a][i]; } if (a==b) { ret=add(ret,g[a][0]); return query(ret); } D(i,mlog-1,0) if (f[a][i]!=f[b][i]) { ret=add(ret,g[a][i]); ret=add(ret,g[b][i]); a=f[a][i];b=f[b][i]; } ret=add(ret,g[a][1]); ret=add(ret,g[b][0]); return query(ret); } int main() { Finout(); memset(h,-1,sizeof h); n=Getint(); q=Getint(); F(i,1,n) g[i][0].init(Getll()); F(i,1,n-1) add(Getint(),Getint()); dfs(1); F(i,1,mlog-1) F(j,1,n) { f[j][i]=f[f[j][i-1]][i-1]; g[j][i]=add(g[j][i-1],g[f[j][i-1]][i-1]); } F(i,1,q) printf("%lld\n",ask(Getint(),Getint())); }