SPOJ375.QTREE树链剖分
题意:一个树,a b c 代表a--b边的权值为c。CHANGE x y 把输入的第x条边的权值改为y,QUERY x y 查询x--y路径上边的权值的最大值。
第一次写树链剖分,其实树链剖分只能说是一种思想。树链剖分 就是 先选择从根节点到叶子节点的最长的路径的权值对应到线段树上,然后从一个子树的根节点到叶子的最长路径的权值对应到线段树上这样直到把所有的点都处理了,然后就是线段树区间查询最值了。
具体可以看这个博客。http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
const int maxn = 1e4+;
int top[maxn],fa[maxn],son[maxn],dep[maxn],siz[maxn],seg_tree[maxn<<],head[maxn],pos[maxn];
int edge,tot;
struct
{
int to,next;
}e[maxn<<];
void add(int x,int y)
{
e[edge].to = y;
e[edge].next = head[x];
head[x] = edge++;
} void dfs(int r)
{
siz[r] = ;
son[r] = ;
for (int i = head[r]; i > ; i = e[i].next)
if (fa[r] != e[i].to)
{
dep[e[i].to] = dep[r] + ;
fa[e[i].to] = r;
dfs(e[i].to);
if (siz[e[i].to] > siz[son[r]])
son[r] = e[i].to;
siz[r] += siz[e[i].to];
}
} void build(int r,int f)
{
pos[r] = tot++;
top[r] = f;
if (son[r] > )
build(son[r],top[r]);
for (int i = head[r]; i > ; i = e[i].next)
{
if (fa[r] != e[i].to && son[r] != e[i].to)
build(e[i].to,e[i].to);
}
} void update(int l,int r,int o,int x,int v)
{
if (l == r)
{
seg_tree[o] = v;
return;
}
int mid = (l + r) >> ;
if (x <= mid)
update(l,mid,o<<,x,v);
if (x > mid)
update(mid+,r,o<<|,x,v);
seg_tree[o] = max(seg_tree[o<<],seg_tree[o<<|]);
} int query(int l,int r,int o,int ua,int ub)
{
if (ua <= l && ub >= r)
return seg_tree[o];
int mid = (l + r) >> ;
int t1,t2;
t1 = t2 = ;
if (ua <= mid)
t1 = query(l,mid,o<<,ua,ub);
if (ub > mid)
t2 = query(mid+,r,o<<|,ua,ub);
return max(t1,t2);
} int get_max(int ua,int ub)
{
int f1 = top[ua];
int f2 = top[ub];
int tmp = ;
while (f1 != f2)
{
if (dep[f1] < dep[f2])
swap(f1,f2),swap(ua,ub);
tmp = max(tmp,query(,tot,,pos[f1],pos[ua]));
ua = fa[f1],f1 = top[ua];
}
if (ua == ub)
return tmp;
if (dep[ua] > dep[ub])
swap(ua,ub);
tmp = max(tmp,query(,tot,,pos[son[ua]],pos[ub]));
return tmp;
} int d[maxn][];
void init()
{
int n;
scanf ("%d",&n);
memset(dep,,sizeof(dep));
memset(son,,sizeof(son));
memset(head,,sizeof(head));
memset(fa,,sizeof(fa));
memset(top,,sizeof(top));
int root = (n+)>>;
fa[root] = dep[root] =;
tot = edge = ;
int a,b,c;
for (int i = ; i < n; i++)
{
scanf ("%d%d%d",&a,&b,&c);
add(a,b),add(b,a);
d[i][] = a,d[i][] = b,d[i][] = c;
}
dfs(root);
build(root,root);
tot--;
for (int i = ; i < n; i++)
{
if (dep[d[i][]] < dep[d[i][]])
swap(d[i][],d[i][]);
update(,tot,,pos[d[i][]],d[i][]);
} }
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int t;
scanf ("%d",&t);
while (t--)
{
init();
char op[];
while (scanf ("%s",op),op[] != 'D')
{
int x,y;
scanf ("%d%d",&x,&y);
if (op[] == 'C')
update(,tot,,pos[d[x][]],y);
if (op[] == 'Q')
printf("%d\n",get_max(x,y));
}
}
return ;
}
SPOJ375.QTREE树链剖分的更多相关文章
- QTREE 树链剖分---模板 spoj QTREE
<树链剖分及其应用> 一文讲得非常清楚,我一早上就把他学会了并且A了这题的入门题. spoj QTREE 题目: 给出一棵树,有两种操作: 1.修改一条边的边权. 2.询问节点a到b的最大 ...
- SPOJ QTREE 树链剖分
树链剖分的第一题,易懂,注意这里是边. #include<queue> #include<stack> #include<cmath> #include<cs ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- 【学术篇】SPOJ QTREE 树链剖分
发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能 ...
- Cogs 1672. [SPOJ375 QTREE]难存的情缘 LCT,树链剖分,填坑计划
题目:http://cojs.tk/cogs/problem/problem.php?pid=1672 1672. [SPOJ375 QTREE]难存的情缘 ★★★☆ 输入文件:qtree.in ...
- [SPOJ375]QTREE - Query on a tree【树链剖分】
题目描述 给你一棵树,两种操作. 修改边权,查找边权的最大值. 分析 我们都知道,树链剖分能够维护点权. 而且每一条边只有一个,且唯一对应一个儿子节点,那么就把信息放到这个儿子节点上. 注意,lca的 ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- 树链剖分边权模板spoj375
树链剖分是树分解成多条链来解决树上两点之间的路径上的问题 如何求出树链:第一次dfs求出树上每个结点的大小和深度和最大的儿子,第二次dfs就能将最大的儿子串起来并hash(映射)到线段树上(或者其他数 ...
- 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 ...
随机推荐
- 形形色色的软件生命周期模型(4)——MSF、实用型
摘要: 读大学时,我们曾经学习过不少软件生命周期模型,当时还不是很懂软件开发,你可能会觉得这些东西很新奇.在实际工作中,你会发现这些模型其实很难应用,与此同时你会接触到RUP.MSF等权威软件公司的生 ...
- erlang mnesia 数据库查询
Mnesia是一个分布式数据库管理系统,适合于电信和其它需要持续运行和具备软实时特性的Erlang应用,越来越受关注和使用,但是目前Mnesia资料却不多,很多都只有官方的用户指南.下面的内容将着重说 ...
- android 初学: 提示No Launcher activity found!
提示No Launcher activity found! 三步检查: 1 必须有 <category android:name="android.intent.category.LA ...
- nginx本地的测试环境添加SSL
要在本地添加SSL,首先要做的是防火墙是不是放开了443端口,同时,在nginx安装时是不是支持了ssl模块,这个安装网上很容易找到相关资料 防火墙,个人还是用iptables比较直观 先将selin ...
- iOS 捕获系统外异常
iOS 捕获系统外异常 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太 ...
- Duanxx的技术问题:word界面显示模糊
今天打开word时,出现了word打开失败的现象,并且word的界面显示特别的模糊,找了好半天,才解决,问题见下图: 解决方式: 在word的文件->选项,这里面找到显示,然后勾选:禁用硬件图形 ...
- using namespace cocos2d;
忘记在头文件添加using namespace cocos2d; 导致一直出现问题,定义的精灵却一直报错. error C2143: 语法错误 : 缺少“;”(在“*”的前面)
- LSI SAS 2308配置操作
介绍LSISAS2308的配置操作 3.1 登录CU界面 介绍登录LSISAS2308的CU配置界面的方法. 3.2 创建RAID 介绍在LSISAS2308扣卡上创建RAID的操作方法. 3.3 配 ...
- Abstract-抽象类
本人理论较差,之前会做却不明原因,最近在改别人的代码发现实现方式完全不同,但对于我这个理论白痴来说完全不知道为什么别人要这么写,好处在哪里. 没有理论的指导,会用也只是不断的Copy前人,永远无法让程 ...
- 从Ueditor跨域上传,总结的一次跨域上传的爬坑经历
项目内其中一个管理后台需要发布文章,需要一个富文本编辑器,经过一番选择后,最终选择了百度的Ueditor. 由于上传的文件是上传到另一台专门存放图片等静态资源的服务器上面的,所以就涉及到了跨域上传. ...