1. 程式人生 > >bzoj4568: [Scoi2016]幸運數字(LCA+線性基)

bzoj4568: [Scoi2016]幸運數字(LCA+線性基)

註意 next ems math ace get geo text clas

4568: [Scoi2016]幸運數字

題目:傳送門


題解:

   好題!!!

   之前就看過,當時說是要用線性基...就沒學

   填坑填坑:

   %%%線性基 && 神犇

   主要還是對於線性基的運用和LCA的靈活運用吧:

   設f[i][j][65]表示i到2^j-1的線性基集合

   跑LCA,邊跑邊暴力合並路徑上的線性基咯,最後find_max一下xor的最大值就好啦

   槽點:註意^符號的優先級還有空間大小...有點惡心


代碼:

  1 #include<cstdio>
  2 #include<cstring>
  3
#include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 typedef long long LL; 8 struct node 9 { 10 int x,y,next; 11 }a[41000];int len,last[21000]; 12 void ins(int x,int y) 13 { 14 len++;a[len].x=x;a[len].y=y; 15 a[len].next=last[x];last[x]=len;
16 } 17 void add(LL *a,LL x) 18 { 19 for(int i=60;i>=0;i--) 20 { 21 if(x&(1LL<<i)) 22 { 23 if(!a[i]){a[i]=x;break;} 24 x^=a[i]; 25 } 26 } 27 } 28 void merge(LL *a,LL *b) 29 { 30 for(int i=0;i<=60;i++)
31 if(b[i])add(a,b[i]); 32 } 33 LL ans[65],bin[65],f[21000][21][65],dep[21000],fa[21000][21]; 34 void pre_tree_node(int x) 35 { 36 for(int i=1;bin[i]<=dep[x];i++) 37 { 38 fa[x][i]=fa[fa[x][i-1]][i-1]; 39 memcpy(f[x][i],f[x][i-1],sizeof(f[x][i])); 40 merge(f[x][i],f[fa[x][i-1]][i-1]); 41 } 42 for(int k=last[x];k;k=a[k].next) 43 { 44 int y=a[k].y; 45 if(y!=fa[x][0]) 46 { 47 fa[y][0]=x; 48 dep[y]=dep[x]+1; 49 pre_tree_node(y); 50 } 51 } 52 } 53 void solve(int x,int y) 54 { 55 if(dep[x]<dep[y])swap(x,y); 56 for(int i=20;i>=0;i--) 57 if(dep[fa[x][i]]>=dep[y]) 58 merge(ans,f[x][i]),x=fa[x][i]; 59 if(x==y){merge(ans,f[x][0]);return ;} 60 for(int i=20;i>=0;i--) 61 if(bin[i]<=dep[x] && fa[x][i]!=fa[y][i]) 62 { 63 merge(ans,f[x][i]),merge(ans,f[y][i]); 64 x=fa[x][i],y=fa[y][i]; 65 } 66 merge(ans,f[x][0]),merge(ans,f[y][0]); 67 merge(ans,f[fa[x][0]][0]); 68 return ; 69 } 70 LL find_max() 71 { 72 LL sum=0; 73 for(int i=60;i>=0;i--) 74 if((sum^ans[i])>sum) 75 sum^=ans[i]; 76 return sum; 77 } 78 int n,T; 79 int main() 80 { 81 scanf("%d%d",&n,&T); 82 bin[0]=1LL;for(int i=1;i<=60;i++)bin[i]=bin[i-1]<<1; 83 len=0;memset(last,0,sizeof(last)); 84 for(int i=1;i<=n;i++) 85 { 86 LL x;scanf("%lld",&x); 87 add(f[i][0],x); 88 } 89 for(int i=1;i<n;i++) 90 { 91 int x,y;scanf("%d%d",&x,&y); 92 ins(x,y);ins(y,x); 93 } 94 fa[1][0]=0;dep[1]=1;pre_tree_node(1); 95 while(T--) 96 { 97 int x,y;scanf("%d%d",&x,&y); 98 memset(ans,0,sizeof(ans)); 99 solve(x,y); 100 printf("%lld\n",find_max()); 101 } 102 return 0; 103 }

bzoj4568: [Scoi2016]幸運數字(LCA+線性基)