題目:
該程序的輸入由很多行構成,每一行爲一條記錄,記錄可能有以下幾種:
1. buy p s 表示一個購買股票的買單,每手出價爲p,購買股數爲s。
2. sell p s 表示一個出售股票的賣單,每手出價爲p,出售股數爲s。
3. cancel i表示撤銷第i行的記錄。
如果開盤價爲p0,則系統可以將所有出價至少爲p0的買單和所有出價至多爲p0的賣單進行匹配。因此,此時的開盤成交量爲出價至少爲p0的買單的總股數和所有出價至多爲p0的賣單的總股數之間的較小值。
你的程序需要確定一個開盤價,使得開盤成交量儘可能地大。如果有多個符合條件的開盤價,你的程序應當輸出最高的那一個。
buy 8.88 175
sell 9.00 1000
buy 9.00 400
sell 8.92 400
cancel 1
buy 100.00 50
關鍵是對p0的選取,這裏p0一定是有效的買單或賣單裏的p。
理由:
若p0不是買單或賣單裏的p,那麼p0必然介於某兩個出價p之間,設爲 p1 和 p2,即 p1 < p0 < p2;
1.當買單和賣單裏都有p2時,這時若以p0爲單價,則必然會使賣單減少,由於成交量是取小的,所以成交量也會減小,就不如開盤價爲p2是的好;
2.當只有買單有p2,和開盤價爲p2時一樣,所以開盤價不會是這個p0;
3.當只有賣單有p2,情況和 1 相同;
4.當買單和賣單裏都有p1時或只有買單有p1時,若以p0爲單價,則會使買單減少,繼而成交量減小,不如開盤價爲p1;
5.當只有賣單有p1時,這時和開盤價爲p1時是一樣的,此時p0優於p1,但是p2則必然優於p0;由於買單是沒有p1,所以此時對於p1,p0,p2買單的成交量都一樣,而 賣單的成交量p1和p0相同,p2則大於等於p1和p0;
代碼:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
#define MAX 5007
typedef struct{
string m;
double p;
int s;
bool e;
}R;
R r[MAX];
set<double> st;
int main(){
/*
這裏的每一條記錄都需要記錄,包括cancel i,
因爲cancel i 是在包含cancel i這條記錄的情況的的第i條記錄
*/
int m=0;
while(cin>>r[m].m){
if(r[m].m == "cancel"){
cin>>r[m].s;
r[r[m].s-1].e=true;
m++;
continue;
}
cin>>r[m].p>>r[m].s;
++m;
}
for(int i=0;i<m;++i)
if(r[i].m != "cancel" && !r[i].e)st.insert(r[i].p);
ll m_sum=0;
double p=0;
for(set<double>::iterator it=st.begin();it!=st.end();++it){
double p0 = *it;
ll sumb=0,sums=0,sum;
for(int i=0;i<m;++i)
if(r[i].m == "sell" && !r[i].e && r[i].p<=p0)sums+=r[i].s;
for(int i=0;i<m;++i)
if(r[i].m == "buy" && !r[i].e && r[i].p>=p0)sumb+=r[i].s;
sum=min(sums,sumb);
if(sum>=m_sum){
m_sum=sum;
p=p0;
}
}
//注意保留到小數點後兩位
printf("%.2f ",p);
cout<<m_sum<<endl;
return 0;
}