HDU 3966 树链剖分模板

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
#define N 50010
#define M 100010
int n, m, p;
class Node
{
public:
    int fa, top, pos, val, siz, heavySon, dep;
};
Node node[N];
class Edge
{
public:
    int u, v, next;
};
Edge edge[M];
int head[N], cnte, tree[N*4], seq[N], seqP;


void addEdge(int u, int v)
{
    edge[cnte].u = u; edge[cnte].v = v;
    edge[cnte].next = head[u]; head[u] = cnte++;
}

void dfs_1(int root, int fa, int d)
{
    node[root].dep = d;
    node[root].siz = 1;
    int p = 0, val = -1;
    node[root].fa = fa;
    for(int i = head[root]; i != -1; i = edge[i].next)
    {
        int v = edge[i].v;
        if(v != fa)
        {
            node[v].dep = node[root].dep+1;
            dfs_1(v, root, d+1);
            node[root].siz += node[v].siz;
            if(node[v].siz > val)
            {
                p = v;
                val = node[v].siz;
            }
        }
    }
    node[root].heavySon = p;
}
void dfs_2(int root, int tp)
{
    node[root].top = tp;
    node[root].pos = ++seqP;
    seq[seqP] = root;
    if(node[root].heavySon == 0) return;
    dfs_2(node[root].heavySon, tp);

    for(int i = head[root]; i != -1; i = edge[i].next)
    {
        int v = edge[i].v;
        if(v != node[root].fa && v != node[root].heavySon)
        {
            dfs_2(v, v);
        }
    }
}
void build(int p, int l, int r)
{
    if(l == r)
    {
        tree[p] = node[seq[l]].val;
        return;
    }
    int mid = (l+r)>>1;
    build(p<<1, l, mid);
    build(p<<1|1, mid+1, r);
}
void update(int p, int l, int r, int x, int y, int delta)
{
    if(x <= l && y >= r)
    {
        tree[p] += delta;
        return;
    }
    tree[p<<1] += tree[p];
    tree[p<<1|1] += tree[p];
    tree[p] = 0;
    int mid = (l+r)>>1;
    if(x <= mid)
        update(p<<1, l, mid, x, y, delta);
    if(y >= mid+1)
        update(p<<1|1, mid+1, r, x, y, delta);
}
int query(int p, int l, int r, int x)
{
    if(l == r)
    {
        return tree[p];
    }
    tree[p<<1] += tree[p];
    tree[p<<1|1] += tree[p];
    tree[p] = 0;
    int mid = (l+r)>>1;
    if(x <= mid)
        return query(p<<1, l, mid, x);
    else return query(p<<1|1, mid+1, r, x);
}
void modify(int u, int v, int w)
{
    while(node[u].top != node[v].top)
    {
        if(node[node[u].top].dep < node[node[v].top].dep)
            swap(v, u);
        update(1, 1, n, node[node[u].top].pos, node[u].pos, w);
        u = node[node[u].top].fa;
    }
    if(node[u].dep > node[v].dep)
    {
        swap(u, v);
    }
    update(1, 1, n, node[u].pos, node[v].pos, w);
}


int main()
{
	//freopen("C:\\Users\\zfh\\Desktop\\in.txt", "r", stdin);
    while(scanf("%d%d%d", &n, &m, &p) != -1)
    {
        cnte = 0; seqP = 0;
        memset(head, -1, sizeof head);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &node[i].val);
        }
        int u, v, w;
        for(int i = 0; i < n-1; i++)
        {
            scanf("%d%d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }

        dfs_1(1, -1, 0);
        dfs_2(1, 1);
        memset(tree, 0, sizeof tree);
        build(1, 1, n);
        char ch;
        for(int i = 0; i < p; i++)
        {
            scanf(" %c", &ch);
            if(ch == 'I')
            {
                scanf("%d%d%d", &u, &v, &w);
                modify(u, v, w);
            }
            else if(ch == 'D')
            {
                scanf("%d%d%d", &u, &v, &w);
                modify(u, v, -w);
            }
            else
            {
                scanf("%d", &u);
                printf("%d\n", query(1, 1, n, node[u].pos));
            }
        }
    }
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值