Exchange UVA - 1598

这题初看题意还是比较友好的,相比于前面几题来说,思路并不是很难想。但是,题目描述误导我了很久,以至于我debug了很久,再次强调英语阅读理解的重要性(认真脸)。不过接下来就是无尽的TLE...

尝试了很多方法,但都没什么用,后来无奈只能查了网上的解法,发现最终的quote都是提前存好的,不是像我要算的时候再计算出来,而且每一个请求都是按照id存储起来以便cancel修改状态。如果用我原来的方法,只使用两个优先队列和一个cancel的数组,每次的quote只能自顶向下遍历还得找是否在cancel里面。最致命的是,优先队列只支持一次访问顶层元素,因此每次访问完需要pop掉顶层元素。然而这步操作是非法的,因此只能copy过来进行这些操作。数据多的时候,这个copy操作的代价可想而知。。

其实这也说明了优先队列(其实就是堆)的一大弱点,只能合法地访问顶层元素,因此如果还想同时访问其他的元素而不改变原有的数据结构,最好是换一种数据结构或是再构造其他的数据结构,比如说这题,把其他请求用一个数组存储,再把答案存在price与size映射的map里面来达到只访问顶层元素就可以获得答案的效果,是一种用空间换时间的方法。只不过自己太笨没有想到。

另外还学到一点,就是用模板代替类型优化代码量,不过我这代码简直就是***,无从优化。可以同时定义<和>操作符,用greater调用大于操作符。

另外还发现了一点,就是优先队列被pop掉最后一个元素时,这个元素并不会真正被删除,依然存在队列的最顶层(可以用top函数输出),不知道是不是人为设计的。总之不能用top元素作为判断依据,因为当它是最后一个元素时是删不去的,最好前面加一个是否为空的判断。

极其辣眼睛的代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <ctime>
#include <map>
#include <bitset>
#define _for(i, a, b) for (int i = (a); i < b; ++i)
#define _rep(i, a, b) for (int i = (a); i <= b; ++i)
//#define fre
//#define DEBUG
using namespace std;
struct Reqbuy
{
    int id, p, s;
    Reqbuy(int id, int p, int s): id(id), p(p), s(s) {}
    bool operator < (const Reqbuy& b) const
    {
        if (p == b.p) return id > b.id;
        else return p < b.p;
    }
};
struct Reqsell
{
    Reqsell(int id, int p, int s): id(id), p(p), s(s) {}
    int id, p, s;
    bool operator < (const Reqsell& b) const
    {
        if (p == b.p) return id > b.id;
        else return p > b.p;
    } 
};

struct Req
{
    int p, s = 0, type;
} req[10005];

map<int, int> buytots, selltots; //这一步太妙了
bitset<10005> bit;
int quote[4] = {0, 0, 0, 99999};

void updatequo(priority_queue<Reqbuy>& buyorder, priority_queue<Reqsell>& sellorder)
{
    while (!buyorder.empty() && ~bit[buyorder.top().id]) buyorder.pop(); //最后一个top删不去
    while (!sellorder.empty() && ~bit[sellorder.top().id]) sellorder.pop();
    if (buyorder.empty()) quote[0] = 0, quote[1] = 0;
    else 
    {
        quote[0] = buytots[buyorder.top().p];
        quote[1] = buyorder.top().p;
    }
    if (sellorder.empty()) quote[2] = 0, quote[3] = 99999;
    else 
    {
        quote[2] = selltots[sellorder.top().p];
        quote[3] = sellorder.top().p;
    }
    printf("QUOTE %d %d - %d %d\n", quote[0], quote[1], quote[2], quote[3]);
}

