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
",ans[i]);
115     return 0;
116 }
原文地址:https://www.cnblogs.com/Ressed/p/10066621.html