poj 3237 tree 树链剖分(边权)

将所有的边权变为边上两点里面的深度更大的节点的点权,然后在更新的时候,最后的一条链如果是一个点的话就不更新,反之,从头节点的儿子开始更新,即不更新头节点

Code:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
using namespace std;
#define ll long long
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
#define imid int mid=(left+right)/2;
const ll MAXN = 10005;
struct edge
{
	int to;
	int nex;
}e[MAXN * 2];
int head[MAXN], tot;
int n, m, q;
int fa[MAXN], son[MAXN], deep[MAXN], num[MAXN];
int top[MAXN], p[MAXN], fp[MAXN];
int pos;
int ql, qr;
ll val;
void init()
{
	tot = 0;
	memset(head, -1, sizeof(head));
	pos = 1;
	memset(son, -1, sizeof(son));
}
void add(int a, int b)
{
	e[tot] = edge{ b,head[a] };
	head[a] = tot++;
}
void dfs1(int u, int pre, int dep)
{
	deep[u] = dep;
	fa[u] = pre;
	num[u] = 1;
	for (int i = head[u]; i + 1; i = e[i].nex)
	{
		int v = e[i].to;
		if (v != pre)
		{
			dfs1(v, u, dep + 1);
			num[u] += num[v];
			if (son[u] == -1 || num[son[u]] < num[v])
				son[u] = v;
		}
	}
}
void dfs2(int u, int sp)
{
	top[u] = sp;
	p[u] = pos++;
	fp[p[u]] = u;
	if (son[u] == -1)
		return;
	dfs2(son[u], sp);
	for (int i = head[u]; i + 1; i = e[i].nex)
	{
		int v = e[i].to;
		if (v != son[u] && v != fa[u])
			dfs2(v, v);
	}
}

struct node
{
	int l;
	int r;
	ll minn;
	ll maxn;
	int mark;
}que[MAXN * 4];
void up(int k)
{
	que[k].maxn = max(que[k << 1].maxn, que[k << 1 | 1].maxn);
	que[k].minn = min(que[k << 1].minn, que[k << 1 | 1].minn);
}
void down(int k)
{
	if (que[k].mark)
	{
		swap(que[k << 1].maxn, que[k << 1].minn);
		que[k << 1].maxn = -que[k << 1].maxn;
		que[k << 1].minn = -que[k << 1].minn;
		que[k << 1].mark ^= 1;
		swap(que[k << 1 | 1].maxn, que[k << 1 | 1].minn);
		que[k << 1 | 1].maxn = -que[k << 1 | 1].maxn;
		que[k << 1 | 1].minn = -que[k << 1 | 1].minn;
		que[k << 1 | 1].mark ^= 1;
		que[k].mark = 0;
	}
}
void build(int left = 1, int right = pos, int k = 1)
{
	que[k].l = left;
	que[k].r = right;
	que[k].mark = 0;
	que[k].maxn = -1e9;
	que[k].minn = 1e9;
	if (left == right)
		return;
	imid;
	build(lson);
	build(rson);
}
void update1(int left = 1, int right = pos, int k = 1)
{
	if (qr < left || right < ql)
		return;
	if (ql <= left && right <= qr)
	{
		que[k].mark = 0;
		que[k].maxn = val;
		que[k].minn = val;
		return;
	}
	down(k);
	imid;
	update1(lson);
	update1(rson);
	up(k);
}
void update2(int left = 1, int right = pos, int k = 1)
{
	if (qr < left || right < ql)
		return;
	if (ql <= left && right <= qr)
	{
		swap(que[k].maxn, que[k].minn);
		que[k].maxn = -que[k].maxn;
		que[k].minn = -que[k].minn;
		que[k].mark ^= 1;
		return;
	}
	down(k);
	imid;
	update2(lson);
	update2(rson);
	up(k);
}
ll query(int left = 1, int right = pos, int k = 1)
{
	if (qr < left || right < ql)
		return -1e9;
	if (ql <= left && right <= qr)
		return que[k].maxn;
	down(k);
	imid;
	return max(query(lson), query(rson));
}

