您的位置:首页 > 其它

UVA 11136 Hoax or what 促销活动

2016-04-30 13:00 423 查看
题意:

题目大意:超市举办一个活动,活动期间,凡是来到超市购物的客人将小票放到一个抽奖箱中,每天结束经理从中间抽出两张小票,一张最高的消费额,一张最低的消费额。然后最高消费的那位客人将获得max - min价值的商品。然后将这两张小票扔掉。活动期间都这么抽出幸运的顾客。问这个活动需要准备花多少钱在提供奖品上。


Input

The input contains a number of cases. The first line in each case contains an integer n, 1 ≤ n ≤ 5000,the number of days of the promotion. Each of the subsequent n lines contains a sequence of non-negativeintegers separated by
whitespace. The numbers in the (i + 1)-st line of a case give the data for the i-thday.The first number in each of these lines, k, 0 ≤ k ≤ 105, is the number of bills and the subsequent knumbers are positive integers of the bill amounts. No bill is bigger
than 106. The total number of allbills is no bigger than 106.The case when n = 0 terminates the input and should not be processed.

Output

For each case of input print one number: the total amount paid to the clients by Mal-Wart as the resultof the promotion.

Sample Input

5

3 1 2 3

2 1 1 

4 10 5 5 1

0

1 2

2

2 1 2

2 1 2

0

Sample Output

19

2

分析:

每一次取序列中最大值和最小值,取他们的差值,计算n次后求差值的和。

注意使用 longlong.

方法一: 

优先队列 分别用大根堆、小根堆每次取出最大值、最小值即可。但是注意一张小票只能取一次,不能在两个堆里都被取出一次。

mark[x]记录当前价值为x的小票张数。

代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define LL long long
using namespace std;
int n,k;
int mark[1000005];
inline void _read(int &x){
char ch=getchar(); bool mark=false;
for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;
for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';
if(mark)x=-x;
}
int main(){
//freopen("ans.out","w",stdout);
int i,x,j,_max,_min;
while(true){
_read(n);
priority_queue<int> big; //大根堆
priority_queue<int,vector<int>,greater<int> > small; //小根堆
memset(mark,0,sizeof(mark)); //多组数据
if(n==0)return 0;
long long ans=0;
for(i=1;i<=n;i++){
_read(k);
for(j=1;j<=k;j++){
_read(x);
big.push(x);
small.push(x);
mark[x]++;
}
while(!mark[big.top()])big.pop();
_max=big.top(); mark[_max]--;
big.pop();
while(!mark[small.top()])small.pop();
_min=small.top(); mark[_min]--;
small.pop();
ans=ans+ (long long)(_max-_min);
}
printf("%lld\n",ans);
}
}


方法二:

动态取最大最小值,保持有序,用set即可,但是可能有几张小票价值相同,所以要用multiset。

代码如下:

#include<cstdio>
#include<iostream>
#include<set>
#define LL long long
using namespace std;
int n,k;
inline void _read(int &x){
char ch=getchar(); bool mark=false;
for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;
for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';
if(mark)x=-x;
}
int main(){
//freopen("ans.out","w",stdout);
int i,x,j,minn,maxx;
while(true){
_read(n);
multiset<int>s;
if(n==0)return 0;
LL ans=0;
for(i=1;i<=n;i++){
_read(k);
for(j=1;j<=k;j++){
_read(x);
s.insert(x);
}
set<int>::iterator it=s.end();
it--;//注意s.end()是哨兵指针
ans=ans+(LL)((*it)-(*s.begin()));
s.erase(s.begin());
if(s.size()>0)s.erase(it);
}
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: