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



  • 相关阅读:
    委托、事件入门(转)
    ArcToolBox——Clip 批量处理
    Geometry 对象浅析 ( 作者:Flyingis)
    AE数据加载
    ADO.NET 的最佳实践技巧(转)
    android调用.net wcf 服的方法
    winform调用dos命令
    变位词实现 编程珠玑一处错误
    元素翻转
    80X86学习笔记转移指令
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789411.html
Copyright © 2011-2022 走看看