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

题意:

一棵树有修改边权值操作和询问两个节点之间的最大边权值操作

代码:

代码:

//每个点和他父节点的边构成一个线段树上的点。所以线段树的点实际从2开始
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=;
int id[MAXN+],fa[MAXN+],max_val[MAXN*+],head[MAXN+],son[MAXN+],top[MAXN+],lev[MAXN+],size[MAXN+];
//id:对应到线段树上的点编号,son:重儿子,top:重链的头,lev:深度,size:子树大小
int tot,cnt,val[MAXN+]; //cnt:线段树节点数
struct Edge
{
int u,v,w,next;
}edge[MAXN*+];
void init()
{
for(int i=;i<=MAXN;i++) fa[i]=top[i]=i;
memset(size,,sizeof(size));
memset(head,-,sizeof(head));
memset(val,,sizeof(val));
tot=cnt=;
}
void add(int x,int y,int z)
{
edge[tot].u=x;edge[tot].v=y;edge[tot].w=z;
edge[tot].next=head[x];
head[x]=tot++;
edge[tot].u=y;edge[tot].v=x;edge[tot].w=z;
edge[tot].next=head[y];
head[y]=tot++;
}
void dfs1(int x,int d)
{
lev[x]=d;
son[x]=;
size[x]=;
for(int i=head[x];i!=-;i=edge[i].next){
int y=edge[i].v;
if(y==fa[x]) continue;
fa[y]=x;
dfs1(y,d+);
size[x]+=size[y];
if(size[son[x]]<size[y]) son[x]=y;
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
id[x]=++cnt;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-;i=edge[i].next){
int y=edge[i].v;
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
void pushup(int rt) { max_val[rt]=max(max_val[rt<<],max_val[rt<<|]); }
void build(int l,int r,int rt)
{
if(l==r) { max_val[rt]=val[l];return; }
int mid=(l+r)>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
pushup(rt);
}
void update(int id,int c,int l,int r,int rt)
{
if(l==r){
max_val[rt]=c;
return;
}
int mid=(l+r)>>;
if(id<=mid) update(id,c,l,mid,rt<<);
else update(id,c,mid+,r,rt<<|);
pushup(rt);
}
int query(int ql,int qr,int l,int r,int rt)
{
if(ql<=l&&qr>=r) return max_val[rt];
int mid=(l+r)>>,ans=;
if(ql<=mid) ans=max(ans,query(ql,qr,l,mid,rt<<));
if(qr>mid) ans=max(ans,query(ql,qr,mid+,r,rt<<|));
return ans;
}
int solve(int l,int r)
{
int ltp=top[l],rtp=top[r],ans=;
while(ltp!=rtp){
if(lev[rtp]<lev[ltp]){
swap(ltp,rtp);
swap(l,r);
}
ans=max(ans,query(id[rtp],id[r],,cnt,));
r=fa[rtp];
rtp=top[r];
}
if(lev[r]>lev[l]) swap(r,l);
if(l!=r) ans=max(ans,query(id[son[r]],id[l],,cnt,));
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
int t,n;
scanf("%d",&t);
while(t--){
init();
scanf("%d",&n);
for(int i=;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
dfs1(,);
dfs2(,);
for(int i=;i<tot;i+=){
if(lev[edge[i].u]>lev[edge[i].v]) swap(edge[i].u,edge[i].v);
val[id[edge[i].v]]=edge[i].w;
}
build(,cnt,);
char ch[];
while(scanf("%s",ch)&&ch[]!='D'){
int x,y;
scanf("%d%d",&x,&y);
if(ch[]=='C') update(id[edge[x*-].v],y,,cnt,);
else printf("%d\n",solve(x,y));
}
}
return ;
}
 

spoj 375 树链剖分 模板的更多相关文章

  1. spoj 375 树链剖分模板

    /* 只是一道树链刨分的入门题,作为模板用. */ #include<stdio.h> #include<string.h> #include<iostream> ...

  2. SPOJ 375 树链剖分

    SPOJ太慢了,SPOJ太慢了, 题意:给定n(n<=10000)个节点的树,每条边有边权,有两种操作:1.修改某条变的边权:2.查询u,v之间路径上的最大边权. 分析:树链剖分入门题,看这里: ...

  3. SPOJ 375 (树链剖分 - 边权剖分 - 修改单边权)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/I 给你一棵有边权的树,有两个操作:一个操作是输出l到 ...

  4. SPOJ 375 (树链剖分+线段树)

    题意:一棵包含N 个结点的树,每条边都有一个权值,要求模拟两种操作:(1)改变某条边的权值,(2)询问U,V 之间的路径中权值最大的边. 思路:最近比赛总是看到有树链剖分的题目,就看了论文,做了这题, ...

  5. SPOJ 375 树链剖分 QTREE - Query on a tree

    人生第一道树链剖分的题目,其实树链剖分并不是特别难. 思想就是把树剖成一些轻链和重链,轻链比较少可以直接修改,重链比较长,用线段树去维护. 貌似大家都是从这篇博客上学的. #include <c ...

  6. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  7. 算法复习——树链剖分模板(bzoj1036)

    题目: 题目背景 ZJOI2008 DAY1 T4 题目描述 一棵树上有 n 个节点,编号分别为 1 到 n ,每个节点都有一个权值 w .我们将以下面的形式来要求你对这棵树完成一些操作:I.CHAN ...

  8. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

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

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

随机推荐

  1. Fourteenth scrum meeting

    闫昊 今日完成:整理上一阶段代码,规划第二阶段实施过程 明日完成:学习讨论区开发 唐彬 今日完成:整理上一阶段代码,规划第二阶段实施过程 明日完成:学习学习进度部分开发 史烨轩 今日完成:整理上一阶段 ...

  2. 20162328蔡文琛 week05 大二

    20162328 2017-2018-1 <程序设计与数据结构>第5周学习总结 教材学习内容总结 集合是收集元素并组织其他对象的对象. 集合中的元素一般由加入集合的次序或元素之间的某些固有 ...

  3. 冲刺One之站立会议7 /2015-5-20

    2015-5-20 在登陆成功之后要实现的是聊天界面的交互过程,不同的IP进行信息和数据的传递,这方面我们上学期Java实验里面有过相关的内容,我们把它拿过来改了一下格式,试着看能不能成功,目前还没实 ...

  4. Task 6.2冲刺会议六 /2015-5-19

    今天主要写的是登陆界面,用户状态,历史登录信息,默认用户等等.由于大部分时间都是把代码组合拳起来的过程,所以总会出现各种bug,有好大一部分不会修复.明天要继续这一部分还有熟悉一下聊天的主界面.

  5. 课堂练习 psp表

    项目计划总结表: 日期 编程 完善程序 测试程序 参考资料 日总结 3.20 18:00---19:30       1.5 3.21   9:30----10:00 10:00---10:30   ...

  6. Java集合技巧

    集合的一些技巧:   需要唯一吗? 需要:Set 需要制定顺序:  需要: TreeSet 不需要:HashSet 但是想要一个和存储一致的顺序(有序):LinkedHashSet 不需要:List ...

  7. SQL语句中 chinese_prc_CS_AI_WS 以及replace用法

          Select * from [DBData].[dbo].[T_Student] where Name='lilei'    查询结果如下:   结论:由查询结果可知 SQL Server ...

  8. angularJS1笔记-(18)-$http及用angular实现JSONP跨域访问过程

    官网上的解释为: The $http service is a core AngularJS service that facilitates communication with the remot ...

  9. Java网络编程二:Socket详解

    Socket又称套接字,是连接运行在网络上两个程序间的双向通讯的端点. 一.使用Socket进行网络通信的过程 服务端:服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户端的连接 ...

  10. windows下的C++ socket服务器(3)

    int make_server_socket(int port) { WSADATA inet_WsaData; WSAStartup(MAKEWORD(), &inet_WsaData); ...