有一棵 N N 个节点的树, Q Q 个询问,每次询问树上从 u u 到 v v 的路径中能 xor x o r 出的最大值。 N≤20000,Q≤200000, N ≤ 20000 , Q ≤ 200000 , 时限 6 6 s.
询问一个数集的 xor x o r 最大值显然线性基模板。
预处理树上每个点到它第 2k−1 2 k − 1 个父亲的线性基,合并时暴力将一个线性基插入另一个,每次合并的复杂度是 O(log2A) O ( log 2 A ) .查询时同样暴力合并即可。
需要用到线性基的插入,合并,求最大值操作。
最终得到了一个 O(nlog3n) O ( n log 3 n ) 的优秀算法(
#include
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=20005;
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct Edge{
int to,nex;
}e[N*2];
int n,q,head[N],tot,fa[N][16],dep[N];
LL a[N],fx[N][16][61],ans[61];
inline void ade(int u,int v)
{e[++tot]=(Edge){v,head[u]};head[u]=tot;}
void ins(LL *w,LL x)
{
for(int i=60;i>=0;i--)
if(x&(1LL<if(!w[i])
{w[i]=x;break;}
x^=w[i];
}
}
LL qmax(LL *w)
{
LL ret=0;
for(int i=60;i>=0;i--)
if((ret^w[i])>ret) ret^=w[i];
return ret;
}
void Merge(LL *x,LL *y,LL *z)
{
for(int i=60;i>=0;i--) x[i]=y[i];
for(int i=60;i>=0;i--)
if(z[i]) ins(x,z[i]);
}
void dfs(int u,int f)
{
dep[u]=dep[f]+1; fa[u][0]=f;
ins(fx[u][0],a[u]);
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to; if(v==f) continue;
dfs(v,u);
}
}
inline int LCA(int x,int y)
{
if(dep[x]for(int i=15;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y) return x;
for(int i=15;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
void solve(int x,int y)
{
clr(ans,0);
if(dep[x]for(int i=15;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
Merge(ans,ans,fx[x][i]),x=fa[x][i];
if(x==y) {ins(ans,a[x]);return;}
for(int i=15;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
Merge(ans,ans,fx[x][i]);
Merge(ans,ans,fx[y][i]);
x=fa[x][i]; y=fa[y][i];
}
ins(ans,a[x]); ins(ans,a[y]); ins(ans,a[fa[x][0]]);
// Merge(ans,ans,fx[fa[x][0]][0]);
}
void solve2(int x,int y,int lca)
{
clr(ans,0);
for(;x!=lca;x=fa[x][0])
ins(ans,a[x]);
for(;y!=lca;y=fa[y][0])
ins(ans,a[y]);
ins(ans,a[lca]);
}
int main()
{
n=read();q=read();
for(int i=1;i<=n;i++) a[i]=read();
// for(int i=1;i<=n;i++) ins(ans,a[i]);
// Merge(ans,fx[0][0]);
// cout<
for(int i=1;iint u=read(),v=read();
ade(u,v); ade(v,u);
}
dfs(1,0);
for(int j=1;j<=15;j++)
for(int i=1;i<=n;i++)
{
fa[i][j]=fa[fa[i][j-1]][j-1];
Merge(fx[i][j],fx[i][j-1],fx[fa[i][j-1]][j-1]);
}
// cout<
while(q--)
{
int u=read(),v=read();
solve(u,v);
printf("%lld\n",qmax(ans));
// solve2(u,v,lca);
// cout<
}
return 0;
}
好久没写博客了。。