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, 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
推荐论文:《树链剖分》:http://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html
《QTREE解法的一些研究》:随便百度一下就有
思路:树链剖分,上面都讲得比较清楚了我就不讲了。对着树链剖分的伪代码写的,那个伪代码有一个错误(应该是错误吧……),询问那里应该是x = father[top[x]]。还有,在这题用线段树,点的权值记录与父节点的边的权值,那么最后的询问是要query(tid[x]+1, tid[y])
代码(3840MS):
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std; const int MAXN = ;
const int MAXE = * MAXN;
const int INF = 0x7fffffff; int head[MAXN], cost[MAXN], id[MAXN];
int weight[MAXE], to[MAXE], next[MAXE];
int n, ecnt; inline void init() {
memset(head, , sizeof(head));
ecnt = ;
} inline void add_edge(int u, int v, int c) {
to[ecnt] = v; weight[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; weight[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
} int maxt[MAXN * ]; void modify(int x, int left, int right, int a, int b, int val) {
if(a <= left && right <= b) maxt[x] = val;
else {
int ll = x << , rr = ll ^ ;
int mid = (left + right) >> ;
if(a <= mid) modify(ll, left, mid, a, b, val);
if(mid < b) modify(rr, mid + , right, a, b, val);
maxt[x] = max(maxt[ll], maxt[rr]);
}
} int query(int x, int left, int right, int a, int b) {
if(a <= left && right <= b) return maxt[x];
else {
int ll = x << , rr = ll ^ ;
int mid = (left + right) >> , ret = ;
if(a <= mid) ret = max(ret, query(ll, left, mid, a, b));
if(mid < b) ret = max(ret, query(rr, mid + , right, a, b));
return ret;
}
} int size[MAXN], fa[MAXN], dep[MAXN], son[MAXN];
int tid[MAXN], top[MAXN], dfs_clock; void dfs_size(int u, int f, int depth) {
fa[u] = f; dep[u] = depth;
size[u] = ; son[u] = ;
int maxsize = ;
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(v == f) continue;
cost[v] = weight[p];
dfs_size(v, u, depth + );
size[u] += size[v];
if(size[v] > maxsize) {
maxsize = size[v];
son[u] = v;
}
}
} void dfs_heavy_edge(int u, int ancestor) {
tid[u] = ++dfs_clock; top[u] = ancestor;
modify(, , n, tid[u], tid[u], cost[u]);
if(son[u]) dfs_heavy_edge(son[u], ancestor);
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(v == fa[u] || v == son[u]) continue;
dfs_heavy_edge(v, v);
}
} int query(int x, int y) {
int ret = ;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ret = max(ret, query(, , n, tid[top[x]], tid[x]));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ret = max(ret, query(, , n, tid[x] + , tid[y]));
return ret;
} void change(int x, int y) {
int u = to[x], v = to[x ^ ];
if(fa[u] == v) swap(u, v);
modify(, , n, tid[v], tid[v], y);
} char str[]; int main() {
int T; scanf("%d", &T);
for(int t = ; t <= T; ++t) {
scanf("%d", &n);
init();
for(int i = ; i < n; ++i) {
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
id[i] = ecnt;
add_edge(u, v, c);
}
memset(maxt, , sizeof(maxt));
dfs_size(, , ); cost[] = -INF;
dfs_clock = ;
dfs_heavy_edge(, );
while(scanf("%s", str) && *str != 'D') {
int x, y;
scanf("%d%d", &x, &y);
if(*str == 'C') change(id[x], y);
else printf("%d\n", query(x, y));
}
}
}
代码(3400MS)(加了个IO优化……):
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std; const int MAXN = ;
const int MAXE = * MAXN;
const int INF = 0x7fffffff; int head[MAXN], cost[MAXN], id[MAXN];
int weight[MAXE], to[MAXE], next[MAXE];
int n, ecnt; inline void init() {
memset(head, , sizeof(head));
ecnt = ;
} inline void add_edge(int u, int v, int c) {
to[ecnt] = v; weight[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; weight[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
} int maxt[MAXN * ]; void modify(int x, int left, int right, int a, int b, int val) {
if(a <= left && right <= b) maxt[x] = val;
else {
int ll = x << , rr = ll ^ ;
int mid = (left + right) >> ;
if(a <= mid) modify(ll, left, mid, a, b, val);
if(mid < b) modify(rr, mid + , right, a, b, val);
maxt[x] = max(maxt[ll], maxt[rr]);
}
} int query(int x, int left, int right, int a, int b) {
if(a <= left && right <= b) return maxt[x];
else {
int ll = x << , rr = ll ^ ;
int mid = (left + right) >> , ret = ;
if(a <= mid) ret = max(ret, query(ll, left, mid, a, b));
if(mid < b) ret = max(ret, query(rr, mid + , right, a, b));
return ret;
}
} int size[MAXN], fa[MAXN], dep[MAXN], son[MAXN];
int tid[MAXN], top[MAXN], dfs_clock; void dfs_size(int u, int f, int depth) {
fa[u] = f; dep[u] = depth;
size[u] = ; son[u] = ;
int maxsize = ;
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(v == f) continue;
cost[v] = weight[p];
dfs_size(v, u, depth + );
size[u] += size[v];
if(size[v] > maxsize) {
maxsize = size[v];
son[u] = v;
}
}
} void dfs_heavy_edge(int u, int ancestor) {
tid[u] = ++dfs_clock; top[u] = ancestor;
modify(, , n, tid[u], tid[u], cost[u]);
if(son[u]) dfs_heavy_edge(son[u], ancestor);
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(v == fa[u] || v == son[u]) continue;
dfs_heavy_edge(v, v);
}
} int query(int x, int y) {
int ret = ;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ret = max(ret, query(, , n, tid[top[x]], tid[x]));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
ret = max(ret, query(, , n, tid[x] + , tid[y]));
return ret;
} void change(int x, int y) {
int u = to[x], v = to[x ^ ];
if(fa[u] == v) swap(u, v);
modify(, , n, tid[v], tid[v], y);
} char str[]; inline int readint() {
char c = getchar();
while(!isdigit(c)) c = getchar();
int ret = ;
while(isdigit(c)) ret = ret * + c - '', c = getchar();
return ret;
} int main() {
int T = readint();
for(int t = ; t <= T; ++t) {
n = readint();
init();
for(int i = ; i < n; ++i) {
int u = readint(), v = readint(), c = readint();
id[i] = ecnt;
add_edge(u, v, c);
}
memset(maxt, , sizeof(maxt));
dfs_size(, , ); cost[] = -INF;
dfs_clock = ;
dfs_heavy_edge(, );
while(scanf("%s", str) && *str != 'D') {
int x = readint(), y = readint();
if(*str == 'C') change(id[x], y);
else printf("%d\n", query(x, y));
}
}
}
SPOJ 375 Query on a tree(树链剖分)(QTREE)的更多相关文章
- spoj 375 Query on a tree (树链剖分)
Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges ...
- SPOJ 375 Query on a tree 树链剖分模板
第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...
- spoj 375 QTREE - Query on a tree 树链剖分
题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #includ ...
- SPOJ QTREE Query on a tree 树链剖分+线段树
题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- SPOJ QTREE Query on a tree ——树链剖分 线段树
[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- Bzoj 2588 Spoj 10628. Count on a tree(树链剖分LCA+主席树)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Description 给定一棵N个节点的树,每个点 ...
- SPOJ QTREE Query on a tree --树链剖分
题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. ...
随机推荐
- Unity 游戏框架搭建 (十三) 无需继承的单例的模板
之前的文章中介绍的Unity 游戏框架搭建 (二) 单例的模板和Unity 游戏框架搭建 (三) MonoBehaviour单例的模板有一些问题. 存在的问题: 只要继承了单例的模板就无法再继承其他的 ...
- linux ccenteros 部署 redis
step one : yum install redis -- 安装redis数据库 step two:安装完成之后开启redis 服务 service redis start syste ...
- Windows 2008 server + IIS 7 设置身份模拟(ASP.NET impersonation)
IIS7 与 IIS 6 相比有了很大的改动,原来在 IIS 6 下可以的设置到了 IIS 7 下有的会发生变化.身份模拟的配置上,IIS7 和 IIS6有很大不同,网上IIS6的身份模拟的文章比较多 ...
- string类中字符的大小写转换
今天做一道题,要用string类,涉及大小写转换,查看了C++文档,string类没有提供这样的方法,只好自己写. 之后是想到一个比较笨的方法,我把string当成一个容器,然后用迭代器一个一个来替换 ...
- LintCode 7.Serialize and Deserialize Binary Tree(含测试代码)
题目描述 设计一个算法,并编写代码来序列化和反序列化二叉树.将树写入一个文件被称为“序列化”,读取文件后重建同样的二叉树被称为“反序列化”. 如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将 ...
- python网络编程,通过服务名称和会话类型(tcp,udp)获取端口号,简单的异常处理
作为一个php程序员,同时有对网络方面感兴趣,php就比较蛋疼了,所以就抽了些时间看python 之前学python基础因为工作原因,断断续续的看了个基础,差不多是可以写代码了 最近在看<pyt ...
- 一、Linux知识体系结构图
参考: https://blog.csdn.net/Swing_Liu/article/details/79202479
- STM32Cube 5.0 使用V1.7.0的固件库生成keil5环境下的F1工程时发现问题
生成的stm32f1xx_hal_msp.c文件里面,HAL_MspInit(void)函数居然没有了之前1.6库里面的系统中断优先级的设置: /* MemoryManagement_IRQn int ...
- 分布式系统的CAP(Redis)
CAP理论就是说在分布式存储系统中,最多只能实现上面的两点.而由于当前的网络硬件肯定会出现延迟丢包等问题,所以 分区容忍性是我们必须需要实现的. 所以我们只能在一致性和可用性之间进行权衡,没有NoSQ ...
- 38-JWT 设计解析及定制
可去官网下载Security项目查看源码 只需修改 AddJwtBearer中的行为即可 public void ConfigureServices(IServiceCollection servic ...