bzoj4568: [Scoi2016]幸运数字 线性基 倍增
洛谷T了,mmp
还是bzoj时限良心,虽然三天两头爆炸
算是简单的题吧,构造出每个点logn个的线性基表
感觉线性基最nb的就是只有log个,所以可以做的很暴力
合并就是拆开再并
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct Bas 4 { 5 long long a[61]; 6 Bas() 7 { 8 for(int i=0;i<=60;i++) 9 a[i]=0; 10 } 11 void add(long long x) 12 { 13 for(int i=60;i>=0;i--) 14 if((x>>i-1)&1) 15 if(a[i]) x^=a[i]; 16 else 17 { 18 a[i]=x; 19 return; 20 } 21 } 22 long long que() 23 { 24 long long ret=0; 25 for(int i=60;i>=0;i--) 26 if((ret^a[i])>ret) 27 ret^=a[i]; 28 return ret; 29 } 30 } ba[20001][16]; 31 int n,m,E,p,q; 32 long long w[20001]; 33 int fa[20001][16],dep[20001]; 34 int fir[20001],nex[40001],to[40001]; 35 Bas merge(Bas a,Bas b) 36 { 37 for(int i=0;i<=60;i++) 38 if(a.a[i]) b.add(a.a[i]); 39 return b; 40 } 41 void add(int x,int y) 42 { 43 to[++E]=y;nex[E]=fir[x];fir[x]=E; 44 } 45 void build(int now,int ft) 46 { 47 fa[now][0]=ft;dep[now]=dep[ft]+1; 48 for(int i=0;fa[now][i];i++) 49 fa[now][i+1]=fa[fa[now][i]][i], 50 ba[now][i+1]=merge(ba[now][i],ba[fa[now][i]][i]); 51 for(int i=fir[now];i;i=nex[i]) 52 if(to[i]!=ft) 53 build(to[i],now); 54 } 55 int main() 56 { 57 scanf("%d%d",&n,&m); 58 for(int i=1;i<=n;i++) 59 { 60 scanf("%lld",&w[i]); 61 ba[i][0].add(w[i]); 62 } 63 for(int i=1;i<n;i++) 64 scanf("%d%d",&p,&q),add(p,q),add(q,p); 65 build(1,0); 66 for(int i=1;i<=m;i++) 67 { 68 scanf("%d%d",&p,&q); 69 Bas ret=Bas(); 70 if(dep[p]<dep[q]) swap(p,q); 71 for(int i=15;dep[p]>dep[q];i--) 72 if(dep[p]-dep[q]>>i) 73 { 74 ret=merge(ret,ba[p][i]); 75 p=fa[p][i]; 76 } 77 for(int i=15;i>=0;i--) 78 if(fa[p][i]!=fa[q][i]) 79 ret=merge(merge(ba[p][i],ba[q][i]),ret), 80 p=fa[p][i],q=fa[q][i]; 81 if(p!=q) 82 { 83 ret=merge(merge(ba[p][0],ba[q][0]),ret); 84 p=fa[p][0];q=fa[q][0]; 85 } 86 ret=merge(ba[p][0],ret); 87 printf("%lld\n",ret.que()); 88 } 89 return 0; 90 }