zoukankan      html  css  js  c++  java
  • 「十二省联考2019」 春节十二响

    Description

    给出一颗有根树,每个点有一个权值,现在要求将这些点划分成若干个集合,要求在同一个集合中的点不存在祖先—后代关系,规定一个集合的代价为集合中所有点的权值的最大值,问所有划分方案中代价和最小的是多少

    Solution

    考虑首先对这颗树进行重链剖分,然后对于对于一条重链,用一个大根堆去维护它链上的节点及其子树中的所有节点的集合代价,那么在合并两条重链时,就直接贪心从两个堆中取出最大值比较下大小进行合并就好了

    Code

     //Created Time:2020年05月12日 星期二 08时57分29秒
     #include <queue>
     #include <vector>
     #include <cstdio>
     #include <cstring>
     #include <iostream>
     #include <algorithm>
     #define N 200005
     
     using namespace std;
     
     int n;
     int fa[N], a[N], son[N], sz[N];
     
     vector<int> e[N];
     priority_queue<int> Q[N];
     
     void dfs1(int);
     void dfs2(int, int);
     
     int main(){
     #ifndef ONLINE_JUDGE
         freopen("a.in", "r", stdin);
         freopen("a.out", "w", stdout);
     #endif
      scanf("%d", &n);
      for(int i = 1; i <= n; ++i)
      scanf("%d", a + i);
      for(int i = 2; i <= n; ++i)
      scanf("%d", fa + i), e[fa[i]].push_back(i);
      dfs1(1); dfs2(1, 1);
      long long res = 0;
      while(!Q[1].empty())
      res += Q[1].top(), Q[1].pop();
      cout << res << endl;
      return 0;
     }
     
     void dfs1(int u){
      sz[u] = 1;
      for(auto v : e[u]){
      dfs1(v); sz[u] += sz[v];
      if(sz[son[u]] < sz[v])
      son[u] = v;
      }
      return ;
     }
     
     void dfs2(int u, int top){
      if(!son[u]) return Q[top].push(a[u]), void();
      dfs2(son[u], top);
      priority_queue<int> tmp;
      for(auto v : e[u]){
      if(v == son[u]) continue;
      dfs2(v, v);
      while(!Q[top].empty() && !Q[v].empty()){
      int x = Q[top].top(), y = Q[v].top();
      Q[top].pop(); Q[v].pop();
      tmp.push(max(x, y));
      }
      while(!Q[v].empty()) Q[top].push(Q[v].top()), Q[v].pop();
      while(!tmp.empty()) Q[top].push(tmp.top()), tmp.pop();
      }
      Q[top].push(a[u]);
      return ;
     }



  • 相关阅读:
    手把手教你在CSDN博客中插入图片之剑走偏锋系列
    PCD文件格式详解及在PCL下读取PCD文件
    C 基于数组存储的堆栈实现
    C++ Opencv remap()重映射函数详解及使用示例
    C 线性表的链式存储实现及插入、删除等操作示例
    C 线性表的顺序存储实现及插入、删除等操作示例
    C 单向链表就地逆转
    C 单向链表的创建、插入及删除
    [C#]SQL Server Express LocalDb(SqlLocalDb)的一些体会
    [C#]关于DataDirectory的一些思考
  • 原文地址:https://www.cnblogs.com/roal-l/p/13085964.html
Copyright © 2011-2022 走看看