首页 > 代码库 > bzoj4568: [Scoi2016]幸运数字 线性基 倍增

bzoj4568: [Scoi2016]幸运数字 线性基 倍增

洛谷T了,mmp

还是bzoj时限良心,虽然三天两头爆炸

算是简单的题吧,构造出每个点logn个的线性基表

感觉线性基最nb的就是只有log个,所以可以做的很暴力

合并就是拆开再并

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct Bas
 4 {
 5     long long a[61];
 6     Bas()
 7     {
 8         for(int i=0;i<=60;i++)
 9             a[i]=0;
10     }
11     void add(long long x)
12     {
13         for(int i=60;i>=0;i--)
14         if((x>>i-1)&1)
15         if(a[i]) x^=a[i];
16         else
17         {
18             a[i]=x;
19             return;
20         }
21     }
22     long long que()
23     {
24         long long ret=0;
25         for(int i=60;i>=0;i--)
26         if((ret^a[i])>ret)
27             ret^=a[i];
28         return ret;
29     }
30 } ba[20001][16];
31 int n,m,E,p,q;
32 long long w[20001];
33 int fa[20001][16],dep[20001];
34 int fir[20001],nex[40001],to[40001];
35 Bas merge(Bas a,Bas b)
36 {
37     for(int i=0;i<=60;i++)
38     if(a.a[i]) b.add(a.a[i]); 
39     return b;
40 }
41 void add(int x,int y)
42 {
43     to[++E]=y;nex[E]=fir[x];fir[x]=E;
44 }
45 void build(int now,int ft)
46 {
47     fa[now][0]=ft;dep[now]=dep[ft]+1;
48     for(int i=0;fa[now][i];i++)
49         fa[now][i+1]=fa[fa[now][i]][i],
50         ba[now][i+1]=merge(ba[now][i],ba[fa[now][i]][i]);
51     for(int i=fir[now];i;i=nex[i])
52     if(to[i]!=ft)
53         build(to[i],now);
54 }
55 int main()
56 {
57     scanf("%d%d",&n,&m);
58     for(int i=1;i<=n;i++)
59     {
60         scanf("%lld",&w[i]);
61         ba[i][0].add(w[i]);
62     }
63     for(int i=1;i<n;i++)
64         scanf("%d%d",&p,&q),add(p,q),add(q,p);
65     build(1,0);
66     for(int i=1;i<=m;i++)
67     {
68         scanf("%d%d",&p,&q);
69         Bas ret=Bas();
70         if(dep[p]<dep[q]) swap(p,q);
71         for(int i=15;dep[p]>dep[q];i--)
72         if(dep[p]-dep[q]>>i)
73         {
74             ret=merge(ret,ba[p][i]);
75             p=fa[p][i];
76         }
77         for(int i=15;i>=0;i--)
78         if(fa[p][i]!=fa[q][i])
79             ret=merge(merge(ba[p][i],ba[q][i]),ret),
80             p=fa[p][i],q=fa[q][i];
81         if(p!=q)
82         {
83             ret=merge(merge(ba[p][0],ba[q][0]),ret);
84             p=fa[p][0];q=fa[q][0];
85         }
86         ret=merge(ba[p][0],ret);
87         printf("%lld\n",ret.que());
88     }
89     return 0;
90 } 

 

bzoj4568: [Scoi2016]幸运数字 线性基 倍增