[luogu3292]幸运数字

考虑点分治,将询问离线后计算重心到每一个点的线性基,然后再询问重心到每一个点的线性基,时间复杂度为$o(3600q)$,可以过(然而太菜的我写了倍增维护线性基,震惊于倍增和线性基常数之小)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 20005
 4 #define oo 0x3f3f3f3f
 5 #define ll long long
 6 struct ji{
 7     ll a[61];
 8 }o,dp[N][21];
 9 struct ji2{
10     int nex,to;
11 }edge[N<<1];
12 int E,n,m,x,y,head[N],in[N],out[N],f[N][21];
13 ll a[N];
14 bool pd(int x,int y){
15     return (in[x]<=in[y])&&(out[y]<=out[x]);
16 }
17 void add(int x,int y){
18     edge[E].nex=head[x];
19     edge[E].to=y;
20     head[x]=E++;
21 }
22 void add(ji &x,ll y){
23     for(int i=60;i>=0;i--)
24         if (y&(1LL<<i))
25             if (x.a[i])y^=x.a[i];
26             else{
27                 x.a[i]=y;
28                 break;
29             }
30 }
31 void merge(ji &x,ji y){
32     for(int i=0;i<=60;i++)
33         if (y.a[i])add(x,y.a[i]);
34 }
35 void dfs(int k,int fa){
36     in[k]=++x;
37     f[k][0]=fa;
38     add(dp[k][0],a[k]);
39     for(int i=1;i<=20;i++){
40         f[k][i]=f[f[k][i-1]][i-1]; 
41         dp[k][i]=dp[k][i-1];
42         merge(dp[k][i],dp[f[k][i-1]][i-1]);
43     }
44     for(int i=head[k];i!=-1;i=edge[i].nex)
45         if (edge[i].to!=fa)dfs(edge[i].to,k);
46     out[k]=++x;
47 }
48 ji calc(int x,int y){
49     if (x==y)return dp[x][0];
50     ji z;
51     memset(z.a,0,sizeof(z.a));
52     for(int i=20;i>=0;i--)
53         if (!pd(f[x][i],y)){
54             merge(z,dp[x][i]);
55             x=f[x][i];
56         }
57     for(int i=20;i>=0;i--)
58         if (!pd(f[y][i],x)){
59             merge(z,dp[y][i]);
60             y=f[y][i];
61         }
62     merge(z,dp[x][pd(x,y)^1]);
63     if (!pd(y,x))merge(z,dp[y][0]);
64     return z;
65 }
66 ll query(ji o){
67     ll ans=0;
68     for(int j=60;j>=0;j--)
69         if ((ans&(1LL<<j))==0)ans^=o.a[j];
70     return ans;
71 }
72 int main(){
73     scanf("%d%d",&n,&m);
74     memset(head,-1,sizeof(head));
75     for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
76     for(int i=1;i<n;i++){
77         scanf("%d%d",&x,&y);
78         add(x,y);
79         add(y,x);
80     }
81     dfs(1,1);
82     for(int i=1;i<=m;i++){
83         scanf("%d%d",&x,&y);
84         printf("%lld\n",query(calc(x,y)));
85     }
86 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/11330369.html