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