CF140C New Year Snowmen(贪心+优先队列)

CF140C


贪心+优先队列


贪心策略:每次取出数量最多的三种球,合成一个答案,再把雪球数都-1再插回去,只要还剩下三种雪球就可以不断地合成

雪球数用优先队列维护


#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,a[N],b[N],nm;
struct ball{
    int i,n; //i是离散数组中的编号,n为该种雪球的剩余数量
    inline bool operator < (const ball &nt) const{
        if(n==nt.n) return i<nt.i;
        return n<nt.n;
    }
};
struct ANS{
    int x,y,z;
    inline void change(){
        int tx=x,ty=y,tz=z;
        x=max(max(tx,ty),tz); //求最大
        z=min(min(tx,ty),tz); //求最小
        y=tx+ty+tz-x-z; //和减去最大最小就是中间值
    }
}ans[N/3];
priority_queue<ball> q;
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+1+n);
    sort(a+1,a+1+n);
    int un=unique(b+1,b+1+n)-b-1; //离散化
    for(int i=1;i<=n;){
        int j=i;
        while(j+1<=n&&a[j+1]==a[i]) j++; //找到该种雪球最右到哪
        int hn=j-i+1,id=lower_bound(b+1,b+1+un,a[i])-b; //该种雪球数量
        q.push((ball){id,hn});
        i=j+1; //跳过这一串相同的雪球
    }
    while(q.size()>=3){ //如果还有三种以上雪球
        ball alpha=q.top();q.pop(); //最多的
        ball beta=q.top();q.pop(); //次多的
        ball gamma=q.top();q.pop(); //第三多的
        alpha.n--;if(alpha.n) q.push(alpha); //都减去一个雪球
        beta.n--;if(beta.n) q.push(beta);
        gamma.n--;if(gamma.n) q.push(gamma);
        ans[++nm]=((ANS){b[alpha.i],b[beta.i],b[gamma.i]}); //合成答案
    }
    printf("%d\n",nm);
    for(int i=1;i<=nm;i++){
        ANS now=ans[i];
        now.change(); //整理一下答案的排序
        printf("%d %d %d\n",now.x,now.y,now.z);
    }
}
posted @ 2019-07-25 22:55  think_twice  阅读(211)  评论(0编辑  收藏  举报