您的位置:首页 > 编程语言 > Go语言

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

2015-03-27 15:33 309 查看
树链剖分的模板题,思路就不说了, 等做了一些题目之后,在写个总结吧。

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

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<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
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);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: