树链剖分

1、HDU 5052 Yaoge’s maximum profit


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 5e4 + 10;

int T, N, Q, X, Y, Z, edge, id_count;
int W[maxn], depth[maxn], son[maxn], top[maxn], size[maxn], father[maxn], id[maxn], key[maxn];
int head[maxn], Next[2*maxn], to[2*maxn];
ll lans[4*maxn], rans[4*maxn], lazy[4*maxn], Max[4*maxn], Min[4*maxn];

void Init(void);
void add_edge(int u, int v);
void dfs_first(int u, int _father, int _depth);
void dfs_second(int u, int _top);
void build(int low, int high, int _id);
void push_up(int _id);
void update(int Left, int Right, ll val, int low, int high, int _id);
void push_down(int _id);
void Update(int u, int v, ll val);
ll slove(int u, int v);
ll query(int Left, int Right, int is_left, ll& max_price, ll& min_price, int low, int high, int _id);

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &N);
        Init();
        for (int i = 1; i <= N; ++i) {
            scanf("%d", &W[i]);
        }
        for (int i = 1; i < N; ++i) {
            scanf("%d %d", &X, &Y);
            add_edge(X, Y), add_edge(Y, X);
        }
        dfs_first(1, 0, 1);
        dfs_second(1, 1);
        build(1, N, 1);
        scanf("%d", &Q);
        while (Q--) {
            scanf("%d %d %d", &X, &Y, &Z);
            printf("%I64d\n", slove(X, Y));
            Update(X, Y, Z);
        }
    }
    return 0;
}

ll slove(int u, int v)
{
    ll ans = 0, max_now_left, min_now_left, max_now_right, min_now_right;
    ll max_pre_left = 0, min_pre_left = Max[1], max_pre_right = 0, min_pre_right = Max[1];
    while (top[u] != top[v]) {
        if (depth[top[u]] > depth[top[v]]) {
            ans = max(ans, query(id[top[u]], id[u], 1, max_now_left, min_now_left, 1, N, 1));
            ans = max(ans, max_now_left - min_pre_left);
            ans = max(ans, max_pre_right - min_now_left);
            max_pre_left = max(max_pre_left, max_now_left);
            min_pre_left = min(min_pre_left, min_now_left);
            u = father[top[u]];
        } else {
            ans = max(ans, query(id[top[v]], id[v], 0, max_now_right, min_now_right, 1, N, 1));
            ans = max(ans, max_pre_right - min_now_right);
            ans = max(ans, max_now_right - min_pre_left);
            max_pre_right = max(max_pre_right, max_now_right);
            min_pre_right = min(min_pre_right, min_now_right);
            v = father[top[v]];
        }
    }
    if (depth[u] > depth[v]) {
        ans = max(ans, query(id[v], id[u], 1, max_now_left, min_now_left, 1, N, 1));
        ans = max(ans, max_now_left - min_pre_left);
        min_pre_left = min(min_pre_left, min_now_left);
        ans = max(ans, max_pre_right - min_pre_left);
    } else {
        ans = max(ans, query(id[u], id[v], 0, max_now_right, min_now_right, 1, N, 1));
        ans = max(ans, max_pre_right - min_now_right);
        max_pre_right = max(max_pre_right, max_now_right);
        ans = max(ans, max_pre_right - min_pre_left);
    }
    return ans;
}

