SPOJ - QTREE(树链剖分+单点更新+区间最大值查询)
题意:给出n个点n-1条边的树,有两个操作,一个是查询节点l到r的边的最大值,然后指定边的更改权值。
题解:差不多是树链剖分的模版题,注意每个点表示的边是连向其父亲节点的边。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int M = 1e4 + 10;
struct Edge {
int v , next;
}edge[M << 1];
int head[M] , e;
int top[M];
int fa[M];
int p[M];
int fp[M];
int son[M];
int deep[M];
int num[M];
int pos;
void init() {
memset(head , -1 , sizeof(head));
memset(son , -1 , sizeof(son));
e = 0;
pos = 0;
}
void add(int u , int v) {
edge[e].v = v;
edge[e].next = head[u];
head[u] = e++;
}
void dfs1(int u , int pre , int d) {
deep[u] = d;
fa[u] = pre;
num[u] = 1;
for(int i = head[u] ; i != -1 ; i = edge[i].next) {
int v = edge[i].v;
if(v != pre) {
dfs1(v , u , d + 1);
num[u] += num[v];
if(son[u] == -1 || num[son[u]] < num[v])
son[u] = v;
}
}
}
void getpos(int u , int sp) {
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1)
return ;
getpos(son[u] , sp);
for(int i = head[u] ; i != -1 ; i = edge[i].next) {
int v = edge[i].v;
if(son[u] != v && v != fa[u]) {
getpos(v , v);
}
}
}
struct TnT {
int l , r , MAX;
}T[M << 2];
void pushup(int i) {
T[i].MAX = max(T[i << 1].MAX , T[(i << 1) | 1].MAX);
}
void build(int l , int r , int i) {
int mid = (l + r) >> 1;
T[i].l = l , T[i].r = r , T[i].MAX = 0;
if(T[i].l == T[i].r)
return ;
build(l , mid , i << 1);
build(mid + 1 , r , (i << 1) | 1);
pushup(i);
}
void updata(int pos , int i , int ad) {
int mid = (T[i].l + T[i].r) >> 1;
if(T[i].l == pos && T[i].r == pos) {
T[i].MAX = ad;
return ;
}
if(mid < pos) {
updata(pos , (i << 1) | 1 , ad);
}
else {
updata(pos , i << 1 , ad);
}
pushup(i);
}
int query(int l , int r , int i) {
int mid = (T[i].l + T[i].r) >> 1;
if(T[i].l == l && T[i].r == r) {
return T[i].MAX;
}
pushup(i);
if(mid < l) {
return query(l , r , (i << 1) | 1);
}
else if(mid >= r) {
return query(l , r , i << 1);
}
else {
return max(query(l , mid , i << 1) , query(mid + 1 , r , (i << 1) | 1));
}
}
int find(int u , int v) {
int f1 = top[u] , f2 = top[v];
int tmp = 0;
while(f1 != f2) {
if(deep[f1] < deep[f2]) {
swap(f1 , f2);
swap(u , v);
}
tmp = max(tmp , query(p[f1] , p[u] , 1));
u = fa[f1] , f1 = top[u];
}
if(u == v) return tmp;
if(deep[u] > deep[v]) swap(u , v);
return max(tmp , query(p[son[u]] , p[v] , 1));
}
int ed[M][3];
int main() {
int t , n , u , v;
scanf("%d" , &t);
while(t--) {
scanf("%d" , &n);
init();
for(int i = 0 ; i < n - 1 ; i++) {
for(int j = 0 ; j < 3 ; j++) {
scanf("%d" , &ed[i][j]);
}
add(ed[i][0] , ed[i][1]);
add(ed[i][1] , ed[i][0]);
}
dfs1(1 , 0 , 0);
getpos(1 , 1);
build(0 , pos , 1);
for(int i = 0 ; i < n - 1 ; i++) {
if(deep[ed[i][0]] > deep[ed[i][1]])
swap(ed[i][0] , ed[i][1]);
updata(p[ed[i][1]] , 1 , ed[i][2]);
}
char cp[10];
while(scanf("%s" , cp)) {
if(cp[0] == 'D')
break;
scanf("%d%d" , &u , &v);
if(cp[0] == 'C') {
updata(p[ed[u - 1][1]] , 1 , v);
}
else {
printf("%d\n" , find(u , v));
}
}
}
return 0;
}
SPOJ - QTREE(树链剖分+单点更新+区间最大值查询)的更多相关文章
- BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分+单点更新+区间求和+区间求最大值)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 题意:略. 题解:树链剖分模版,注意一些细节即可. #include <ios ...
- HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)
Problem Description Dylans is given a tree with N nodes. All nodes have a value A[i].Nodes on tree i ...
- SPOJ QTREE 树链剖分
树链剖分的第一题,易懂,注意这里是边. #include<queue> #include<stack> #include<cmath> #include<cs ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- 【学术篇】SPOJ QTREE 树链剖分
发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能 ...
- QTREE 树链剖分---模板 spoj QTREE
<树链剖分及其应用> 一文讲得非常清楚,我一早上就把他学会了并且A了这题的入门题. spoj QTREE 题目: 给出一棵树,有两种操作: 1.修改一条边的边权. 2.询问节点a到b的最大 ...
- SPOJ 375 树链剖分 QTREE - Query on a tree
人生第一道树链剖分的题目,其实树链剖分并不是特别难. 思想就是把树剖成一些轻链和重链,轻链比较少可以直接修改,重链比较长,用线段树去维护. 貌似大家都是从这篇博客上学的. #include <c ...
- poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)
题目链接:http://poj.org/problem?id=2763 题意:给一个数,边之间有权值,然后两种操作,第一种:求任意两点的权值和,第二,修改树上两点的权值. 题解:简单的树链剖分. #i ...
- SPOJ 375 树链剖分
SPOJ太慢了,SPOJ太慢了, 题意:给定n(n<=10000)个节点的树,每条边有边权,有两种操作:1.修改某条变的边权:2.查询u,v之间路径上的最大边权. 分析:树链剖分入门题,看这里: ...
随机推荐
- Codeforces Round #192 (Div. 2) (329A)C.Purification
题意: 在一个正常的点可以净化该行该列的所有细胞,判断是否可以净化所有的细胞,并且输出所选的点. 思路: 如果可以的话,一定会选n个点. 先判断每一行是否有正常细胞,然后判断每一列是否有,如果都没有肯 ...
- Golang Context 包详解
Golang Context 包详解 0. 引言 在 Go 语言编写的服务器程序中,服务器通常要为每个 HTTP 请求创建一个 goroutine 以并发地处理业务.同时,这个 goroutine 也 ...
- Java基础之二十 并发
20.1 并发得多面性 并发编程令人困惑的一个主要原因:使用并发时需要解决的问题有多个,而实现并发的方法也有多种,并且在这两者之间没有明显的映射关系. 20.1.1 更快的执行 速度问题初听起来很简单 ...
- js 共有和私有
//共有 var SunHang = function(){ var name = "ssss"; this.name = "hhhhh"; function ...
- java NIO知多少
背景 Linux系统中的IO操作内部相当复杂,下面是一张带图片的LinuxIO相关层级关系: 下面是一个简化版本Linux内部IO层级图: 对此我的理解,java程序员版本的IO理解: java中的I ...
- QMS 的趨勢概述
自泰勒Taylor提出的科学管理被奉行后,制造业的分工已然成形,而产品不再是由工匠单独负责完成.为确保产品的质量,产品在完工后的检验为确保瑕疵品不外流出给客户的必要关卡.然而当产品依靠检验结果并无法减 ...
- C++实现微信WeChat网页接口推送股票报警消息
QStockView微信推送股票报警 1.功能简介 最近很多用户反馈,软件只能在电脑上使用,不能在手机上使用.所以增加了微信推送报警的功能,电脑端的报警提示消息可以通过微信同步发送到手机微信.这样即可 ...
- c语言的图形库
图形库链接http://www.easyx.cn/ 使用图形库头文件easyx.h或graphics.h 同样在里面下载图形库帮助文档进行查询 vs vc都可使用图形库 图形库窗口: initgrap ...
- @RequestBody 注意的问题
contentType : "application/json", //只能是这个 RequestBody 不能和form/data共存: @RequestMapping(valu ...
- 【MySql】linux下,设置mysql表名忽略大小写
[障碍再现] 状况描述01: 在LINUX下调一个程序经常报出找不到表,但是我明明是建了表的, 测试的时候,遇到一些问题,从Windows平台访问虚拟机中的Web应用,经常报出找不到表 ...