zoukankan      html  css  js  c++  java
  • CJOJ 2482 【POI2000】促销活动(STL优先队列,大根堆,小根堆)

    CJOJ 2482 【POI2000】促销活动(STL优先队列,大根堆,小根堆)

    Description

    促销活动遵守以下规则:

    • 一个消费者 —— 想参加促销活动的消费者,在账单下记下他自己所付的费用,他个人的详细情况,然后将账单放入一个特殊的投票箱。
    • 当每天促销活动结束时,从投票箱中抽出两张账单:

    第一张被抽出的账单是金额最大的账单

    然后被抽出的是金额最小的账单,对于付了金额最大账单的这位消费者,将得到一定数目的奖金,其奖金数等于他账单上的金额与选出的最小金额的差。
    为了避免一个消费者多次获奖,根据上面所抽出的两张账单都不返回到投票箱,但是剩下的账单还继续参加下一天的促销活动。

    超市的售出额是巨大的,这样可以假定,在每天结束,拿出数额最大账单和数额最小账之前,在投票箱内就已经至少存在了 2 张账单。你的任务是去计算每天促销活动投进投票箱的账单数额的基本信息。在整个活动中开销总数。

    本题中约定:
    整个活动持续了 N 天 (N<=5000) 。 第 i 天放入的帐单有 a[i] 张, a[i]<=10^5 。且 sigma(a[1]...a[n])<=10^6 。 每一天放入的帐单的面值均 <=10^6 。

    Input

    第一行是一个整数 n ( 1 <= n <= 5000 ),表示促销活动历时的天数。
    以下的 n 行,每行包含若干由空格分隔的非负整数。第 i+1 行的数表示在第 i 天投入箱子的账单金额。每行的第一个数是一个整数 k ( 0 <= k <= 10^5 ), 表示当日账单的数目。后面的 k 个正整数代表这 k 笔账单的金额,均小于10^6 。
    整个活动中涉及到的账单笔数不会超过 10^6 。

    Output

    输出唯一一行是一个整数,等于整个促销活动中应该付出的奖金总额。

    Sample Input

    5
    3 1 2 3
    2 1 1
    4 10 5 5 1
    0
    1 2

    Sample Output

    19

    Http

    CJOJ:http://oj.changjun.com.cn/problem/detail/pid/2482

    Source

    STL,优先队列

    题目大意

    一个商场搞促销活动n天,每天选出最高账单和最低账单,求所有最高账单-最低账单的总和。

    解决思路

    这道题是优先队列的运用。分别维护两个优先队列,一个最小值优先,一个最大值优先,每次弹出队首元素即可。需要注意的是,一个元素是在两个队列中同时存在的,而有可能在这个队列中弹出去了,而在另一个队列中还没有,所以要用一个Cnt数组统计一下每个元素出现的次数,若某次发现队首元素的Cnt已经为0了,则说明已经在另外一个队列中弹出,将重复的去除即可。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int maxN=5001;
    const int inf=2147483647;
    
    int n;
    priority_queue<int,vector<int>,less<int> > Q1;//大的优先
    priority_queue<int,vector<int>,greater<int> > Q2;//小的优先
    int Cnt[1000001]={0};//统计每一种金额的次数
    
    int main()
    {
        int K;
        int value;
        int Ans=0;
        cin>>n;
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&K);
            for (int j=1;j<=K;j++)
            {
                scanf("%d",&value);
                Cnt[value]++;
                Q1.push(value);
                Q2.push(value);
            }
            while (Cnt[Q1.top()]==0)//如果这种金额次数已经没有了,说明在另一个优先队列中已经弹出直接去掉即可
                Q1.pop();
            while (Cnt[Q2.top()]==0)//与上面同理
                Q2.pop();
            Ans=Ans+Q1.top()-Q2.top();
            //cout<<Q1.top()<<" "<<Q2.top()<<endl;
            Cnt[Q1.top()]--;
            Cnt[Q2.top()]--;
            Q1.pop();
            Q2.pop();
        }
        cout<<Ans<<endl;
        return 0;
    }
    
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    Asp.NET 4.0 ajax实例DataView 模板编程1
    ASP.NET 4.0 Ajax 实例DataView模板编程 DEMO 下载
    部分东北话、北京话
    .NET 培训课程解析(一)
    ASP.NET 4.0 Ajax 实例DataView模板编程2
    ASP.NET Web Game 架构设计1服务器基本结构
    ASP.NET Web Game 构架设计2数据库设计
    TFS2008 基本安装
    Linux上Oracle 11g安装步骤图解
    plsql developer远程连接oracle数据库
  • 原文地址:https://www.cnblogs.com/SYCstudio/p/7137746.html
Copyright © 2011-2022 走看看