void buy(int p, int s, int id, priority_queue<Reqbuy>& buyorder, priority_queue<Reqsell>& sellorder)
{
    int trades, tradep;
    while (!sellorder.empty() && s > 0 && sellorder.top().p <= p)
    {
        if (~bit[sellorder.top().id])
        {
            sellorder.pop();
            continue;
        }
        tradep = sellorder.top().p;
        if (sellorder.top().s <= s)
        {
            trades = sellorder.top().s;
            s -= sellorder.top().s;
            req[sellorder.top().id].s -= trades;
            selltots[sellorder.top().p] -= trades;
            sellorder.pop();
        }
        else 
        {
            trades = s;
            req[sellorder.top().id].s -= trades;
            selltots[sellorder.top().p] -= trades;
            Reqsell tmp = sellorder.top();
            tmp.s -= s;
            sellorder.pop();
            sellorder.push(tmp);
            s = 0;
        }
        printf("TRADE %d %d\n", trades, tradep);
    }
    if (s > 0) 
    {
        req[id].p = p, req[id].s = s, req[id].type = 0;
        if (!buytots.count(p)) buytots[p] = s;
        else buytots[p] += s;
        buyorder.push(Reqbuy(id, p, s));
    }
    updatequo(buyorder, sellorder);
}

void sell(int p, int s, int id, priority_queue<Reqbuy>& buyorder, priority_queue<Reqsell>& sellorder)
{
    int trades, tradep;
    while (!buyorder.empty() && s > 0 && buyorder.top().p >= p)
    {
        if (~bit[buyorder.top().id])
        {
            buyorder.pop();
            continue;
        }
        tradep = buyorder.top().p;
        if (buyorder.top().s <= s)
        {
            trades = buyorder.top().s;
            s -= buyorder.top().s;
            req[buyorder.top().id].s -= trades;
            buytots[buyorder.top().p] -= trades;
            buyorder.pop();
        }
        else 
        {
            trades = s;
            Reqbuy tmp = buyorder.top();
            tmp.s -= s;
            req[buyorder.top().id].s -= trades;
            buytots[buyorder.top().p] -= trades;
            buyorder.pop();
            buyorder.push(tmp);
            s = 0;
        }
        printf("TRADE %d %d\n", trades, tradep);
    }
    if (s > 0)
    {
        req[id].p = p, req[id].s = s, req[id].type = 1;
        if (!selltots.count(p)) selltots[p] = s;
        else selltots[p] += s;
        sellorder.push(Reqsell(id, p, s));
    } 
    updatequo(buyorder, sellorder);
}

int main()
{
    #ifdef fre
    freopen("in.in", "r", stdin);
    freopen("out.txt", "w", stdout);
    #endif
    int n;
    char line[100];
    int a, b;
    bool fir = true;
    while (~scanf("%d", &n))
    {
        if (fir) fir = false;
        else putchar('\n');
        priority_queue<Reqbuy> buyorder;
        priority_queue<Reqsell> sellorder;
        gets(line);
        bit.set();
        buytots.clear();
        selltots.clear();
        memset(req, 0, sizeof(req));
        _rep(i, 1, n)
        {
            gets(line);
            /*#ifdef DEBUG
            printf("%s", line);
            cout << endl;
            #endif*/
            if (line[0] == 'C')
            {
                a = 0;
                for (int i = 7; line[i]; ++i)
                    a = (a << 3) + (a << 1) + line[i] - 48;
                bit[a] = 0;
                if (req[a].s != 0) 
                {
                    if (req[a].type == 0) buytots[req[a].p] -= req[a].s;
                    else selltots[req[a].p] -= req[a].s;
                    req[a].s = 0;
                }
                updatequo(buyorder, sellorder);
            }
            else
            {
                a = 0, b = 0;
                int ti;
                if (line[0] == 'B') 
                {
                    //用sscanf跟这个时间复杂度相当
                    for (ti = 4; line[ti] != ' '; ++ti)
                        a = (a << 3) + (a << 1) + line[ti] - 48;
                    for (++ti; line[ti]; ++ti)
                        b = (b << 3) + (b << 1) + line[ti] - 48;
                    buy(b, a, i, buyorder, sellorder);
                }
                else
                {
                    for (ti = 5; line[ti] != ' '; ++ti)
                        a = (a << 3) + (a << 1) + line[ti] - 48;
                    for (++ti; line[ti]; ++ti)
                        b = (b << 3) + (b << 1) + line[ti] - 48;
                    sell(b, a, i, buyorder, sellorder);
                }
            }
        }
    }
    #ifdef DEBUG
    printf("time used %.2f", double(clock()) / CLOCKS_PER_SEC); //输出时间
    #endif
}

 

posted @ 2020-02-04 09:48  JonKitten  阅读(102)  评论(0编辑  收藏  举报