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个节点的树,每个点 ...
随机推荐
- MYSQL中的BlackHole引擎
MYSQL中的BlackHole引擎 http://blog.csdn.net/ylspirit/article/details/7234021 http://blog.chinaunix.net/u ...
- SQL死锁知识及解决办法
[翻译]:SQL死锁-死锁排除 min.jiang 2014-03-18 00:23 阅读:874 评论:1 项目中死锁的解决经历 min.jiang 2014-03-17 01:09 阅读: ...
- 小希的迷宫(hdu1272 并查集)
http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=259#problem/D Description 上次Gardon的迷宫城堡小希 ...
- 部署 Flask 应用时,为什么会需要 gunicorn 或 uWSGI?
Flask自带的wsgi性能低下 只适合你开发调试的时候用, 线上你必须用Gunicorn+Nginx才能获得更强的性能,和更高的安全性
- python 的math模块
数学模块用法:import math# 或 from math import * 变量 描述 math.e 自然对数的底e math.pi 圆周率pi 函数名 描述 math.ceil(x) 对x向上 ...
- addEventListener的click和onclick的区别
前两节都和addEventListener的click有关,于是在想它与onclick有什么区别呢,自己调试了一下,网上也有相关资料 事件绑定 onclick绑定方式 优点: - 简洁 - 处理事件的 ...
- WiFi攻击的三种方式
WiFi的安全问题已经引起了不少的使用者重视,甚至已经出现草木皆兵的现象.那么黑客到底是如何做到绕过身份验证来获取WiFi使用权的呢?主要有以下三种方式,其中最后一种方式十分简单. WiFi的安全问题 ...
- Python之路----迭代器与生成器
一.迭代器 L=[1,,2,3,4,5,] 取值:索引.循环for 循环for的取值:list列表 dic字典 str字符串 tuple元组 set f=open()句柄 range() enumer ...
- SQL学习之Can't connect to MySQL server on localhost (10061)
最近升级 了系统,开机后连接MySQL报错,Can't connect to MySQL server on localhost (10061): 估计是升级系统清除了以前的缓存设置,网上很多方法是命 ...
- SACD ISO镜像中提取DSDIFF(DFF)、DSF文件
听语音 | 浏览:5620 | 更新:2015-08-25 11:46 | 标签:硬件 1 2 3 4 5 分步阅读 现在有一种比较流行的无损音乐传输介质是SACD ...