QTREE - Query on a tree

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.

We will ask you to perfrom some instructions of the following form:

  • CHANGE i ti : change the cost of the i-th edge to ti
    or
  • QUERY a b : ask for the maximum edge cost on the path from node a to node b

Input

The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.

For each test case:

  • In the first line there is an integer N (N <= 10000),
  • In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 1000000),
  • The next lines contain instructions "CHANGE i ti" or "QUERY a b",
  • The end of each test case is signified by the string "DONE".

There is one blank line between successive tests.

Output

For each "QUERY" operation, write one integer representing its result.

Example

Input:
1 3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE Output:
1
3 传送门
一句话题意:给出一棵树,要求在树上:
  1)更新某个节点的值
  2)求两个节点间最短路径上的最大值 模板题,数据结构解析详见代码。
 #include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define clr(a) memset(a,0,sizeof(a));
#define foru(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
const int N=;
struct edge{int to,nxt;}e[N*];
int t[N],a[N][],d[N],id[N],head[N],f[N],siz[N],son[N],top[N];
//f[v] 节点v的父节点编号
//id[v] 节点v的父边在线段树中的编号
//siz[v] 以节点v为根的数中的节点数
//son[v] 节点v的子节点中siz[]最大的节点编号
//top[v] 节点v所在重链的顶端节点编号
//d[v] 节点v的深度
int ne,cnt,n; void add(int a,int b){
e[++ne]=(edge){b,head[a]};head[a]=ne;
} /////////////////////////////树剖//////////////////////////////////// void dfs(int k,int fa,int dep){//统计f[] siz[] son[] d[]
f[k]=fa;d[k]=dep;siz[k]=;son[k]=;
for(int i=head[k];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;//无向图判是否走过,易漏
dfs(v,k,dep+);
siz[k]+=siz[v];
if(siz[v]>siz[son[k]])son[k]=v;
}
} void build(int k,int tp){
id[k]=++cnt;//按序将边加入线段树
top[k]=tp;
if(son[k])build(son[k],tp);//重儿子的top[]从重链顶端继承
for(int i=head[k];i;i=e[i].nxt)
if(e[i].to!=son[k]&&e[i].to!=f[k])
build(e[i].to,e[i].to);//轻儿子top[]为自身
}
/////////////////////////////树剖//////////////////////////////////// /////////////////////////////线段树////////////////////////////////////
#define mid ((L+R)>>1)
#define ls (k<<1)//写位运算一定要开-Wall,否则一定要记得加括号
#define rs ls+1 void update(int k,int L,int R,int p,int x){
if(p>R||p<L)return;
if(L==R){t[k]=x;return;}
update(ls,L,mid,p,x); update(rs,mid+,R,p,x);
t[k]=max(t[ls],t[rs]);
} int query(int k,int L,int R,int l,int r){
if(l>R||r<L)return ;
if(l<=L&&R<=r)return t[k];
return max(query(ls,L,mid,l,r),query(rs,mid+,R,l,r));
}
/////////////////////////////线段树//////////////////////////////////// int find(int x,int y){
int ans=-1e9;
while(top[x]!=top[y]){//类似LCA,每次将较低的节点上跳,并统计路径上的最大值
if(d[top[x]]<d[top[y]])swap(x,y);
ans=max(ans,query(,,cnt,id[top[x]],id[x]));
x=f[top[x]];
}
if(d[x]>d[y])swap(x,y);//当两点处于同一条链上的时候,进行最后一次统计
if(x!=y)ans=max(ans,query(,,cnt,id[x]+,id[y]));//注意,因为id[x]为x的父边,所以若不+1,就会多统计一条边
return ans;
} char ch[];
void work(){
int x,y;
while(scanf("%s",ch),ch[]!='D'){
scanf("%d%d",&x,&y);
if(ch[]=='C')update(,,cnt,id[a[x][]],y);
else printf("%d\n",find(x,y));
}
} void init(){
clr(a);clr(e);clr(t);clr(son);clr(siz);clr(id);clr(top);clr(head);clr(d);clr(f);
ne=cnt=n=;
scanf("%d",&n);
foru(i,,n-){
scanf("%d%d%d",&a[i][],&a[i][],&a[i][]);
add(a[i][],a[i][]);add(a[i][],a[i][]);
}
dfs(,,);
build(,);
foru(i,,n-){
if(d[a[i][]]>d[a[i][]])swap(a[i][],a[i][]);
update(,,cnt,id[a[i][]],a[i][]);//建树
}
} int main(){
int T;
scanf("%d",&T);
while(T--){
init();
work();
}
}
												

