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个节点的树,每个点 ...
随机推荐
- 2017php经典面试题
1.PHP语言的一大优势是跨平台,什么是跨平台?一.PHP基础: PHP的运行环境最优搭配为Apache+MySQL+PHP,此运行环境可以在不同操作系统(例如windows.Linux等)上配置,不 ...
- SQL 2
SQL SELECT 语句 SELECT 语句用于从数据库中选取数据. SQL SELECT 语句 SELECT 语句用于从数据库中选取数据. 结果被存储在一个结果表中,称为结果集. SQL SELE ...
- [vue]v-bind: sytle/class-bind&属性值绑定
v-bind - style绑定 - class绑定 - 属性值绑定 <!DOCTYPE html> <html lang="en"> <head&g ...
- Sublime text 3搭建Python-Anaconda开发环境
网络上的教程各种各样,大同小异.自己安装时还是出了些问题,因此总结一篇博文. Sublime Text 是一款轻量级跨平台的文本编辑器,可通过包(Package)扩充自身功能. 有很多搭建python ...
- 《Enhanced LSTM for Natural Language Inference》(自然语言推理)
解决的问题 自然语言推理,判断a是否可以推理出b.简单讲就是判断2个句子ab是否有相同的含义. 方法 我们的自然语言推理网络由以下部分组成:输入编码(Input Encoding ),局部推理模型(L ...
- BP神经网络的Java实现(转)
http://fantasticinblur.iteye.com/blog/1465497 课程作业要求实现一个BPNN.这次尝试使用Java实现了一个.现共享之.版权属于大家.关于BPNN的原理,就 ...
- KM算法模板
大白书P248有证明,此处贴出两种复杂度的方案, n^4 大白书P350 n^3 #include <algorithm> #include <string.h> #inclu ...
- Python: 正则表达式匹配反斜杠 "\"
Python正则表达式匹配反斜杠 "\" eg: >>>a='w\w\w' 'w\\w\\w' # 打印出来的 "\\" 被转义成 一个反斜 ...
- Linux基础命令---resizefs
resize2fs 调整ext2\ext3\ext4文件系统的大小,它可以放大或者缩小没有挂载的文件系统的大小.如果文件系统已经挂载,它可以扩大文件系统的大小,前提是内核支持在线调整大小. size参 ...
- MockWebServer--环境
MockWebServer是一个可脚本化的用于测试HTTP客户端的Web服务器.主要用于测试你的应用在进行HTTP.HTTPS请求时是否按照预期的行为动作.使用该工具,你可以验证应用的请求是否符合预期 ...