BZOJ4034【树链剖分】【线段树】

/* I will wait for you */  
  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <cmath>  
#include <ctime>  
#include <algorithm>  
#include <iostream>  
#include <fstream>  
#include <vector>  
#include <queue>  
#include <deque>  
#include <set>  
#include <map>  
#include <string>  
#define make(a,b) make_pair(a,b)  
#define fi first  
#define se second  
  
using namespace std;  
  
typedef long long ll;  
typedef unsigned long long ull;  
typedef pair<int, int> pii;  
typedef map<int, int> mii;  
  
const int maxn = 100010;  
const int maxm = 1010;  
const int maxs = 26;  
const int inf = 0x3f3f3f3f;  
const int P = 1000000007;  
const double error = 1e-9;  
  
inline ll read()  
{  
    ll x = 0, f = 1; char ch = getchar();  
    while (ch > '9' || ch < '0' )  
        f = (ch == '-' ? -1 : 1), ch = getchar();  
    while (ch <= '9' && ch >= '0')  
        x = x * 10 + ch - '0', ch = getchar();  
    return f * x;  
}  
  
struct edge  
{  
    int v, next;  
} e[2 * maxn];  
  
struct node  
{  
    int l, r; ll sum, add;  
} t[4 * maxn];  
  
int n, m, cnt, dfn, per[maxn], fa[maxn], mx[maxn], pr[maxn],
	deep[maxn], size[maxn], pos[maxn], head[maxn];
  
void insert(int u, int v)  
{  
    e[cnt] = (edge) {v, head[u]}, head[u] = cnt++;  
    e[cnt] = (edge) {u, head[v]}, head[v] = cnt++;  
}  
  
void dfs1(int u)  
{  
    size[u] = 1;  
  
    for (int i = head[u]; i != -1; i = e[i].next) {  
        int v = e[i].v;  
        if (v != fa[u]) {  
            fa[v] = u, deep[v] = deep[u] + 1;  
            dfs1(v), size[u] += size[v];  
  
            if (size[v] > size[mx[u]])  
                mx[u] = v;  
        }  
    }  
}  
  
void dfs2(int u, int p)  
{  
    pos[u] = ++dfn, per[u] = p;  
  
    if (mx[u])  
        dfs2(mx[u], p);  
  
    for (int i = head[u]; i != -1; i = e[i].next) {  
        int v = e[i].v;  
        if (v != fa[u] && v != mx[u])  
            dfs2(v, v);  
    }  
}  

void build(int u, int l, int r)  
{  
    t[u].l = l, t[u].r = r;  
      
    if (l != r) {  
        int mid = (l + r) / 2;  
  
        build(2 * u, l, mid);  
        build(2 * u + 1, mid + 1, r);  
    }  
}  

void maintain(int u)
{
	int l = t[u].l, r = t[u].r;
	
	t[u].sum = 0;
	
	if (r > l)
		t[u].sum = t[2 * u].sum + t[2 * u + 1].sum;
	
	t[u].sum += (r - l + 1) * t[u].add;
}

void add(int u, int x, int y, int c)
{
	int l = t[u].l, r = t[u].r;
	
	if (l >= x && r <= y)
		t[u].add += c;
		
	else {
		int mid = (l + r) / 2;
		
		if (x <= mid)
			add(2 * u, x, y, c);
		if (y > mid)
			add(2 * u + 1, x, y, c);
	}
	
	maintain(u);
}

ll query(int u, int x, int y, ll add)
{
	int l = t[u].l, r = t[u].r;
	
	if (l >= x && r <= y)
		return t[u].sum + (r - l + 1) * add;
		
	else {
		int mid = (l + r) / 2; ll ans = 0;
		
		if (x <= mid)
			ans += query(2 * u, x, y, add + t[u].add);
		if (y > mid)
			ans += query(2 * u + 1, x, y, add + t[u].add);
			
		return ans;
	}
}

ll query(int u)
{
	ll ans = 0;
	
	while (u) {
		ans += query(1, pos[per[u]], pos[u], 0);
		u = fa[per[u]];
	}
	
	return ans;
}

int main()  
{  
    n = read(), m = read(), build(1, 1, n);  
  
    memset(head, -1, sizeof head);  
    
    for (int i = 1; i <= n; i++)
    	pr[i] = read();
    
    for (int i = 1; i < n; i++) {  
        int u = read(), v = read();  
        insert(u, v);  
    }  
  
    dfs1(1), dfs2(1, 1);
    
    for (int i = 1; i <= n; i++)
    	add(1, pos[i], pos[i], pr[i]);
    	
    for (int i = 1; i <= m; i++) {
    	int t = read();
    	
    	if (t == 1) {
    		int u = read(), c = read();
    		add(1, pos[u], pos[u], c);
    	}
    	
    	if (t == 2) {
    		int u = read(), c = read();
    		add(1, pos[u], pos[u] + size[u] - 1, c);
    	}
    	
    	if (t == 3) {
    		int u = read();
    		printf("%lld\n", query(u));
    	}
    }
  
    return 0;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值