题目大意:给你一棵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. smrtlink

    SMRT Link is the web-based end-to-end workflow manager for the Sequel™ System. It includes software ...

  2. 【c3p0】 C3P0的三种配置方式以及基本配置项详解

    数据库连接池C3P0框架是个非常优异的开源jar,高性能的管理着数据源,这里只讨论程序本身负责数据源,不讨论容器管理. ---------------------------------------- ...

  3. dbutils封装对象,单列,一行一列(用)

    基本用法:查找并封装对象与对象集合 public User findUserByNamePassword(String name,String password){ QueryRunner runne ...

  4. Check time of different search methods

    https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...

  5. 2018.09.26 bzoj5221: [Lydsy2017省队十连测]偏题(数学推导+矩阵快速幂)

    传送门 由于没有考虑n<=1的情况T了很久啊. 这题很有意思啊. 考试的时候根本不会,骗了30分走人. 实际上变一个形就可以了. 推导过程有点繁杂. 直接粘题解上的请谅解. 不得不说这个推导很妙 ...

  6. Java synchronized关键字的理解

    转载自:http://blog.csdn.net/xiao__gui/article/details/8188833 在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环 ...

  7. Java static说明

    class Person{ String name;//成员变量,实例变量 static String country = "CN";//静态变量.类变量 public void ...

  8. DVWA

    DVWA默认的用户有5个,用户名密码如下(一个足以): admin/password gordonb/abc123 1337/charley pablo/letmein smithy/password

  9. 保留注释换行的python模块configparser

    python语言用来解析配置文件的模块是ConfigParser,python3中是configparser模块,我在使用中发现write方法在将配置项重新写入文 件时,配置文件中的空行和注释行都会被 ...

  10. (连通图 模板题 无向图求割点)Network --UVA--315(POJ--1144)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...