CJOJ 2482 【POI2000】促銷活動

CJOJ 2482 【POI2000】促銷活動

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章