\(\\\)

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. Ubuntu系统备份工具大全(官方整理推荐)

    其实官方在系统备份这块已经有Wiki整理和收集各类实用的工具.以下是翻译自官方Wiki的部分文档: 备份工具  wiki文档实用程序 工具 界面 格式类型 Raw/File 支持 远程 增量 差异 自 ...

  2. How to force immediate stop of threads in Jmeter servers如何在jmeter执行完,立即停止jmeter

    https://stackoverflow.com/questions/38900315/how-to-force-immediate-stop-of-threads-in-jmeter-server ...

  3. Spring Boot中微信全局token的缓存实现

    为什么要缓存token? 这里的token指的是微信JSAPI中基础支持的ACCESS_TOKEN,并非网页授权ACCESS_TOKEN.网页授权Token每天的调用次数没有限制,不需要缓存. 接口 ...

  4. MariaDB基础操作

    MariaDB: MariaDB是MySQL源代码的一个分支,随着Oracle买下Sun,MySQL也落入了关系型数据库王者之手.在意识到Oracle会对MySQL许可做什么后便分离了出来(MySQL ...

  5. HTTP请求库——axios源码阅读与分析

    概述 在前端开发过程中,我们经常会遇到需要发送异步请求的情况.而使用一个功能齐全,接口完善的HTTP请求库,能够在很大程度上减少我们的开发成本,提高我们的开发效率. axios是一个在近些年来非常火的 ...

  6. linux下alias命令具体解释

    linux下alias命令具体解释 用途说明 设置命令的别名.在linux系统中假设命令太长又不符合用户的习惯,那么我们能够为它指定一个别名. 尽管能够为命令建立"链接" 解决长文 ...

  7. Mali GPU OpenGL ES 应用性能优化--基本方法

    1. 经常使用优化工具 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTXlBcnJvdw==/font/5a6L5L2T/fontsize/400/fil ...

  8. gcc的搜索路径,头文件和库

    1 抛开默认的搜索路径,自己指定搜索路径 第一,明确自己编写的代码所需要的头文件和库放在了哪里 第二,使用“-I”指定头文件的搜索路径,使用-rpath指定库的搜索路径 2 无论是本地编译还是交叉编译 ...

  9. JOIN a table with a subquery

    统计数据产品消耗量与产量 注意join 方向 join中子查询 How to use subquery in JOIN operation in MySQL http://www.geeksengin ...

  10. python2.x里unicode错误问题

    import sys reload(sys) sys.setdefaultencoding('utf8')