\(\\\)

Description


给定 \(n\) 个点的树,边按输入顺序编号为\(1,2,...n-1\) 。

现要求按顺序执行以下操作(共 \(m\) 次):

  • \(CHANGE\ i\ t_i\) 将第 \(i\) 条边权值改为 \(t_i\)

  • \(QUERY\ a\ b\) 询问从 \(a\) 点到 \(b\) 点路径上的最大边权

有多组测试数据,每组数据以 \(DONE\) 结尾

  • \(n,m\le 10^5\)

\(\\\)

Solution


重链剖分,线段树维护。

把边权记录在深度较深的叶节点上,具体编号的处理可以利用邻接表存图的方式。

修改就直接找到对应节点时间戳改了就好。

查询找 \(Lca\) 的时候注意不要算上 \(Lca\) 的答案,因为那里记录的是 \(Lca\) 到其父节点的边权。

Updata 的时候把 dfn 手残写成 pos 调了一天

\(\\\)

Code


#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100010
#define gc getchar
#define Rg register
#define mid ((l+r)>>1)
#define inf 2000000000
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} int n,m,tot,hd[N],bl[N],val[N]; struct edge{int to,nxt,w;}e[N<<1]; inline void add(int u,int v,int w){
e[++tot].to=v; e[tot].w=w;
e[tot].nxt=hd[u]; hd[u]=tot;
} int sz[N],f[N],d[N],son[N]; void dfs1(int u,int fa){
sz[u]=1; son[u]=0;
for(Rg int i=hd[u],v;i;i=e[i].nxt)
if((v=e[i].to)!=fa){
d[v]=d[u]+1; dfs1(v,u);
val[v]=e[i].w; bl[(i+1)/2]=v;
sz[u]+=sz[v]; f[v]=u;
if(sz[v]>sz[son[u]]) son[u]=v;
}
} int cnt,dfn[N],top[N],pos[N]; void dfs2(int u,int fa){
dfn[u]=++cnt;
pos[cnt]=u;
if(!top[u]) top[u]=u;
if(son[u]) top[son[u]]=top[u],dfs2(son[u],u);
for(Rg int i=hd[u],v;i;i=e[i].nxt)
if((v=e[i].to)!=fa&&v!=son[u]) dfs2(v,u);
} struct segment{ int root,ptr; inline int newnode(){return ++ptr;} struct node{int ls,rs,mx;}c[N<<1]; inline void pushup(int rt){
c[rt].mx=max(c[c[rt].ls].mx,c[c[rt].rs].mx);
} void build(int &rt,int l,int r){
rt=newnode();
if(l==r){
c[rt].mx=val[pos[l]];
return;
}
build(c[rt].ls,l,mid);
build(c[rt].rs,mid+1,r);
pushup(rt);
} void updata(int rt,int l,int r,int p,int x){
if(l==r){c[rt].mx=x;return;}
if(p<=mid) updata(c[rt].ls,l,mid,p,x);
else updata(c[rt].rs,mid+1,r,p,x);
pushup(rt);
} int query(int rt,int l,int r,int L,int R){
if(l>R||r<L) return 0;
if(l>=L&&r<=R) return c[rt].mx;
int res=-inf;
if(L<=mid) res=max(res,query(c[rt].ls,l,mid,L,R));
if(R>mid) res=max(res,query(c[rt].rs,mid+1,r,L,R));
return res;
} }tree; inline int lca(int u,int v){
if(u==v) return 0;
int res=-inf;
while(top[u]!=top[v]){
if(d[top[u]]>d[top[v]]) u^=v^=u^=v;
res=max(res,tree.query(tree.root,1,n,dfn[top[v]],dfn[v]));
v=f[top[v]];
}
if(d[u]>d[v]) u^=v^=u^=v;
res=max(res,tree.query(tree.root,1,n,dfn[u]+1,dfn[v]));
return res;
} void work(){
n=rd(); cnt=tot=0;
memset(f,0,sizeof(f));
memset(hd,0,sizeof(hd));
memset(top,0,sizeof(top));
memset(val,0,sizeof(val));
for(Rg int i=1,u,v,w;i<n;++i){
u=rd(); v=rd(); w=rd();
add(u,v,w); add(v,u,w);
}
dfs1(1,0); dfs2(1,0);
tree.build(tree.root,1,n);
char c; int x,y;
while(1){
c=gc(); while(!isalpha(c)) c=gc();
if(c=='D') return;
if(c=='Q'){x=rd();y=rd();printf("%d\n",lca(x,y));}
else{x=rd();y=rd();tree.updata(tree.root,1,n,dfn[bl[x]],y);}
}
} int main(){
int t=rd();
while(t--) work();
return 0;
}

