Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub ebi-fly13/Library

:heavy_check_mark: Sliding Window Aggregation (Queue)
(data_structure/queue_aggregation.hpp)

説明

半群の列$(a_0,a_1, \dots, a_{n-1})$を扱う. 詳しくは https://scrapbox.io/data-structures/Sliding_Window_Aggregation 参照

コンストラクタ

queue_aggregation<Semigroup, op> swag;

を定義する必要がある.例としてスライド最小値ならば以下のようになる.

int op(int a, int b) {
    return std::min(a,b);
}
queue_aggregation<int, op> swag;

Operations

Verified with

Code

#pragma once

/*
    reference: https://scrapbox.io/data-structures/Sliding_Window_Aggregation
*/

#include <cassert>

#include <stack>


namespace ebi {

template <class Semigroup, Semigroup (*op)(Semigroup, Semigroup)>
struct queue_aggregation {
  private:
    struct Node {
        Semigroup val;
        Semigroup fold;
    };

    void move() {
        assert(!_back.empty());
        Node p = _back.top();
        _back.pop();
        _front.push({p.val, p.val});
        while (!_back.empty()) {
            Semigroup x = _back.top().val;
            _back.pop();
            _front.push({x, op(x, _front.top().fold)});
        }
    }

  public:
    queue_aggregation() {}

    int size() {
        return _front.size() + _back.size();
    }

    bool empty() {
        return size() == 0;
    }

    void push(Semigroup x) {
        Node node = {x, x};
        if (!_back.empty()) {
            node.fold = op(_back.top().fold, x);
        }
        _back.push(node);
    }

    Semigroup front() {
        assert(!empty());
        if (_front.empty()) {
            move();
        }
        return _front.top().val;
    }

    void pop() {
        assert(!empty());
        if (_front.empty()) {
            move();
        }
        _front.pop();
    }

    void clear() {
        _front = std::stack<Node>();
        _back = std::stack<Node>();
    }

    Semigroup fold_all() {
        assert(!empty());
        if (_front.empty()) {
            return _back.top().fold;
        } else if (_back.empty()) {
            return _front.top().fold;
        } else {
            return op(_front.top().fold, _back.top().fold);
        }
    }

  private:
    std::stack<Node> _front, _back;
};

}  // namespace ebi
#line 2 "data_structure/queue_aggregation.hpp"

/*
    reference: https://scrapbox.io/data-structures/Sliding_Window_Aggregation
*/

#include <cassert>

#include <stack>


namespace ebi {

template <class Semigroup, Semigroup (*op)(Semigroup, Semigroup)>
struct queue_aggregation {
  private:
    struct Node {
        Semigroup val;
        Semigroup fold;
    };

    void move() {
        assert(!_back.empty());
        Node p = _back.top();
        _back.pop();
        _front.push({p.val, p.val});
        while (!_back.empty()) {
            Semigroup x = _back.top().val;
            _back.pop();
            _front.push({x, op(x, _front.top().fold)});
        }
    }

  public:
    queue_aggregation() {}

    int size() {
        return _front.size() + _back.size();
    }

    bool empty() {
        return size() == 0;
    }

    void push(Semigroup x) {
        Node node = {x, x};
        if (!_back.empty()) {
            node.fold = op(_back.top().fold, x);
        }
        _back.push(node);
    }

    Semigroup front() {
        assert(!empty());
        if (_front.empty()) {
            move();
        }
        return _front.top().val;
    }

    void pop() {
        assert(!empty());
        if (_front.empty()) {
            move();
        }
        _front.pop();
    }

    void clear() {
        _front = std::stack<Node>();
        _back = std::stack<Node>();
    }

    Semigroup fold_all() {
        assert(!empty());
        if (_front.empty()) {
            return _back.top().fold;
        } else if (_back.empty()) {
            return _front.top().fold;
        } else {
            return op(_front.top().fold, _back.top().fold);
        }
    }

  private:
    std::stack<Node> _front, _back;
};

}  // namespace ebi
Back to top page