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个节点的树,每个点 ...
随机推荐
- vue.js常用的
<input v-model.number="age" type="number"> //自动将用户的输入值转为数值类型 <input v-m ...
- 万恶之源 - Python运算符与编码
格式化输出 现在有个需要我们录入我们身边好友的信息,格式如下: ------------ info of Alex Li ---------- Name : Alex Li Age : 22 job ...
- Java-使用IO流对大文件进行分割和分割后的合并
有的时候我们想要操作的文件很大,比如:我们想要上传一个大文件,但是收到上传文件大小的限制,无法上传,这是我们可以将一个大的文件分割成若干个小文件进行操作,然后再把小文件还原成源文件.分割后的每个小文件 ...
- 在Keras模型中one-hot编码,Embedding层,使用预训练的词向量/处理图片
最近看了吴恩达老师的深度学习课程,又看了python深度学习这本书,对深度学习有了大概的了解,但是在实战的时候, 还是会有一些细枝末节没有完全弄懂,这篇文章就用来总结一下用keras实现深度学习算法的 ...
- numpy的ravel()和flatten()函数
相同点: 两者所要实现的功能是一致的(将多维数组降位一维).这点从两个单词的意也可以看出来,ravel(散开,解开),flatten(变平). In [14]: x=np.array([[1,2],[ ...
- 7.12 Models -- Frequently Asked Questions
一.Should I use a query or a filter to seach records?我应该使用一个查询或者过滤器来搜索记录吗? 这取决于你想要搜索多少reocrds并且它们是否被加 ...
- pandas练习(二)------ 数据过滤与排序
数据过滤与排序------探索2012欧洲杯数据 相关数据见(github) 步骤1 - 导入pandas库 import pandas as pd 步骤2 - 数据集 path2 = ". ...
- Linux命令: 结束命令
1)ctrl+c,退出命令 2)q,退出文件
- C/C++之单例模式实现
/*** * 保证一个类仅有一个实例,并提供一个访问它的全局访问点 */ #include <iostream> #include <string> using namespa ...
- ubuntu服务器安装FTP服务
目录 ubuntu服务器安装FTP服务 一.实验环境 二.安装配置FTP 下载ftp 配置环境 新建用户 ubuntu服务器安装FTP服务 参考教程 [ubuntu16.04搭建ftp服务器 一.实验 ...