알고리즘/알고리즘 이론, 템플릿

레이지세그

b1ackhand 2023. 8. 21. 14:01
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <unordered_set>
#include <numeric>

#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define rep1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define range(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define x first
#define y second

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
typedef vector<int> vi;
typedef vector<long long> vll;

const int INF = 100000000;
const double pi = 3.14159265358979;
const ll MOD = 1000000007;

ll arr[1000002];
ll lazy[4 * 1000002];
ll tree[4 * 1000002];
ll N, M, K;
ll a, b, c, d;
ll order;

ll init(ll start, ll end, ll node)
{
	if (start == end)
		return tree[node] = arr[start];

	ll mid = (start + end) / 2;

	return tree[node] = init(start, mid, node * 2) + init(mid + 1, end, node * 2 + 1);
}

ll query(ll start, ll end, ll node, ll left, ll right)
{
	if (left > end || right < start)
		return 0;

	if (left <= start && end <= right)
		return tree[node];

	ll mid = (start + end) / 2;

	return query(start, mid, node * 2, left, right) + query(mid + 1, end, node * 2 + 1, left, right);
}

ll update(ll start, ll end, ll node, ll index, ll diff)
{
	if (index < start || end < index)
		return tree[node];

	if (start == end)
		return tree[node] += diff;;

	ll mid = (start + end) / 2;

	return tree[node] = update(start, mid, node * 2, index, diff) + update(mid + 1, end, node * 2 + 1, index, diff);
}

void update_lazy(ll start, ll end, ll node) {
	if (lazy[node] != 0)
	{
		tree[node] += (end - start + 1) * lazy[node];
		if (start != end)
		{
			lazy[node * 2] += lazy[node];
			lazy[node * 2 + 1] += lazy[node];
		}
		lazy[node] = 0;
	}
}

ll query_range(ll start, ll end, ll node, ll left, ll right)
{
	update_lazy(start, end, node);

	if (left > end || right < start)
		return 0;

	if (left <= start && end <= right)
		return tree[node];

	ll mid = (start + end) / 2;

	return query_range(start, mid, node * 2, left, right) + query_range(mid + 1, end, node * 2 + 1, left, right);
}


void update_range(ll start, ll end, ll node, ll left, ll right, ll diff)
{
	update_lazy(start, end, node);

	if (left > end || right < start) 
		return;

	if (left <= start && end <= right) 
	{
		tree[node] += (end - start + 1) * diff;
		if (start != end) {
			lazy[node * 2] += diff;
			lazy[node * 2 + 1] += diff;
		}
		return;
	}

	ll mid = (start + end) / 2;

	update_range( start, mid, node * 2,  left, right, diff);
	update_range( mid + 1, end, node * 2 + 1, left, right, diff);
	tree[node] = tree[node * 2] + tree[node * 2 + 1];
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

	cin >> N >> M >> K;

	rep1(i, N)
	{
		cin >> a;
		arr[i] = a;
	}

	init(1, N, 1);

	rep(i, M + K)
	{
		cin >> order;

		if (order == 1)
		{
			cin >> a >> b >> c;
			update_range(1, N, 1, a, b, c);
		}
		else if(order == 2)
		{
			cin >> a >> b;
			cout << query_range(1, N, 1, a, b) << "\n";
		}
	}

    return 0;

}