SPOJ 375 Query on a tree(树链剖分)
https://vjudge.net/problem/SPOJ-QTREE
题意:
给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值。
思路:
树链剖分的模板题。
树链剖分简单来说,就是把树分成多条链,然后再将这些链映射到数据结构上处理(线段树,树状数组等等)。
具体的话可以看看这个http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=+; int n;
int tot;
int pos;
int head[maxn];
int dep[maxn]; //节点在树上的深度
int top[maxn]; //节点所在重链的顶端节点
int num[maxn]; //节点的子节点数
int fa[maxn]; //父亲结点
int p[maxn]; //节点与其父亲结点在线段树中的位置
int fp[maxn]; //和p数组相反
int son[maxn]; //节点的重儿子
int e[maxn][]; struct node
{
int v,next;
}edge[*maxn]; void addEdge(int u, int v)
{
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
} //求出重儿子等等
void dfs(int u, int pre, int d)
{
dep[u]=d;
son[u]=-;
num[u]=;
fa[u]=pre;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre) continue;
dfs(v,u,d+);
num[u]+=num[v];
if(son[u]==- || num[son[u]]<num[v]) //找到子节点最多的作为重儿子
son[u]=v;
}
} //处理top值以及在线段树上的位置
void getpos(int u, int sp)
{
top[u]=sp;
if(son[u]!=-) //先处理重儿子
{
p[u]=pos++; //保证了一条链上的顶点在线段树上连续
fp[p[u]]=u;
getpos(son[u],sp);
}
else //到了叶子节点就不再往下处理
{
p[u]=pos++;
fp[p[u]]=u;
return;
}
for(int i=head[u];i!=-;i=edge[i].next) //处理其他顶点
{
int v=edge[i].v;
if(v==son[u] || v==fa[u]) continue;
getpos(v,v);
}
} int val[maxn<<];
int MAX[maxn<<]; void PushUp(int o)
{
MAX[o]=max(MAX[o<<],MAX[o<<|]);
} void build(int l, int r, int o)
{
if(l==r)
{
MAX[o]=val[l];
return;
}
int mid=(l+r)>>;
build(l,mid,o<<);
build(mid+,r,o<<|);
PushUp(o);
} void update(int pos, int x, int l, int r, int o)
{
if(l==r) {MAX[o]=x;return;}
int mid=(l+r)>>;
if(pos<=mid) update(pos,x,l,mid,o<<);
else update(pos,x,mid+,r,o<<|);
PushUp(o);
} int query(int ql, int qr, int l, int r, int o)
{
if(ql<=l && qr>= r) return MAX[o];
int mid=(l+r)>>;
int res=;
if(ql<=mid) res=max(res,query(ql,qr,l,mid,o<<));
if(qr>mid) res=max(res,query(ql,qr,mid+,r,o<<|));
return res;
} int lca(int x, int y)
{
int ans=;
while(top[x]!=top[y]) //不在一条链上时
{
if(dep[top[x]]<dep[top[y]]) swap(x,y); //从深度较深的开始
ans=max(ans,query(p[top[x]],p[x],,n,));
x=fa[top[x]]; //x所在链的顶点的父节点,转到另一条链上
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) ans=max(ans,query(p[son[x]],p[y],,n,));
return ans;
} int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
tot=;
memset(head,-,sizeof(head));
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d%d",&e[i][],&e[i][],&e[i][]);
addEdge(e[i][],e[i][]);
addEdge(e[i][],e[i][]);
}
dfs(,,);
pos=;
getpos(,);
for(int i=;i<n;i++)
{
if(dep[e[i][]]<dep[e[i][]]) swap(e[i][],e[i][]);
val[p[e[i][]]]=e[i][];
}
build(,n,);
char s[]; int u,v;
while(scanf("%s",s))
{
if(s[]=='D') break;
scanf("%d%d",&u,&v);
if(s[]=='Q') printf("%d\n",lca(u,v));
else update(p[e[u][]],v,,n,);
}
}
return ;
}
SPOJ 375 Query on a tree(树链剖分)的更多相关文章
- spoj 375 Query on a tree (树链剖分)
Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges ...
- SPOJ 375 Query on a tree 树链剖分模板
第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...
- SPOJ QTREE Query on a tree 树链剖分+线段树
题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- SPOJ QTREE Query on a tree ——树链剖分 线段树
[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...
- SPOJ QTREE Query on a tree --树链剖分
题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...
- spoj 375 QTREE - Query on a tree 树链剖分
题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #includ ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...
随机推荐
- ffmpeg综合应用示例(三)——安卓手机摄像头编码
本文的示例将实现:读取安卓手机摄像头数据并使用H.264编码格式实时编码保存为flv文件.示例包含了 1.编译适用于安卓平台的ffmpeg库 2.在java中通过JNI使用ffmpeg 3.读取安卓摄 ...
- [py][mx]django课程模型
课程模型分析 分3个表 先设计课程表, 这是1 在设计lesson表,添加一个外键,course. 课程 1 course 章节 n lesson 视频 n video 资源 n coursereso ...
- 百度编辑器UEditor源码模式下过滤div/style等html标签
UEditor在html代码模式下,当输入带有<div style="">.<iframe>这类带有html标签的内容时,切换为编辑器模式后,会发现输入的内 ...
- php array_rand()函数从数组中随机选择一个或多个元素
php使用array_rand()函数从数组中随机选择一个或多个元素的方法. 使用array_rand() 函数从数组中随机选出一个或多个元素,并返回. array_rand(array,numbe ...
- Postman使用js获取日期
在用postman进行接口自动化测试的时候,某个查询接口需要使用到日期参数进行请求: 假设当前日期为2018-05-07 10:30:20 ,需要传的日期为: beginTime:2018-05-01 ...
- Echarts使用及动态加载图表数据 折线图X轴数据动态加载
Echarts简介 echarts,缩写来自Enterprise Charts,商业级数据图表,一个纯JavaScript的图表库,来自百度...我想应该够简洁了 使用Echarts 目前,就官网的文 ...
- Ignite初探
Guava是一个很方便的本地缓存工具,但是在多节点处理的过程中,本地缓存无法满足数据一致性的问题.分布式缓存Ignite很好的解决了数据一致性,可靠性,事务性等方面的问题. Ignite支持分区方式和 ...
- Filter过滤器与Session会话跟踪技术
Filter过滤器 适用场景 1.为web应用程序的新功能建立模型(可被添加到web应用程序中或者从web应用程序中删除而不需要重写基层应用程序代码)2.用户授权Filter:负责检查用户请求,根据请 ...
- postman接口测试——笔记
接口测试理论: 一.接口 1.程序内部接口:方法与方法之间,模块与模块之间的交互,程序内部抛出的接口,比如bbs系统,有登录模块,发帖模块等等,那你要发帖就必须先登录,那么这两个模块就得有交互,它 ...
- (一)github之基础概念篇
1.github: 一项为开发者提供git仓库的托管服务, 开发者间共享代码的场所.github上公开的软件源代码全都由git进行管理. 2.git: 开发者将源代码存入名为git仓库的资料库中,而g ...