原题:猫狗收容所

有家动物收容所只收留猫和狗,但有特殊的收养规则,收养人有两种收养方式,第一种为直接收养所有动物中最早进入收容所的,第二种为选择收养的动物类型(猫或狗),并收养该种动物中最早进入收容所的。
给定一个操作序列int[][2] ope(C++中为vector<vector<int>>)代表所有事件。若第一个元素为1,则代表有动物进入收容所,第二个元素为动物的编号,正数代表狗,负数代表猫;若第一个元素为2,则代表有人收养动物,第二个元素若为0,则采取第一种收养方式,若为1,则指定收养狗,若为-1则指定收养猫。请按顺序返回收养的序列。若出现不合法的操作,即没有可以符合领养要求的动物,则将这次领养操作忽略。</int>

题解

用两个 deque 分开存🐱和🐶,附带计数,以供按顺序出院时用(按种类出院直接先进先出即可)

Python

from collections import deque
CAT=0
DOG=1
class CatDogAsylum:
    def asylum(self, ope):
        q = [deque(), deque()]
        cnt = 0
        res = []
        for op, opr in ope:
            if op == 1:
                q[opr > 0].append((opr, cnt))
                cnt += 1
            else:
                if opr == 0:
                    nxt = q[CAT] or q[DOG]
                    try:
                        nxt = q[CAT] if q[CAT][0][1] < q[DOG][0][1] else q[DOG]
                    except IndexError: # one of two queues is empty
                        pass
                else:
                    nxt = q[opr > 0]
                if nxt:
                    opr, _ = nxt.popleft()
                    res.append(opr)
        return res

C++

#include <exception>
class CatDogAsylum {
public:
    vector<int> asylum(vector<vector<int> > ope) {
        vector<int> ret;
        deque<pair<int, int>> q[2];
        int cnt = 0;
        for (auto &v: ope) {
            auto op = v[0], opr = v[1];
            if (op == 1) {
                q[opr>0].push_back(make_pair(opr, cnt++));
            } else {
                #define num first
                #define idx second
                auto *nxt = &q[0];
                if (opr == 0) {
                    nxt = q[0].size() ? &q[0] : &q[1];
                    try {
                        // use at to trigger out_of_range
                        auto t = q[0].at(0).idx < q[1].at(0).idx ? &q[0] : &q[1];
                        nxt = t;
                    } catch (std::out_of_range &e) {}
                } else nxt = &q[opr>0];

                if (nxt->size()) {
                    ret.emplace_back(nxt->front().num);
                    nxt->pop_front();
                }
                #undef idx
                #undef num
            }
        }
        return ret;
    }
};