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);
}
}
题目大意:超市举办一个活动,活动期间,凡是来到超市购物的客人将小票放到一个抽奖箱中,每天结束经理从中间抽出两张小票,一张最高的消费额,一张最低的消费额。然后最高消费的那位客人将获得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);
}
}
相关文章推荐
- 谈谈IPC
- Java对象与Json之间的转换
- 基于Boost方法的人脸检测(4):弱分类器生成、强分类器生成(AdaBoost)
- POJ-2253-Frogger
- Kylin的Hierarchies,Derived维度方面配置优化
- 对于高质量代码的认知
- js判断手机浏览器操作系统和微信浏览器的方法
- lintcode:组成最大的数
- 同一个C语言工程不同C文件之间的函数互相调用问题(二)
- Program3_B
- 基于Boost方法的人脸检测(3):特征生成、特征值计算(积分图)
- android学习记录 Onclick事件监听
- Hanoi双塔问题(hanoi)
- 对C++中mutable、inline、volatile关键字的理解
- Leetcode - Best Time to Buy and Sell Stock
- 基于Boost方法的人脸检测(2):样本生成(切割图像、resize图像、灰度化图像、保存图片)
- POJ 2135 Farm Tour (最小费用最大流)
- 【模板】Lucas定理
- 搭建Windows Embedded Compact 7开发环境
- 纪念品分组(贪心)