zoukankan      html  css  js  c++  java
  • [NOI2015]荷马史诗

    嘟嘟嘟


    在luogu上看到这是一道蓝题,结果自己想了一个多点也没做出来……


    但是自己概括的题意还是很准的:构建一棵最多有(K)个叉的(n)个叶子节点的树,每一个叶子节点有一个给定的权值,使每一个叶子节点的权值*到根节点的距离之和最小。


    当时只发现了如果把权值从大到小排序,那么他们距树根的距离一定是单调不减的。然后按这个方法爆搜+(w_i)都相等的情况,总共就拿了40分。
    啊,(w_i)都相等的情况就是一个完全(K)叉树,(O(1))算一下即可。


    正解是一个哈夫曼树的东西,定义和我上面说的题面一样。然后用哈夫曼树可以构造出哈夫曼编码。
    做法就是“(K)维合并果子”:每次选出(K)个权值最小的果子合并成一个,直到剩1个果子,即树根。合并的同时维护深度最大值,第二问就解决了。
    有一个细节,就是最后一次合并不足(k)个,那么这时候根节点会不足(K)个叉,而他的子树反而都是(K)个叉,这显然是不优的。所以我们在合并之前先补零,满足最后刚好剩(K)个果子合并成一个。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<assert.h>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 1e5 + 5;
    In ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    In void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
      freopen("ha.in", "r", stdin);
      freopen("ha.out", "w", stdout);
    #endif
    }
    
    int n, K, N;
    ll a[maxn];
    
    struct Node
    {
      ll val; int tot;
      In bool operator < (const Node& oth)const
      {
        return val > oth.val || (val == oth.val && tot > oth.tot);
      }
    };
    priority_queue<Node> q;
    
    int main()
    {
      MYFILE();
      n = read(), K = read();
      N = (n - 1 + K - 2) / (K - 1) * (K - 1) + 1;
      for(int i = 1; i <= n; ++i) a[i] = read(), q.push((Node){a[i], 1});
      for(int i = n + 1; i <= N; ++i) q.push((Node){0, 1});
      ll ans1 = 0;
      for(int i = N; i > 1; i -= (K - 1))
        {
          ll sum = 0; int tot = 0;
          for(int j = 1; j <= K; ++j)
    	{
    	  Node tp = q.top();
    	  sum += tp.val; tot = max(tot, tp.tot);
    	  q.pop();
    	}
          q.push((Node){sum, tot + 1});
          ans1 += sum;
        }
      write(ans1), enter, write(q.top().tot - 1), enter;
      return 0;
    }
    
  • 相关阅读:
    UVA 10600 ACM Contest and Blackout(次小生成树)
    UVA 10369
    UVA Live 6437 Power Plant 最小生成树
    UVA 1151 Buy or Build MST(最小生成树)
    UVA 1395 Slim Span 最小生成树
    POJ 1679 The Unique MST 次小生成树
    POJ 1789 Truck History 最小生成树
    POJ 1258 Agri-Net 最小生成树
    ubuntu 用法
    ubuntu 搭建ftp服务器,可以通过浏览器访问,filezilla上传文件等功能
  • 原文地址:https://www.cnblogs.com/mrclr/p/10904110.html
Copyright © 2011-2022 走看看