[ SPOJ Qtree1 ] Query on a tree的更多相关文章

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

    Query on a tree Time Limit: 5000ms Memory Limit: 262144KB   This problem will be judged on SPOJ. Ori ...

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

  3. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

  4. spoj 375 Query on a tree(树链剖分,线段树)

      Query on a tree Time Limit: 851MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Sub ...

  5. 动态树(Link Cut Tree) :SPOJ 375 Query on a tree

    QTREE - Query on a tree #number-theory You are given a tree (an acyclic undirected connected graph) ...

  6. SPOJ 375. Query on a tree (动态树)

    375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ...

  7. SPOJ PT07J - Query on a tree III(划分树)

    PT07J - Query on a tree III #tree You are given a node-labeled rooted tree with n nodes. Define the ...

  8. spoj 913 Query on a tree II (倍增lca)

    Query on a tree II You are given a tree (an undirected acyclic connected graph) with N nodes, and ed ...

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

随机推荐

  1. 在springBoot与quartz 整合中 @Transaction 失效

    问题1::springBoot在与quartz 整合时,使用@Transaction 注解时事务失效 解决方案:创建一个类使用@component被spring管理 ,使用@Transaction标识 ...

  2. dubbo的jmeter压测时jar包的热加载/动态加载

    在做dubbo的jmeter压测时,需要把jar包放入jmeter的lib/ext目录下,但是jmeter启动的时候会自动加载这个目录lib目录及lib/ext目录,这样启动后放入这些目录下的jar包 ...

  3. [无线路由] “免费”斐讯K2路由器刷OpenWRT(实战MWAN多宽带网速叠加)

    (阿财首发于什么值得买)斐讯K2可以算是一个非常另类的跨界数码产品,其产品完全的醉翁之意不在酒.最多值99元的 MT7260硬件架构和用料,售价399元,金额激活K码后自动转入合作理财P2P平台,等待 ...

  4. vue全局注册与局部注册的写法

    vue全局注册是每个实例化的vue都可以使用,而局部则是实例化注册的那个可以用.举个例子,看看写法: <div id="app"> <p>页面载入时,inp ...

  5. 高速清空linux下文本文件内容

    1.[root@desktop huage]# : > filename :是一个占位符.不会产生不论什么输入   2.[root@desktop huage]# > filename 相 ...

  6. NPOI2.2.0.0实例详解(十)—设置EXCEL单元格【文本格式】 NPOI 单元格 格式设为文本 HSSFDataFormat

    NPOI2.2.0.0实例详解(十)—设置EXCEL单元格[文本格式] 2015年12月10日 09:55:17 阅读数:3150 using System; using System.Collect ...

  7. [Python]基于权重的随机数2种实现方式

    问题: 比如我们要选从不同省份选取一个号码.每一个省份的权重不一样,直接选随机数肯定是不行的了,就须要一个模型来解决问题. 简化成以下的问题: 字典的key代表是省份,value代表的是权重,我们如今 ...

  8. jquery.validate自己定义验证--成功提示与择要提示

    1. 自己定义验证--成功提示 1) 加入选项 errorClass: "unchecked". validClass: "checked", errorEle ...

  9. [LeetCode][Java] Jump Game II

    题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...

  10. 经典面试题回答——学习Java基础的目的

    本系列知识解释:相信每个学习Java的人都是从JavaSE開始的,也就是Java基础開始. 可是却并不清楚学习Java基础究竟有什么用?        首先我来回答这个问题,学习Java基础是有两个目 ...