P4315 月下“毛景树”

heavy-light decomposition & segment tree problem which need lots of detail

Last night I reinstalled my manjaro linux and it hasn't installed any app which can input Chinese. So in this time I will show my awful English.

In this problem we should deal with the weight of edges, but it is difficult.

In fact, we can press the weight into the son node so that we can turn the problem into the weight of nodes. It can easily be maintained by segment tree.

But the whole weight of a path from \(u\) to \(v\) doesn't include the weight of LCA!

So when we find the ultimate u(actually LCA), don't forget to add 1 after its dfn!

But there is also a detail in segment tree: interval cover's lazytag will make interval add's lazytag disappear!

If you are careful to all the program, I believe you can solve it easily.

But I have submitted 13 times with all WA

Code:

#include<cstdio>
#include<algorithm>
const int maxn = 100005;
const int INF = 0x3f3f3f3f;
int n;
struct Edges
{
    int next, to, weight, id;
} e[maxn << 1];
int head[maxn], tot;
//
int dep[maxn], size[maxn], wson[maxn], fa[maxn];
int weight[maxn], id[maxn];
int dfn[maxn], pre[maxn], top[maxn], dtot;
//
int maxv[maxn << 2], lazy[maxn << 2], tag[maxn << 2];
#define lson (root << 1)
#define rson (root << 1 | 1)
void pushup(int root)
{
    maxv[root] = std::max(maxv[lson], maxv[rson]);
}
void pushdown(int root)
{
    if(tag[root] != -1)
    {
        maxv[lson] = maxv[rson] = maxv[root];
        tag[lson] = tag[rson] = tag[root];
        //lazy[lson] = lazy[rson] = 0;
        lazy[root] = 0;
        tag[root] = -1;
    }
    if(lazy[root] != 0)
    {
        maxv[lson] += lazy[root];
        lazy[lson] += lazy[root];
        maxv[rson] += lazy[root];
        lazy[rson] += lazy[root];
        lazy[root] = 0;
    }
}
void build(int root, int l, int r)
{
    lazy[root] = 0; tag[root] = -1;
    if(l == r) maxv[root] = weight[pre[l]];
    else
    {
        int mid = (l + r) >> 1;
        build(lson, l, mid);
        build(rson, mid + 1, r);
        pushup(root);
    }
}
void interval_add(int root, int l, int r, int x, int y, int k)
{
    if(r < x || y < l) return;
    if(x <= l && r <= y)
    {
        maxv[root] += k;
        lazy[root] += k;
        return;
    }
    pushdown(root);
    int mid = (l + r) >> 1;
    interval_add(lson, l, mid, x, y, k);
    interval_add(rson, mid + 1, r, x, y, k);
    pushup(root);
}
void interval_cover(int root, int l, int r, int x, int y, int k)
{
    if(r < x || y < l) return;
    if(x <= l && r <= y)
    {
        maxv[root] = k;
        tag[root] = k;
        //lazy[lson] = lazy[rson] = 0;
        return;
    }
    pushdown(root);
    int mid = (l + r) >> 1;
    interval_cover(lson, l, mid, x, y, k);
    interval_cover(rson, mid + 1, r, x, y, k);
    pushup(root);
}
int query(int root, int l, int r, int x, int y)
{
    if(r < x || y < l) return -INF;
    if(x <= l && r <= y) return maxv[root];
    pushdown(root);
    int mid = (l + r) >> 1;
    return std::max(query(lson, l, mid, x, y), query(rson, mid + 1, r, x, y));
}
#undef lson
#undef rson
void link(int u, int v, int w, int i)
{
    e[++tot] = (Edges){head[u], v, w, i};
    head[u] = tot;
}
int read()
{
    int ans = 0, s = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar();
    return s * ans;
}
void dfs1(int u, int f)
{
    dep[u] = dep[f] + 1; fa[u] = f; size[u] = 1;
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to;
        if(v == f) continue;
        dfs1(v, u);
        size[u] += size[v];
        weight[v] = e[i].weight;
        id[e[i].id] = v;
        if(size[v] > size[wson[u]]) wson[u] = v;
    }
}
void dfs2(int u, int topf)
{
    dfn[u] = ++dtot; pre[dtot] = u; top[u] = topf;
    if(wson[u]) dfs2(wson[u], topf);
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to;
        if(v == fa[u] || v == wson[u]) continue;
        dfs2(v, v);
    }
}

void Add(int u, int v, int w)
{
    while(top[u] != top[v])
    {
        if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
        interval_add(1, 1, n, dfn[top[u]], dfn[u], w);
        u = fa[top[u]];
    }
    if(dep[u] > dep[v]) std::swap(u, v);
    interval_add(1, 1, n, dfn[u] + 1, dfn[v], w);
}
int Max(int u, int v)
{
    int ans = -INF;
    while(top[u] != top[v])
    {
        if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
        ans = std::max(ans, query(1, 1, n, dfn[top[u]], dfn[u]));
        u = fa[top[u]];
    }
    if(dep[u] > dep[v]) std::swap(u, v);
    ans = std::max(ans, query(1, 1, n, dfn[u] + 1, dfn[v]));
    return ans;
}
void Change(int k, int w)
{
    interval_cover(1, 1, n, dfn[id[k]], dfn[id[k]], w);
}
void Cover(int u, int v, int w)
{
    while(top[u] != top[v])
    {
        if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
        interval_cover(1, 1, n, dfn[top[u]], dfn[u], w);
        u = fa[top[u]];
    }
    if(dep[u] > dep[v]) std::swap(u, v);
    interval_cover(1, 1, n, dfn[u] + 1, dfn[v], w);
}
int main()
{
    n = read();
    for(int i = 1; i < n; i++)
    {
        int u = read(), v = read(), w = read();
        link(u, v, w, i); link(v, u, w, i);
    }
    dfs1(1, 0); dfs2(1, 1);
    build(1, 1, n);
    char opt[10];
    while(2333)
    {
        scanf("%s", opt);
        if(opt[0] == 'S') break;
        if(opt[0] == 'A')
        {
            int u = read(), v = read(), w = read();
            Add(u, v, w);
        }
        else if(opt[0] == 'M')
        {
            int u = read(), v = read();
            printf("%d\n", Max(u, v));
        }
        else if(opt[1] == 'h')
        {
            int k = read(), w = read();
            Change(k, w);
        }
        else if(opt[1] == 'o')
        {
            int u = read(), v = read(), w = read();
            Cover(u, v, w);
        }
    }
    return 0;
}
posted @ 2018-10-28 10:00  Garen-Wang  阅读(201)  评论(0编辑  收藏  举报