【HDU】3966 Aragorn's Story(树链剖分+线段树)

树链剖分的模板题,思路就不说了, 等做了一些题目之后,在写个总结吧。

先说一下这道题错误的地方。

1、爆栈。看大神的博客才找到解决的方法。

说是hdu的oj是window的系统,容易爆栈

所以在之前应该要手动扩栈。

在代码之前加上:#pragma comment(linker, "/STACK:1024000000,1024000000")就可以了。

2、

是在路径的缩短中写错了。

int fu = top[u], fv = top[v];//这条重链的顶端

一开始写成pre数组,结果就wa了。

/*

第一次栈溢出:添加:#pragma comment(linker, "/STACK:1024000000,1024000000")解决!

*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
using namespace std;
#define MAX 50005
#define ls rt<<1
#define rs ls|1
#define m (l+r)>>1
int sum[MAX << 2];
int p[MAX], head[MAX], posx[MAX], top[MAX], son[MAX], pre[MAX], size[MAX], deep[MAX];
int posx2[MAX];
int cnt, pos;
int n, k, q;
struct edg{
	int v, next;
}edge[MAX<<1];

void addedge(int u, int v)
{
	edge[cnt].v = v;
	edge[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 = edge[i].next)
	{
		int v = edge[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 = edge[i].next)
	{
		int v = edge[i].v;
		if (v != son[u] && v != pre[u])
			getpos(v, v);
	}
}

void ups( int rt)
{
	if (sum[rt])
	{
		sum[ls] += sum[rt];
		sum[rs] += sum[rt];
		sum[rt] = 0;
	}
}

void updata(int L, int R, int c, int l, int r, int rt)
{
	if (L <= l&&r <= R)
	{
		sum[rt] += c;
		return;
	}
	ups( rt);
	int mid = m;
	if (L <= mid)
		updata(L, R, c, l, mid, ls);
	if (mid < R)
		updata(L, R, c, mid + 1, r, rs);
}

int query(int q, int l, int r, int rt)
{
	if (l == r)
		return sum[rt];
	ups( rt);
	int mid = m;
	if (q <= mid)
		return query(q, l, mid, ls);
	else
		return query(q, mid + 1, r, rs);
}

void updata(int u, int v, int c)
{
	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], c, 0,pos-1, 1);
		u = pre[fu];
		fu = top[u];
	}
	if (u == v)
	{
		updata(posx[u], posx[u], c, 0, pos - 1, 1);
		return;
	}
	if (deep[u]>deep[v])
		swap(u, v);
	updata(posx[u], posx[v], c, 0,pos-1, 1);
}

void init()
{
	cnt = 0;
	pos = 0;
	memset(son, -1, sizeof(son));
	memset(head, -1, sizeof(head));
}
int a[MAX], e[MAX][2];
void build(int l, int r, int rt)
{
	if (l == r)
	{
		sum[rt] = a[posx2[l]];
		return;
	}
	sum[rt] = 0;
	int mid = m;
	build(l, mid, ls);
	build(mid + 1, r, rs);
}
int main()
{

	while (~scanf("%d%d%d", &n, &k, &q))
	{
		init();
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &a[i]);
		}
		for (int i = 0; i < k; i++)
		{
			scanf("%d%d", &e[i][0], &e[i][1]);
			addedge(e[i][0], e[i][1]);
			addedge(e[i][1], e[i][0]);
		}
		dfs(1, 1, 0);//这个第二个1写成0或者写成1都是可以的,不过写成1快了400ms
		getpos(1, 1);
		build(0, pos - 1, 1);
		char str[5];
		int a, b, c;
		while (q--)
		{
			scanf("%s", str);
			
			if (str[0] == 'Q')
			{
				scanf("%d", &a);
				printf("%d\n", query(posx[a], 0,pos-1, 1));
			}
			else
			{
				scanf("%d%d%d", &a, &b, &c);
				if (str[0] == 'D')
					c = -c;
				updata(a, b, c);
			}
		}
	}
}

你可能感兴趣的:(HDU,线段树,树链剖分)