题意
每个点有点权,求两条没有交点的路径,使得两条路径的异或和的和最大
n ≤ 3 e 4 时 限 : 3.5 s n \le 3e4 \\ 时限:3.5s n≤3e4时限:3.5s
分析
给每个点求出 i n [ i ] o u t [ i ] in[i] \ out[i] in[i] out[i]表示子树内的最大异或路径和子树外的最大异或路径
in只需要给树dfs时,给Trie进行启发式合并即可两只log求出
对于求out,我们找出全局最大异或路径A-B的异或和为ans,考虑只有A->rt 和 B->rt 这两条路径上的点的out不是ans
我们要求两条链上的out,依次加入除了子节点子树外的部分到trie即可
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=3e4+5;
int n;
vector <PII> G[maxn];
struct Trie
{
int ch[2];
int gs;
}tr[maxn<<7];
int rt[maxn],a[maxn],tot;
int in[maxn],out[maxn];
int A,B,p,q;
void insert(int &p,int val)
{
if(!p) p=++tot;
int now=p;
tr[now].gs++;
for(int i=30;i>=0;i--)
{
int dig=val>>i&1;
if(!tr[now].ch[dig]) tr[now].ch[dig]=++tot;
now=tr[now].ch[dig];
tr[now].gs++;
}
}
int query(int now,int val)
{
int res=0;
for(int i=30;i>=0;i--)
{
int dig=val>>i&1;
if(tr[tr[now].ch[!dig]].gs) now=tr[now].ch[!dig],res|=1<<i;
else now=tr[now].ch[dig];
}
return res;
}
void merge(int x,int p,int val,int wei,int &v)
{
if(!x) return;
if(wei==-1)
{
v=max(v,query(rt[p],val));
insert(rt[p],val);
return;
}
merge(tr[x].ch[0],p,val,wei-1,v);
merge(tr[x].ch[1],p,val|1<<wei,wei-1,v);
}
int father[maxn],dfn[maxn],dfs_time;
void dfs(int u,int fa)
{
father[u]=fa; dfn[++dfs_time]=u;
insert(rt[u],a[u]);
for(auto to:G[u])
{
int v=to.first;
if(v==fa) continue;
a[v]=a[u]^to.second;
dfs(v,u);
if(tr[rt[v]].gs>tr[rt[u]].gs) swap(rt[u],rt[v]);
merge(rt[v],u,0,30,in[u]);
in[u]=max(in[u],in[v]);
}
}
int tag[maxn],bel[maxn];
vector <int> v[maxn];
void calc(int x)
{
for(int i=1;i<=tot;i++) tr[i].gs=0;
for(int i=x;i;i=father[i]) tag[i]=1;
int now=0;
for(int k=1,i;k<=n;k++,v[i].clear(),v[bel[i]].push_back(a[i]))
{
if(tag[i=dfn[k]]) bel[i]=i;
else bel[i]=bel[father[i]];
}
for(int i,k=1;k<=n;k++)
if(tag[i=dfn[k]])
{
for(int w:v[father[i]])
now=max(now,query(rt[0],w)),insert(rt[0],w);
out[i]=max(out[i],now);
tag[i]=0;
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
int x,y,z;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
G[x].push_back(make_pair(y,z));
G[y].push_back(make_pair(x,z));
}
dfs(1,0);
// for(int i=1;i<=n;i++) printf("%d ",in[i]);
for(int i=1;i<=tot;i++) tr[i].gs=0;
for(int i=1;i<=n;i++)
{
int val=query(rt[0],a[i]);
insert(rt[0],a[i]); out[i]=-1;
if((A^B)<val)
{
A=a[i];
B=a[i]^val;
p=i;
}
}
for(int i=1;i<=n;i++) if(B==a[i]) q=i;
calc(p); calc(q);
for(int i=1;i<=n;i++) if(out[i]==-1) out[i]=A^B;
int ans=0;
for(int i=2;i<=n;i++) ans=max(ans,in[i]+out[i]);
printf("%d\n",ans);
return 0;
}