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
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 100005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
#define mclr(x,a) memset((x),a,sizeof(x))
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-5
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii; inline int rd() {
int x = 0;
char c = getchar();
bool f = false;
while (!isdigit(c)) {
if (c == '-') f = true;
c = getchar();
}
while (isdigit(c)) {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return f ? -x : x;
} ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; } /*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1; y = 0; return a;
}
ans = exgcd(b, a%b, x, y);
ll t = x; x = y; y = t - a / b * y;
return ans;
}
*/
struct node {
int to, nxt;
}e[maxn];
int head[maxn], tot;
int top[maxn];// top[v]表示v所在的重链的顶点
int fa[maxn];
int dep[maxn];
int num[maxn];// num[v]表示以v为根的子树大小
int p[maxn];// p[v]表示v与其父亲节点在线段树的位置
int fp[maxn];
int son[maxn];// 重儿子
int pos;
int n; void init() {
tot = 0; memset(head, -1, sizeof(head));
pos = 1; memset(son, -1, sizeof(son));
}
void addedge(int u, int v) {
e[tot].to = v; e[tot].nxt = head[u]; head[u] = tot++;
} void dfs1(int u, int pre, int d) {
dep[u] = d; fa[u] = pre; num[u] = 1;
for (int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if (v != pre) {
dfs1(v, u, d + 1);
num[u] += num[v];
if (son[u] == -1 || num[v] > num[son[u]])son[u] = v;
}
}
} void dfs2(int u, int sp) {
top[u] = sp;
if (son[u] != -1) {
p[u] = pos++;
fp[p[u]] = u;
dfs2(son[u], sp);
}
else {
p[u] = pos++; fp[p[u]] = u; return;
}
for (int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if (v != son[u] && v != fa[u])dfs2(v, v);
}
} #define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int maxx[maxn];
int val[maxn];
void pushup(int rt) {
maxx[rt] = max(maxx[rt << 1], maxx[rt << 1 | 1]);
}
void build(int l, int r, int rt) {
if (l == r) {
maxx[rt] = val[l]; return;
}
int m = (l + r) >> 1;
build(lson); build(rson); pushup(rt);
}
void upd(int p, int x, int l, int r, int rt) {
if (l == r) {
maxx[rt] = x; return;
}
int m = (l + r) >> 1;
if (p <= m)upd(p, x, lson);
else upd(p, x, rson);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return maxx[rt];
}
int m = (l + r) >> 1;
int ans = 0;
if (L <= m)ans = max(ans, query(L, R, lson));
if (m < R)ans = max(ans, query(L, R, rson));
return ans;
} int Find(int u, int v) {
int f1 = top[u], f2 = top[v];
int tmp = 0;
while (f1 != f2) {
if (dep[f1] < dep[f2]) {
swap(f1, f2); swap(u, v);
}
tmp = max(tmp, query(p[f1], p[u], 1, n, 1));
u = fa[f1]; f1 = top[u];
}
if (u == v)return tmp;
if (dep[u] > dep[v])swap(u, v);
return max(tmp, query(p[son[u]], p[v], 1, n, 1));
}
int ed[maxn][3]; int main()
{
// ios::sync_with_stdio(0);
int t; t = rd();
while (t--) {
init(); n = rd();
// getchar();
for (int i = 0; i < n - 1; i++) {
ed[i][0] = rd(); ed[i][1] = rd(); ed[i][2] = rd();
addedge(ed[i][0], ed[i][1]);
addedge(ed[i][1], ed[i][0]);
}
dfs1(1, 0, 0); dfs2(1, 1);
for (int i = 0; i < n - 1; i++) {
if (dep[ed[i][0]] < dep[ed[i][1]]) {
swap(ed[i][0], ed[i][1]);
}
val[p[ed[i][0]]] = ed[i][2];
}
build(1, n, 1);
char opt[10];
while (scanf("%s",opt)) {
if (opt[0] == 'D')break;
int u, v; u = rd(); v = rd();
if (opt[0] == 'Q') {
printf("%d\n", Find(u, v));
}
else upd(p[ed[u - 1][0]], v, 1, n, 1);
}
}
return 0;
}
Query on a tree 树链剖分 [模板]的更多相关文章
- SPOJ 375 Query on a tree 树链剖分模板
第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- spoj 375 QTREE - Query on a tree 树链剖分
题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #includ ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- 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 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 QTREE Query on a tree ——树链剖分 线段树
[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #incl ...
随机推荐
- SQL和NoSQL
SQL和NoSQL 目前的数据库系统非常多,有传统的关系型的数据库系统(又被称为SQL数据库系统),有最近几年流行起来的NoSQL数据库系统.其中NoSQL数据库系统又分为很多种不同的类型,根据各个系 ...
- Java基础-JDK、JRE与JVM的区别
JRE与JVM.JDK的区别 从下而上:最上层 JDK -- java development kit (java开发工具包)中间层 JRE -- java runtime enviro ...
- jmeter 插件
- OS线程模型
线程模型 N对1 内核线程 映射 用户进程, 用户进程里可以启多个线程 1对1 内核线程和用户线程 1对1 Linux采用这种方式 N对M 用户线程被抽象为更轻量的线程, 内核线程和轻量的线程对应 进 ...
- js-修改url中某个指定的参数的值
/* * url 目标url * arg 需要替换的参数名称 * arg_val 替换后的参数的值 * return url 参数替换后的url */ function changeURLArg(ur ...
- oracle数据库基本操作
我们主要学习数据库的一些基本操作,比如如何在数据库创建用户,授权,删除用户,回收权限,为用户加锁或者解锁等一些常用的操作. 首先,我们要知道数据库中创建用户的语句怎么写,看下面: 1.创建用户 cre ...
- 三年经验的C,超过两题答不出请离开软件界
1.double free是什么问题?申请地址与释放地址不一致会有什么问题? 2.main函数最多有几个参数?各是什么作用? 3.crt是什么?编译器是怎么样连接crt的(描述cl或者gcc方式) 4 ...
- LibreOJ 6002 最小路径覆盖(最大流)
题解:最小路径覆盖=总点数减去最大匹配数,拆点,按照每条边前一个点连源点,后一个点连汇点跑最大流,即可跑出最大匹配数,然后减一减就可以了~ 代码如下: #include<queue> #i ...
- Ubuntu下vi编辑器不听话
编辑文件/etc/vim/vimrc.tiny,将“compatible”改成“nocompatible”非兼容模式: 并添加一句:set backspace=2
- 关于MVC刷新页面会两次请求页面的原因
遇到这个奇葩的问题刚开始关注点全放在后台了 ,以为后台哪个地方存在问题,找了半天一无所获之后才开始把问题关注点移到前端,通过不断的注释前台代码, 终于发现了问题,没想到是这个js导致的问题 因为的Vi ...