维护每一个点到根路径的异或和(记作$d_{k}$),根据异或自反性,$(x,y)$的异或和即$d_{x}\oplus d_{y}$

考虑两条路径的lca,选择其中深度较大的点,另一条路径必然在其子树外,枚举这个点,分别统计子树内外异或和最大的路径

对于子树内,用启发式合并trie树,在合并时顺便统计出答案(枚举较小的一棵trie树中的点,在另一颗trie树中查询),时间复杂度为$o(n\log_{2}n\log_{2}w)$

对于子树外,任选一条全局异或和最大的路径$(p,q)$,然后将其以$p$为根建树(子树内也需要以$p$为根考虑)

将所有点分为两类:1.子树内不含有$q$;2.子树内含有$q$,对于前者必然选择$(p,q)$这条路径,否则也就是从$p$递归到$q$为止的时候

此时,暴力合并子树外的节点(即父亲子树外的节点与父亲子树内除自己外的节点),不难发现每一个节点至多合并一次,暴力合并即可做到$o(n\log_{2}w)$

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 30005
4 int E,n,x,y,z,mx,now_mx,ans,head[N],d[N],vis[N],f[N];
5 struct ji{
6 int nex,to,len;
7 }edge[N<<1];
8 struct trie{
9 int V;
10 vector<int>v,ch[2];
11 void New(){
12 ch[0].push_back(-1);
13 ch[1].push_back(-1);
14 V++;
15 }
16 void init(){
17 V=0;
18 v.clear(),ch[0].clear(),ch[1].clear();
19 New();
20 }
21 void add(int x){
22 v.push_back(x);
23 int k=0;
24 for(int i=29;i>=0;i--){
25 int p=((x&(1<<i))>0);
26 if (ch[p][k]<0){
27 ch[p][k]=V;
28 New();
29 assert(ch[p][k]>=0);
30 }
31 k=ch[p][k];
32 }
33 }
34 int query(int x){
35 if (!v.size())return 0;
36 int k=0,ans=0;
37 for(int i=29;i>=0;i--){
38 int p=((x&(1<<i))==0);
39 if (ch[p][k]<0)p^=1;
40 else ans+=(1<<i);
41 k=ch[p][k];
42 }
43 return ans;
44 }
45 int merge(int x){
46 add(x);
47 return query(x);
48 }
49 }T[N];
50 int find(int k){
51 if (k==f[k])return k;
52 return f[k]=find(f[k]);
53 }
54 int merge(int x,int y){
55 x=find(x),y=find(y);
56 assert(x!=y);
57 if (T[x].v.size()<T[y].v.size())swap(x,y);
58 f[y]=x;
59 int ans=0;
60 for(int i=0;i<T[y].v.size();i++)ans=max(ans,T[x].merge(T[y].v[i]));
61 T[y].init();
62 return ans;
63 }
64 void add(int x,int y,int z){
65 edge[E].nex=head[x];
66 edge[E].to=y;
67 edge[E].len=z;
68 head[x]=E++;
69 }
70 void dfs(int k,int fa,int s){
71 d[k]=s;
72 f[k]=fa;
73 for(int i=head[k];i!=-1;i=edge[i].nex)
74 if (edge[i].to!=fa)dfs(edge[i].to,k,s^edge[i].len);
75 }
76 void tot(int k,int fa){
77 now_mx=max(now_mx,T[0].merge(d[k]));
78 for(int i=head[k];i!=-1;i=edge[i].nex)
79 if (edge[i].to!=fa)tot(edge[i].to,k);
80 }
81 void calc(int k,int fa){
82 int si=T[k].merge(d[k]),so=mx;
83 if (vis[k]){
84 so=now_mx;
85 now_mx=max(now_mx,T[0].merge(d[k]));
86 for(int i=head[k];i!=-1;i=edge[i].nex)
87 if (!vis[edge[i].to])tot(edge[i].to,k);
88 }
89 for(int i=head[k];i!=-1;i=edge[i].nex)
90 if (edge[i].to!=fa){
91 calc(edge[i].to,k);
92 si=max(si,merge(k,edge[i].to));
93 }
94 if (fa)ans=max(ans,si+so);
95 }
96 int main(){
97 scanf("%d",&n);
98 memset(head,-1,sizeof(head));
99 for(int i=1;i<n;i++){
100 scanf("%d%d%d",&x,&y,&z);
101 add(x,y,z);
102 add(y,x,z);
103 }
104 dfs(1,0,0);
105 T[0].init();
106 for(int i=1;i<=n;i++)mx=max(mx,T[0].merge(d[i]));
107 for(int i=1;i<=n;i++)
108 if (T[0].query(d[i])==mx){
109 x=i;
110 break;
111 }
112 for(int i=1;i<=n;i++)
113 if ((d[x]^d[i])==mx){
114 y=i;
115 break;
116 }
117 dfs(x,0,0);
118 while (y){
119 vis[y]=1;
120 y=f[y];
121 }
122 for(int i=0;i<=n;i++)T[i].init();
123 for(int i=1;i<=n;i++)f[i]=i;
124 calc(x,0);
125 printf("%d",ans);
126 }

