題目:
問題描述
某股票交易所請你編寫一個程序,根據開盤前客戶提交的訂單來確定某特定股票的開盤價和開盤成交量。
該程序的輸入由很多行構成,每一行為一條記錄,記錄可能有以下幾種:
1. buy p s 表示一個購買股票的買單,每手出價為p,購買股數為s。
2. sell p s 表示一個出售股票的賣單,每手出價為p,出售股數為s。
3. cancel i表示撤銷第i行的記錄。
如果開盤價為p 0,則系統可以將所有出價至少為p 0的買單和所有出價至多為p 0的賣單進行匹配。因此,此時的開盤成交量為出價至少為p 0的買單的總股數和所有出價至多為p 0的賣單的總股數之間的較小值。
你的程序需要確定一個開盤價,使得開盤成交量盡可能地大。如果有多個符合條件的開盤價,你的程序應當輸出最高的那一個。
該程序的輸入由很多行構成,每一行為一條記錄,記錄可能有以下幾種:
1. buy p s 表示一個購買股票的買單,每手出價為p,購買股數為s。
2. sell p s 表示一個出售股票的賣單,每手出價為p,出售股數為s。
3. cancel i表示撤銷第i行的記錄。
如果開盤價為p 0,則系統可以將所有出價至少為p 0的買單和所有出價至多為p 0的賣單進行匹配。因此,此時的開盤成交量為出價至少為p 0的買單的總股數和所有出價至多為p 0的賣單的總股數之間的較小值。
你的程序需要確定一個開盤價,使得開盤成交量盡可能地大。如果有多個符合條件的開盤價,你的程序應當輸出最高的那一個。
輸入格式
輸入數據有任意多行,每一行是一條記錄。保證輸入合法。股數為不超過10
8的正整數,出價為精確到恰好小數點后兩位的正實數,且不超過10000.00。
輸出格式
你需要輸出一行,包含兩個數,以一個空格分隔。第一個數是開盤價,第二個是此開盤價下的成交量。開盤價需要精確到小數點后恰好兩位。
樣例輸入
buy 9.25 100
buy 8.88 175
sell 9.00 1000
buy 9.00 400
sell 8.92 400
cancel 1
buy 100.00 50
buy 8.88 175
sell 9.00 1000
buy 9.00 400
sell 8.92 400
cancel 1
buy 100.00 50
樣例輸出
9.00 450
評測用例規模與約定
對於100%的數據,輸入的行數不超過5000。
思路:
關鍵是對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;
代碼:

1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<set> 5 using namespace std; 6 typedef long long ll; 7 #define MAX 5007 8 typedef struct{ 9 string m; 10 double p; 11 int s; 12 bool e; 13 }R; 14 R r[MAX]; 15 set<double> st; 16 int main(){ 17 /* 18 這里的每一條記錄都需要記錄,包括cancel i, 19 因為cancel i 是在包含cancel i這條記錄的情況的的第i條記錄 20 */ 21 int m=0; 22 while(cin>>r[m].m){ 23 if(r[m].m == "cancel"){ 24 cin>>r[m].s; 25 r[r[m].s-1].e=true; 26 m++; 27 continue; 28 } 29 cin>>r[m].p>>r[m].s; 30 ++m; 31 } 32 for(int i=0;i<m;++i) 33 if(r[i].m != "cancel" && !r[i].e)st.insert(r[i].p); 34 35 ll m_sum=0; 36 double p=0; 37 for(set<double>::iterator it=st.begin();it!=st.end();++it){ 38 double p0 = *it; 39 ll sumb=0,sums=0,sum; 40 for(int i=0;i<m;++i) 41 if(r[i].m == "sell" && !r[i].e && r[i].p<=p0)sums+=r[i].s; 42 for(int i=0;i<m;++i) 43 if(r[i].m == "buy" && !r[i].e && r[i].p>=p0)sumb+=r[i].s; 44 sum=min(sums,sumb); 45 46 if(sum>=m_sum){ 47 m_sum=sum; 48 p=p0; 49 } 50 } 51 //注意保留到小數點后兩位 52 printf("%.2f ",p); 53 cout<<m_sum<<endl; 54 return 0; 55 }