码迷,mamicode.com
首页 > 其他好文 > 详细

[luogu3292]幸运数字

时间:2019-08-10 09:32:28      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:def   opened   时间   clu   else   div   图片   isp   show   

考虑点分治,将询问离线后计算重心到每一个点的线性基,然后再询问重心到每一个点的线性基,时间复杂度为$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

 

[luogu3292]幸运数字

标签:def   opened   时间   clu   else   div   图片   isp   show   

原文地址:https://www.cnblogs.com/PYWBKTDA/p/11330369.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!