zoukankan      html  css  js  c++  java
  • P6033 [NOIP2004 提高组] 合并果子 加强版 题解

    CSDN同步

    原题链接

    我们先解决弱化版,即 P1090 ,对于 (n leq 10^5) 的数据,如何解决?

    很明显我们可以采取贪心,对于 (a leq b leq c),我们应先将 (a,b) 先合并,再与 (c) 合并。具体证明:

    先并 (a,b)((a+b)+(a+b+c)),而其余答案为 ((a+c)+(a+b+c))((b+c)+(a+b+c)),均比其劣。于是可说明,每次把两个最小的并,总是最优的。并完之后我们需要把 (a+b) 丢到数组里,再重新排序。

    当然我们不需要每次都重新排序。可以用插入排序维护,或者更方便地用优先队列维护,时间复杂度均为 (mathcal{O}(n log n)).

    强化版(即本题),如何解决?

    考虑到,由于 (a_i leq 10^5 (forall i in [1,n])),因此可以用桶排序来进行线性的排序。然后主要是如何维护 (a+b) 的位置?

    考虑把排序过后的原数列放在一个队列(非优先队列)(q1) 中,把由于合并产生的数放在另一个队列 (q2) 中。每次从两个队列中挑出最小值和次小值将其踢出,然后再放到 (q2) 中。由于每次合并的总是当前最小的,因此 (q2) 满足单调性。(q1) 显然满足单调性,因此可保证正确。

    时间复杂度:(mathcal{O}(n)).

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int N=1e7+1;
    
    inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
    
    inline void write(int x) {
    	if(x<0) {putchar('-');write(-x);return;}
    	if(x<10) {putchar(char(x%10+'0'));return;}
    	write(x/10);putchar(char(x%10+'0'));
    }
    
    int n,a[N],h[N];
    ll ans=0;
    queue<ll> q1,q2;
    
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++) h[read()]++;
    	for(int i=1;i<=100000;i++)
    	for(int j=1;j<=h[i];j++) q1.push(i);
    	for(int i=1;i<n;i++) {
    		ll x,y;
    		if(q2.empty() || !q1.empty() && q1.front()<q2.front()) x=q1.front(),q1.pop();
    		else x=q2.front(),q2.pop();
    		if(q2.empty() || !q1.empty() && q1.front()<q2.front()) y=q1.front(),q1.pop();
    		else y=q2.front(),q2.pop();
    		ans+=x+y; q2.push(x+y);
    	} printf("%lld
    ",ans);
    	return 0;
    }
    
    
    
    简易的代码胜过复杂的说教。
  • 相关阅读:
    MyBatis使用
    华为如何实现基于Git的跨地域协同开发
    推荐一款华为最新的自动化代码检查工具
    我是如何进行code review的
    谈谈敏捷开发
    软件测试管理的一点小心得
    (转)技术转管理可能遇到的 3 大挑战及解决方案
    领域驱动设计和实践
    NET开源项目
    asp.net搭建mybatis开发环境
  • 原文地址:https://www.cnblogs.com/bifanwen/p/15081197.html
Copyright © 2011-2022 走看看