ll query(int Left, int Right, int is_left, ll& max_price, ll& min_price, int low, int high, int _id)
{
    if (low == Left && high == Right) {
        max_price = Max[_id], min_price = Min[_id];
        if (is_left) {
            return lans[_id];
        } else {
            return rans[_id];
        }
    }
    push_down(_id);
    int mid = (low + high) >> 1;
    if (Right <= mid) {
        return query(Left, Right, is_left, max_price, min_price, lson);
    } else if (Left > mid) {
        return query(Left, Right, is_left, max_price, min_price, rson);
    } else {
        ll ans_t, max_left, max_right, min_left, min_right;
        ll ans = max(query(Left, mid, is_left, max_left, min_left, lson), query(mid+1, Right, is_left, max_right, min_right, rson));
        if (is_left) {
            ans_t = max_left - min_right;
        } else {
            ans_t = max_right - min_left;
        }
        max_price = max(max_left, max_right), min_price = min(min_left, min_right);
        ans_t = max(ans_t, 0ll), ans = max(ans, ans_t);
        return ans;
    }
}

void Update(int u, int v, ll val)
{
    while (top[u] != top[v]) {
        if (depth[top[u]] < depth[top[v]]) {
            swap(u, v);
        }
        update(id[top[u]], id[u], val, 1, N, 1);
        u = father[top[u]];
    }
    if (depth[u] > depth[v]) {
        swap(u, v);
    }
    update(id[u], id[v], val, 1, N, 1);
}

void update(int Left, int Right, ll val, int low, int high, int _id)
{
    if (low == Left && high == Right) {
        Max[_id] += val, Min[_id] += val, lazy[_id] += val;
        return;
    }
    push_down(_id);
    int mid = (low + high) >> 1;
    if (Right <= mid) {
        update(Left, Right, val, lson);
    } else if (Left > mid) {
        update(Left, Right, val, rson);
    } else {
        update(Left, mid, val, lson), update(mid+1, Right, val, rson);
    }
    push_up(_id);
}

void push_down(int _id)
{
    if (lazy[_id]) {
        Max[_id<<1] += lazy[_id], Min[_id<<1] += lazy[_id], lazy[_id<<1] += lazy[_id];
        Max[_id<<1|1] += lazy[_id], Min[_id<<1|1] += lazy[_id], lazy[_id<<1|1] += lazy[_id];
        lazy[_id] = 0;
    }
}

void build(int low, int high, int _id)
{
    lazy[_id] = lans[_id] = rans[_id] = 0;
    if (low == high) {
        Max[_id] = Min[_id] = W[key[low]];
        return;
    }
    int mid = (low + high) >> 1;
    build(lson), build(rson);
    push_up(_id);
}

void push_up(int _id)
{
    Max[_id] = max(Max[_id<<1], Max[_id<<1|1]), Min[_id] = min(Min[_id<<1], Min[_id<<1|1]);
    lans[_id] = max(Max[_id<<1] - Min[_id<<1|1], max(lans[_id<<1], lans[_id<<1|1]));
    rans[_id] = max(Max[_id<<1|1] - Min[_id<<1], max(rans[_id<<1], rans[_id<<1|1]));
    if (lans[_id] < 0) {
        lans[_id] = 0;
    }
    if (rans[_id] < 0) {
        rans[_id] = 0;
    }
}

void dfs_second(int u, int _top)
{
	top[u] = _top;
	id[u] = ++id_count;
	key[id[u]] = u;
	if (son[u] == -1) {
		return;
	}
	dfs_second(son[u], _top);
	for (int i = head[u]; ~i; i = Next[i]) {
		int v = to[i];
		if (v != son[u] && v != father[u]) {
			dfs_second(v, v);
		}
	}
}

void dfs_first(int u, int _father, int _depth)
{
	depth[u] = _depth, father[u] = _father, size[u] = 1;
	for (int i = head[u]; ~i; i = Next[i]) {
		int v = to[i];
		if (v != _father) {
			dfs_first(v, u, _depth+1);
			size[u] += size[v];
			if (son[u] == -1 || size[v] > size[son[u]]) {
				son[u] = v;
			}
		}
	}
}

void add_edge(int u, int v)
{
	to[edge] = v, Next[edge] = head[u], head[u] = edge++;
}

void Init(void)
{
	memset(head, -1, sizeof(head));
	memset(son, -1, sizeof(son));
	edge = id_count = 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值