zoukankan      html  css  js  c++  java
  • bzoj5457 城市

    一棵树,每个点有一个民族,和一个人数,求每个子树里最多的民族及其人数,如果一样,输出编号最小的

    $n leq 500000$

    sol:

    卡莫队的毒瘤题,需要 dsu on tree

    大概就是 dfs 顺便维护一个数组叫“当前答案”,每次先把轻儿子加进来,再把重儿子加进来,然后把轻儿子删掉,重儿子继承这个“当前答案”数组

    然后由于两点间最多有 log 条重链,复杂度很对劲

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0, f = 1; char ch;
        for (ch = getchar(); !isdigit(ch); ch = getchar()) if (ch == '-') f = -f;
        for (; isdigit(ch); ch = getchar()) x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 400010;
    int n, m, a[maxn], b[maxn];
    int first[maxn], to[maxn << 1], nx[maxn << 1], pnt;
    inline void add(int u, int v) {
        to[++pnt] = v;
        nx[pnt] = first[u];
        first[u] = pnt;
    }
    int fa[maxn], mxs[maxn], size[maxn];
    inline void dfs1(int x) {
        size[x] = 1;
        for(int i=first[x];i;i=nx[i]) {
            if(to[i] == fa[x]) continue;
            fa[to[i]] = x;
            dfs1(to[i]); size[x] += size[to[i]];
            if(size[to[i]] > size[mxs[x]]) mxs[x] = to[i];
        }
    }
    int cnt[maxn], now;
    int ans[maxn], ansn[maxn];
    inline void cal(int x, int opt) {
        cnt[b[x]] += opt * a[x];
        if((cnt[b[x]] > cnt[now]) || ((cnt[b[x]] == cnt[now]) && (b[x] < now) && (opt == 1))) now = b[x];
        for(int i=first[x];i;i=nx[i])
            if(to[i] != fa[x]) cal(to[i], opt);
    }
    inline void dfs(int x, int opt) {
        for(int i=first[x];i;i=nx[i])
            if(to[i] != fa[x] && to[i] != mxs[x]) dfs(to[i], 0);
        if(mxs[x]) dfs(mxs[x], 1);
        for(int i=first[x];i;i=nx[i])
            if(to[i] != fa[x] && to[i] != mxs[x]) cal(to[i], 1);
        cnt[b[x]] += a[x];
        if((cnt[b[x]] > cnt[now]) || ((cnt[b[x]] == cnt[now]) && (b[x] < now))) now = b[x];
        ans[x] = now; ansn[x] = cnt[now];
        if(!opt) now = 0, cal(x, -1);
    }
    int main() {
        n = read(), m = read();
        rep(i, 2, n) {
            int u = read(), v = read();
            add(u, v); add(v, u);
        } dfs1(1); cnt[0] = -1;
        rep(i, 1, n) b[i] = read(), a[i] = read();
        dfs(1, 1);
        rep(i, 1, n) printf("%d %d
    ", ans[i], ansn[i]);
    }
    View Code
  • 相关阅读:
    8月3日云栖精选夜读:LSF-SCNN:一种基于CNN的短文本表达模型及相似度计算的全新优化模型
    linux(centos)下安装PHP的PDO扩展
    Linux中find常见用法示例
    01 编译原理概述
    20145221 《信息安全系统设计基础》第5周学习总结
    20145221 《信息安全系统设计基础》第4周学习总结
    爱春秋之戏说春秋 Writeup
    20145221 《信息安全系统设计基础》第3周学习总结
    20145221 《信息安全系统设计基础》第2周学习总结
    20145221 《信息安全系统设计基础》第1周学习总结
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10515600.html
Copyright © 2011-2022 走看看