tkmst201's Library

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

View the Project on GitHub tkmst201/Library

:heavy_check_mark: Sliding Window Aggregation (SWAG)
(DataStructure/SlidingWindowAggregation.hpp)

概要

数列を扱うデータ構造です。
キューの enqueuedequeue 操作をならし $\Theta(1)$ で、キューに入っている要素全体の fold 演算を $\Theta(1)$ でできます。
区間に対して一意に値が定まり、区間をまとめて計算できるような演算が扱えます。例: +, xor, min, gcd, 関数の合成 など。


コンストラクタ

F は二項演算 std::function<T (const T &, const T &)> の略記です。

制約


SlidingWindowAggregation(const T & id_elem, const F & f)

単位元 id_elem 、二項演算 $f$ で初期化します。

計算量



メンバ関数

size_t size()

現在キューに入っている要素数を返します。

計算量


void push(const T & x)

値 $x$ をキューに追加します。

計算量


void pop()

キューの先頭要素を削除します。

制約

計算量


T fold_all()

キューに入っている要素の個数を $N$ 、キューに入っている要素を追加した順に $A_1, A_2, \ldots, A_N$ として、$f(A_1, f(A_2, f(\ldots, A_N)\ldots))$ を返します。
キューに何も入っていない場合は単位元を返します。

計算量



使用例

min を載せました。

#include <bits/stdc++.h>
#include "DataStructure/SlidingWindowAggregation.hpp"
using namespace std;

int main() {
	SlidingWindowAggregation<int> swag(numeric_limits<int>::max(),
		[](auto x, auto y) { return min(x, y); });
	
	cout << "size() = " << swag.size() << endl; // 0
	cout << "fold_all() = " << swag.fold_all() << endl; // INF
	swag.push(10);
	cout << "fold_all() = " << swag.fold_all() << endl; // 10
	swag.push(9);
	swag.push(12);
	swag.push(13);
	cout << "size() = " << swag.size() << endl; // 4
	cout << "fold_all() = " << swag.fold_all() << endl; // 9
	swag.pop();
	cout << "fold_all() = " << swag.fold_all() << endl; // 9
	swag.pop();
	cout << "fold_all() = " << swag.fold_all() << endl; // 12
	cout << "size() = " << swag.size() << endl; // 2
	swag.pop();
	cout << "fold_all() = " << swag.fold_all() << endl; // 13
	swag.pop();
	cout << "size() = " << swag.size() << endl; // 0
	cout << "fold_all() = " << swag.fold_all() << endl; // INF
}


参考

2020/09/22: https://scrapbox.io/data-structures/Sliding_Window_Aggregation
2020/09/22: https://snuke.hatenablog.com/entry/2018/09/18/135640


Verified with

Code

#ifndef INCLUDE_GUARD_SLIDING_WINDOW_AGGREGATION_HPP
#define INCLUDE_GUARD_SLIDING_WINDOW_AGGREGATION_HPP

#include <cassert>
#include <vector>
#include <functional>

/**
 * @brief https://tkmst201.github.io/Library/DataStructure/SlidingWindowAggregation.hpp
 */
template<typename T>
struct SlidingWindowAggregation {
	using value_type = T;
	using const_reference = const value_type &;
	using size_type = std::size_t;
	using F = std::function<value_type (const_reference, const_reference)>;
	
private:
	value_type id_elem;
	F f;
	std::vector<value_type> lstack, rstack;
	value_type rsum;
	
public:
	SlidingWindowAggregation(const_reference id_elem, const F & f)
		: id_elem(id_elem), f(f), lstack(1, id_elem), rsum(id_elem) {}
	
	size_type size() const noexcept {
		return lstack.size() - 1 + rstack.size();
	}
	
	void push(const_reference x) {
		rstack.emplace_back(x);
		rsum = f(rsum, x);
	}
	
	void pop() {
		assert(size() > 0);
		if (lstack.size() == 1) {
			while (rstack.size() > 1) {
				lstack.emplace_back(f(rstack.back(), lstack.back()));
				rstack.pop_back();
			}
			rstack.pop_back();
			rsum = id_elem;
		}
		else lstack.pop_back();
	}
	
	value_type fold_all() const {
		return f(lstack.back(), rsum);
	}
};

#endif // INCLUDE_GUARD_SLIDING_WINDOW_AGGREGATION_HPP
#line 1 "DataStructure/SlidingWindowAggregation.hpp"



#include <cassert>
#include <vector>
#include <functional>

/**
 * @brief https://tkmst201.github.io/Library/DataStructure/SlidingWindowAggregation.hpp
 */
template<typename T>
struct SlidingWindowAggregation {
	using value_type = T;
	using const_reference = const value_type &;
	using size_type = std::size_t;
	using F = std::function<value_type (const_reference, const_reference)>;
	
private:
	value_type id_elem;
	F f;
	std::vector<value_type> lstack, rstack;
	value_type rsum;
	
public:
	SlidingWindowAggregation(const_reference id_elem, const F & f)
		: id_elem(id_elem), f(f), lstack(1, id_elem), rsum(id_elem) {}
	
	size_type size() const noexcept {
		return lstack.size() - 1 + rstack.size();
	}
	
	void push(const_reference x) {
		rstack.emplace_back(x);
		rsum = f(rsum, x);
	}
	
	void pop() {
		assert(size() > 0);
		if (lstack.size() == 1) {
			while (rstack.size() > 1) {
				lstack.emplace_back(f(rstack.back(), lstack.back()));
				rstack.pop_back();
			}
			rstack.pop_back();
			rsum = id_elem;
		}
		else lstack.pop_back();
	}
	
	value_type fold_all() const {
		return f(lstack.back(), rsum);
	}
};
Back to top page