Language: C++

#include <iostream>
#include <algorithm>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <list>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <bitset>
#include <random>
#include <complex>
#include <assert.h>

#include <atcoder/dsu.hpp>
#include <atcoder/fenwicktree.hpp>
#include <atcoder/segtree.hpp>

using namespace std;
using namespace atcoder;

typedef long long ll;
#define endl '\n'

const ll INF = 1LL << 60;

template<typename T>
inline bool chmin(T& x, T a) {
	if (x >= a) { x = a; return true; }
	return false;
}

template<typename T>
inline bool chmax(T& x, T a) {
	if (x <= a) { x = a; return true; }
	return false;
}

#define unionFind dsu

template <class T> struct BIT : fenwick_tree<T> {
public:
	BIT() : fenwick_tree<T>() {}
	BIT(int n) : fenwick_tree<T>(n) {}
	BIT(const vector<T>& A) : fenwick_tree<T>((int)A.size()) {
		for (int i = 0; i < (int)A.size(); i++) {
			fenwick_tree<T>::add(i, A[i]);
		}
	}
	
	void get(int p) { return fenwick_tree<T>::sum(p, p + 1); }
	void set(int p, T x) { fenwick_tree<T>::add(p, x - get(p)); }
};

///////////////   セグメント木

// ここでセグ木の設定をする

// #define SEGTREE_DATA_ADD			// 和をとるセグ木
#define SEGTREE_DATA_MAX			// 最大値をとるセグ木
// #define SEGTREE_DATA_MIN			// 最小値をとるセグ木

// #define SEGTREE_LAZY_SET			// 区間代入する遅延セグ木
// #define SEGTREE_LAZY_ADD			// 区間加算する遅延セグ木
// #define SEGTREE_LAZY_MAX			// 最大値を更新する遅延セグ木
// #define SEGTREE_LAZY_MIN			// 最小値を更新する遅延セグ木


using segtree_data_type = ll;

#ifdef SEGTREE_DATA_ADD
const segtree_data_type segtree_data_init_value = 0;
inline segtree_data_type segtree_data_merge(segtree_data_type a, segtree_data_type b) {// 要素aのbの和
	return a + b;
}
#endif
#ifdef SEGTREE_DATA_MAX
const segtree_data_type segtree_data_init_value = -INF;
inline segtree_data_type segtree_data_merge(segtree_data_type a, segtree_data_type b) {// 要素aのbの最大値
	return max(a, b);
}
#endif
#ifdef SEGTREE_DATA_MIN
const segtree_data_type segtree_data_init_value = INF;
inline segtree_data_type segtree_data_merge(segtree_data_type a, segtree_data_type b) {// 要素aのbの最小値
	return min(a, b);
}
#endif
segtree_data_type segtree_data_init() { return segtree_data_init_value; }


segtree_data_type segtree_max_right_value;
bool segtree_max_right_func(segtree_data_type x) {
	return x < segtree_max_right_value;
}

template <class T> struct SegmentTree : segtree<T, > {
public:
	SegmentTree() : segtree<T>() {}
	SegmentTree(int n) : fenwick_tree<T>(n) {}
	SegmentTree(const vector<T>& A) : fenwick_tree<T>((int)A.size()) {
		for (int i = 0; i < (int)A.size(); i++) {
			fenwick_tree<T>::add(i, A[i]);
		}
	}

	void get(int p) { return fenwick_tree<T>::sum(p, p + 1); }
	void set(int p, T x) { fenwick_tree<T>::add(p, x - get(p)); }
};

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(0);

	int N, Q; cin >> N >> Q;
	vector<ll> A(N);
	for (int i = 0; i < N; i++) {
		cin >> A[i];
	}
	segtree<segtree_data_type, segtree_data_merge, segtree_data_init> ST(A);

	for (int q = 0; q < Q; q++) {
		ll t, a, b; cin >> t >> a >> b;
		if (t == 1) {
			ST.set(a - 1, b);
		}
		else if (t == 2) {
			cout << ST.prod(a - 1, b) << endl;
		}
		else {
			segtree_max_right_value = b;
			cout << ST.max_right<segtree_max_right_func>(a - 1) + 1 << endl;
		}
	}

	return 0;
}

Compiler output:
a.cc:22:10: fatal error: atcoder/dsu.hpp: No such file or directory
   22 | #include <atcoder/dsu.hpp>
      |          ^~~~~~~~~~~~~~~~~
compilation terminated.