luogu3292 幸运数字 (点分治+线性基)
首先第一眼是一个倍增套线性基,但是$O(Qlog^2Vlog^N)=10^{10}$的复杂度...
即使是st表也只是变成了$O(Nlog^2Vlog^N)$啊
考虑点分治,相对于倍增显著减少了线性基合并(一个往另一个里暴力插)这一O(log^2V)的过程
就是在分治到一个询问的两端点分立于两个子树的时候,合并它们的线性基来统计答案
1 #include<bits/stdc++.h> 2 #define CLR(a,x) memset(a,x,sizeof(a)) 3 #define MP make_pair 4 using namespace std; 5 typedef long long ll; 6 typedef unsigned long long ull; 7 typedef pair<int,int> pa; 8 const int maxn=2e4+10,maxq=2e5+10; 9 10 inline ll rd(){ 11 ll x=0;char c=getchar();int neg=1; 12 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 13 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 14 return x*neg; 15 } 16 17 struct Node{ 18 int b,i; 19 }; 20 int N,Q,siz[maxn]; 21 vector<Node> q[maxn]; 22 int eg[maxn*2][2],egh[maxn],ect; 23 bool flag[maxn]; 24 ll base[maxn][62],tmp[62],val[maxn],ans[maxq]; 25 int son[maxn],sct,bel[maxn]; 26 27 inline void adeg(int a,int b){ 28 eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect; 29 } 30 inline void getroot(int x,int f,int ssiz,int &rt,int &sm){ 31 siz[x]=1;int m=0; 32 for(int i=egh[x];i;i=eg[i][1]){ 33 int b=eg[i][0];if(b==f||flag[b]) continue; 34 getroot(b,x,ssiz,rt,sm); 35 m=max(siz[b],m);siz[x]+=siz[b]; 36 }m=max(ssiz-siz[x],m); 37 if(m<sm) rt=x,sm=m; 38 } 39 40 inline void update(ll *bs,ll v){ 41 for(int i=60;i>=0;i--){ 42 if(v&(1ll<<i)){ 43 if(!bs[i]){bs[i]=v;break;} 44 else v^=bs[i]; 45 } 46 } 47 } 48 49 inline ll query(ll *bs,ll v){ 50 for(int i=60;i>=0;i--){ 51 if((v^bs[i])>v) v^=bs[i]; 52 }return v; 53 } 54 55 inline void getbase(int x,int f){ 56 update(base[x],val[x]); 57 son[++sct]=x; 58 for(int i=egh[x];i;i=eg[i][1]){ 59 int b=eg[i][0];if(b==f||flag[b]) continue; 60 memcpy(base[b],base[x],sizeof(base[x])); 61 getbase(b,x); 62 } 63 } 64 65 inline void solve(int x,int ssiz){ 66 flag[x]=1;bel[x]=x;CLR(base[x],0); 67 for(int i=egh[x];i;i=eg[i][1]){ 68 int b=eg[i][0];if(flag[b]) continue; 69 CLR(base[b],0);sct=0; 70 getbase(b,0); 71 for(int i=1;i<=sct;i++){ 72 int y=son[i]; 73 for(int j=0;j<q[y].size();j++){ 74 int b=q[y][j].b; 75 if(bel[b]!=x) continue; 76 memcpy(tmp,base[y],sizeof(tmp)); 77 for(int k=0;k<=60;k++){ 78 if(base[b][k]) update(tmp,base[b][k]); 79 } 80 ans[q[y][j].i]=max(query(tmp,0),query(tmp,val[x])); 81 } 82 } 83 for(int i=1;i<=sct;i++) bel[son[i]]=x; 84 } 85 for(int i=egh[x];i;i=eg[i][1]){ 86 int b=eg[i][0];if(flag[b]) continue; 87 int rt,sm=1e9; 88 getroot(b,0,siz[b]>siz[x]?ssiz-siz[x]:siz[b],rt,sm); 89 solve(rt,siz[b]>siz[x]?ssiz-siz[x]:siz[b]); 90 } 91 } 92 93 int main(){ 94 int i,j,k; 95 N=rd(),Q=rd(); 96 for(i=1;i<=N;i++) val[i]=rd(); 97 for(i=1;i<N;i++){ 98 int a=rd(),b=rd(); 99 adeg(a,b);adeg(b,a); 100 } 101 for(i=1;i<=Q;i++){ 102 int a=rd(),b=rd(); 103 if(a==b) ans[i]=val[a]; 104 else{ 105 q[a].push_back((Node){b,i}); 106 q[b].push_back((Node){a,i}); 107 } 108 109 } 110 int rt,sm=1e9; 111 getroot(1,0,N,rt,sm); 112 solve(rt,N); 113 for(i=1;i<=Q;i++) 114 printf("%lld\n",ans[i]); 115 return 0; 116 }