【xsy1122】 路径 点分治+trie
题目大意:给你一棵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的更多相关文章
- 【Tsinsen-A1486】树(王康宁) 点分治 + Trie
A1486. 树(王康宁) 时间限制:1.0s 内存限制:512.0MB 总提交次数:455 AC次数:97 平均分:52.62 查看未格式化的试题 提交 试题讨论 试题来源 ...
- 【BZOJ-3784】树上的路径 点分治 + ST + 堆
3784: 树上的路径 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 462 Solved: 153[Submit][Status][Discuss ...
- BZOJ 3697: 采药人的路径 [点分治] [我想上化学课]
传送门 题意: 路径有$-1,1$两种权值,求有多少路径满足权值和为$0$且有一个点将路径分成权值和为$0$的两段 第四节课本来想去上化学,然后快上课了这道题还没调出来.....可恶我想上化学 昨天两 ...
- Codeforces 888G(分治+trie)
按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...
- 【BZOJ3697】采药人的路径 点分治
[BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...
- BZOJ.3784.树上的路径(点分治 贪心 堆)
BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...
- BZOJ3697采药人的路径——点分治
题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...
- BZOJ3697:采药人的路径(点分治)
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...
- 【BZOJ3784】树上的路径 点分治序+ST表
[BZOJ3784]树上的路径 Description 给定一个N个结点的树,结点用正整数1..N编号.每条边有一个正整数权值.用d(a,b)表示从结点a到结点b路边上经过边的权值.其中要求a< ...
随机推荐
- java中配置自定义拦截器中exclude-mapping path是什么意思?
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/>//过滤全部请求 & ...
- 2018.09.28 bzoj3688: 折线统计(dp+树状数组)
传送门 简单树状数组优化dp. 注意到k很小提示我们搜(d)(d)(d)索(p)(p)(p). 先按第一维排序. 用f[i][j][0/1]f[i][j][0/1]f[i][j][0/1]表示第i个点 ...
- Linux 系统中进程5中常见状态
运行.中断.不可终端.僵死.停止 R(运行):正在运行 or 在运行队列中等待: S(中断):处于休眠中,等待接收信号,并脱离改状态: D(不可中断):不响应信号输入,即使kill也不起作用: Z(僵 ...
- 挂载镜像SD卡的FAT32文件系统分区到Linux中
首先使用fdisk –l命令查看sd卡的分区息 可以看到,sd卡有三个分区,第一个分区是FAT32系统,主要存放内核img文件和dtb文件,第二个分区是Linux系统分区,第三个分区格式未知,实际是U ...
- hdu 4956
http://acm.hdu.edu.cn/showproblem.php?pid=4956 首先给出一个范围 [l, r],问能否从中找到一个数证明 Hanamichi's solution 的解法 ...
- nodejs async
官网:https://github.com/caolan/async 流程控制:简化十种常见流程的处理集合处理:如何使用异步操作处理集合中的数据工具类:几个常用的工具类 流程控制 详细说明:http: ...
- 无限存储之胖文本数据库TTD(Thick Text Database)
无限存储之胖文本数据库TTD(Thick Text Database) 阅读: 评论: 作者:Rybby 日期: 来源:rybby.com 所谓的“胖”就是多.大.丰富的意思,像我们平时看到的 ...
- 简便方法搞定第三方SDK的Jar包在DelphiXE5中的引入
简便方法搞定第三方SDK的Jar包在DelphiXE5中的引入 (2014-02-21 17:30:17) 转载▼ 标签: android delphi xe5 jar sdk 分类: 编程杂集 折腾 ...
- WPF核心对象模型-类图和解析
DispatcherObject是根基类,通过继承该类,可以得到访问创建该对象的UI线程的Dispatcher对象的能力.通过Dispatcher对象,可以将代码段合并入该UI线程执行. Depend ...
- 拒绝“高冷”词汇!初学C#中实用的泛型!
初学C#,整天对着业务逻辑,写反反复复的“过程型”代码逻辑十分枯燥,不如用点新东西提升一下代码效率,让代码看起来更有逼格?! 好,下面我们看看C#中简单易学的泛型. 首先,我写了一个这样的方法 --- ...