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的最大 ...
随机推荐
- LeetCode 561. Array Partition I (C++)
题目: Given an array of 2n integers, your task is to group these integers into npairs of integer, say ...
- 软件团队项目第一次Sprint评价(评价人:张家军)
组号 组名 缺点及建议 1 理财猫 (1)没有附带的计算器 (2)支入支出没有详细菜单说明 (3)界面背景单调 ...
- 图论 Kruskal算法 并查集
#include<iostream> #include<cstring> #include<string> #include<cstdio> #incl ...
- Unity发布Exe后,去掉提示分辨率的窗口
Unity版本:2017.4 菜单File->Build Settings...,修改如下图的位置,将“Display Resolution Dialog”从Enabled改为Disabled
- ORACLE中 %TYPE 和 %ROWTYPE 的使用
%TYPE 用在变量的声明里,用于取得表中的字段类型: %ROWTYPE 用于声明基于某个表的行类型: 示例: %ROWTYPE 使用 DECLARE CURSOR pdct_cur ...
- apache DBUtils 使用例子demo
转自:http://blog.csdn.net/earbao/article/details/44901061 apache DBUtils是java编程中的数据库操作实用工具,小巧简单实用, 1.对 ...
- 使用docker-compose编排django、mysql实战
背景: 本萌最近在部署自己开发的项目的时候发现同一套代码上传到服务器上后,部分功能莫名其妙的有点问题,服务器的各项配置都没有做过变动,所以想把项目转战到docker. 奈何刚接触docker,很多地方 ...
- vSphere Client 连接ESXi 或者是vCenter 时虚拟机提示VMRC异常的解决办法
1. 自己的vSphere 连接vCenter 向管理虚拟机 结果发现总是有异常. 提示如图示 VMRC控制台的连接已经断开 2. 花了比较长的时间也没搞定. 后来百度发现 关闭一个进程 然后重新登录 ...
- [转帖]MBR与UEFI
从Intel 6系列主板之后,就开始提供UEFI BIOS支持,正式支持GPT硬盘分区表,一举取代了此前的MBR分区表格式,不过为了保持对老平台的兼容,微软即使最新的Windows 10系统也继续提供 ...
- vue 组件 组件2
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>T ...