HYSBZ 1036 树的统计Count(树链剖分)

简单题,1A

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX 30030
#define ls rt<<1
#define rs ls|1
#define m (l+r)>>1
int sum[MAX << 2], sum2[MAX << 2];
int size[MAX], son[MAX], deep[MAX], pre[MAX], top[MAX],val[MAX];
int posx[MAX], head[MAX],posx2[MAX];
int cnt, pos;
struct edge
{
	int v, next;
}edg[MAX<<1];

void addedge(int u, int v)
{
	edg[cnt].v = v;
	edg[cnt].next = head[u];
	head[u] = cnt++;
}

void dfs(int u, int p, int d)
{
	deep[u] = d;
	size[u] = 1;
	pre[u] = p;
	for (int i = head[u]; i != -1; i = edg[i].next)
	{
		int v = edg[i].v;
		if (v != p)
		{
			dfs(v,u, d+ 1);
			size[u] += size[v];
			if (son[u] == -1 || size[v] > size[son[u]])
				son[u] = v;
		}
	}
}

void getpos(int u, int p)
{
	top[u] = p;
	posx2[pos] = u;
	posx[u] = pos++;
	if (son[u] == -1)
		return;
	getpos(son[u], p);
	for (int i = head[u]; i != -1; i = edg[i].next)
	{
		int v = edg[i].v;
		if (v != son[u]&&v!=pre[u])
			getpos(v, v);
	}
}

//线段树
void uprt(int rt)
{
	sum[rt] = sum[ls] + sum[rs];
	sum2[rt] = max(sum2[ls], sum2[rs]);
}

void build(int l, int r, int rt)
{
	if (l == r)
	{
		sum[rt] = val[posx2[l]];
		sum2[rt] = sum[rt];
		return;
	}
	int mid = m;
	build(l, mid, ls);
	build(mid + 1, r, rs);
	uprt(rt);
}


void updata(int q, int val, int l, int r, int rt)
{
	if (l == r)
	{
		sum[rt] = val;
		sum2[rt] = val;
		return;
	}
	int mid = m;
	if (q <= mid)
		updata(q ,val, l, mid, ls);
	else
		updata(q,val, mid + 1, r, rs);
	uprt(rt);
}

int queryS(int L, int R, int l, int r, int rt)
{
	if (L <= l&&r <= R)
		return sum[rt];
	int mid = m;
	int ans = 0;
	if (L <= mid)
		ans = queryS(L, R, l, mid, ls);
	if (mid < R)
		ans += queryS(L, R, mid + 1, r, rs);
	return ans;
}

int queryM(int L, int R, int l, int r, int rt)
{
	if (L <= l&&r <= R)
		return sum2[rt];
	int mid = m;
	int ans =-0x7ffffff;
	if (L <= mid)
		ans = max(ans, queryM(L, R, l, mid, ls));
	if (mid < R)
		ans = max(ans, queryM(L, R, mid + 1, r, rs));
	return ans;
}

int solve(int u, int v,int tg)
{
	int fu = top[u], fv = top[v];
	int ans;
	if (tg)
		ans = -0x7ffffff;
	else
		ans = 0;
	while (fu != fv)
	{
		if (deep[fu] < deep[fv])
		{
			swap(fu, fv);
			swap(u, v);
		}
		if (tg)
			ans = max(ans, queryM(posx[fu], posx[u], 1, pos - 1, 1));
		else
			ans += queryS(posx[fu], posx[u], 1, pos - 1, 1);
		u = pre[fu];
		fu = top[u];
	}
	if (u == v)
	{
		if (tg)
			ans = max(ans, queryM(posx[u], posx[u], 1, pos - 1, 1));
		else
			ans += queryS(posx[u], posx[u], 1, pos - 1, 1);
		return ans;
	}
	if (deep[u] > deep[v])
		swap(u, v);
	if (tg)
		ans = max(ans, queryM(posx[u], posx[v], 1, pos - 1, 1));
	else
		ans += queryS(posx[u], posx[v], 1, pos - 1, 1);
	return ans;
}

//void gao(int u, int v, int val)
//{
//	int fu = top[u], fv = top[v];
//	while (fu != fv)
//	{
//		if (deep[fu] < deep[fv])
//		{
//			swap(fu, fv);
//			swap(u, v);
//		}
//		updata(posx[fu], posx[u], val, 1, pos - 1, 1);
//		u = pre[fu];
//		fu = top[fu];
//	}
//	if (u == v)
//		updata(posx[u], posx[u], val, 1, pos - 1, 1);
//	else
//	{
//		if (deep[u] > deep[v])
//			swap(u, v);
//		updata(posx[u], posx[v], val, 1, pos - 1, 1);
//	}
//}

void init()
{
	cnt = 0;
	pos = 1;
	memset(son, -1, sizeof(son));
	memset(head, -1, sizeof(head));
}
int main()
{
	int n;
	while (~scanf("%d", &n))
	{
		int a, b;
		init();
		for (int i = 1; i < n; i++)
		{
			scanf("%d%d", &a, &b);
			addedge(a, b);
			addedge(b, a);
		}
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &val[i]);
		}
		dfs(1, 1, 0);
		getpos(1, 1);
		build(1, pos - 1, 1);
		char str[10];
		int q;
		scanf("%d", &q);
		while (q--)
		{
			scanf("%s%d%d", str,&a,&b);
			if (str[0] == 'C')
			{
				updata(posx[a], b, 1, pos - 1, 1);
			}
			else
			if (str[1] == 'M')
				printf("%d\n", solve(a, b, 1));
			else
				printf("%d\n", solve(a, b, 0));
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值