[ SPOJ Qtree1 ] Query on a tree
\(\\\)
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的更多相关文章
- SPOJ 375. Query on a tree (树链剖分)
Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Ori ...
- 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 ...
- QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树
Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...
- spoj 375 Query on a tree(树链剖分,线段树)
Query on a tree Time Limit: 851MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Sub ...
- 动态树(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) ...
- SPOJ 375. Query on a tree (动态树)
375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ...
- 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 ...
- 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 ...
- 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 ...
随机推荐
- 智能社区--HI3516C可视门禁研发出来咯
铝壳.非常大气的外壳. 200W像素,HI3516C,携带server.创新的产品.欢迎交流:QQ237753582 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5u ...
- 在C++代码中调用L脚本语言
L脚本语言同意被其他编程语言调用.如C++,非常easy.仅仅要在宿主语言中载入L脚本引擎的动态库 直接调用这两个函数就能够了 extern "C" int __stdcall S ...
- Java中的字节输入出流和字符输入输出流
Java中的字节输入出流和字符输入输出流 以下哪个流类属于面向字符的输入流( ) A BufferedWriter B FileInputStream C ObjectInputStream D In ...
- tf.float32 implicity
简介 | TensorFlow https://tensorflow.google.cn/programmers_guide/low_level_intro 我们来构建一个简单的计算图.最基本的指 ...
- Cholesky分解 平方根法
一种矩阵运算方法,又叫Cholesky分解.所谓平方根法,就是利用对称正定矩阵的三角分解得到的求解对称正定方程组的一种有效方法.它是把一个对称正定的矩阵表示成一个下三角矩阵L和其转置的乘积的分解.它要 ...
- Oracle学习(四):组函数
1.知识点:能够对比以下的录屏进行阅读 SQL> --组函数类型:avg,count,max.min,sum SQL> --工资总额 SQL> select sum(sal) fro ...
- [Android6.0][RK3399] 双屏异显代码实现流程分析(一)【转】
本文转载自:http://blog.csdn.net/dearsq/article/details/55049182 Platform: RK3399 OS: Android 6.0 Version: ...
- 【OI新闻】2016.10.06
今天有人说好多OJ都狗记邓了- 翻了一下,恭喜以下OJ赢得大奖,获得狗记邓徽章一枚 一等奖Codevs 二等奖Bzoj 三等奖洛谷 后记-感悟 如果正在为OJ发愁的朋友,不要悲伤,不要心急,换一换OJ ...
- flask-migrate 数据迁移
作用:做数据库迁移依赖:flask-script flask-sqlalchemy 使用 项目结构 manage.py(其它文件内容与flask-sqlalchemy中一样) from s8day13 ...
- Code First:Data Anotation (2)
示例一 本例演示与索引有关的内容,模型: using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAn ...