meaning of the title
Give a tree with nnn nodes edge weight.Defines the exclusive or sum of edge weights for a path.Find a path where two nodes do not intersect, giving the two paths the maximum weight.
n≤30000n\le 30000n≤30000
Analysis
The problem can be converted to finding two numbers inside and outside the subtree of each point, making their XOR sum as large as possible.
By finding the dfs order and doubling it, you can convert it to selecting two numbers in the interval so that the exclusive sum of the two numbers is as large as possible.
Just use Rollback Mouse+Trie.
Rolling back the Moquoise team specifically means that both the left and right endpoints are directly engaged in violent interrogation within the same block.Sort the other queries by the first key in the block where the left endpoint is located and the second key in the right endpoint.When processing queries within a block, record ansansans as the answer to the right endpoint-to-right pointer of the block.Each time you push the right pointer to the right end of the query, then the left pointer from the right end of the block to the left end of the query, and then the left pointer will be restored.
Time Complexity O (n n log_V) O (nsqrt nlog V) O (n n logV).
Code
#include<bits/stdc++.h> #define pb push_back const int N=30005; int n,cnt,last[N],bel[N],tim,dfn[N],val[N],w[N*2],mx[N],sz,tot,B,bin[35],ans[N],rt; struct edge{int to,next,w;}e[N*2]; struct data{int l,r,id;}q[N*2]; struct tree{int l,r,s;}t[N*30]; std::vector<int> vec[N]; void addedge(int u,int v,int w) { e[++cnt].to=v;e[cnt].w=w;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].w=w;e[cnt].next=last[v];last[v]=cnt; } void dfs(int x,int fa) { dfn[x]=++tim; bel[tim]=x; for (int i=last[x];i;i=e[i].next) if (e[i].to!=fa) val[e[i].to]=val[x]^e[i].w,dfs(e[i].to,x); mx[x]=tim; } int cmp(int x,int y) { return q[x].r<q[y].r; } int get(int x) { return (x+B-1)/B; } void ins(int &x,int d,int w,int c) { if (!x) x=++sz; t[x].s+=c; if (d<0) return; if (w&bin[d]) ins(t[x].r,d-1,w,c); else ins(t[x].l,d-1,w,c); } int query(int x,int d,int w) { if (d<0) return 0; if (w&bin[d]) if (t[t[x].l].s) return query(t[x].l,d-1,w)+bin[d]; else return query(t[x].r,d-1,w); else if (t[t[x].r].s) return query(t[x].r,d-1,w)+bin[d]; else return query(t[x].l,d-1,w); } int calc(int l,int r) { int mx=0; for (int i=l;i<=r;i++) mx=std::max(mx,query(rt,30,w[i])),ins(rt,30,w[i],1); for (int i=l;i<=r;i++) ins(rt,30,w[i],-1); return mx; } void pre() { B=sqrt(n*2); for (int i=1;i<=n;i++) w[i]=w[i+n]=val[bel[i]]; for (int i=2;i<=n;i++) { int l=dfn[i],r=mx[i],pos=get(l); if (get(l)==get(r)) ans[i]+=calc(l,r); else q[++tot].l=l,q[tot].r=r,q[tot].id=i,vec[pos].pb(tot); l=mx[i]+1;r=dfn[i]+n-1;pos=get(l); if (get(l)==get(r)) ans[i]+=calc(l,r); else q[++tot].l=l,q[tot].r=r,q[tot].id=i,vec[pos].pb(tot); } for (int i=1;i<=get(n*2);i++) std::sort(vec[i].begin(),vec[i].end(),cmp); } void solve() { for (int i=1;i<=get(n*2);i++) { int r=B*i-1,mx=0; for (int j=0;j<vec[i].size();j++) { int now=vec[i][j],tmp=0; while (r<q[now].r) mx=std::max(mx,query(rt,30,w[++r])),ins(rt,30,w[r],1); int l=B*i; while (l>q[now].l) tmp=std::max(tmp,query(rt,30,w[--l])),ins(rt,30,w[l],1); while (l<B*i) ins(rt,30,w[l++],-1); ans[q[now].id]+=std::max(mx,tmp); } while (r>B*i-1) ins(rt,30,w[r--],-1); } } int main() { bin[0]=1; for (int i=1;i<=30;i++) bin[i]=bin[i-1]*2; scanf("%d",&n); for (int i=1;i<n;i++) { int x,y,z;scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); } dfs(1,0); pre(); solve(); int mx=0; for (int i=2;i<=n;i++) mx=std::max(mx,ans[i]); printf("%d\n",mx); return 0; }