这题的数据能用跳表过吗,理论应该可以的吧,MLE 5个点
查看原帖
这题的数据能用跳表过吗,理论应该可以的吧,MLE 5个点
921018
winterl楼主2024/9/10 13:33
#include <iostream>
#include <limits>
#include <random>
#include <stdexcept>
#include <string>
#include <vector>

template <typename T, size_t kMaxLevel = 16> class Skiplist {
    struct Node {
        T Key;
        std::vector<size_t> SkipSpans;
        std::vector<Node *> Nexts;
        Node(const T &key, const size_t &size)
            : Key(key), SkipSpans(size + 1, 0), Nexts(size + 1, nullptr) {}
    };
    std::bernoulli_distribution rand_;
    std::minstd_rand seed{std::random_device{}()};
    size_t count_ = 0;
    Node *head_ = new Node(std::numeric_limits<T>::min(), kMaxLevel);

    size_t random_level() {
        size_t level = 1;
        while (level < kMaxLevel and rand_(seed))
            level++;
        return level;
    }

    std::pair<std::vector<Node *>, std::vector<size_t>>
    search_updates(const T &item) {
        std::vector<Node *> updates(kMaxLevel + 1);
        auto current = head_;
        std::vector<size_t> totalSpans(kMaxLevel + 2, 0);
        for (auto level = kMaxLevel; level != -1; --level) {
            totalSpans[level] = totalSpans[level + 1];
            while (current->Nexts[level] and
                   current->Nexts[level]->Key < item) {
                totalSpans[level] += current->SkipSpans[level];
                current = current->Nexts[level];
            }
            updates[level] = current;
        }
        return {updates, totalSpans};
    }

    Node *lower_bound(const T &item) {
        auto current = head_;
        for (auto level = kMaxLevel; level != -1; --level)
            while (current->Nexts[level] and current->Nexts[level]->Key < item)
                current = current->Nexts[level];
        return current;
    }

    Node *upper_bound(const T &item) {
        auto current = head_;
        for (auto level = kMaxLevel; level != -1; --level)
            while (current->Nexts[level] and current->Nexts[level]->Key <= item)
                current = current->Nexts[level];
        return current;
    }

  public:
    bool empty() { return count_ == 0; }
    size_t size() { return count_; }

    void add(const T &item) {
        auto [updates, totalSpans] = search_updates(item);
        auto level = random_level();
        auto newNode = new Node(item, level);
        if (newNode == nullptr)
            throw std::bad_alloc();
        const auto totalSpan = totalSpans.front() + 1;
        for (size_t currentLevel = 0; currentLevel <= level; ++currentLevel) {
            newNode->Nexts[currentLevel] =
                updates[currentLevel]->Nexts[currentLevel];
            updates[currentLevel]->Nexts[currentLevel] = newNode;
            auto diff = totalSpan - totalSpans[currentLevel];
            if (newNode->Nexts[currentLevel])
                newNode->SkipSpans[currentLevel] =
                    updates[currentLevel]->SkipSpans[currentLevel] - diff + 1;
            updates[currentLevel]->SkipSpans[currentLevel] = diff;
        }
        // 记得处理在高层前插入低层的情况的 skipSpan
        for (auto currentLevel = level + 1; currentLevel <= kMaxLevel;
             ++currentLevel)
            if (updates[currentLevel]->Nexts[currentLevel])
                updates[currentLevel]->SkipSpans[currentLevel]++;
        count_++;
    }

    bool erase(const T &item) {
        if (empty())
            return false;
        auto updates = search_updates(item).first;
        auto node = updates.front()->Nexts.front();
        if (node == nullptr or node->Key != item)
            return false;
        for (size_t currentLevel = 0; currentLevel < node->Nexts.size();
             ++currentLevel) {
            if (updates[currentLevel]->Nexts[currentLevel] != node)
                continue;
            updates[currentLevel]->Nexts[currentLevel] =
                node->Nexts[currentLevel];
            if (updates[currentLevel]->Nexts[currentLevel])
                updates[currentLevel]->SkipSpans[currentLevel] +=
                    node->SkipSpans[currentLevel] - 1;
            else
                updates[currentLevel]->SkipSpans[currentLevel] = 0;
        }
        // 记得处理在高层前删除低层的情况的 skipSpan
        for (auto currentLevel = node->Nexts.size(); currentLevel <= kMaxLevel;
             ++currentLevel)
            if (updates[currentLevel]->Nexts[currentLevel])
                updates[currentLevel]->SkipSpans[currentLevel]--;
        delete node;
        count_--;
        return true;
    }

    bool search(const T &item) {
        auto updates = search_updates(item).first;
        auto node = updates.front()->Nexts.front();
        return node and node->Key == item;
    }

    size_t rank_of(const T &item) {
        return search_updates(item).second.front() + 1;
    }

    T get_by_rank(const size_t &rank) {
        if (rank > count_)
            throw std::out_of_range("rank can't not greater than list size");
        size_t currentRank = 0;
        auto current = head_;
        for (auto currentLevel = kMaxLevel; currentLevel != -1; --currentLevel)
            while (current->Nexts[currentLevel] and
                   current->SkipSpans[currentLevel] + currentRank <= rank) {
                currentRank += current->SkipSpans[currentLevel];
                current = current->Nexts[currentLevel];
            }
        return current->Key;
    }

    T lower_to(const T &item) { return lower_bound(item)->Key; }

    T upper_to(const T &item) { return upper_bound(item)->Nexts[0]->Key; }

    class iterator {
        Node *current_;

      public:
        iterator(Node *start) : current_(start) {}
        T &operator*() { return current_->Key; }
        iterator &operator++() {
            current_ = current_->Nexts[0];
            return *this;
        }
        bool operator!=(const iterator &other) const {
            return current_ != other.current_;
        }
    };
    iterator begin() const { return iterator(head_->Nexts[0]); }
    iterator end() const { return iterator(nullptr); }

    void makeView() {

        std::endl(std::cout);
        for (auto current = head_; current != nullptr;
             current = current->Nexts[0]) {
            for (size_t i = 0; i < current->Nexts.size(); ++i)
                std::cout << current->Key << '['
                          << (current->Nexts[i]
                                  ? std::to_string(current->Nexts[i]->Key)
                                  : "nullptr")
                          << "](" << current->SkipSpans[i] << ") ";
            std::endl(std::cout);
        }
        std::endl(std::cout);
    }

    Skiplist(const double &p = 0.5) : rand_(p) {}

    ~Skiplist() {
        auto current = head_;
        while (current) {
            auto next = current->Nexts[0];
            delete current;
            current = next;
        }
    }
};

namespace std {
std::ostream &endl(std::ostream &os) { return os.put('\n'); }
} // namespace std

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::int64_t n, m, opt, x, answer{}, last{};
    std::cin >> n >> m;
    Skiplist<std::int64_t> lst;
    for (std::int64_t x; n--;) {
        std::cin >> x;
        lst.add(x);
    }
    while (m--) {
        std::cin >> opt >> x;
        x ^= last;
        switch (opt) {
        case 1:
            lst.add(x);
            break;
        case 2:
            lst.erase(x);
            break;
        case 3:
            last = lst.rank_of(x);
            break;
        case 4:
            last = lst.get_by_rank(x);
            break;
        case 5:
            last = lst.lower_to(x);
            break;
        case 6:
            last = lst.upper_to(x);
            break;
        }
        if (opt > 2)
            answer ^= last;
    }
    std::cout << answer << std::endl;
    return 0;
}

2024/9/10 13:33
加载中...