CodeForces 140C New Year Snowmen(堆)

题面

CodeForces

题解

因为要保证两两不同,所以不能单纯的开堆来维护,堆维护一个二元组,个数为第一关键字,编号为第二关键字,对于一个相同的颜色,统计一下这个颜色的个数再用堆来维护就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using std::min; using std::max;
using std::sort; using std::swap;
using std::unique; using std::lower_bound;
using std::priority_queue;
typedef long long ll;

template<typename T>
void read(T &x) {
    int flag = 1; x = 0; char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}

const int N = 1e5 + 10;
int n, a[N], b[N], zc[N], col[N];
struct Memb { int val, ind; };
struct Ans { int x, y, z; } A[N]; int tot;
inline bool operator < (const Memb &a, const Memb &b) { return a.val < b.val; }
priority_queue<Memb> q;

int main () {
    read(n); int m = n;
    for(int i = 1; i <= n; ++i)
        read(a[i]), b[i] = a[i];
    sort(&b[1], &b[m + 1]), m = unique(&b[1], &b[m + 1]) - b - 1;
    for(int i = 1; i <= n; ++i) {
        int tmp = lower_bound(&b[1], &b[m + 1], a[i]) - b;
        zc[tmp] = a[i], a[i] = tmp, ++col[tmp];
    }
    for(int i = 1; i <= m; ++i)
        q.push((Memb){col[i], i});
    Memb a_, b_, c_;
    while(q.size() >= 3) {
        a_ = q.top(); q.pop();
        b_ = q.top(); q.pop();
        c_ = q.top(); q.pop();
        A[++tot] = (Ans){zc[a_.ind], zc[b_.ind], zc[c_.ind]};
        if(--a_.val) q.push(a_);
        if(--b_.val) q.push(b_);
        if(--c_.val) q.push(c_);
    }
    printf("%d\n", tot);
    for(int i = 1; i <= tot; ++i) {
        if(A[i].y > A[i].x) swap(A[i].y, A[i].x);
        if(A[i].z > A[i].y) swap(A[i].z, A[i].y);
        if(A[i].y > A[i].x) swap(A[i].y, A[i].x);
        if(A[i].z > A[i].y) swap(A[i].z, A[i].y);
        printf("%d %d %d\n", A[i].x, A[i].y, A[i].z);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/water-mi/p/10350680.html

时间: 2024-10-09 16:49:32

CodeForces 140C New Year Snowmen(堆)的相关文章

CodeForces 140C - New Year Snowmen(数据结构)

题目链接:click here~~ [题目大意]给你一个整数序列,求最多选出每个长度为3的且序列元素单调的子序列的个数,并且输出每个子序列的元素,作为一个子序列,每个元素只能选一次,也就是满足一次性,但每个子序列里可以存在相同的元素, [解题思路]刚开始以为比较简单,就顺着思路写了一遍,第一发W了之后发现此题还是有一定的思维性,之后一直纠结在最多能选出多少子序列,因为考虑到如果序列里相同的元素的个数对最后结果会产生不同的影响,于是就想到了set容器的自动去重. 思想: 1,在判断set.size

New Year Snowmen CodeForces - 140C

As meticulous Gerald sets the table and caring Alexander sends the postcards, Sergey makes snowmen. Each showman should consist of three snowballs: a big one, a medium one and a small one. Sergey's twins help him: they've already made n snowballs wit

Codeforces Round #521 D Shop 堆

题目大意:给定k个数,n个操作,每个操作有三种类型: 1.a[i]=b 2.a[i]+=b 3.a[i]*=b 其中i和b是操作指定的 现在你可以进行最多m次操作,每个操作最多进行一次,要求操作结束后所有数的乘积最大 按使用的顺序输出每个操作的编号 乱七八糟地写了一发D--结果最后没调出来QAQ B题也没写 到最后就写了A和C 排了100+... 首先对于同一个数我们执行的所有操作一定是按照1-2-3的顺序 操作1最多执行1次 因此我们不妨将每个数的操作1取最大后当做操作2处理 现在就只剩下了两

Codeforces 854C Planning(贪心+堆)

贪心:让代价大的尽量移到靠前的位置. 做法:先让前k个数加进堆里,枚举k+1~n+k,每次把新元素加进堆后找到最大代价放在当前位置即可. #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=500010; struct poi{int c,pos;}; priority_queue<poi>q; bool operator<(poi a,poi b){return a

【题解】Berland.Taxi Codeforces 883L 模拟 线段树 堆

Prelude 题目传送门:ヾ(?ω?`)o Solution 按照题意模拟即可. 维护一个优先队列,里面装的是正在运营中的出租车,关键字是乘客的下车时间. 维护一个线段树,第\(i\)个位置表示第\(i\)个房子前面有没有停放出租车,这样在有人需要打车的时候可以快速找到离她最近的车的位置. 对每个房子维护一个堆,里面装的是停在这个房子前面的出租车,关键字是出租车的编号和上一个乘客下车的时间,上一个乘客下车越早,等待时间越长. 然后模拟时间的流逝就可以了,代码非常好写. Code #includ

CodeForces 140C New Year Snowm

题目链接:http://codeforces.com/contest/140/problem/C 题目大意: 给定n个数组成的序列(有重复),从中选3个数为一组,使得这三个数严格递增,请问最多能选出多少组,把每组数据输出. 分析: 很明显是贪心,不过贪心策略有待斟酌. 一开始我想当然的把数据按大小排序后从小到大贪心,结果就Wa了,很容易找到反例:1 2 3 4 4 4 5 5 5 如果从小到大贪,那么答案为1,不过这组数据眼睛看看答案都应该是3.造成这种情况的原因是我把数量少的先贪掉了,很多数量

Codeforces Gym100187C Very Spacious Office 贪心 堆

原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100187C.html 题目传送门 - CF-Gym100187C 题意 给定 $n$ 个房间以及 $n$ 个人. 第 $i$ 个房间的大小为 $a_i$. 第 $i$ 个人要的房间的大小范围为 $[L_i,R_i]$ . 现在给每一个人安排房间,一个房间只能被一个人拥有. 问是否存在方案满足条件. 如果不存在,输出:Let's search for another office. 如果存在多种方

Codeforces 505E Mr. Kitayuta vs. Bamboos (贪心,二分答案,堆)

题目传送门 题意 有\(n\)根竹子,竹子\(i\)初始高度为\(h_i\),每天晚上会长高\(a_i\). 每天白天,你可以选择\(k\)根竹子(同一根竹子在同一个白天可以多次选择),把他们的高度减少\(p\),若竹子当前高度\(-p\)后\(<0\),则竹子高度变为\(0\). 最小化\(m\)天后最高的竹子的高度. 题解 首先最小化最大的...这种问题,显然可以用二分答案. 二分\(m\)天后最高的竹子的高度\(H\),然后问题就变成了判定性问题:是否存在一种方案,使得\(m\)天后竹子高

Codeforces 1132D(二分答案+堆)

题面 传送门 分析 二分答案,考虑如何判定 可以用贪心的方法,每次找最快没电的电脑,在没电前1单位时间给它充电 正确性显然 实现上可以维护一个堆,存储每个电脑电用完的时刻,每次从堆顶取出最小的一个给它充电.设二分值为mid,对于每个电脑记录它的充电次数num[i],则没电的时间就是\(\lfloor \frac{a_i+num_i\times mid}{b_i} \rfloor+1\) 如果在维护堆的过程中发现当前时间已经超过某个电脑的没电时间,则返回false 代码 #include<iost