Info

末尾追加と先頭消去の操作が可能な半群の列のfoldができるデータ構造

Complexity

末尾追加 - \(O(1)\ \text{amortized}\)
先頭消去 - \(O(1)\ \text{amortized}\)
全体fold - \(O(1)\)

Interface

SWAG<T>(func g) 要素の型\(T\)と関数\(g:(T,T)\rightarrow T\)で初期化する
push(T a) 末尾に\(a\)を追加する
pop() 先頭から要素を一つ消去する
fold_all() 全体をfoldした値を返す

Code

using lnt = long long;
/* <SWAG> */

template <typename T = lnt>
struct SWAG
{
	std::stack<T> f,b,fa,ba;
	const std::function<T(T,T)> g;
	SWAG(std::function<T(T,T)> g)
		: g(g) {}
	bool empty() const { return f.empty()&&b.empty(); }
	void push(T a) {
		b.emplace(a);
		if(ba.empty()) ba.emplace(a);
		else ba.emplace(g(ba.top(),a));
	}
	void pop() {
		assert(!empty());
		if(f.empty()) {
			while(!b.empty()) {
				f.emplace(b.top()); b.pop(); ba.pop();
				if(fa.empty()) fa.emplace(f.top());
				else fa.emplace(g(f.top(), fa.top()));
			}
		}
		f.pop(); fa.pop();
	}
	T fold_all() const {
		assert(!empty());
		if(fa.empty()) return ba.top();
		if(ba.empty()) return fa.top();
		return g(fa.top(),ba.top());
	}
};

/* <SWAG> */

Examples

SWAG<int> sw([](int a, int b){return std::gcd(a,b)});
sw.push(2);
sw.push(4);
sw.push(8);
sw.push(16);
std::cout << sw.fold_all() << '\n'; // 2
sw.pop();
std::cout << sw.fold_all() << '\n'; // 4
sw.push(6);
std::cout << sw.fold_all() << '\n'; // 2