https://vjudge.net/problem/SPOJ-QTREE

题意:

给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值。

思路:

树链剖分的模板题。

树链剖分简单来说,就是把树分成多条链,然后再将这些链映射到数据结构上处理(线段树,树状数组等等)。

具体的话可以看看这个http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=+; int n;
int tot;
int pos;
int head[maxn];
int dep[maxn]; //节点在树上的深度
int top[maxn]; //节点所在重链的顶端节点
int num[maxn]; //节点的子节点数
int fa[maxn]; //父亲结点
int p[maxn]; //节点与其父亲结点在线段树中的位置
int fp[maxn]; //和p数组相反
int son[maxn]; //节点的重儿子
int e[maxn][]; struct node
{
int v,next;
}edge[*maxn]; void addEdge(int u, int v)
{
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
} //求出重儿子等等
void dfs(int u, int pre, int d)
{
dep[u]=d;
son[u]=-;
num[u]=;
fa[u]=pre;
for(int i=head[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre) continue;
dfs(v,u,d+);
num[u]+=num[v];
if(son[u]==- || num[son[u]]<num[v]) //找到子节点最多的作为重儿子
son[u]=v;
}
} //处理top值以及在线段树上的位置
void getpos(int u, int sp)
{
top[u]=sp;
if(son[u]!=-) //先处理重儿子
{
p[u]=pos++; //保证了一条链上的顶点在线段树上连续
fp[p[u]]=u;
getpos(son[u],sp);
}
else //到了叶子节点就不再往下处理
{
p[u]=pos++;
fp[p[u]]=u;
return;
}
for(int i=head[u];i!=-;i=edge[i].next) //处理其他顶点
{
int v=edge[i].v;
if(v==son[u] || v==fa[u]) continue;
getpos(v,v);
}
} int val[maxn<<];
int MAX[maxn<<]; void PushUp(int o)
{
MAX[o]=max(MAX[o<<],MAX[o<<|]);
} void build(int l, int r, int o)
{
if(l==r)
{
MAX[o]=val[l];
return;
}
int mid=(l+r)>>;
build(l,mid,o<<);
build(mid+,r,o<<|);
PushUp(o);
} void update(int pos, int x, int l, int r, int o)
{
if(l==r) {MAX[o]=x;return;}
int mid=(l+r)>>;
if(pos<=mid) update(pos,x,l,mid,o<<);
else update(pos,x,mid+,r,o<<|);
PushUp(o);
} int query(int ql, int qr, int l, int r, int o)
{
if(ql<=l && qr>= r) return MAX[o];
int mid=(l+r)>>;
int res=;
if(ql<=mid) res=max(res,query(ql,qr,l,mid,o<<));
if(qr>mid) res=max(res,query(ql,qr,mid+,r,o<<|));
return res;
} int lca(int x, int y)
{
int ans=;
while(top[x]!=top[y]) //不在一条链上时
{
if(dep[top[x]]<dep[top[y]]) swap(x,y); //从深度较深的开始
ans=max(ans,query(p[top[x]],p[x],,n,));
x=fa[top[x]]; //x所在链的顶点的父节点,转到另一条链上
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) ans=max(ans,query(p[son[x]],p[y],,n,));
return ans;
} int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
tot=;
memset(head,-,sizeof(head));
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d%d",&e[i][],&e[i][],&e[i][]);
addEdge(e[i][],e[i][]);
addEdge(e[i][],e[i][]);
}
dfs(,,);
pos=;
getpos(,);
for(int i=;i<n;i++)
{
if(dep[e[i][]]<dep[e[i][]]) swap(e[i][],e[i][]);
val[p[e[i][]]]=e[i][];
}
build(,n,);
char s[]; int u,v;
while(scanf("%s",s))
{
if(s[]=='D') break;
scanf("%d%d",&u,&v);
if(s[]=='Q') printf("%d\n",lca(u,v));
else update(p[e[u][]],v,,n,);
}
}
return ;
}

SPOJ 375 Query on a tree(树链剖分)的更多相关文章

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

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

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

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

  4. spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)

    传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...

  5. SPOJ QTREE Query on a tree ——树链剖分 线段树

    [题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...

  6. SPOJ QTREE Query on a tree --树链剖分

    题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...

  7. spoj 375 QTREE - Query on a tree 树链剖分

    题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #includ ...

  8. SPOJ Query on a tree 树链剖分 水题

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  9. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  10. Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...

随机推荐

  1. MySQL管理之道:性能调优、高可用与监控》迷你书

    MySQL管理之道:性能调优.高可用与监控>迷你书 MYSQL5.5.X主要改进 1.默认使用innodb存储引擎2.充分利用CPU多核处理能力3.提高刷写脏页数量和合并插入数量,改善I/O4. ...

  2. [py]pycharm远程环境添加

    pycharm配置settings.jar pycharm远程环境调用.zip xadmin xadmin-django2 pycharm激活 最新2018.2激活---更新2018年8月8日 15: ...

  3. (转)Linux Oracle服务启动&停止脚本与开机自启动

    在CentOS 6.3下安装完Oracle 10g R2,重开机之后,你会发现Oracle没有自行启动,这是正常的,因为在Linux下安装Oracle的确不会自行启动,必须要自行设定相关参数,首先先介 ...

  4. Windows2008 IIS配置FTP站点

    视频教程:http://vodcdn.video.taobao.com/player/ugc/tb_ugc_pieces_core_player_loader.swf?version=1.0.2015 ...

  5. 好消息啊,有些c似乎不用加厂商前缀了

    今天写程序,一个不小心,没写厂商前缀,然而,,,,,,, 可以运行了(我居然不知道这个消息!!!!) 赶紧写几个字纪念一下. (把鼠标移动到红色的字上边~~~) don' you think that ...

  6. 谷歌浏览器 URL无法访问

    使用谷歌浏览器老是会崩溃,或者访问的时候发现“URL无法访问”等失败的问题,连淘宝都没法访问,这个让人很恼火, 最后在扩展应用那里搜到个URL的redirect,问题解决了,~~发现没有再出现类似问题 ...

  7. linux常用命令:tr 命令

    tr 命令实现字符转换功能,其功能类似于 sed 命令,但是,tr 命令比 sed 命令简单.也就是说,tr 命令能实现的功能,sed 命令都可以实现.尽管如此,tr 命令依然是 Linux 系统下处 ...

  8. python-安装,设置环境变量(win10)

    python官网: https://www.python.org/ 选择需要的版本下载 下载后安装 我装的是默认位置C:\Python27 打开环境变量设置: 右键电脑--->属性----> ...

  9. html5 manifest 离线缓存知识点

    1.最大缓存容量为 5M. 2.manifest文件需要配置正确的MIME-type,即“text/cache-manifest”,这个是在web服务器上进行配置. ②编写.manifest文件,文件 ...

  10. LLVM/Clang编译相关研究

    https://blog.csdn.net/guojin08/article/details/54310858 https://juejin.im/entry/5c64da44518825620b45 ...