HDU

HDU - 5770

没想出来, 感觉不应该啊, 没有想到转换成二维上的点的问题。

对于对钥匙和宝藏(u, v), 如果lca != u && lca != v 那么起点从u子树出发, 终点在v子树就能得到贡献。

子树在dfs序下是连续一段, 所以就对应到二维平面一个矩形加上一个数值, 求值最大的点。

对于lca == u || lca == v同样可以讨论出来。 

还有一种情况就是u == v, 我们先把贡献都加上, 然后对于不经过u 的所有路径进去这个贡献。

然后扫描线扫一遍就好了。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = (int)1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}

const int LOG = 17;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1

struct SegmentTree {
    int mx[N << 2], lazy[N << 2];
    void build(int l, int r, int rt) {
        mx[rt] = lazy[rt] = 0;
        if(l == r) return;
        int mid = l + r >> 1;
        build(lson); build(rson);
    }
    inline void push(int rt) {
        if(lazy[rt]) {
            mx[rt << 1] += lazy[rt];
            mx[rt << 1 | 1] += lazy[rt];
            lazy[rt << 1] += lazy[rt];
            lazy[rt << 1 | 1] += lazy[rt];
            lazy[rt] = 0;
        }
    }
    void update(int L, int R, int val, int l, int r, int rt) {
        if(R < l || r < L || R < L) return;
        if(L <= l && r <= R) {
            mx[rt] += val;
            lazy[rt] += val;
            return;
        }
        push(rt);
        int mid = l + r >> 1;
        update(L, R, val, lson);
        update(L, R, val, rson);
        mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
    }
    inline int getMax() {
        return mx[1];
    }
} Tree;


int n, m;
int sig_val;
int add_val[N];
int in[N], ot[N], idx;
int depth[N], pa[N][LOG];
vector<int> G[N];

void dfs(int u, int fa) {
    depth[u] = depth[fa] + 1;
    pa[u][0] = fa;
    in[u] = ++idx;
    for(int i = 1; i < LOG; i++) {
        pa[u][i] = pa[pa[u][i - 1]][i - 1];
    }
    for(auto &v : G[u]) {
        if(v == fa) continue;
        dfs(v, u);
    }
    ot[u] = idx;
}

int getLca(int u, int v) {
    if(depth[u] < depth[v]) swap(u, v);
    int d = depth[u] - depth[v];
    for(int i = LOG - 1; i >= 0; i--) {
        if(d >> i & 1) {
            u = pa[u][i];
        }
    }
    if(u == v) return u;
    for(int i = LOG - 1; i >= 0; i--) {
        if(pa[u][i] != pa[v][i]) {
            u = pa[u][i];
            v = pa[v][i];
        }
    }
    return pa[u][0];
}

inline int go(int u, int step) {
    for(int i = LOG - 1; i >= 0; i--) {
        if(step >> i & 1) {
            u = pa[u][i];
        }
    }
    return u;
}

int L_cnt;
struct Line {
    int x, y1, y2, val;
    bool operator < (const Line &rhs) const {
        return x < rhs.x;
    }
} L[N * 10];

void init() {
    idx = L_cnt = sig_val = 0;
    for(int i = 1; i <= n; i++) {
        add_val[i] = 0;
        G[i].clear();
    }
    Tree.build(1, n, 1);
}

int main() {
    int cas = 0;
    int T; scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        init();
        for(int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1, 0);
        for(int i = 1; i <= m; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            int lca = getLca(u, v);
            if(u == v) {
                sig_val += w;
                add_val[u] -= w;
            }
            else {
                if(u == lca) {
                    u = go(v, depth[v] - depth[u] - 1);
                    if(in[u] > 1) {
                        L[++L_cnt] = Line{1, in[v], ot[v], w};
                        L[++L_cnt] = Line{in[u], in[v], ot[v], -w};
                    }
                    if(ot[u] < n) {
                        L[++L_cnt] = Line{ot[u] + 1, in[v], ot[v], w};
                        L[++L_cnt] = Line{n + 1, in[v], ot[v], -w};
                    }
                }
                else if(v == lca) {
                    v = go(u, depth[u] - depth[v] - 1);
                    if(in[v] > 1) {
                        L[++L_cnt] = Line{in[u], 1, in[v] - 1, w};
                        L[++L_cnt] = Line{ot[u] + 1, 1, in[v] - 1, -w};
                    }
                    if(ot[v] < n) {
                        L[++L_cnt] = Line{in[u], ot[v] + 1, n, w};
                        L[++L_cnt] = Line{ot[u] + 1, ot[v] + 1, n, -w};
                    }
                }
                else {
                    L[++L_cnt] = Line{in[u], in[v], ot[v], w};
                    L[++L_cnt] = Line{ot[u] + 1, in[v], ot[v], -w};
                }
            }
        }
        for(int u = 1; u <= n; u++) {
            if(add_val[u]) {
                for(auto &v : G[u]) {
                    if(v == pa[u][0]) continue;
                    L[++L_cnt] = Line{in[v], in[v], ot[v], add_val[u]};
                    L[++L_cnt] = Line{ot[v] + 1, in[v], ot[v], -add_val[u]};
                }
                if(pa[u][0]) {
                    int v = u;
                    L[++L_cnt] = Line{1, 1, in[v] - 1, add_val[u]};
                    L[++L_cnt] = Line{1, ot[v] + 1, n, add_val[u]};
                    L[++L_cnt] = Line{in[v], 1, in[v] - 1, -add_val[u]};
                    L[++L_cnt] = Line{in[v], ot[v] + 1, n, -add_val[u]};

                    L[++L_cnt] = Line{ot[v] + 1, 1, in[v] - 1, add_val[u]};
                    L[++L_cnt] = Line{ot[v] + 1, ot[v] + 1, n, add_val[u]};
                }
            }
        }
        int ans = -inf;
        sort(L + 1, L + 1 + L_cnt);
        for(int i = 1, j = 1; i <= n; i++) {
            while(j <= L_cnt && L[j].x <= i) {
                if(L[j].y1 <= L[j].y2) {
                    Tree.update(L[j].y1, L[j].y2, L[j].val, 1, n, 1);
                }
                j++;
            }
            chkmax(ans, sig_val + Tree.getMax());
        }
        printf("Case #%d: ", ++cas);
        printf("%d
", ans);
    }
    return 0;
}

/*
*/
原文地址:https://www.cnblogs.com/CJLHY/p/11512419.html