SPOJ - QTREE 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 ab 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<bits/stdc++.h>
using namespace std;
const int maxn = 50010;
struct edge {
	int v, ne;
}ed[maxn * 2];
int head[maxn], cnt, n;
int fa[maxn], son[maxn], num[maxn], deep[maxn];
int p[maxn], fp[maxn], top[maxn];
int pos;
void init() {
	cnt = 0;
	memset(head, -1, sizeof head);
	pos = 1;
	memset(son, -1, sizeof son);
}
void addedge(int u, int v) {
	ed[cnt].v = v;
	ed[cnt].ne = head[u];
	head[u] = cnt++;
}
void dfs1(int u, int pre, int d) {
	deep[u] = d;
	fa[u] = pre;
	num[u] = 1;
	for (int i = head[u]; ~i; i = ed[i].ne) {
		int v = ed[i].v;
		if (v == pre)continue;
		dfs1(v, u, d + 1);
		num[u] += num[v];
		if (son[u] == -1 || num[v] > num[son[u]])
			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; i = ed[i].ne) {
		int v = ed[i].v;
		if (v != son[u] && v != fa[u]) {
			getpos(v, v);
		}
	}
}
struct node {
	int l, r;
	int Max;
}c[maxn * 4];
void build(int rt, int l, int r) {
	c[rt].l = l; c[rt].r = r;
	c[rt].Max = 0;
	if (l == r)return;
	int mid = (l + r) >> 1;
	build(rt << 1, l, mid);
	build((rt << 1) | 1, mid + 1, r);
}
void pushup(int rt) {
	c[rt].Max = max(c[rt << 1].Max, c[(rt << 1) | 1].Max);
}
void update(int rt, int k, int val) {
	if (c[rt].l == k&&c[rt].r == k) {
		c[rt].Max = val;
		return;
	}
	int mid = (c[rt].l + c[rt].r) >> 1;
	if (k <= mid)update(rt << 1, k, val);
	else update(((rt << 1) | 1), k, val);
	pushup(rt);
}
int query(int rt, int l, int r) {
	if (c[rt].l == l&&c[rt].r == r)
		return c[rt].Max;
	int mid = (c[rt].l + c[rt].r) >> 1;
	if (r <= mid)return query(rt << 1, l, r);
	else if (l > mid)return query((rt << 1) | 1, l, r);
	else return max(query(rt << 1, l, mid), query((rt << 1) | 1, mid + 1, r));
}
//查询u->v的最大值
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(1, p[f1], p[u]));
		u = fa[f1]; f1 = top[u];
	}
	if (u == v)return tmp;
	if (deep[u] > deep[v])swap(u, v);
	return max(tmp, query(1, p[son[u]], p[v]));
}
int e[maxn][3];
int main() {
	int te, n;
	ios::sync_with_stdio(0);
	cin >> te;
	while (te--) {
		init();
		cin >> n;
		for (int i = 1; i <= n - 1; i++) {
			cin >> e[i][0] >> e[i][1] >> e[i][2];
			addedge(e[i][0], e[i][1]);
			addedge(e[i][1], e[i][0]);
		}
		dfs1(1, 0, 0);
		getpos(1, 1);
		build(1, 1, pos);
		for (int i = 1; i <= n - 1; i++) {
			if (deep[e[i][0]] < deep[e[i][1]]) {
				swap(e[i][0], e[i][1]);
			}
			update(1, p[e[i][0]], e[i][2]);
		}
		string que;
		while (cin >> que) {
			int a, b;
			if (que[0] == 'D')break;
			else if (que[0] == 'C') {
				cin >> a >> b;
				update(1, p[e[a][0]], b);
			}
			else {
				cin >> a >> b;
				cout << find(a, b) << endl;
			}
		}
	}
	return 0;
}

 

全部评论

相关推荐

11-26 22:34
已编辑
重庆邮电大学 Java
快手 客户端开发 (n+5)k*16 公积金12
牛客895077908号:佬 什么双非硕啊
点赞 评论 收藏
分享
最近又搬回宿舍了,在工位坐不住,写一写秋招起伏不断的心态变化,也算对自己心态的一些思考表演式学习从开始为实习准备的时候就特别焦虑,楼主一开始选择的是cpp后端,但是24届这个方向已经炸了,同时自己又因为本科非92且非科班,所以感到机会更加迷茫。在某天晚上用java写出hello&nbsp;world并失眠一整晚后选择老本行干嵌入式。理想是美好的,现实情况是每天忙但又没有实质性进展,总是在配环境,调工具,顺带还要推科研。而这时候才发现自己一直在表演式学习,徘徊在设想如何展开工作的循环里,导致没有实质性进展。现在看来当时如果把精力专注在动手写而不是两只手端着看教程,基本功或许不会那么差。实习的焦虑5月,楼主...
耶比:哲学上有一个问题,玛丽的房间:玛丽知道眼睛识别色彩的原理知道各种颜色,但是她生活在黑白的房间里,直到有一天玛丽的房门打开了她亲眼看到了颜色,才知道什么是色彩。我现在最大可能的减少对非工作事情的思考,如果有一件事困扰了我, 能解决的我就直接做(去哪里或者和谁吵架等等……),解决不了的我就不想了,每一天都是最年轻的一天,珍惜今天吧
投递比亚迪等公司10个岗位 > 秋招被确诊为…… 牛客创作赏金赛
点赞 评论 收藏
分享
双非坐过牢:非佬,可以啊10.28笔试,11.06评估11.11,11.12两面,11.19oc➕offer
点赞 评论 收藏
分享
10-09 22:05
666 C++
找到工作就狠狠玩CSGO:报联合国演讲,报电子烟设计与制造
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务