Bzoj4568: [Scoi2016]幸运数字
线性基+倍增+LCA
原来线性基还能这么考……一开始看到这个题以为是树上差分线性基,然而线性基不支持删除,所以就挂了。
后来想到倍增线性基,其实到这里思路就很清晰了。
倍增线性基,A[i][j]表示从i开始向上2j步的线性基,询问时暴力合并即可。
1 xxj hb(xxj a,xxj b) 2 { 3 xxj ans;ans.qk(); 4 for(int i=0;i<=60;i++) 5 { 6 if(a.b[i])ans.ins(a.b[i]);//不加if会T 7 if(b.b[i])ans.ins(b.b[i]); 8 } 9 return ans; 10 }
1 //幸运数字 2 #include<iostream> 3 #include<cstdio> 4 #define MAXN 20010 5 #define LL long long 6 const int L=1<<20|1; 7 char buffer[L],*S,*T; 8 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) 9 using namespace std; 10 struct xxj 11 { 12 LL b[65]; 13 void qk() 14 { 15 for(int i=0;i<=64;i++)b[i]=0; 16 } 17 bool ins(LL x) 18 { 19 for(int i=60;i>=0;i--) 20 if(x&(1ll<<i)) 21 { 22 if(!b[i]){b[i]=x;break;} 23 else x=x^b[i]; 24 } 25 if(x)return 1; 26 else return 0; 27 } 28 LL findmax() 29 { 30 LL ans=0; 31 for(int i=60;i>=0;i--) 32 ans=max(ans,ans^b[i]); 33 return ans; 34 } 35 }A[MAXN][16],ta; 36 xxj hb(xxj a,xxj b) 37 { 38 xxj ans;ans.qk(); 39 for(int i=0;i<=60;i++) 40 { 41 if(a.b[i])ans.ins(a.b[i]); 42 if(b.b[i])ans.ins(b.b[i]); 43 } 44 return ans; 45 } 46 struct edge 47 { 48 int u,v,nxt; 49 #define u(x) ed[x].u 50 #define v(x) ed[x].v 51 #define n(x) ed[x].nxt 52 }ed[MAXN*2]; 53 int first[MAXN],num_e; 54 #define f(x) first[x] 55 LL n,q,g[MAXN]; 56 int fa[MAXN][16],dep[MAXN]; 57 void dfs(int x,int ff,int de) 58 { 59 fa[x][0]=ff;dep[x]=de;A[x][0].ins(g[x]);//A[x][0].ins(g[ff]); 60 for(int i=f(x);i;i=n(i)) 61 if(v(i)!=ff)dfs(v(i),x,de+1); 62 } 63 int LCA(int x,int y) 64 { 65 if(dep[x]>dep[y])swap(x,y); 66 for(int i=15;i>=0;i--) 67 if(dep[fa[y][i]]>=dep[x]) 68 y=fa[y][i]; 69 if(x==y)return x; 70 for(int i=15;i>=0;i--) 71 if(fa[x][i]!=fa[y][i]) 72 x=fa[x][i],y=fa[y][i]; 73 return fa[x][0]; 74 } 75 inline LL read() 76 { 77 LL s=0;char a=getchar(); 78 while(a<'0'||a>'9')a=getchar(); 79 while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} 80 return s; 81 } 82 inline void adde(int u,int v); 83 signed main() 84 { 85 // freopen("10.in","r",stdin); 86 87 n=read(),q=read(); 88 for(int i=1;i<=n;i++)g[i]=read(); 89 int a,b; 90 for(int i=1;i<n;i++) 91 { 92 a=read(),b=read(); 93 adde(a,b);adde(b,a); 94 } 95 dfs(1,0,1); 96 for(int i=1;i<=15;i++) 97 for(int j=1;j<=n;j++) 98 { 99 fa[j][i]=fa[fa[j][i-1]][i-1]; 100 A[j][i]=hb(A[j][i-1],A[fa[j][i-1]][i-1]); 101 } 102 for(int i=1;i<=q;i++) 103 { 104 int xi=read(),yi=read(); 105 int lca=LCA(xi,yi); 106 ta.qk(); 107 for(int j=15;j>=0;j--) 108 if(dep[fa[xi][j]]>=dep[lca]) 109 ta=hb(ta,A[xi][j]),xi=fa[xi][j]; 110 for(int j=15;j>=0;j--) 111 if(dep[fa[yi][j]]>=dep[lca]) 112 ta=hb(ta,A[yi][j]),yi=fa[yi][j]; 113 ta.ins(g[lca]); 114 printf("%lld\n",ta.findmax()); 115 } 116 } 117 inline void adde(int u,int v) 118 { 119 ++num_e; 120 u(num_e)=u; 121 v(num_e)=v; 122 n(num_e)=f(u); 123 f(u)=num_e; 124 }
波澜前,面不惊。