洛谷P3292 [SCOI2016]幸运数字(倍增+线性基)

传送门

 

 

不知道线性基是什么东西的可以看看蒟蒻的总结

第一眼:这不会是个倍增LCA暴力合并线性基吧……

打了一发……A了?

所以这真的是个暴力倍增LCA合并线性基么……

ps:据某大佬说其实可以离线之后用点分做,那样的话因为每次只要合并两个线性基,复杂度可以减一个$log$

 1 //minamoto
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #define ll long long
 6 #define max(a,b) ((a)>(b)?(a):(b))
 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 8 char buf[1<<21],*p1=buf,*p2=buf;
 9 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
10 using namespace std;
11 inline ll read(){
12     #define num ch-'0'
13     char ch;bool flag=0;ll res;
14     while((ch=getc())>'9'||ch<'0')
15     (ch=='-')&&(flag=true);
16     for(res=num;(ch=getc())<='9'&&ch>='0';res=res*10+num);
17     (flag)&&(res=-res);
18     #undef num
19     return res;
20 }
21 char sr[1<<21],z[20];int C=-1,Z;
22 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
23 inline void print(ll x){
24     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
25     while(z[++Z]=x%10+48,x/=10);
26     while(sr[++C]=z[Z],--Z);sr[++C]='\n';
27 }
28 const int N=20005;
29 int n,q,tot,head[N],Next[N<<1],ver[N<<1],dep[N];
30 ll fa[N][21],b[N][21][62],sum,ans[62],val[N];
31 inline void add(int u,int v){
32     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
33 }
34 inline void get(ll *b,ll x){
35     for(int i=61;i>=0;--i)
36     if(x>>i&1){
37         if(!b[i]) return (void)(b[i]=x);
38         x^=b[i];
39     }
40 }
41 inline void merge(ll *b,ll *x){
42     for(int i=61;i>=0;--i)
43     if(x[i]) get(b,x[i]);
44 }
45 inline void init(int i){
46     for(int j=1;j<20;++j){
47         fa[i][j]=fa[fa[i][j-1]][j-1];
48         memcpy(b[i][j],b[i][j-1],sizeof(b[i][j-1]));
49         merge(b[i][j],b[fa[i][j-1]][j-1]);
50     }
51 }
52 void dfs(int u,int f){
53     fa[u][0]=f,dep[u]=dep[f]+1,init(u);
54     for(int i=head[u];i;i=Next[i])
55     if(ver[i]!=f) dfs(ver[i],u);
56 }
57 void LCA(int u,int v){
58     if(dep[u]<dep[v]) swap(u,v);
59     for(int i=20;i>=0;--i)
60     if(dep[fa[u][i]]>=dep[v])
61     merge(ans,b[u][i]),u=fa[u][i];
62     if(u==v) return (void)(merge(ans,b[u][0]));
63     for(int i=20;i>=0;--i)
64     if(fa[u][i]!=fa[v][i]){
65         merge(ans,b[u][i]),merge(ans,b[v][i]);
66         u=fa[u][i],v=fa[v][i];
67     }
68     merge(ans,b[u][0]),merge(ans,b[v][0]),merge(ans,b[fa[u][0]][0]);
69 }
70 int main(){
71 //    freopen("testdata.in","r",stdin);
72     n=read(),q=read();
73     for(int i=1;i<=n;++i)
74     get(b[i][0],val[i]=read());
75     for(int i=1,u,v;i<n;++i)
76     u=read(),v=read(),add(u,v),add(v,u);
77     dfs(1,0);
78     while(q--){
79         memset(ans,0,sizeof(ans));
80         int u=read(),v=read();
81         LCA(u,v);
82         sum=0;
83         for(int i=61;i>=0;--i)
84         cmax(sum,sum^ans[i]);
85         print(sum);
86     }
87     Ot();
88     return 0;
89 }

 

posted @ 2018-09-28 19:01  bztMinamoto  阅读(195)  评论(0编辑  收藏  举报
Live2D