zoukankan      html  css  js  c++  java
  • UVA

    /*
      法一借鉴自:
      http://blog.csdn.net/xienaoban/article/details/52818530
      
      这题的特点和注意点,在上面的博客的解析中,已经说得十分详细了
    */
    
    #include <iostream>
    #include <map>
    #include <set>
    #include <string>
    #include <vector>
    #define rep(i, n) for (int i = 0; i < (n); i++)
    using namespace std;
    
    map<int, set<int> > Buy; //映射:购买价格到购买的指令编号
    map<int, int> Buy_no; //映射:购买价格到购买总量
    map<int, set<int> > Sell; //映射:卖的价格到卖的指令编号
    map<int, int> Sell_no;//映射:贩卖价格到贩卖总量
    
    struct command
    {
    	string com;
    	int num, price, id;
    };
    
    vector<command> Com; //存储指令
    
    void Deal(int flag)
    {
    	//输出"TRADE"
    	while (!Buy.empty() && !Sell.empty())
    	{
    		if (Buy.rbegin()->first >= Sell.begin()->first) //最高买价大于等于最低卖价 
    		{
    			set<int> &v1 = Buy.rbegin()->second; //最高买价组成的集合
    			set<int> &v2 = Sell.begin()->second; //最低卖价组成的集合
    			
    			int num1 = *v1.begin(), num2 = *v2.begin(); //按照订单产生的先后次序,在集合中选订单产生最早的那个 
    			auto &c1 = Com[num1];
    			auto &c2 = Com[num2];
    			int amount = min(c1.num, c2.num); //按供需取最小值交易
    			c1.num -= amount;
    			c2.num -= amount;
    			Buy_no[c1.price] -= amount;
    			Sell_no[c2.price] -= amount;
    			cout << "TRADE " << amount << " " << (flag ? c1.price : c2.price) << endl;
    			if (!c1.num) v1.erase(num1);
    			if (!c2.num) v2.erase(num2);
    			if (!Buy_no[c1.price]) Buy_no.erase(c1.price);
    			if (!Sell_no[c2.price]) Sell_no.erase(c2.price); //购买 / 贩卖总量为0时,该购买 / 贩卖价格从map中删除
    			if (!v1.size()) Buy.erase(c1.price);
    			if (!v2.size()) Sell.erase(c2.price); 
    		}
    		else return;
    	}
    }
    
    void Print()
    {
    	//输出"QUOTE"
    	cout << "QUOTE ";
    	if(!Buy_no.size()) cout << "0 0 - ";
    	else
    	{
    		auto it = Buy_no.rbegin();
    		cout << it->second << " " << it->first << " - ";
    	}
    	if (!Sell_no.size()) cout << "0 99999" << endl;
    	else
    	{
    		auto it = Sell_no.begin();
    		cout << it->second << " " << it->first << endl;
    	}
    }
     
    
    int main()
    {
    	int kase = 0, n;
    	while (cin >> n)
    	{
    		Buy.clear(), Buy_no.clear(), Sell.clear(), Sell_no.clear(), Com.clear();
    		if (kase++) cout << endl;
    		
    		rep(i, n)
    		{
    			command temp;
    			cin >> temp.com;
    			if (temp.com == "BUY")
    			{
    				cin >> temp.num >> temp.price;
    				Com.push_back(temp);
    				Buy[temp.price].insert(i);
    				Buy_no[temp.price] += temp.num;
    				Deal(0); //"买"指令 				
    			}
    			else if (temp.com == "SELL")
    			{
    				cin >> temp.num >> temp.price;
    				Com.push_back(temp);
    				Sell[temp.price].insert(i); //今天发现一直一直TLE,找了很久的bug,最后发现这句代码,该写price的地方,一开始是被我写成了 num。怪不得一直一直TLE!!!这也提醒我们,细节很重要、很重要,我觉得如果真正比赛时,来一个这种错误,又一直检查不出来,心态真的会崩掉....T^T 
    				Sell_no[temp.price] += temp.num;
    				Deal(1); //"卖"指令 
    			}
    			else
    			{
    				int id;
    				cin >> id; id--; //下标从0开始
    				temp.id = id;
    				Com.push_back(temp);
    				auto &c = Com[id];
    				int price = c.price;
    				if (c.com == "BUY")
    				{
    					Buy[price].erase(id);
    					if (Buy[price].empty()) Buy.erase(price);
    					Buy_no[price] -= c.num;
    					if (!Buy_no[price]) Buy_no.erase(price);
    					c.num = 0;
    					
    				}
    				else if (c.com == "SELL")
    				{
    					Sell[price].erase(id);
    					if (Sell[price].empty()) Sell.erase(price);
    					Sell_no[price] -= c.num;
    					if (!Sell_no[price]) Sell_no.erase(price);
    					c.num = 0;
    				}
    			}
    			Print();
    		}
    	}
    	return 0;
    } 


    /*
      法二借鉴自:
      http://blog.csdn.net/xienaoban/article/details/52818530
      
      收获:
      1. 内联函数 inline
      http://www.cnblogs.com/fnlingnzb-learner/p/6423917.html
      
      2. C++中的move,其中有两篇博客写的比较清楚详细:
      http://blog.csdn.net/booirror/article/details/24503461
      http://blog.csdn.net/liyongofdm/article/details/7667942
      
      3.STL中set的erase函数,不仅可以在set中删除某一值(见法一 v1.erase(num1); 是指删除v1集合中的元素num1),也可以在set中删除set::ieterator类型,也就是其的迭代器类型,例如:s1.erase(s1.begin());
      
      
      有个相关的博客:
      http://blog.csdn.net/s_o_q/article/details/7279508
      
    */
    #include <iostream>
    #include <string>
    #include <map>
    #include <set>
    #include <vector>
    using namespace std;
    
    struct INFO
    {
    	char type;
    	int num, price;
    }info;
    string type;
    vector<INFO> orders;
    int N, T(0);
    map<int, set<int>, greater<int> > BUY;
    map<int, set<int>, less<int> > SELL;
    map<int, int> BUY_SUM;
    map<int, int> SELL_SUM;
    
    void trade(bool flag)
    {
    	int bid_num, bid_price, ask_num, ask_price;
    	while (true)
    	{
    		auto bid(BUY.begin()), ask(SELL.begin());
    		if (bid == BUY.end()) bid_num = 0, bid_price = 0;
    		else bid_num = BUY_SUM[bid->first], bid_price = bid->first;
    		
    		if (ask == SELL.end()) ask_num = 0, ask_price = 1e6;
    		else ask_num = SELL_SUM[ask->first], ask_price = ask->first;
    		
    		if (bid_price < ask_price) //如果购买的最高出价,比最低售价还低,此时交易不能达成
    		{
    			cout << "QUOTE " << bid_num <<  " " << bid_price << " - " << ask_num << " " << (ask_price == 1e6 ? 99999 : ask_price) << endl;
    			//注意此步的处理是必须做的,如果当所有的售价都已被删除(如果某一售价对应的商品数目已经全部被购买,则该售价删除),那么ask迭代器的值会是 SELL.end(),此时先将 ask_price置为一个正常情况下不可能取到的售价,在输出前,再将其变回99999
    			return;
    		}
    		auto &c1 = orders[*bid->second.begin()], &c2 = orders[*ask->second.begin()]; //command
    		auto num1 = c1.num, num2 = c2.num;
    		auto amount = min(num1, num2);
    		
    		cout << "TRADE " << amount << " " << (flag ? ask_price : bid_price) << endl;
    		
    		auto &s1(bid->second), &s2(ask->second);
    		BUY_SUM[bid->first] -= amount;
    		if (!s1.empty() && (orders[*s1.begin()].num -= amount) == 0)
    		s1.erase(s1.begin());
    		if (s1.empty()) BUY.erase(bid);
    		
    		SELL_SUM[ask->first] -= amount;
    		if (!s2.empty() && (orders[*s2.begin()].num -= amount) == 0)
    		s2.erase(s2.begin());
    		if (s2.empty()) SELL.erase(ask);
    	}
    }
    
    int main()
    {
    	cin.tie(0);
    	cin.sync_with_stdio(false);
    	while (cin >> N)
    	{
    		if (T++) cout << endl;
    		orders.clear(), BUY.clear(), SELL.clear(), BUY_SUM.clear(), SELL_SUM.clear();
            orders.push_back(info); //保证序号从1开始 
    		for (int i = 1; i <= N; i++)
    		{
    			INFO temp;
    			cin >> type;
    			if (type[0] == 'C')
    			{
    				int id;
    				cin >> id;
    				auto& tp(orders[id]);
    				if (tp.type == 'B')
    				{
    					BUY_SUM[tp.price] -= tp.num;
    					tp.num = 0;
    					auto &now (BUY[tp.price]);
    					now.erase(id);
    					if (now.empty()) BUY.erase(tp.price);
    				}
    				else
    				{
    					SELL_SUM[tp.price] -= tp.num;
    					tp.num = 0;
    					auto &now (SELL[tp.price]);
    					now.erase(id);
    					if (now.empty()) SELL.erase(tp.price);
    				}
    			}
    			else
    			{
    				temp.type = type[0];
    				cin >> temp.num >> temp.price;
    				if (type[0] == 'B') BUY[temp.price].insert(i), BUY_SUM[temp.price] += temp.num;
    				else SELL[temp.price].insert(i), SELL_SUM[temp.price] += temp.num;
    			}
    			orders.push_back(move(temp));
    			trade(type[0] == 'B');
    		}
    	}
    	return 0;
    }



  • 相关阅读:
    401. Binary Watch
    46. Permutations
    61. Rotate List
    142. Linked List Cycle II
    86. Partition List
    234. Palindrome Linked List
    19. Remove Nth Node From End of List
    141. Linked List Cycle
    524. Longest Word in Dictionary through Deleting
    android ListView详解
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789411.html
Copyright © 2011-2022 走看看