zoukankan      html  css  js  c++  java
  • [CF600E]Lomsat gelral[dsu on tree/树上启发式合并]

    题意:求每个节点子树众数和(比如3和5都是众数 答案是8)

    树上启发式合并可以解决一些无修改的子树询问

    先solve轻儿子,后solve重儿子,如果该节点是轻儿子,然后重新统计轻儿子的贡献,更新该节点的答案,如果该节点是轻儿子,那么将该节点的贡献删除,回溯(其实就是保留了重儿子的答案)

    由于轻重链剖分一个点到根节点至多有(O(logn))条轻边的性质,所以每个节点最多被重复遍历(O(logn))次,总复杂度(O(nlogn))

    int cnt[MAXN], son[MAXN], siz[MAXN], head[MAXN], c[MAXN], n, m;
    bool vis[MAXN];
    
    struct Edge {
      int v, next;
    }G[MAXN<<1];
    inline void add(int u, int v) {
      static int tot = 0;
      G[++tot] = (Edge) {v, head[u]}; head[u] = tot;
    }
    ll cur, ans[MAXN];
    int Max;
    inline void dfs(int u, int fa) {
      siz[u] = 1;
      for(int i = head[u]; i; i = G[i].next) {
        int v = G[i].v;
        if (v == fa) continue;
        dfs(v, u); siz[u] += siz[v];
        if (siz[v] >= siz[son[u]]) son[u] = v;
      }
    }
    
    inline void update(int u, int fa, int V) {
      cnt[c[u]] += V;
      if (cnt[c[u]] > Max) Max = cnt[c[u]], cur = c[u];
      else if (cnt[c[u]] == Max) cur += c[u];
      for(int i = head[u]; i; i = G[i].next) {
        int v = G[i].v;
        if (v == fa || vis[v]) continue;
        update(v, u, V);
      }
    }
    
    inline void solve(int u, int fa, bool is) {
      for(int i = head[u]; i; i = G[i].next) {
        int v = G[i].v;
        if (v == fa || v == son[u]) continue;
        solve(v, u, 0);
      }
      if (son[u]) solve(son[u], u, 1), vis[son[u]] = 1;
      update(u, fa, 1);
      ans[u] = cur;
      vis[son[u]] = 0;
      if (!is) {
        update(u, fa, -1);
        Max = cur = 0;
      }
    }
    
    int main() {
    #ifdef LOCAL_DEBUG
      // freopen("data.in", "r", stdin), freopen("data.out", "w", stdout);
      Dbg = 1; uint tim1 = clock();
    #endif
      in, n;
      lop(i,1,n) in, c[i];
      lop(i,1,n-1) { 
        int u, v; in, u, v; add(u, v), add(v, u);
      }
      dfs(1, 0);
      solve(1, 0, 1);
      lop(i,1,n) out, ans[i], ' ';
    #ifdef LOCAL_DEBUG
      fprintf(stderr, "
    time:%.5lfms", (clock() - tim1) / (1.0 * CLOCKS_PER_SEC) * 1000);
    #endif
      return 0;
    }
    
  • 相关阅读:
    Markdown入门
    HTTP协议 keep-alive连接 与 BS(firefox-thttpd)实验
    emoji探寻之路
    JavaScript实现绑定DOM的定时器插件
    C语言 str2bin 和 bin2str 实现
    LUA OOP 单例模式实现的 一个 方案
    LUA OOP编程实现方法
    以一则LUA实例说明敏捷开发中“分离构造和使用”原则
    HTML 中按钮作为form表单元素提交特性两则 --- 参HTML考标准分析
    分享:一款前端布局工具(alloydesigner)
  • 原文地址:https://www.cnblogs.com/storz/p/10190880.html
Copyright © 2011-2022 走看看