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;
}

原文地址:https://www.cnblogs.com/zxyqzy/p/10354449.html

时间: 2024-10-12 17:26:16

Query on a tree 树链剖分 [模板]的相关文章

spoj Query on a tree(树链剖分模板题)

375. Query on a tree Problem code: 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

SPOJ375 Query on a tree 树链剖分

SPOJ375  Query on a tree   树链剖分 no tags 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

SPOJ - QTREE 375 Query on a tree 树链剖分+线段树

操作1:修改第k条边权. 操作2:询问两点间最大边权. 树链剖分,然后线段树维护最大值 #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #inclu

spoj 375 QTREE - Query on a tree 树链剖分

题目链接 给一棵树, 每条边有权值, 两种操作, 一种是将一条边的权值改变, 一种是询问u到v路径上最大的边的权值. 树链剖分模板. #include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set&g

SPOJ 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 tior QUERY a b : ask fo

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 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 Q

SPOJ QTREE Query on a tree ——树链剖分 线段树

[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 20005 int T,n,fr[maxn],h[maxn],to[maxn],ne[maxn]

SPOJ QTREE Query on a tree --树链剖分

题意:给一棵树,每次更新某条边或者查询u->v路径上的边权最大值. 解法:做过上一题,这题就没太大问题了,以终点的标号作为边的标号,因为dfs只能给点分配位置,而一棵树每条树边的终点只有一个. 询问的时候,在从u找到v的过程中顺便查询到此为止的最大值即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath&

Query on a tree 树链剖分

题意: 给你一棵树,和树上边的权值,在有q组询问a,b,问你从节点a->节点1的路径上,不小于b的最大的边的权值是多少,输出 离线维护最大值线段树即可 模板题 #include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define R