void change2(int u, int v)
{
	int f1 = top[u], f2 = top[v];
	while (f1 != f2)
	{
		if (deep[f1] < deep[f2])
		{
			swap(f1, f2);
			swap(u, v);
		}
		ql = p[f1];
		qr = p[u];
		update2();

		u = fa[f1];
		f1 = top[u];
	}
	if (u == v)
		return;
	if (deep[u] > deep[v])
		swap(u, v);
	ql = p[son[u]];
	qr = p[v];
	update2();
}
ll changes(int u, int v)
{
	ll res = -1e9;
	int f1 = top[u], f2 = top[v];
	while (f1 != f2)
	{
		if (deep[f1] < deep[f2])
		{
			swap(f1, f2);
			swap(u, v);
		}
		ql = p[f1];
		qr = p[u];
		res = max(res, query());
		u = fa[f1];
		f1 = top[u];
	}
	if (u == v)
		return res;
	if (deep[u] > deep[v])
		swap(u, v);
	ql = p[son[u]];
	qr = p[v];
	res = max(res, query());
	return res;
}

char op[10];
int in[MAXN][3];
int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d", &n);
		init();
		for (int i = 0; i < n - 1; i++)
		{
			scanf("%d%d%d", &in[i][0], &in[i][1], &in[i][2]);
			add(in[i][0], in[i][1]);
			add(in[i][1], in[i][0]);
		}
		dfs1(1, 0, 0);
		dfs2(1, 1);
		build();
		for (int i = 0; i < n - 1; i++)
		{
			if (deep[in[i][0]] > deep[in[i][1]])
				swap(in[i][0], in[i][1]);
			ql = p[in[i][1]];
			qr = ql;
			val = in[i][2];
			update1();
		}
		while (true)
		{
			scanf("%s", op);
			if (op[0] == 'C')
			{
				scanf("%d%lld", &ql, &val);
				ql = p[in[ql - 1][1]];
				qr = ql;
				update1();
			}
			else if (op[0] == 'N')
			{
				scanf("%d%d", &ql, &qr);
				change2(ql, qr);
			}
			else if (op[0] == 'Q')
			{
				scanf("%d%d", &ql, &qr);
				ll res = changes(ql, qr);
				printf("%lld\n", res);
			}
			else
				break;
		}
	}
}

 

全部评论

相关推荐

12-08 07:42
门头沟学院 Java
27届末九,由于是女生,身边人几乎没有就业导向的,自学只能跟着网课,没人指导,很迷茫。下图是我目前的简历,不知道有需要修改的地方吗?求拷打。下面是目前的学习情况:目前算法过完了一遍力扣100和代码随想录,不过不是很熟,面经看了小林coding、JavaGuide,有一些没用过的技术看得不是很明白,掌握得不是很扎实。再加上常年跟黑马网课听思路,真正自己动手写代码的时间很少,这让我一直不敢投简历,总觉得内里空虚。项目没准备好面试相关的问题,简历上相应的考点不熟。如此种种。。。看到很多很多学长学姐大佬们的面经,愈发觉得面试可怕,自己没准备好,总担心自己是不是无望后端开发了。看到牛客很多同届以及更小一届的同学都找到实习了,很希望自己也能找到实习。而自己又好像摸不到后端学习的门路,只能不断赞叹黑马虎哥写的代码真优雅!微服务架构实在巧妙!消息队列、redis、sentinel、nacos、mybatisplus等等的引入都会让我赞叹这些工具的设计者的巧思,以及包括但不限于Java语言的优雅。然而只是停留在了解的程度,并不熟练。我是很希望能够继续深入探索这些知识的,只不过有一大部分时间都花在学校课程上了。我感觉我被困住了,我一方面必须保证我能够有个不错的学业分使我能有我几乎不想选择的读研退路(还有个原因是复习不全我会焦虑考试挂科,因此我会做好全面的准备,而这一步很费时间),一方面在B站学习各种网课,一方面得考虑提升自己并不扎实的算法基础,另一方面还得准备八股面经。这让我有点苦恼,我好像没那么多时间,因为绝大部分时间都花在了复习学校科目中了。我好像处处用时间,但收效甚微。想问问各位大佬是怎么平衡时间的呢?算法、项目和八股是怎么准备的呢?有什么高效的方法吗?谢谢您们花时间阅读我的稿件!
菜菜狗🐶:大胆投,我当时也是害怕面试,投多了发现根本约不到面🤡
投递哔哩哔哩等公司6个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务