树链剖分-SPOJ375(QTREE)的更多相关文章

  1. Cogs 1672. [SPOJ375 QTREE]难存的情缘 LCT,树链剖分,填坑计划

    题目:http://cojs.tk/cogs/problem/problem.php?pid=1672 1672. [SPOJ375 QTREE]难存的情缘 ★★★☆   输入文件:qtree.in  ...

  2. SPOJ375.QTREE树链剖分

    题意:一个树,a b c 代表a--b边的权值为c.CHANGE x y  把输入的第x条边的权值改为y,QUERY x y 查询x--y路径上边的权值的最大值. 第一次写树链剖分,其实树链剖分只能说 ...

  3. [SPOJ375]QTREE - Query on a tree【树链剖分】

    题目描述 给你一棵树,两种操作. 修改边权,查找边权的最大值. 分析 我们都知道,树链剖分能够维护点权. 而且每一条边只有一个,且唯一对应一个儿子节点,那么就把信息放到这个儿子节点上. 注意,lca的 ...

  4. QTREE 树链剖分---模板 spoj QTREE

    <树链剖分及其应用> 一文讲得非常清楚,我一早上就把他学会了并且A了这题的入门题. spoj QTREE 题目: 给出一棵树,有两种操作: 1.修改一条边的边权. 2.询问节点a到b的最大 ...

  5. spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)

    传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...

  6. 树链剖分边权模板spoj375

    树链剖分是树分解成多条链来解决树上两点之间的路径上的问题 如何求出树链:第一次dfs求出树上每个结点的大小和深度和最大的儿子,第二次dfs就能将最大的儿子串起来并hash(映射)到线段树上(或者其他数 ...

  7. 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 ...

  8. SPOJ 375 Query on a tree(树链剖分)(QTREE)

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  9. SPOJ QTree【树链剖分】

    一 题目 QTREE 二 分析 第一道树链剖分的题,写的好艰难啊. 题意还是比较好理解的,就是在树上操作. 对于修改,题中要求的是单点修改,就算是直接树上操作也是非常简单的. 对于查询,查询的时候,是 ...

随机推荐

  1. Modelbuilder进阶教程

    Modelbuilder进阶教程 By 李远祥 Modelbuilder 进阶1 自定义变量 参数是用来交互操作的,因此,参数具备非常大的灵活性,包括参数的定义和调用. 除了工具里面的参数之外,还可以 ...

  2. 【小梅哥FPGA进阶教程】第九章 基于串口猎人软件的串口示波器

    九.基于串口猎人软件的串口示波器 1.实验介绍 本实验,为芯航线开发板的综合实验,该实验利用芯航线开发板上的ADC.独立按键.UART等外设,搭建了一个具备丰富功能的数据采集卡,芯航线开发板负责进行数 ...

  3. python面向对象编程对象和实例的理解

    给你一个眼神,自己体会

  4. Android注解学习(2)

    最近考试周没什么时间写,回归正题.前面的一次简单的讲了关于注解的的基础部分,这一次分析xutils注解封装的源码(奉上github源码). 补充下:xUtils 2.x对Android 6.0兼容不是 ...

  5. LAMP学习小记

    记录今天学习到的解决LAMP环境搭建的两个小问题: 问题1.xshell无法连接到虚拟机上的linux主机 解决方法: (1)进入网络配置文件: vi /etc/sysconfig/network-s ...

  6. 前端开发面试题总结之——HTML

    ______________________________________________________________________________________________ 相关知识点 ...

  7. 检查浏览器url改变,处理ajax前进和后退键

    在用ajax获取数据,不刷新页面情况下,保持前进后退按钮功能,网页端兼容性最好的方式如下: 首先url后面参数用#  如http://www.xxx.com/#txf; 使用改变location.ha ...

  8. IE浏览器和CSS盒模型

    网页设计中常听的属性名:内容(content).填充(padding).边框(border).边界(margin), CSS盒子模式都具备这些属性. 盒子模型是CSS中一个重要的概念,理解了盒子模型才 ...

  9. win8 wifi开关显示关闭,且设置里面wifi开关显示灰色的解决办法

    只要从华硕官网下载驱动,电源管理驱动,安装下面显示的几个软件即可,然后重启电脑,即可看见wifi热点,另外设置里面的wifi开关也将显示正常(刚开始安装了个驱动人生根本没用,最后在华硕官网下载了个电源 ...

  10. 不想当程序员的CEO不是好投资人:小米雷军23年前所写代码曝光

    众所周知,雷军是小米创办人,董事长兼CEO,但是较少人知道,其实雷军是程序员出身,并且在程序员这个行业里一做就是十年.有网友曝光了一段23年前雷军所写的代码,一起来看下. 可以看出这段代码写于1994 ...