CCF——集合競價(模擬)

題目:

問題描述
  某股票交易所請你編寫一個程序,根據開盤前客戶提交的訂單來確定某特定股票的開盤價和開盤成交量。
  該程序的輸入由很多行構成,每一行爲一條記錄,記錄可能有以下幾種:
  1. buy p s 表示一個購買股票的買單,每手出價爲p,購買股數爲s。
  2. sell p s 表示一個出售股票的賣單,每手出價爲p,出售股數爲s。
  3. cancel i表示撤銷第i行的記錄。
  如果開盤價爲p0,則系統可以將所有出價至少爲p0的買單和所有出價至多爲p0的賣單進行匹配。因此,此時的開盤成交量爲出價至少爲p0的買單的總股數和所有出價至多爲p0的賣單的總股數之間的較小值。
  你的程序需要確定一個開盤價,使得開盤成交量儘可能地大。如果有多個符合條件的開盤價,你的程序應當輸出最高的那一個。
輸入格式
  輸入數據有任意多行,每一行是一條記錄。保證輸入合法。股數爲不超過108的正整數,出價爲精確到恰好小數點後兩位的正實數,且不超過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
樣例輸出
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;

代碼:

#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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章