• 洛谷P4556 雨天的尾巴(线段树合并)


    洛谷P4556 雨天的尾巴

    题目链接

    题解:
    因为一个点可能存放多种物品,直接开二维数组进行统计时间、空间复杂度都不能承受。因为每一个点所拥有的物品只与其子树中的点有关,所以可以考虑对每一个点来建立一颗权值线段树来维护多种物品以及其数量,然后最后在回溯时合并,这样就可以得到我们所需要的信息了。
    因为题目中要求的是哪一种物品,所以我们可以顺带维护一下位置信息,就不用到时候每次去query了。
    注意一下,就是当一个点的sum为0时,其pos应该为置为0。
    详见代码吧:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 5;
    int n, m;
    struct Edge{
        int v, next;
    }e[N << 1];
    int head[N], tot, D;
    void adde(int u, int v) {
        e[tot].v = v; e[tot].next = head[u]; head[u] = tot++;
    }
    int f[N][22], deep[N] ;
    int rt[N], ls[N * 100], rs[N * 100], pos[N * 100], sum[N * 100] ;
    int X[N], Y[N], Z[N], b[N], ans[N];
    void dfs1(int u, int fa) {
        deep[u] = deep[fa] + 1;
        for(int i = head[u]; i != -1; i = e[i].next){
            int v = e[i].v;
            if(v == fa) continue ;
            f[v][0] = u;
            for(int j = 1; j <= 20; j++) f[v][j] = f[f[v][j - 1]][j - 1] ;
            dfs1(v, u) ;
        }
    }
    int LCA(int x, int y) {
        if(deep[x] < deep[y]) swap(x, y);
        for(int i = 20; i >= 0; i--) {
            if(deep[f[x][i]] >= deep[y]) x = f[x][i] ;
        }
        if(x == y) return x;
        for(int i = 20; i >= 0; i--) {
            if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i] ;
        }
        return f[x][0] ;
    }
    void insert(int o, int l, int r, int val, int sign) {
        if(l == r) {
            sum[o] += sign;
            pos[o] = sum[o] > 0 ? l : 0;
            return ;
        }
        int mid = (l + r) >> 1;
        if(val <= mid) {
            if(!ls[o]) ls[o] = ++tot;
            insert(ls[o], l, mid, val, sign) ;
        } else {
            if(!rs[o]) rs[o] = ++tot;
            insert(rs[o], mid + 1, r, val, sign) ;
        }
        sum[o] = max(sum[ls[o]], sum[rs[o]]) ;
        pos[o] = sum[ls[o]] >= sum[rs[o]] ? pos[ls[o]] : pos[rs[o]];
    }
    int merge(int x, int y, int l, int r) {
        if(!x) return y;
        if(!y) return x;
        if(l == r) {
            sum[x] += sum[y] ;
            pos[x] = sum[x] > 0 ? l : 0;
            return x;
        }
        int mid = (l + r) >> 1;
        ls[x] = merge(ls[x], ls[y], l, mid) ;
        rs[x] = merge(rs[x], rs[y], mid + 1, r) ;
        sum[x] = max(sum[ls[x]], sum[rs[x]]) ;
        pos[x] = sum[ls[x]] >= sum[rs[x]] ? pos[ls[x]] : pos[rs[x]] ;
        return x;
    }
    void dfs2(int u, int fa) {
        for(int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].v;
            if(v == fa) continue ;
            dfs2(v, u) ;
            rt[u] = merge(rt[u], rt[v], 1, D) ;
        }
        ans[u] = pos[rt[u]];
    }
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> n >> m;
        memset(head, -1, sizeof(head)) ;
        for(int i = 1; i < n; i++) {
            int u, v;
            cin >> u >> v;
            adde(u, v); adde(v, u);
        }
        dfs1(1, 0) ;
        for(int i = 1; i <= n; i++) rt[i] = i;
        tot = n;
        for(int i = 1; i <= m; i++) {
            cin >> X[i] >> Y[i] >> Z[i] ;
            b[i] = Z[i] ;
        }
        sort(b + 1, b + m + 1);
        D = unique(b + 1, b + m + 1) - b - 1;
        for(int i = 1; i <= m; i++) {
            int x = X[i], y = Y[i], z = Z[i] ;
            int k = lower_bound(b + 1, b + D + 1, z) - b;
            int lca = LCA(x, y) ;
            insert(rt[x], 1, D, k, 1) ;
            insert(rt[y], 1, D, k, 1) ;
            insert(rt[lca], 1, D, k, -1) ;
            if(f[lca][0]) insert(rt[f[lca][0]], 1, D, k, -1) ;
        }
        dfs2(1, 0) ;
        for(int i = 1; i <= n; i++) cout << b[ans[i]] << '
    ' ;
        return 0;
    }
    
    
  • 相关阅读:
    1054 The Dominant Color (20 分)
    1120 Friend Numbers (20 分)
    19. JSP
    18. Javaweb中文件的上传和下载【重要】
    8. 颜色和样式
    clear 清除浮动 CSS
    17. JSP
    Session
    16. JSP 过滤器解决Post编码【乱码】问题
    HTML <form> 标签的 的 属性
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10891233.html
Copyright © 2020-2023  润新知