题目大意:给你一棵n个点的树,树边上有边权,对于每一个点,你要求出经过该点的所有的路径中,路径异或和最大的值。

数据范围:$n≤10^5$,边权$≤10^9$。

我们考虑枚举每一条路径,显然这个是会T的,于是我们用点分治来实现这个过程。

对于一棵以$x$为根的子树,假设它有$k$个儿子,编号$v1....k$。

我们维护一棵$trie$树,记录所有从根到以$v1,v2.....vp$为跟的子树中的路径长度。

对于从跟到第$p+1$个儿子为跟的树中的每一条路径,我们都丢到$trie$树中查询与最大的异或值。

在查询最大值的过程中,我们维护一个$max_i$,表示从根到i的路径上的最大路径异或和。我们可以通过简单的标记上传去实现更新。

然后再将所有终点在$p+1$个子树中的路径加入到$trie$树种。

时间复杂度:$O(n\ log\ n\ log\ v)$。

 #include<bits/stdc++.h>
#define M 100005
#define INF ((1<<31)-1)
using namespace std; struct edge{int u,v,next;}e[M*]={}; int head[M]={},Use=;
void add(int x,int y,int z){Use++;e[Use].u=y;e[Use].v=z;e[Use].next=head[x];head[x]=Use;} int use=;
struct trie{int a[];}a[M*]={};
void add(int x){
int now=;
for(int i=;~i;i--){
bool k=(<<i)&x;
if(a[now].a[k]) now=a[now].a[k];
else a[now].a[k]=++use,a[use].a[]=a[use].a[]=,now=use;
}
}
int query(int x){
int now=,res=;
for(int i=;~i;i--){
bool k=(<<i)&x;
if(a[now].a[k^]) now=a[now].a[k^],res+=(<<i);
else now=a[now].a[k];
}
return res;
} int siz[M]={},vis[M]={};
int minn=INF,minid=;
void dfssiz(int x,int fa){
siz[x]=;
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa&&vis[e[i].u]==)
dfssiz(e[i].u,x),siz[x]+=siz[e[i].u];
}
void dfsmax(int x,int fa,int fsiz){
int maxn=fsiz-siz[x];
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa&&vis[e[i].u]==){
dfsmax(e[i].u,x,fsiz);
maxn=max(maxn,siz[e[i].u]);
}
if(maxn<minn) minn=maxn,minid=x;
}
int makeroot(int x){
dfssiz(x,);
minn=INF; minid=;
dfsmax(x,,siz[x]);
return minid;
} int ans[M]={},now[M]={};
void upans(int x,int fa,int Val){
int hh=query(Val);
now[x]=hh;
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa&&vis[e[i].u]==){
upans(e[i].u,x,Val^e[i].v);
now[x]=max(now[x],now[e[i].u]);
}
ans[x]=max(ans[x],now[x]);
}
void addtrie(int x,int fa,int Val){
add(Val);
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa&&vis[e[i].u]==){
addtrie(e[i].u,x,Val^e[i].v);
}
} stack<int> s;
void dfs(int x){
x=makeroot(x); vis[x]=; a[].a[]=a[].a[]=; use=;
add();
for(int i=head[x];i;i=e[i].next) if(vis[e[i].u]==){
upans(e[i].u,x,e[i].v);
ans[x]=max(ans[x],now[e[i].u]);
addtrie(e[i].u,x,e[i].v);
s.push(i);
} a[].a[]=a[].a[]=; use=;
add();
while(!s.empty()){
int i=s.top(); s.pop();
upans(e[i].u,x,e[i].v);
ans[x]=max(ans[x],now[e[i].u]);
addtrie(e[i].u,x,e[i].v);
} for(int i=head[x];i;i=e[i].next) if(vis[e[i].u]==)
dfs(e[i].u);
} int main(){
int n; scanf("%d",&n);
for(int i=;i<n;i++){
int x,y,z; scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
dfs();
for(int i=;i<=n;i++) printf("%d\n",ans[i]);
}

【xsy1122】 路径 点分治+trie的更多相关文章

  1. 【Tsinsen-A1486】树(王康宁) 点分治 + Trie

    A1486. 树(王康宁) 时间限制:1.0s   内存限制:512.0MB   总提交次数:455   AC次数:97   平均分:52.62 查看未格式化的试题   提交   试题讨论 试题来源 ...

  2. 【BZOJ-3784】树上的路径 点分治 + ST + 堆

    3784: 树上的路径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 462  Solved: 153[Submit][Status][Discuss ...

  3. BZOJ 3697: 采药人的路径 [点分治] [我想上化学课]

    传送门 题意: 路径有$-1,1$两种权值,求有多少路径满足权值和为$0$且有一个点将路径分成权值和为$0$的两段 第四节课本来想去上化学,然后快上课了这道题还没调出来.....可恶我想上化学 昨天两 ...

  4. Codeforces 888G(分治+trie)

    按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...

  5. 【BZOJ3697】采药人的路径 点分治

    [BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...

  6. BZOJ.3784.树上的路径(点分治 贪心 堆)

    BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...

  7. BZOJ3697采药人的路径——点分治

    题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...

  8. BZOJ3697:采药人的路径(点分治)

    Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...

  9. 【BZOJ3784】树上的路径 点分治序+ST表

    [BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...

随机推荐

  1. apk签名方法

    生成签名文件: 1.右击项目管理器 选择 Export...  菜单: 2.在弹出的Export窗口中选择 Android->Export Android Application 后 next: ...

  2. IT 技术网站收集

    ## 脚本之家 http://www.jb51.net/ ## 菜鸟教程 http://www.runoob.com/ ## 编程中国 https://www.bccn.net/ ##

  3. 使用ntpdate校正linux系统的时间

    当Linux服务器的时间不对的时候,可以使用ntpdate工具来校正时间. 安装:yum install ntpdate ntpdate简单用法: # ntpdate ip # ntpdate 210 ...

  4. 如何使用 Visual C# 2005 或 Visual C# .NET 向 Excel 工作簿传输数据

    本文分步介绍了多种从 Microsoft Visual C# 2005 或 Microsoft Visual C# .NET 程序向 Microsoft Excel 2002 传输数据的方法.本文还提 ...

  5. Python中的replace方法

    replace 方法:返回根据正则表达式进行文字替换后的字符串的复制. stringObj.replace(rgExp, replaceText) 参数 stringObj必选项.要执行该替换的 St ...

  6. 批量远程执行shell命令工具

    使用示例(使用了默认用户root,和默认端口号22): ./mooon_ssh --h=192.168.4.1,192.168.4.2 -P=password -c='cat /etc/hosts' ...

  7. 201709015工作日记--上下文的理解,ASM

    1.Android上下文理解 Android上下文对象,在Context中封装一个所谓的“语境”,Activity.Service.Application都继承自Context,所以在这三者创建时都会 ...

  8. (线段树)Mayor's posters --poj -- 2528

    链接: http://poj.org/problem?id=2528 覆盖问题, 要从后往前找, 如果已经被覆盖就不能再覆盖了,否则就可以覆盖 递归呀递归什么时候我才能吃透你 代码: #include ...

  9. 基于Maven的S2SH(Struts2+Spring+Hibernate)框架搭建

    1. 前言 基于Maven的开发方式开发项目已经成为主流.Maven能很好的对项目的层次及依赖关系进行管理.方便的解决大型项目中复杂的依赖关系.S2SH(Struts2+Spring+Hibernat ...

  10. C++显式转换

    标准C++包含一个显式的转换语法: --static_cast:用于“良性”和“适度良性”的转换,包括不用强制转换 --const_cast:用于“const”和/或“volatile”进行转换 -- ...