URAL 1553. Caves and Tunnels 树链剖分

一棵树 开始每个点的权值都为0

2种操作1.将第i个点的权值增加x 2.求u到v这条路上最大的权值

树链剖分基础题

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010;
struct edge
{
	int v, next;
}e[maxn*2];
int first[maxn], cnt;

void AddEdge(int u, int v)
{
	e[cnt].v = v;
	e[cnt].next = first[u];
	first[u] = cnt++;
	e[cnt].v = u;
	e[cnt].next = first[v];
	first[v] = cnt++;
}

int top[maxn], sz[maxn], son[maxn], f[maxn], dep[maxn];
int n, id[maxn], rank[maxn], tid;
void init()
{
	memset(first, -1, sizeof(first));
	cnt = 0;
	memset(son, -1, sizeof(son));
	tid = 0;
}

void dfs1(int u, int fa, int d)
{
	sz[u] = 1;
	f[u] = fa;
	dep[u] = d;
	for(int i = first[u]; i != -1; i = e[i].next)
	{
		int v = e[i].v;
		if(v == fa)
			continue;
		dfs1(v, u, d+1);
		sz[u] += sz[v];
		if(son[u] == -1 || sz[son[u]] < sz[v])
			son[u] = v;
	}
}

void dfs2(int u, int tp)
{
	top[u] = tp;
	id[u] = ++tid;
	rank[tid] = u;
	if(son[u] == -1)
		return;
	dfs2(son[u], tp);
	for(int i = first[u]; i != -1; i = e[i].next)
	{
		int v = e[i].v;
		if(v != f[u] && son[u] != v)
			dfs2(v, v);
	}
}
int a[maxn<<2];

void pushup(int rt)
{
	a[rt] = max(a[rt<<1], a[rt<<1|1]);
}
void build(int l, int r, int rt)
{
	a[rt] = 0;
	if(l == r)
		return;
	int m = (l + r) >> 1;
	build(l, m, rt<<1);
	build(m+1, r, rt<<1|1);
}

int query(int x, int y, int l, int r, int rt)
{
	if(x == l && y == r)
	{
		return a[rt];
	}
	int m = (l + r) >> 1;
	if(y <= m)
		return query(x, y, l, m, rt<<1);
	else if(x > m)
		return query(x, y, m+1, r, rt<<1|1);
	else
	{
		return max(query(x, m, l, m, rt<<1), query(m+1, y, m+1, r, rt<<1|1));
	}
}

void update(int x, int l, int r, int rt, int d)
{
	if(l == r)
	{
		a[rt] += d;
		return;
	}

	int m = (l + r) >> 1;
	if(x <= m)
		update(x, l, m, rt<<1, d);
	else
		update(x, m+1, r, rt<<1|1, d);
	pushup(rt);
}

int change(int u, int v)
{
	int ans = 0;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]])
			swap(u, v);
		ans = max(ans, query(id[top[u]], id[u], 1, n, 1));
		u = f[top[u]];
	}
	if(dep[u] > dep[v])
		swap(u, v);
	ans = max(ans, query(id[u], id[v], 1, n, 1));
	return ans;
}
int main()
{
	while(scanf("%d", &n) != EOF)
	{
		init();
		for(int i = 1; i < n; i++)
		{
			int u, v;
			scanf("%d %d", &u, &v);
			AddEdge(u, v);
		}
		dfs1(1, 0, 0);
		dfs2(1, 1);
		build(1, n, 1);
		int q;
		scanf("%d", &q);

		while(q--)
		{
			char s[10];
			int u, v;
			scanf("%s %d %d", s, &u, &v);
			if(s[0] == 'G')
			{
				printf("%d\n", change(u, v));
			}
			else
			{
				update(id[u], 1, n, 1, v);
			}
		}
	}
	return 0;
}
时间: 2024-10-15 13:31:26

URAL 1553. Caves and Tunnels 树链剖分的相关文章

URAL 1553. Caves and Tunnels 树链拆分

一颗树 每次出发点右键值是0 2操作模式1.第一i右键点值添加x 2.乞讨u至v在这条路上右上方值 树为主的连锁分裂称号 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100010; struct edge { int v, next; }e[maxn*2]; int first[maxn], cnt; void AddEdg

URAL 题目1553. Caves and Tunnels(Link Cut Tree 改动点权,求两点之间最大)

1553. Caves and Tunnels Time limit: 3.0 second Memory limit: 64 MB After landing on Mars surface, scientists found a strange system of caves connected by tunnels. So they began to research it using remote controlled robots. It was found out that ther

URAL 题目1553. Caves and Tunnels(Link Cut Tree 修改点权,求两点之间最大)

1553. Caves and Tunnels Time limit: 3.0 second Memory limit: 64 MB After landing on Mars surface, scientists found a strange system of caves connected by tunnels. So they began to research it using remote controlled robots. It was found out that ther

BZOJ 2243: [SDOI2011]染色 树链剖分

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1886  Solved: 752[Submit][Status] Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写一个程序依次完成这m个操作. In

bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 7925  Solved: 2975[Submit][Status][Discuss] Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写一个程序依次完

bzoj3694: 最短路(树链剖分/并查集)

bzoj1576的帮我们跑好最短路版本23333(双倍经验!嘿嘿嘿 这题可以用树链剖分或并查集写.树链剖分非常显然,并查集的写法比较妙,涨了个姿势,原来并查集的路径压缩还能这么用... 首先对于不在最短路径树上的边x->y,设t为最短路径树上lca(x,y),则t到y上的路径上的点i到根的距离都可以用h[x]+dis[x][y]+h[y]-h[i](h[]为深度)来更新,因为h[i]一定,只要让h[x]+dis[x][y]+h[y]最小就行,这里用树剖直接修改整条链上的数,就可以过了. 并查集的

洛谷 P3384 【模板】树链剖分

题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数N.M.R.P,分别表示树的结点个数.操作个数

bzoj1036 树的统计(树链剖分+线段树)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 15120  Solved: 6141[Submit][Status][Discuss] Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I

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]