spoj 375 树链剖分 模板
QTREE - Query on a tree
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.
We will ask you to perfrom some instructions of the following form:
- CHANGE i ti : change the cost of the i-th edge to ti
or - QUERY a b : ask for the maximum edge cost on the path from node a to node b
Input
The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.
For each test case:
- In the first line there is an integer N (N <= 10000),
- In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 1000000),
- The next lines contain instructions "CHANGE i ti" or "QUERY a b",
- The end of each test case is signified by the string "DONE".
There is one blank line between successive tests.
Output
For each "QUERY" operation, write one integer representing its result.
Example
Input:
1 3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE Output:
1
3
题意:
一棵树有修改边权值操作和询问两个节点之间的最大边权值操作
代码:
代码:
//每个点和他父节点的边构成一个线段树上的点。所以线段树的点实际从2开始
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=;
int id[MAXN+],fa[MAXN+],max_val[MAXN*+],head[MAXN+],son[MAXN+],top[MAXN+],lev[MAXN+],size[MAXN+];
//id:对应到线段树上的点编号,son:重儿子,top:重链的头,lev:深度,size:子树大小
int tot,cnt,val[MAXN+]; //cnt:线段树节点数
struct Edge
{
int u,v,w,next;
}edge[MAXN*+];
void init()
{
for(int i=;i<=MAXN;i++) fa[i]=top[i]=i;
memset(size,,sizeof(size));
memset(head,-,sizeof(head));
memset(val,,sizeof(val));
tot=cnt=;
}
void add(int x,int y,int z)
{
edge[tot].u=x;edge[tot].v=y;edge[tot].w=z;
edge[tot].next=head[x];
head[x]=tot++;
edge[tot].u=y;edge[tot].v=x;edge[tot].w=z;
edge[tot].next=head[y];
head[y]=tot++;
}
void dfs1(int x,int d)
{
lev[x]=d;
son[x]=;
size[x]=;
for(int i=head[x];i!=-;i=edge[i].next){
int y=edge[i].v;
if(y==fa[x]) continue;
fa[y]=x;
dfs1(y,d+);
size[x]+=size[y];
if(size[son[x]]<size[y]) son[x]=y;
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
id[x]=++cnt;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-;i=edge[i].next){
int y=edge[i].v;
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
void pushup(int rt) { max_val[rt]=max(max_val[rt<<],max_val[rt<<|]); }
void build(int l,int r,int rt)
{
if(l==r) { max_val[rt]=val[l];return; }
int mid=(l+r)>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
pushup(rt);
}
void update(int id,int c,int l,int r,int rt)
{
if(l==r){
max_val[rt]=c;
return;
}
int mid=(l+r)>>;
if(id<=mid) update(id,c,l,mid,rt<<);
else update(id,c,mid+,r,rt<<|);
pushup(rt);
}
int query(int ql,int qr,int l,int r,int rt)
{
if(ql<=l&&qr>=r) return max_val[rt];
int mid=(l+r)>>,ans=;
if(ql<=mid) ans=max(ans,query(ql,qr,l,mid,rt<<));
if(qr>mid) ans=max(ans,query(ql,qr,mid+,r,rt<<|));
return ans;
}
int solve(int l,int r)
{
int ltp=top[l],rtp=top[r],ans=;
while(ltp!=rtp){
if(lev[rtp]<lev[ltp]){
swap(ltp,rtp);
swap(l,r);
}
ans=max(ans,query(id[rtp],id[r],,cnt,));
r=fa[rtp];
rtp=top[r];
}
if(lev[r]>lev[l]) swap(r,l);
if(l!=r) ans=max(ans,query(id[son[r]],id[l],,cnt,));
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
int t,n;
scanf("%d",&t);
while(t--){
init();
scanf("%d",&n);
for(int i=;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
dfs1(,);
dfs2(,);
for(int i=;i<tot;i+=){
if(lev[edge[i].u]>lev[edge[i].v]) swap(edge[i].u,edge[i].v);
val[id[edge[i].v]]=edge[i].w;
}
build(,cnt,);
char ch[];
while(scanf("%s",ch)&&ch[]!='D'){
int x,y;
scanf("%d%d",&x,&y);
if(ch[]=='C') update(id[edge[x*-].v],y,,cnt,);
else printf("%d\n",solve(x,y));
}
}
return ;
}
spoj 375 树链剖分 模板的更多相关文章
- spoj 375 树链剖分模板
/* 只是一道树链刨分的入门题,作为模板用. */ #include<stdio.h> #include<string.h> #include<iostream> ...
- SPOJ 375 树链剖分
SPOJ太慢了,SPOJ太慢了, 题意:给定n(n<=10000)个节点的树,每条边有边权,有两种操作:1.修改某条变的边权:2.查询u,v之间路径上的最大边权. 分析:树链剖分入门题,看这里: ...
- SPOJ 375 (树链剖分 - 边权剖分 - 修改单边权)
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/I 给你一棵有边权的树,有两个操作:一个操作是输出l到 ...
- SPOJ 375 (树链剖分+线段树)
题意:一棵包含N 个结点的树,每条边都有一个权值,要求模拟两种操作:(1)改变某条边的权值,(2)询问U,V 之间的路径中权值最大的边. 思路:最近比赛总是看到有树链剖分的题目,就看了论文,做了这题, ...
- SPOJ 375 树链剖分 QTREE - Query on a tree
人生第一道树链剖分的题目,其实树链剖分并不是特别难. 思想就是把树剖成一些轻链和重链,轻链比较少可以直接修改,重链比较长,用线段树去维护. 貌似大家都是从这篇博客上学的. #include <c ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- 算法复习——树链剖分模板(bzoj1036)
题目: 题目背景 ZJOI2008 DAY1 T4 题目描述 一棵树上有 n 个节点,编号分别为 1 到 n ,每个节点都有一个权值 w .我们将以下面的形式来要求你对这棵树完成一些操作:I.CHAN ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- QTREE 树链剖分---模板 spoj QTREE
<树链剖分及其应用> 一文讲得非常清楚,我一早上就把他学会了并且A了这题的入门题. spoj QTREE 题目: 给出一棵树,有两种操作: 1.修改一条边的边权. 2.询问节点a到b的最大 ...
随机推荐
- python基础_字符编码
字符编码的历史 阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII 阶段二:为了满足中文,中国人定制了GBK 阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的 ...
- YQCB冲刺第二周第一天
今天的任务为实现查看消费明细的功能. 遇到的问题是按类别显示. 站立会议为: 任务面板为:
- iOS开发学习-如何优化tableview的使用
1.复用单元格 2.单元格中的视图尽量都使用不透明的,单元格中尽量少使用动画 3.图片加载使用异步加载 4.滑动时不加载图片,停止滑动时开始加载 5.单元格中的内容可以在自定义cell类中的drawR ...
- Structs2笔记①--structs的背景、structs2框架的意义、第一个helloworld
Struts2的背景 由出色稳定的框架struts1和webwork框架整合而来的 吸取了两大框架的优点 提高了开发的效率和规范性 更好的实现了MVC架构 解除了与servlet的强耦合性 使用str ...
- Visual Studio 中配置openCV问题
1. 首先强调一点:VS与openCV的版本对应问题,一般而言,openCV对于VS采用向下的支持方式: vc6 -> VS6.0 vc7.0 -> VS2002 vc7.1 -> ...
- Java分布式应用
分布式计算就是通过计算机网络将计算工作分布到多台主机上,多个主机一起协同完成工作. 我试着列一下相关知识吧. 网络通讯,网络是分布式的基础,对分布式的理解建立在对网络的理解上,包括: OSI模型的7层 ...
- 评论alpha发布
第一组:新蜂小组 题目:俄罗斯方块 评论:很荣幸被邀请体验此游戏,感到加速下落时不是很灵敏,没有计分,页面不够美观(据说还在改善),整体框架已完成,基本功能已具备. 第二组:天天向上 题目:连连看 评 ...
- PAT 甲级 1137 Final Grading
https://pintia.cn/problem-sets/994805342720868352/problems/994805345401028608 For a student taking t ...
- lr几个常用的函数
将字符串保存为参数 lr_save_string("string you want to save", "arg_name"); 将int型数字保存为参数 lr ...
- 微信小程序使用函数的三种方法
使用来自不同页面的函数 函数写在util.js页面 function formatTime(date) { var year = date.getFullYear() var month = date ...