template <typename T>
struct array2d_t {
lli n, m;
vector<T> data;
array2d_t(lli n, lli m) : n(n), m(m), data(n* m) { }
array2d_t(lli n, lli m, lli v) : n(n), m(m), data(n* m, v) { }
decltype(auto) operator[](tuple<lli, lli> ind) { auto [i, j] = ind; return data[i * m + j]; }
decltype(auto) operator[](tuple<lli, lli> ind) const { auto [i, j] = ind; return data[i * m + j]; }
void print() const {
for (lli i = 0; i < n; ++i) {
for (lli j = 0; j < m; ++j)
write((*this)[{ i, j }], ' ');
write('\n');
}
}
};
template <typename T>
struct array3d_t {
lli n, m, l;
vector<T> data;
array3d_t(lli n, lli m, lli l) : n(n), m(m), l(l), data(n* m* l) { }
array3d_t(lli n, lli m, lli l, lli v) : n(n), m(m), l(l), data(n* m* l, v) { }
decltype(auto) operator[](tuple<lli, lli, lli> ind) { auto [i, j, k] = ind; return data[i * m * l + j * l + k]; }
decltype(auto) operator[](tuple<lli, lli, lli> ind) const { auto [i, j, k] = ind; return data[i * m * l + j * l + k]; }
void print() const {
for (lli i = 0; i < n; ++i) {
for (lli j = 0; j < m; ++j) {
for (lli k = 0; k < l; ++k)
write((*this)[{ i, j, k }], ' ');
write('\n');
}
}
}
};