• [NOIP模拟题]poker 大根堆 小根堆 贪心


    本人水平有限,题解不到为处,请多多谅解

    本蒟蒻谢谢大家观看

    不会小根堆的点这里

    点击这里了解什么是priority_queue 

    题目

    扑克牌

    (poker.cpp/in/out 1s 256M)

    一副扑克牌有n张牌。一般你买的一副新扑克牌里除了这n张牌外还会有一些张特殊的牌,如果你不小心弄丢了n张牌中的某一张,就可以用特殊牌来代替,但是如果你弄丢两张的话就没有办法了,因为特殊牌上的图案是一样的。现在你得到了很多扑克牌,准确来说,n种牌你各有a1a2、……、an张,同时你还有b张特

    殊牌,现在你需要从这些牌中整理出若干副牌供大家使用。整理出的一副牌可以由n种普通牌各一张组成,也可以由n-1种普通牌各一张再加一张特殊牌组成。请你设计出一种方案,整理出尽可能多的牌。

    Input

    输入包括2

    第一行给出nb

    第二行给出a1,a2an

    1<=n<=1000000,牌的数量<=10^6

    Output

    输出最多能整理出的牌的副数。

    Sample Input

    5 5

    5 5 5 5 5

    Sample Output

    6

    【数据规模】
    对于20%的数据 1<=n<=100。牌的数量小于100。
    对于40%的数据 1<=n<=3000
    对于100%的数据 1<=n<=1000000 牌的数量<=10^6

    本题样例注意事项:特殊牌每次只能使用一次

    一般思维

    考虑不断求最小值,再拿a[i]-min ,看最大是多少。

    但是在N=1e6的范围下,此做法是O(N^2)的,显然会TLE。所以只能逆向思维。

    逆向思维:

    一样的先求最小值,但可以拿一个小根堆来维护,用当前最小值+使用的一张特殊牌。这样就只需要输出栈顶元素即可。

    样例深度剖析:

    拿个样例来说吧,比如五种牌各有1 2 3 4 5张,有四张特殊牌。设ans代表目前使用了几张特殊牌

    将五种普遍牌丢到堆里。取出最少的一张,也就是1出来。然后给它配一张特殊牌,再丢到堆里,ans=1

    堆中有2 2 3 4 5.然后再取出最小的一张,也就是2出来。然后给它配一张特殊牌,再丢到堆里,ans=2

    堆中有2 3 3 4 5 然后再取出最小的一张,也就是2出来。然后给它配一张特殊牌,再丢到堆里,ans=3

    堆中有3 3 3 4 5.

    当我们取出堆中的最小的两个数字3 3时,发现它们均等于ans,说明,其实这两堆牌其实是都已用完了的

    此时如果再要派特殊牌的话,则一次要派两张了。与题意不合

    code:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e6+10;
     4 int a[maxn],ans=0;
     5 priority_queue<int,vector<int>,greater<int> >q;
     6 inline int read(){
     7     int x=0,f=1;char ch=getchar();
     8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    10     return x*f;
    11 }
    12 int main(){
    13     int n=read(),b=read();
    14     for(int i=1;i<=n;i++){
    15         a[i]=read();
    16         q.push(a[i]);
    17     }
    18     for(int i=1;i<=b;i++){
    19         ans++;
    20         int x=q.top();
    21         q.pop();
    22         x++;
    23         q.push(x); 
    24         int x1=q.top();
    25         q.pop();
    26         int x2=q.top();
    27         q.pop();
    28         q.push(x1);
    29         q.push(x2);
    30         if(ans==x2&&ans==x1){
    31             break;
    32         }
    33     }
    34     printf("%d
    ",q.top());
    35     return 0;
    36 }
  • 相关阅读:
    【EFCORE笔记】客户端与服务端求值&跟踪与非跟踪查询
    【EFCORE笔记】预先加载&显式加载&延迟加载
    【EFCORE笔记】在远程查询数据
    【EFCORE笔记】远程数据查询支持
    【EFCORE笔记】元素操作&集合运算&转换类型
    【EFCORE笔记】生成操作&相等比较&串联运算
    【EFCORE笔记】联接运算与数据分组
    【EFCORE笔记】投影运算与数据分区
    【EFCORE笔记】排序&集运算&筛选&限定
    【EFCORE笔记】团队环境中的迁移
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11657074.html
Copyright © 2020-2023  润新知