1. 程式人生 > >集合競價-CCF往屆題(90分,系統顯示WA)

集合競價-CCF往屆題(90分,系統顯示WA)

題記:這道題就此打住,再也不去做優化,刷分了。 分析: 1.需要這道題需要將資料先暫時儲存起來,後面根據局cancel的情況,決定那些行有效(最坑的一點); 2.目標是要找出最大化交易量的最高價格,那麼這個最大價格肯定在buy的離散價格裡面,因為丟擲的價格要小於等於買入價格才能成交; 3.遍歷買入價格,尋找當前價格下最大成交量,迴圈更新最大成交量和價格。 有幾個坑: 1.關於Java在刷題時的效率問題,不要隨隨便便就上On2的程式碼。在提交時有一次90分超時的情況出現,是因為在最後遍歷尋找最優成交量時用了On2遍歷;將內迴圈優化後,即避免每次都從最小丟擲價格開始遍歷(儲存上一次內迴圈的index位置)後,成功去掉了程式超時的困擾。 2.題目自身表達不清:未說明cancel的作用範圍,是否存在cancel巢狀的情況。 3.儲存交易量一定不能選擇int型別,簡單算一下4個位元組夠不夠存就知道啦 下方的程式碼對cancel功能處理為:每次由後來的cancel輸入將cancel所指示的那一行的可用性取反(初始都是可用),直到巢狀指示的那一行不是cancel語句為止。 如有不妥,還請看官指正!
試題編號: 201412-3
試題名稱: 集合競價
時間限制: 1.0s
記憶體限制: 256.0MB
問題描述: 問題描述   某股票交易所請你編寫一個程式,根據開盤前客戶提交的訂單來確定某特定股票的開盤價和開盤成交量。
  該程式的輸入由很多行構成,每一行為一條記錄,記錄可能有以下幾種:
  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。

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Scanner;
import java.util.ArrayList;

public class Main{
	static HashMap<Double,Integer> buy=new HashMap<Double,Integer>(5000);
	static HashMap<Double,Integer> sell=new HashMap<Double,Integer>(5000);
	static ArrayList<trade> Nbuy=new ArrayList<trade>(5000);
	static ArrayList<trade> Nsell=new ArrayList<trade>(5000);

	static String inputrecord[]=new String[5001];
	static boolean youxiao[]=new boolean[5001];

	public static void main(String[] args){
		Scanner in=new Scanner(System.in);
		int index=1;
		while(in.hasNext()){
			inputrecord[index]=in.nextLine();
			youxiao[index]=true;
			//if(inputrecord[index].equals("f"))break;
			index++;
		}
		in.close();

		int indexbuy=0,indexsell=0;
		double sumbuy=0,sumsell=0;
		for(int i=index-1;i>0;i--){
			if(youxiao[i]==true){
				String[] input=inputrecord[i].split(" ");
				
				if(input[0].equals("cancel")){

					int nx=Integer.parseInt(input[1]);//yingshe dao child line
					
					while(true){
						String te[]=inputrecord[nx].split(" ");//child line data
						if(!te[0].equals("cancel")){
							if(youxiao[nx]==true){
								youxiao[nx]=false;
								break;
							}
							else break;		
						}
						else{
							if(youxiao[nx]==true){
								youxiao[nx]=false;
								nx=Integer.parseInt(te[1]);
							}
							else break;
						}
					}
				}else{

					double price=Double.parseDouble(input[1]);
					double num=Double.parseDouble(input[2]);

					if(input[0].equals("buy")){
						sumbuy+=num;
						if(buy.containsKey(price)){
							int ind=buy.get(price);
							Nbuy.set( ind,new trade(price,Nbuy.get(ind).num+num) );
						}else{
							Nbuy.add(indexbuy,new trade(price,num) );
							indexbuy++;
						}
					}else{
						sumsell+=num;
						if(sell.containsKey(price)){
							int ind=sell.get(price);
							Nsell.set( ind,new trade(price,Nsell.get(ind).num+num) );
						}else{
							Nsell.add(indexsell,new trade(price,num) );
							indexsell++;
						}
					}
				}
			}

		}

		Comparator<trade> comparator=new Comparator<trade>(){
			public int compare(trade s1,trade s2){
				return (s1.price>s2.price)?1:(s1.price==s2.price?0:-1);
			}
		};
		Collections.sort(Nbuy,comparator);
		Collections.sort(Nsell,comparator);

		double less=0,above=sumbuy;
		//above==bigger and equals
		//less== smaller
		for(int i=0;i<Nbuy.size();i++){
			Nbuy.get(i).less=less;
			Nbuy.get(i).above=above;
			less+=Nbuy.get(i).num;
			above-=Nbuy.get(i).num;
		}

		//above==bigger
		//less== smaller and equals
		less=0;
		above=sumsell;
		for(int i=0;i<Nsell.size();i++){
			less+=Nsell.get(i).num;
			above-=Nsell.get(i).num;
			Nsell.get(i).less=less;
			Nsell.get(i).above=above;
		}

		double dealnum=0;
		double dealprice=0;
		for(int i=0,j=0;i<Nbuy.size();i++){
			while(true){
				if(Nbuy.get(i).price>=Nsell.get(j).price){
					if(Math.min(Nbuy.get(i).above, Nsell.get(j).less)>dealnum){
						dealprice=Nbuy.get(i).price;
						dealnum=Math.min(Nbuy.get(i).above, Nsell.get(j).less);
					}else if(Math.min(Nbuy.get(i).above, Nsell.get(j).less)==dealnum){
						if(Nbuy.get(i).price>dealprice){
							dealprice=Nbuy.get(i).price;
						}
					}
					if(j<Nsell.size()-1)j++;
					else break;
				}else break;
			}
		}
		

		if(Nbuy.size()==0&&Nsell.size()==0){
			System.out.printf("%.2f %.0f",0.0,dealnum);
			return;
		}
		if(Nbuy.size()==0){
			System.out.printf("%.2f %.0f",Nsell.get(Nsell.size()-1).price,dealnum);
			return;
		}
		if(Nsell.size()==0){
			System.out.printf("%.2f %.0f",Nbuy.get(Nbuy.size()-1).price,dealnum);
			return;
		}
		if(dealprice==0)System.out.printf("%.2f %.0f",Math.max(Nbuy.get(Nbuy.size()-1).price, Nsell.get(Nsell.size()-1).price),dealnum);
		else System.out.printf("%.2f %.0f",dealprice,dealnum);
	}
}

class trade{
	double price=0;
	double num=0;
	double less=0;
	double above=0;
	public trade(double price,double num){
		this.price=price;
		this.num=num;
	}
}