試題編號: 201412-3
試題名稱: 集合競價
時間限制: 1.0s
內存限制: 256.0MB
整個交易中有多個買單和賣單,要求求一個開盤價使得出價大於等於開盤價的買單總股數與小於等於開盤價的賣單總股數之間最小值最大,即能把最多的賣出股票賣給買入的人。
注意讀入數據的方式,因爲題目中輸入數據有任意多行,所以以EOF(end of file)作爲讀入結束的條件。在C++中可以直接使用while(cin>>SOMETHING)語句。,每一筆交易的信息可以用一個結構體來保存,其中還需要保存交易的類型(買,賣,被取消)。可以使用一個結構體數組保存所有交易的信息,方便交易取消時進行修改。
容易發現答案中的開盤價一定是所有的賣出價和買入價中的一個值。所以一個簡單的做法是遍歷所有出現過的價格,計算這個價格下能交易的股票數量,如果數量大於當前最大值,就更新這個最大值,並保存這個價格。
如果要使程序的時間效率更優,可以分別保存買單和賣單並進行排序,計算交易數量時只需要統計到最後一個滿足條件的交易單。比這個更好的解法是使用優先隊列。
下面的程序使用了最簡單的方法計算答案。
注意點:交易的股票數量可能超過int範圍,需要使用long long保存。答案可以使用printf輸出,printf(“%.2f “, ans)即輸出保留兩位小數的ans值。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
//保存交易信息
struct Order {
double price;
int num, sell;
}order[5010];
vector<double>vec;//保存所有出現過的價格
int main() {
char s[10];
int num = 0, t;//num用於記錄交易的數量
while (cin >> s) {
if (s[0] == 'c') {
cin >> t;
order[t - 1].sell = order[num++].sell = -1;
}
else {
cin >> order[num].price >> order[num].num;
vec.push_back(order[num].price);
//判斷是買入還是買出
if (s[0] == 's')
order[num].sell = 1;
else
order[num].sell = 0;
num++;
}
}
double ans = 0;//保存開盤價
long long maxn = 0;//保存最大交易量,交易量可能超過int範圍,所以使用long long保存
for (int i = 0; i < vec.size(); i++) {
long long num1 = 0, num2 = 0;//num1保存可賣出的股票數量,num2保存可買入的股票數量
for (int j = 0; j < num; j++) {
if (order[j].sell == 1 && order[j].price <= vec[i])
num1 += (long long)order[j].num;
}
for (int j = 0; j < num; j++) {
if (order[j].sell == 0 && order[j].price >= vec[i])
num2 += (long long)order[j].num;
}
num1 = min(num1, num2);//num1保存交易數
//更新答案
if (num1 > maxn) {
maxn = num1;
ans = vec[i];
}
else if (num1 == maxn) {
ans = max(ans, vec[i]);
}
}
//答案可以用printf輸出
printf("%.2f %lld\n", ans, maxn);
}