[luogu6702]Path的更多相关文章

  1. NodeJs之Path

    Path模块 NodeJs提供的Path模块,使得我们可以对文件路径进行简单的操作. API var path = require('path'); var path_str = '\\Users\\ ...

  2. 【原】实时渲染中常用的几种Rendering Path

    [原]实时渲染中常用的几种Rendering Path 本文转载请注明出处 —— polobymulberry-博客园 本文为我的图形学大作业的论文部分,介绍了一些Rendering Path,比较简 ...

  3. Node.js:path、url、querystring模块

    Path模块 该模块提供了对文件或目录路径处理的方法,使用require('path')引用. 1.获取文件路径最后部分basename 使用basename(path[,ext])方法来获取路径的最 ...

  4. VSCode调试go语言出现:exec: "gcc": executable file not found in %PATH%

    1.问题描述 由于安装VS15 Preview 5,搞的系统由重新安装一次:在用vscdoe编译go语言时,出现以下问题: # odbcexec: "gcc": executabl ...

  5. Leetcode 笔记 113 - Path Sum II

    题目链接:Path Sum II | LeetCode OJ Given a binary tree and a sum, find all root-to-leaf paths where each ...

  6. Leetcode 笔记 112 - Path Sum

    题目链接:Path Sum | LeetCode OJ Given a binary tree and a sum, determine if the tree has a root-to-leaf ...

  7. Thinking in Unity3D:渲染管线中的Rendering Path

      关于<Thinking in Unity3D> 笔者在研究和使用Unity3D的过程中,获得了一些Unity3D方面的信息,同时也感叹Unity3D设计之精妙.不得不说,笔者最近几年的 ...

  8. node之path模块

    node之path模块 原文链接 //引用该模块 var path = require("path"); 1.路径解析,得到规范化的路径格式 对window系统,目录分隔为'', ...

  9. Linux系统修改PATH环境变量方法

    在Linux安装一些软件通常要添加路径环境变量PATH.PATH环境变量通俗的讲就是把程序的路径"备案"到系统中,这样执行这些程序时就不需要输入完整路径,直接在bash输入程序名就 ...

随机推荐

  1. Linux文件系统与inode、Block笔记

    Linux文件系统与inode.Block笔记 在Linux下一切都是文件,无论是设备还是接口,亦或是网卡等均被抽象成了文件,并且有相关的内核代码进行调度.然而,在一切都是文件的前提下,最需要进行探讨 ...

  2. uoj21 缩进优化(整除分块,乱搞)

    题目大意: 给定一个长度为\(n\)的序列 让你找一个\(x\),使得\(ans\)尽可能小 其中$$ans=\sum_{i=1}^{n}\lfloor\frac{a_i}{x}\rfloor + \ ...

  3. C 字符串相关的库函数

    字符串操作函数 size_t strlen( char *string ); 返回字符串长度 char* strcpy( char *dst, char const *src ); 将src复制到ds ...

  4. IP包头结构

    版本号(Version): 长度4比特.标识目前采用的IP协议的版本号.一般的值为0100(IPv4),0110(IPv6) IP包头长度(Header Length): 长度4比特.这个字段的作用是 ...

  5. Visual Studio Debug only user code with Just My Code

    Debug only user code with Just My Code By default, the debugger skips over non-user code (if you wan ...

  6. CSS绘制三角的小技巧

    网页中常见一些三角形,使用css直接画出来就可以,不必做成图片或者字体图标当把一个盒子的高和宽的长度都设置为0,并且分别指定边框样式时,就会得到以下图形: 受此启发,可以知道三角是如何制作的(想要保留 ...

  7. Java泛型背后是什么?

    文Java中泛型的应用,让大家更好地理解泛型,以及常说的泛型类型擦除是什么概念,举一个简单的例子,如下: 这里可以看出来在代码编写阶段就已经报错了,不能往string类型的集合中添加int类型的数据. ...

  8. 【UE4 设计模式】观察者模式 Observer Pattern

    概述 描述 定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新.观察者模式又叫做 发布-订阅(Publish/Subscribe)模式 模型-视图(M ...

  9. Java:String对象小记

    Java:String对象小记 对 Java 中的 String 对象,做一个微不足道的小小小小记 字节和字符的区别 字节 byte: 一个字节包含8个位(bit),因此byte的取值范围为-128~ ...

  10. Ruby on Rails 单元测试

    Ruby on Rails 单元测试 为什么要写测试文件? 软件开发中,一个重要的环节就是编写测试文件,对代码进行单元测试,确保程序各部分功能执行正确.但是,这一环节很容易被我们轻视,认为进行单元测试 ...