SPOJ 375 QTREE
题目链接:传送门
题目大意:给一棵无根树,树边有权值,有很多次操作,QUERY代表询问从 x 到 y 路径上的边的最大
权值,CHANGE代表改变按输入顺序第 x 条边的权值为 y。 对于每个QUERY,输出一个答案。
题目思路:树链剖分(第一次学树链,还有点云里雾里的)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cctype>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <climits>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define fi first
#define se second
#define ping(x,y) ((x-y)*(x-y))
#define mst(x,y) memset(x,y,sizeof(x))
#define mcp(x,y) memcpy(x,y,sizeof(y))
using namespace std;
#define gamma 0.5772156649015328606065120
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define N 10050
#define maxn 30010
typedef pair<int,int> PII;
typedef long long LL;
LL read(){
LL x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,k,head[N],hcnt,rt;
char str[];
struct Node{
int to,nxt,v;
}node[maxn];
struct Edge{
int x,y,v;
}edge[maxn];
int seg[N<<]; int siz[N]; ///当前节点保存的儿子数
int top[N]; ///当前节点所在链的顶端节点
int son[N]; ///保存重儿子
int dep[N]; ///当前节点深度
int fa[N]; ///当前节点的父亲
int id[N]; ///用来保存树中每个节点剖分后的新编号
int posi[N]; ///在线段树中的位置
int tid,pos; ///树链剖分
void dfs1(int u,int f,int deep){ ///找重边
dep[u]=deep;
fa[u]=f;
siz[u]=;
for(int i=head[u];~i;i=node[i].nxt){
int e=node[i].to;
if(e==f)continue;
dfs1(e,u,deep+);
siz[u]+=siz[e];
if(!son[u]||siz[son[u]]<siz[e])
son[u]=e;
}
}
void dfs2(int u,int tp){ ///连重边成重链
top[u]=tp;
id[u]=++tid;
posi[id[u]]=u;
if(!son[u])return;
dfs2(son[u],tp);
for(int i=head[u];~i;i=node[i].nxt){
int e=node[i].to;
if(e!=son[u]&&e!=fa[u])
dfs2(e,e);
}
} ///线段树
void build(int rt,int l,int r){
seg[rt]=-inf;
if(l==r) return;
int mid=l+r>>;
build(lson); build(rson);
seg[rt]=max(seg[rt<<],seg[rt<<|]);
} void add(int rt,int l,int r,int v){
if(l==r){
seg[rt]=v;
return;
}
int mid=l+r>>;
if(pos<=mid)add(lson,v);
else add(rson,v);
seg[rt]=max(seg[rt<<],seg[rt<<|]);
}
int query(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R){return seg[rt];}
int mid=l+r>>;
int temp=INT_MIN;
if(L<=mid)temp=max(temp,query(lson,L,R));
if(R>mid) temp=max(temp,query(rson,L,R));
return temp;
} void ini(){
mst(head,-);hcnt=tid=;mst(seg,);
mst(son,);mst(siz,);
}
void add(int x,int y,int v){
node[hcnt].to=y,node[hcnt].nxt=head[x],node[hcnt].v=v,head[x]=hcnt++;
node[hcnt].to=x,node[hcnt].nxt=head[y],node[hcnt].v=v,head[y]=hcnt++;
}
int lca(int x,int y){
int ans=-inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=max(ans,query(,,n,id[top[x]],id[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
if(x!=y)ans=max(ans,query(,,n,id[x]+,id[y]));
return ans;
}
int main(){
//freopen("in.txt","r",stdin);
int i,j,group,x,y,v,Case=;
group=read();
while(group--){
ini();
n=read();
for(i=;i<n;++i){
scanf("%d%d%d",&x,&y,&v);
edge[i].x=x,edge[i].y=y,edge[i].v=v;
add(x,y,v);
}
dfs1(,,);
dfs2(,);
build(,,n);
for(i=;i<n;i++){
if(dep[edge[i].x]<dep[edge[i].y])
swap(edge[i].x,edge[i].y);
pos=id[edge[i].x];
add(,,n,edge[i].v);
}
while(scanf("%s",str)!=EOF){
if(str[]=='D')break;
x=read();y=read();
if(str[]=='Q'){
printf("%d\n",lca(x,y));
}
else{
pos=id[edge[x].x];
add(,,n,y);
}
}
printf("\n");
}
return ;
}
SPOJ 375 QTREE的更多相关文章
- spoj 375 QTREE - Query on a tree 树链剖分
题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #includ ...
- SPOJ 375 QTREE - Query on a tree
思路 注意本题只能用C,不能用C++ 其他的都和上一题一样 代码 #include <stdio.h> #include <string.h> #define MAXN 100 ...
- 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, ...
- SPOJ 375 树链剖分 QTREE - Query on a tree
人生第一道树链剖分的题目,其实树链剖分并不是特别难. 思想就是把树剖成一些轻链和重链,轻链比较少可以直接修改,重链比较长,用线段树去维护. 貌似大家都是从这篇博客上学的. #include <c ...
- SPOJ 375. Query on a tree (树链剖分)
Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Ori ...
- SPOJ 375 树链剖分
SPOJ太慢了,SPOJ太慢了, 题意:给定n(n<=10000)个节点的树,每条边有边权,有两种操作:1.修改某条变的边权:2.查询u,v之间路径上的最大边权. 分析:树链剖分入门题,看这里: ...
- SPOJ 375. Query on a tree (动态树)
375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ...
- 动态树(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) ...
- spoj 375 树链剖分 模板
QTREE - Query on a tree #tree You are given a tree (an acyclic undirected connected graph) with N no ...
随机推荐
- OCR 识别原理
https://mp.weixin.qq.com/s?__biz=MzA3MDExNzcyNA==&mid=402907292&idx=1&sn=889c4abcf576e24 ...
- unity, undo
如果在操作一个Object之前调用Undo.RecordObject(Object),且操作确实造成Object某些属性的改变,则会产生一个undo记录. 如果我们的架构不是直接操作Object,而是 ...
- MySQL主从双向同步复制
本文介绍了mysql主从,实现mysql的双向同步复制. MySQL支持单向.异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.主服务器将更新写入二进制日志文件,并维护日 ...
- python登陆Tom邮箱的代码一例
本文出处参考:http://www.cnblogs.com/LinuxHunter/archive/2010/11/30/1891635.html 在很多的python 教程中都会讲到登录邮箱或发送邮 ...
- sed n/N使用说明
sed的语法格式: sed [option] {sed-command} {input-file} sed在正常情况下,将处理的行读入模式空间(pattern space),脚本中的“sed-comm ...
- 信号处理函数(3)-sigaction() 为信号注册信号捕捉函数
定义: int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact); 表头文件: #include& ...
- 什么是:before和:after?
前几天的晚上较全面的去看了下css的一些文档和资料,大部分的样式运用都没什么大问题了,只是有些许较陌生,但是也知道他们的存在和实现的是什么样式.今天主要想在这篇学习笔记中写的也不多,主要是针对:bef ...
- rip中的连续子网以及不连续子网
RIPv1 RIPv2 距离矢量2 距离矢量 最大跳计数15 最大跳计数15 有类的 无类的 基于广播的 基于组播224.0.09 不支持VLSM 支持VLSM 无认证 允许MD5认证 不支持不 ...
- 解决The markup in the document following the root element must be well-formed.
出现问题的代码: <security-constraint> <web-resource-collection> <web-resource-name>Regist ...
- eclipse生成export生成jar详解
使用eclipse打jar包可能还有很多人不是很了解,今天特意测试整理一番. 打jar包有3种形式 JAR file JAR Javadoc ja ...