传送:https://www.luogu.org/problem/P3292
题意:
$n$座城市,$n-1$条路,每个城市有一个价值$a_i$。$q$个询问,每次询问城市$x$到城市$y$的路径上经过的城市的价值的最大异或和为多少。
数据范围:
$1<=n<=20000,q<=200000,a_i<=2^{60}$。
分析:
对于一次询问$x-->y$的路径上的答案,很明显就是$x-->lca(x,y)$的线性基并上$y-->lca(x,y)$的线性基,然后求最大异或和。
那么对于多个询问来说怎么考虑呢?
在一棵树上查询$lca$有两种做法:1)tarjan/dfs(离线);2)ST表+倍增(在线)。对于这个题很明显需要维护路径上的线性基,我们用第二种倍增的做法在求$lca$的同时,就可以维护线性基,然后查询答案。
用$f[i][j]$代表点$i$向上跳$2^j$布达到哪一个点。用$LB[i][j]$代表向上$2^j$步路径上的线性基。
然后求$lca$的过程中同时暴力合并线性基可以了鸭。(qaaaaq
1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn=2e4+10;
5 struct node{
6 int to,nxt;
7 }edge[maxn*2];
8 int head[maxn],f[maxn][20],deep[maxn],tot,N,n,q;
9 ll a[maxn];
10 struct Linear_basis{
11 ll b[65];
12 bool insert(ll x){
13 for (int i=62;i>=0;i--){
14 if (x&(1ll<<i)){
15 if (!b[i]){b[i]=x; break;}
16 x^=b[i];
17 }
18 }
19 return x>0; //是否可插入 true:可插入,false:不可插入
20 }
21 ll mx(){
22 ll res=0;
23 for (int i=62;i>=0;i--) res=max(res,res^b[i]);
24 return res;
25 }
26 void clear(){
27 memset(b,0,sizeof(b));
28 }
29 }LB[maxn][20],ans;
30 void add(int x,int y){
31 edge[++tot]={y,head[x]}; head[x]=tot;
32 }
33 void dfs(int x,int fa){
34 f[x][0]=fa; //倍增数组
35 LB[x][0].insert(a[x]);
36 for (int i=head[x];i!=-1;i=edge[i].nxt){
37 node tmp=edge[i];
38 if (tmp.to==fa) continue;
39 deep[tmp.to]=deep[x]+1;
40 dfs(tmp.to,x);
41 }
42 }
43 Linear_basis merge(Linear_basis p,Linear_basis q){
44 Linear_basis tmp=p;
45 for (int i=62;i>=0;i--){
46 if (q.b[i]) tmp.insert(q.b[i]);
47 }
48 return tmp;
49 }
50 void init(){
51 N=floor(log(1.0*n)/log(2.0));
52 deep[1]=0;
53 dfs(1,0);
54 for (int j=1;j<=N;j++){
55 for (int i=1;i<=n;i++){
56 f[i][j]=f[f[i][j-1]][j-1];
57 LB[i][j]=merge(LB[i][j-1],LB[f[i][j-1]][j-1]);
58 }
59 }
60 }
61 int _LCA(int x,int y){
62 if (deep[x]<deep[y]) swap(x,y);
63 for (int j=N;j>=0;j--)
64 if (deep[f[x][j]]>=deep[y]){
65 ans=merge(ans,LB[x][j]);
66 x=f[x][j];
67 }
68 if (x==y){
69 ans=merge(ans,LB[x][0]); return x;
70 }
71 for (int j=N;j>=0;j--){
72 if (f[x][j]!=f[y][j]){
73 ans=merge(ans,merge(LB[x][j],LB[y][j]));
74 x=f[x][j]; y=f[y][j];
75 }
76 }
77 Linear_basis tmp=merge(LB[x][0],LB[y][0]);
78 Linear_basis tmp2=merge(ans,LB[f[x][0]][0]);
79 ans=merge(tmp2,tmp);
80 return f[x][0]; //lca
81 }
82 int main(){
83 scanf("%d%d",&n,&q);
84 for (int i=1;i<=n;i++) scanf("%lld",&a[i]),head[i]=-1;
85 int x,y; tot=0;
86 for (int i=1;i<=n-1;i++){
87 scanf("%d%d",&x,&y);
88 add(x,y);add(y,x);
89 }
90 init();
91 while (q--){
92 scanf("%d%d",&x,&y);
93 ans.clear();
94 _LCA(x,y);
95 printf("%lld\n",ans.mx());
96 }
97 return 0;
98 }
来源:https://www.cnblogs.com/changer-qyz/p/11355642.html