总时间限制: 6000ms 内存限制: 65536kB
描述
Great Bytelandish超市联盟想请你编写一个程序模拟计算促销活动的开销
促销活动遵守以下规则:
参加促销活动的客户,可以在消费结束后将自己的消费账单投入一个指定的投票箱里
当一天的促销活动结束时,将从投票箱中选出两份账单:一份是消费金额最大的账单,一份是消费金额最小的账单。最大金额账单对应的客户,将得到一笔奖金,奖金数等于金额最大的账单与金额最小的账单之间的差值。输入保证总可以找到这样的两份账单
为了避免一个消费者重复获奖,抽出的两份账单都不能放回投票箱,但是其他账单还会留在投票箱里继续参加下一天的促销活动
你的任务是根据每天促销活动的信息,计算出超市在整个促销活动期间的奖金开销
输入
输入的第一行是一个整数n(1 <= n <= 5000),表示促销活动的天数
接下来有n行输入,每行有若干个非负整数,整数之间用空格分隔
第i+1行的数据代表第i天的账单信息,每行的第一个整数k(0 <= k <= 105)表示当天有多少个账单,接下来是k个正整数,对应每份账单的金额,账单金额都不超过106
整个促销活动涉及到的账单数之和不超过10^6
输出
一个整数,表示超市在整个促销活动中的奖金开销
样例输入
5
3 1 2 3
2 1 1
4 10 5 5 1
0
1 2
样例输出
19
思路
天数 | 序列 | 选中 | 当天开销 |
---|---|---|---|
1 | 1, 2, 3 | max: 3, min: 1 | 3 - 1 = 2 |
2 | 1, 1 | max: 2, min: 1 | 2 - 1 = 1 |
3 | 10, 5, 5, 1 | max: 10, min: 1 | 10 - 1 = 9 |
4 | max: 5, min: 1 | 5 - 1 = 4 | |
5 | 2 | max: 5, min: 2 | 5 - 2 = 3 |
sum = 2 + 1 + 9 + 4 + 3 = 19
错误操作
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
long n, m, t, max, min, sum = 0;
deque<long> q;
cin >> n;
for(long i = 1; i <= n; ++i) {
cin >> m;
for(long j = 1; j <= m; ++j) {
cin >> t;
q.push_back(t);
}
sort(q.begin(), q.end());
max = q.back();
q.pop_back();
min = q.front();
q.pop_front();
sum += max - min;
}
cout << sum;
}
Code
用优先队列的原因是优先队列每次取出的值分别是最大值或最小值,此时,可以省去排序的时间。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m, t, max, min, in[1000001] = {0};
long long sum = 0;
priority_queue<int, vector<int>, less<int>> q1;
priority_queue<int, vector<int>, greater<int>> q2;
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> m;
for(int j = 1; j <= m; ++j) {
cin >> t;
q1.push(t);
q2.push(t);
++in[t];
}
while(in[q1.top()] == 0) q1.pop();
while(in[q2.top()] == 0) q2.pop();
sum += q1.top() - q2.top();
--in[q1.top()];
--in[q2.top()];
q1.pop();
q2.pop();
}
cout << sum;
}
其中,最为重要的部分是
++in[t];
和
while(in[q1.top()] == 0) q1.pop();
while(in[q2.top()] == 0) q2.pop();
--in[q1.top()];
--in[q2.top()];
主要是解决未完全删除,即如下情况: