Description

给出一个树,每条边有边权,支持两种操作,询问 \(u,v\) 路径上边权最大值,修改第 \(i\) 条边的边权,\(n\leqslant 10^4,T\leqslant 10\)

Sol

树链剖分.

基于边的树链剖分,对于一个点,可能有许多儿子,但是它只能有一个父亲,给它编号表示它到它父亲的边,只需要修改查询的是最后一步就可以了.

Code

#include<cstdio>
#include<vector>
#include<iostream>
using namespace std; #define debug(a) cout<<#a<<"="<<a<<" "
#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc (o<<1|1)
const int N = 10005; inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } int n,e,cnt;
struct Edge{ int fr,to,v; }edge[N];
vector<Edge> g[N];
int f[N],cost[N],dep[N],son[N],top[N],sz[N],p[N];
int d[N<<2]; void Add_Edge(int fr,int to,int v){
edge[++e]=(Edge){ fr,to,v };
g[fr].push_back((Edge){ fr,to,v });
g[to].push_back((Edge){ to,fr,v });
}
void DFS1(int u,int fa){
sz[u]=1,son[u]=0,dep[u]=dep[fa]+1,f[u]=fa;
for(int i=0,lim=g[u].size(),v;i<lim;i++) if((v=g[u][i].to)!=fa){
DFS1(v,u),sz[u]++;
if(!son[u]||sz[son[u]]<sz[v]) son[u]=v;
}
}
void DFS2(int u,int tp){
p[u]=++cnt,top[u]=tp;
if(son[u]) DFS2(son[u],tp);
for(int i=0,lim=g[u].size(),v;i<lim;i++) if((v=g[u][i].to)!=f[u]&&v!=son[u])
DFS2(v,v);
}
void Build(int o,int l,int r){
if(l==r){ d[o]=cost[l];return; }
Build(lc,l,mid),Build(rc,mid+1,r);
d[o]=max(d[lc],d[rc]);
}
void Change(int o,int l,int r,int x,int v){
if(l==r){ d[o]=v;return; }
if(x<=mid) Change(lc,l,mid,x,v);
else Change(rc,mid+1,r,x,v);
d[o]=max(d[lc],d[rc]);
}
int QueryMax(int o,int l,int r,int L,int R){
if(L<=l&&r<=R) return d[o];int res=0;
if(L<=mid) res=max(res,QueryMax(lc,l,mid,L,R));
if(R>mid) res=max(res,QueryMax(rc,mid+1,r,L,R));
return res;
}
int GetAns(int u,int v){
int res=0,f1=top[u],f2=top[v];
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(u,v),swap(f1,f2);
res=max(res,QueryMax(1,1,n,p[f1],p[u]));
u=f[f1],f1=top[u];
}
if(dep[u]>dep[v]) swap(u,v);
if(dep[v]==dep[u]) return res;
else return max(res,QueryMax(1,1,n,p[u]+1,p[v]));
}
void clr(){ for(int i=0;i<N;i++) g[i].clear();cnt=0,e=0; } int main(){
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
ios::sync_with_stdio(false);
for(int T=in();T--;){
clr();
n=in();
for(int i=1,a,b,c;i<n;i++) a=in(),b=in(),c=in(),Add_Edge(a,b,c);
DFS1(1,1),DFS2(1,1); for(int i=1;i<n;i++){
int a=edge[i].fr,b=edge[i].to;
if(dep[a]>dep[b]) swap(a,b),swap(edge[i].fr,edge[i].to);
cost[p[b]]=edge[i].v;
} Build(1,1,n);
for(char opt[10];;){
scanf("%s",opt);
if(opt[0]=='D') break;
int a=in(),b=in();
if(opt[0]=='C') Change(1,1,n,p[edge[a].to],b);
else printf("%d\n",GetAns(a,b));
// debug(QueryMax(1,1,n,1,1)),debug(QueryMax(1,1,n,2,2)),debug(QueryMax(1,1,n,3,3))<<endl;
}
}return 0;
}

  

SPOJ 375 Query on a tree的更多相关文章

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

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

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

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

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

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

  4. 动态树(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) ...

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

  6. SPOJ 375 Query on a tree 树链剖分模板

    第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...

  7. spoj 375 query on a tree LCT

    这道题是树链剖分的裸题,正在学LCT,用LCT写了,发现LCT代码比树链剖分还短点(但我的LCT跑极限数据用的时间大概是kuangbin大神的树链剖分的1.6倍,所以在spoj上是850ms卡过的). ...

  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 375 Query on a tree【树链剖分】

    题目大意:给你一棵树,有两个操作1.修改一条边的值,2.询问从x到y路径上边的最大值 思路:如果树退化成一条链的话线段树就很明显了,然后这题就是套了个树连剖分,调了很久终于调出来第一个模板了 #inc ...

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

    https://vjudge.net/problem/SPOJ-QTREE 题意: 给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值. 思路: 树链剖 ...

随机推荐

  1. WebDataGrid设置某行某列的值

    <ig:WebDataGrid ID="grid"  OnRowSelectionChanged="grid_RowSelectionChanged" O ...

  2. ubuntu下怎么解决python "Non-ASCII character"错误

    解决方法:源代码文件第一行添加:#coding:utf-8 参考:  http://jingyan.baidu.com/album/219f4bf7d04887de442d3899.html?pici ...

  3. 重载new操作符

    http://book.51cto.com/art/201202/317799.htm

  4. HTML5基本布局

    HTML4布局 HTML5布局 基本的HTML5文档的模式为: <!DOCTYPE html> <html lang = "en"> <head> ...

  5. OSX10.11 删除系统自带的软件

    之前一直用sudo rm - rf 系统的浏览器名字 正常删除safari 升级到10.11后,完全没作用了 需要关闭系统的什么安全模式 csrutil disable 再进入系统使用此命令可正常删除 ...

  6. phpmyadmin 链接远程mysql

    这个只是自己的笔记 新手 不记下来以后又忘记了~ 在这以前已经给mysql设置了可以远程连接的账户 版本 phpMyAdmin-4.2.11-all-languages 解压到D盘下www   本地环 ...

  7. State Threads——异步回调的线性实现

    State Threads——异步回调的线性实现 原文链接:http://coolshell.cn/articles/12012.html 本文的标题看起来有点拗口,其实State Threads库就 ...

  8. Mongodb副本集搭建经验

    一.环境配置经验 1.一般安装的副本集的时候,主实例可以有数据库和用户:从实例不能.仲裁机不能有任何数据库包括用户 2.搭建副本集的时候Host使用外网IP,否则使用Mongodb VUE 1.6.9 ...

  9. 使用微信JS-SDK调用微信浏览器的接口

    先附上微信公众平台的相关链接: 微信公众平台:https://mp.weixin.qq.com/ 微信公众平台开发文档:https://mp.weixin.qq.com/wiki 微信公众平台JS-S ...

  10. [C#]System.Timers.Timer

    摘要 在.Net中有几种定时器,最喜欢用的是System.Timers命名空间下的定时器,使用起来比较简单,作为定时任务,有Quartz.net,但有时候,一个非常简单的任务,不想引入这个定时任务框架 ...