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. Java——新IO 通道

    import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.ch ...

  2. C++ 泛型基础

    C++ 泛型基础 泛型的基本思想:泛型编程(Generic Programming)是一种语言机制,通过它可以实现一个标准的容器库.像类一样,泛型也是一种抽象数据类型,但是泛型不属于面向对象,它是面向 ...

  3. 端口扫描(TCP)

    还待优化... #include <string.h> #include <WinSock.h> #include <stdio.h> #pragma commen ...

  4. socket+mysql

    测试windows 下 Socket+Mysql调用. 环境: OS:Win7; DBMS:Mysql;  IDE:codeblockS. server: #include <WINSOCK2. ...

  5. CodeForces 716A Crazy Computer

    题目链接:http://codeforces.com/problemset/problem/716/A 题目大意: 输入 n c, 第二行 n 个整数,c表示时间间隔 秒. 每个整数代表是第几秒.如果 ...

  6. OpenGL瓶颈

    在优化Erya3D引擎的过程中,遇到的瓶颈: 1. 字符串操作,避免逐个字符的比较,使用哈希码比较2. 贴图操作:切换绑定贴图.更改贴图参数3. 切换绑定GLSL程序4. Draw Call:http ...

  7. webapi输入验证过滤器ValidationActionFilter

    public class validationActionFilter:ActionFilterAttribute { public override void OnActionExecuting(S ...

  8. Windows下安装Tomcat服务

    startup.bat中添加以下内容 setlocal SET JAVA_HOME=D:\Program Files\Java\jdk1.8.0_05 SET CATALINA_HOME=D:\Pro ...

  9. c# 多线程 --Mutex(互斥锁)

    互斥锁(Mutex) 互斥锁是一个互斥的同步对象,意味着同一时间有且仅有一个线程可以获取它. 互斥锁可适用于一个共享资源每次只能被一个线程访问的情况 函数: //创建一个处于未获取状态的互斥锁 Pub ...

  10. bootstrapValidator.js 做表单验证

    有这样的一个场景,我们在提交form表单的时候 可能要做一些验证,比如判断是不是为空,电话的格式验证,邮箱的格式验证等等,手写起来也是可以得. 但是今天我介绍一个bootstrap插件简化开发.就是b ...