This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/2/DSL_2_G"
#include "../src/dataStructure/lazySegmentTree.hpp"
#include "../src/utility/monoid/rangeAddMonoid.hpp"
#include "../src/utility/monoid/addMonoid.hpp"
struct addAction {
using valueMonoid = zawa::rangeAddMonoid<long long>;
using operatorMonoid = zawa::addMonoid<long long>;
static valueMonoid::valueType mapping(const valueMonoid::valueType& a, const operatorMonoid::valueType& b) {
return valueMonoid::valueType(a.value + a.size * b, a.size);
}
};
#include <vector>
#include <iostream>
int main() {
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
int N, Q; std::cin >> N >> Q;
zawa::lazySegmentTree<addAction> S(std::vector(N, addAction::valueMonoid::valueType(0LL, 1ULL)));
for (int _ = 0 ; _ < Q ; _++) {
int type; std::cin >> type;
if (type == 0) {
int s, t, x; std::cin >> s >> t >> x;
S.update(s - 1, t, x);
}
if (type == 1) {
int s, t; std::cin >> s >> t;
std::cout << S.prod(s - 1, t).value << std::endl;
}
}
}
#line 1 "test/lazySegmentTree-AOJ-RAQRSQ.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/3/DSL/2/DSL_2_G"
#line 2 "src/dataStructure/lazySegmentTree.hpp"
#include <vector>
#include <cassert>
namespace zawa {
template <class structure>
class lazySegmentTree {
// valueMonoid prodの時の演算
using V = typename structure::valueMonoid::valueType;
// operatorMonoid updateの時の演算
using O = typename structure::operatorMonoid::valueType;
private:
// prodの単位元
static constexpr V vId = structure::valueMonoid::identity;
// updateの単位元
static constexpr O oId = structure::operatorMonoid::identity;
struct node {
V value;
O lazy;
node() : value(vId), lazy(oId) {}
};
// @brief ノードvの左子の添字を返す
constexpr std::size_t left(std::size_t v) const {
return v << 1;
}
// @brief ノードvの右子の添字を返す
constexpr std::size_t right(std::size_t v) const {
return v << 1 | 1;
}
// @brief ノードvの親の添字を返す。
constexpr std::size_t parent(std::size_t v) const {
return (v >> 1);
}
std::size_t N;
std::size_t powTwo;
std::vector<node> dat;
// @brief 遅延した値を子に伝播する
void propagate(std::size_t v) {
if (dat[v].lazy == oId) {
return;
}
dat[v].value = structure::mapping(dat[v].value, dat[v].lazy);
if (right(v) < dat.size()) {
dat[left(v)].lazy = structure::operatorMonoid::operation(dat[left(v)].lazy, dat[v].lazy);
dat[right(v)].lazy = structure::operatorMonoid::operation(dat[right(v)].lazy, dat[v].lazy);
}
dat[v].lazy = oId;
}
// @brief 内部更新用
// LRがクエリの範囲、lrがvの持つ範囲
void update(std::size_t L, std::size_t R, std::size_t l, std::size_t r, std::size_t v, const O& value) {
// 先延ばししていたものを評価する
propagate(v);
// まったくかぶってない時、特に何もしない
if (R <= l or r <= L) {
return;
}
// lrがLRにまたがっている時、先延ばしにする
if (L <= l and r <= R) {
dat[v].lazy = structure::operatorMonoid::operation(dat[v].lazy, value);
propagate(v);
}
// 子を計算する場合
else {
assert(right(v) < dat.size());
std::size_t childRange = (r - l) >> 1;
update(L, R, l, l + childRange, left(v), value);
update(L, R, l + childRange, r, right(v), value);
dat[v].value = structure::valueMonoid::operation(dat[left(v)].value, dat[right(v)].value);
}
}
// @brief 内部計算用
// LRがクエリの範囲、lrがvの持つ範囲
V prod(std::size_t L, std::size_t R, std::size_t l, std::size_t r, std::size_t v) {
// 区間が被ってない時、単位元を返す
if (R <= l or r <= L) {
return vId;
}
// 先延ばしが許されなくなったので遅延評価する
propagate(v);
// lrがLRにすっぽりおさまっている時、そのノードの値を掛け合わせる
if (L <= l and r <= R) {
return dat[v].value;
}
// 子を辿る
else {
V res = vId;
std::size_t childRange = (r - l) >> 1;
assert(right(v) < dat.size());
res = structure::valueMonoid::operation(res, prod(L, R, l, l + childRange, left(v)));
res = structure::valueMonoid::operation(res, prod(L, R, l + childRange, r, right(v)));
return res;
}
}
public:
// @brief A = ( vId, vId, ... , vId ), |A| = Nとする
// @param N |A|
lazySegmentTree(std::size_t _N) : N(_N) {
std::size_t sz = 1;
while (sz < N) {
sz <<= 1;
}
powTwo = sz;
dat.resize((sz << 1));
}
// @brief Aを引数の列で初期化する
// @param A 扱う列
lazySegmentTree(const std::vector<V>& A) : N(A.size()) {
std::size_t sz = 1;
while (sz < N) {
sz <<= 1;
}
powTwo = sz;
dat.resize((sz << 1));
for (std::size_t i = 0 ; i < A.size() ; i++) {
dat[i + powTwo].value = A[i];
}
for (std::size_t i = powTwo - 1 ; i > 0 ; i--) {
dat[i].value = structure::valueMonoid::operation(dat[left(i)].value, dat[right(i)].value);
}
}
// @brief A_l .. A_{r - 1}にvalueで列を更新する
// @param L 左
// @param R 右、半開区間で与える必要がある
// @param value 更新させる値
void update(std::size_t L, std::size_t R, const O& value) {
assert(0 <= L and R <= N);
assert(L < R);
update(L, R, 0, powTwo, 1, value);
}
// @brief A_l .. A_R の総積(総valueMonoid::operation)を得る
// @param L 左
// @param R 右、半開区間で与える必要がある
// @return 計算結果
V prod(std::size_t L, std::size_t R) {
assert(0 <= L and R <= N);
if (L == R) {
return vId;
}
return prod(L, R, 0, powTwo, 1);
}
// @brief デバッグ用、datを返す
// @return dat
inline std::vector<node> _dat() const {
return dat;
}
};
} // namespace zawa
#line 2 "src/utility/monoid/rangeAddMonoid.hpp"
#include <cstddef>
namespace zawa {
template <class T>
struct dat {
T value;
std::size_t size;
constexpr dat(const T& value = 0, const std::size_t& size = 0ULL) : value(value), size(size) {}
};
template <class T>
struct rangeAddMonoid {
using valueType = dat<T>;
static constexpr valueType identity{};
static valueType operation(const valueType& a, const valueType& b) {
return valueType(a.value + b.value, a.size + b.size);
}
};
} // namespace zawa
#line 2 "src/utility/monoid/addMonoid.hpp"
namespace zawa {
template <class T>
struct addMonoid {
using valueType = T;
static constexpr valueType identity{};
static valueType operation(const valueType& a, const valueType& b) {
return a + b;
}
};
} // namespace zawa
#line 6 "test/lazySegmentTree-AOJ-RAQRSQ.test.cpp"
struct addAction {
using valueMonoid = zawa::rangeAddMonoid<long long>;
using operatorMonoid = zawa::addMonoid<long long>;
static valueMonoid::valueType mapping(const valueMonoid::valueType& a, const operatorMonoid::valueType& b) {
return valueMonoid::valueType(a.value + a.size * b, a.size);
}
};
#line 16 "test/lazySegmentTree-AOJ-RAQRSQ.test.cpp"
#include <iostream>
int main() {
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
int N, Q; std::cin >> N >> Q;
zawa::lazySegmentTree<addAction> S(std::vector(N, addAction::valueMonoid::valueType(0LL, 1ULL)));
for (int _ = 0 ; _ < Q ; _++) {
int type; std::cin >> type;
if (type == 0) {
int s, t, x; std::cin >> s >> t >> x;
S.update(s - 1, t, x);
}
if (type == 1) {
int s, t; std::cin >> s >> t;
std::cout << S.prod(s - 1, t).value << std::endl;
}
}
}