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 ...
随机推荐
- C# 基础: new 和 overrider 的区别
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- ArcGis10.0常见错误
1. 问题: Arcgis10.0 组件初始化失败 解决方法: ESRI.ArcGIS.RuntimeManager.BindLicense(ESRI.ArcGIS.ProductCode.Eng ...
- 类模板、Stack的类模板实现(自定义链栈方式,自定义数组方式)
一.类模板 类模板:将类定义中的数据类型参数化 类模板实际上是函数模板的推广,可以用相同的类模板来组建任意类型的对象集合 (一).类模板的定义 template <类型形参表> clas ...
- HDU 3746 数据结构之KMP
pid=3746">点击打开链接 题意:给T组数据,每组一个字符串,问最少加入多少个字符能够使这个串变成一个子串连续出现的串 思路:利用KMP的next数组进行变换,next数组保存的 ...
- 如何用C#做一个悬浮窗口程序
用C#做一个像FlashGet的悬浮窗口,其实很简单,不像以前需要调用很多系统API.大致的步骤如下. 首先是主窗体部分,即要判断窗体的状态来决定是否显示悬浮窗口. 局部成员声明: private F ...
- C#位操作
一.原码与补码 在计算机系统中,数值一律用补码来存储(表示).主要原因:使用补码,可以将符号位和其他位统一处理:同时减法也可按加法来处理.另外,两个补码表示的数相加时,如果最高位(符号位)有进位,则进 ...
- PhotoView
PhotoView 介绍 追求美是人的天性 PhotoView.js 灵感来自于picasa 本功能是为了解决运营对后台管理系统中用户上传的各种角度和尺寸的图片难以浏览的问题,于是花了两天时间写了这个 ...
- 如何编写安全的PHP代码
转于:http://www.nowamagic.net/php/php_HowToWriteSafePhpCode.php
- JsonHelper修改4.0
public class JsonHelper { /// <summary> /// 将对象序列化为JSON格式 /// </summary> /// <param n ...
- CBiontCache
/************************************************************************/ /* 预先加载一些生物以备将来使用 */ /* 专 ...