/*
法一借鉴自:
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;
}