zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj4198:loj2132:uoj130:p2168:[NOI2015]荷马史诗

    题目大意

    (n)((nleq10^5))种单词,其中第(i)种单词在文章中的出现次数为(w_i)
    要将每个单词替换成一个字符集为(k)((kleq9))的字符串,使对于任意两个单词,其中一个的字符串不是另一个的前缀

    题解

    哈夫曼树贪心,每次合并(k)
    需要注意的是,有时候第一层填不满。
    除了连接叶子的分支节点以外,如果有一个点的儿子数目不是0或k,就一定不是最优解(可以把子树中的一个叶子拿上来使答案更优)。
    但是按照哈夫曼树的贪心方式,最连接叶子节点的分支节点最先安排,无法确定每个这类分别安排多少个儿子。
    会发现添加若干个出现次数为0的单词并不会影响答案。
    可以添加一些出现次数为0的单词,使刚好补满叶子节点的分支节点的儿子。

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define maxn 100010
    #define maxm 200010
    #define int long long
    #define pii pair<int,int>
    #define fi first
    #define se second
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return x*f;
    }
    void write(int x)
    {
        if(x==0){putchar('0'),putchar('
    ');return;}
        int f=0;char ch[20];
        if(x<0)putchar('-'),x=-x;
        while(x)ch[++f]=x%10+'0',x/=10;
        while(f)putchar(ch[f--]);
        putchar('
    ');
        return;
    }
    int n,k,ans1,ans2;
    priority_queue<pii >q;
    signed main()
    {
        n=read(),k=read();
        rep(i,1,n){int w=read();q.push(make_pair(-w,0));}
        if((n-1)%(k-1))
        {
            int lim=k-1-(n-1)%(k-1);
            rep(i,1,lim)q.push(make_pair(0,0));
        }
        while(q.size()>k)
        {
            int cnt=0,tmp1=0,tmp2=0;
            while((++cnt)<=k)
            {
                pii x=q.top();q.pop();
                tmp1+=-x.fi,tmp2=max(-x.se+1,tmp2);
            }
            ans1+=tmp1;q.push(make_pair(-tmp1,-tmp2));
        }
        while(!q.empty())
        {
            pii x=q.top();q.pop();
            ans1+=-x.fi,ans2=max(ans2,-x.se+1);
        }
        write(ans1),write(ans2);
        return 0;
    }
    
  • 相关阅读:
    排序总结[3]_线性排序算法
    Spring九问
    DP-最大递增子序列与最大递增子数组; 最大公共子序列与最大公共子数组。
    java 8 新特性
    数据库事务隔离等级
    算法思维方式之二——DP与DFS
    算法思维方式—— 由排列组合想到的
    java Servlet简介
    java hashCode, 引用以及equals().
    java反射简介
  • 原文地址:https://www.cnblogs.com/xzyf/p/10391458.html
Copyright © 2011-2022 走看看