#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5 + 10, inf = 1e18;
struct node {
int sum, valmax, cntmax, secmax, valmin, cntmin, secmin;
friend node operator + (node a, node b) {
node c;
c.sum = a.sum + b.sum;
c.valmax = max(a.valmax, b.valmax);
if (a.valmax == b.valmax)
c.cntmax = a.cntmax + b.cntmax, c.secmax = max(a.secmax, b.secmax);
else if (a.valmax > b.valmax)
c.cntmax = a.cntmax, c.secmax = max(a.secmax, b.valmax);
else
c.cntmax = b.cntmax, c.secmax = max(b.secmax, a.valmax);
c.valmin = min(a.valmin, b.valmin);
if (a.valmin == b.valmin)
c.cntmin = a.cntmin + b.cntmin, c.secmin = min(a.secmin, b.secmin);
else if (a.valmin < b.valmin)
c.cntmin = a.cntmin, c.secmin = min(a.secmin, b.valmin);
else
c.cntmin = b.cntmin, c.secmin = min(b.secmin, a.valmin);
return c;
}
};
int n, m;
int a[N], MaxAdd[N << 2], MaxOtherAdd[N << 2], MinAdd[N << 2], MinMax[N << 2], MinOtherAdd[N << 2];
node tree[N << 2];
void pushup (int rt) {
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
void build (int l, int r, int rt) {
if (l == r) {
tree[rt] = {a[l], a[l], 1, -inf, a[l], 1, inf};
return ;
}
int mid = l + r >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
pushup(rt);
}
void lazy (int len, int rt, int maxadd, int maxotheradd, int minadd, int minmax, int minotheradd) {
tree[rt].sum += maxadd * tree[rt].cntmax + maxotheradd * (len - tree[rt].cntmax) + minmax * tree[rt].cntmin;
if (tree[rt].valmax == tree[rt].valmin) {
if (maxadd)
tree[rt].valmax = tree[rt].valmin = tree[rt].valmax + maxadd;
else
tree[rt].valmax = tree[rt].valmin = tree[rt].valmax + minadd;
tree[rt].valmax = tree[rt].valmin = tree[rt].valmax + minmax;
}
else if (tree[rt].valmax == tree[rt].secmin) {
tree[rt].secmin = tree[rt].valmax = tree[rt].valmax + maxadd;
tree[rt].secmax = tree[rt].valmin = tree[rt].valmin + minadd + minmax;
}
else {
tree[rt].valmax += maxadd;
tree[rt].secmax += tree[rt].secmax == -inf ? 0 : maxotheradd;
tree[rt].valmin += minadd + minmax;
tree[rt].secmin += tree[rt].secmin == inf ? 0 : minotheradd;
}
MaxAdd[rt] += maxadd;
MaxOtherAdd[rt] += maxotheradd;
MinAdd[rt] += minadd;
MinMax[rt] += minmax;
MinOtherAdd[rt] += minotheradd;
}
void pushdown (int l, int r, int rt) {
int mid = l + r >> 1, tmpmax = max(tree[rt << 1].valmax, tree[rt << 1 | 1].valmax), tmpmin = min(tree[rt << 1].valmin, tree[rt << 1 | 1].valmin);
if (tree[rt << 1].valmax == tmpmax)
lazy(mid - l + 1, rt << 1, MaxAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
else
lazy(mid - l + 1, rt << 1, MaxOtherAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
if (tree[rt << 1 | 1].valmax == tmpmax)
lazy(r - mid, rt << 1 | 1, MaxAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
else
lazy(r - mid, rt << 1 | 1, MaxOtherAdd[rt], MaxOtherAdd[rt], 0, 0, 0);
if (tree[rt << 1].valmin == tmpmin)
lazy(mid - l + 1, rt << 1, 0, 0, MinAdd[rt], MinMax[rt], MinOtherAdd[rt]);
else
lazy(mid - l + 1, rt << 1, 0, 0, MinOtherAdd[rt], 0, MinOtherAdd[rt]);
if (tree[rt << 1 | 1].valmin == tmpmin)
lazy(r - mid, rt << 1 | 1, 0, 0, MinAdd[rt], MinMax[rt], MinOtherAdd[rt]);
else
lazy(r - mid, rt << 1 | 1, 0, 0, MinOtherAdd[rt], 0, MinOtherAdd[rt]);
MaxAdd[rt] = MaxOtherAdd[rt] = MinAdd[rt] = MinMax[rt] = MinOtherAdd[rt] = 0;
}
void add (int l, int r, int rt, int L, int R, int c) {
if (L <= l && r <= R) {
lazy(r - l + 1, rt, c, c, c, 0, c);
return ;
}
pushdown(l, r, rt);
int mid = l + r >> 1;
if (L <= mid)
add(l, mid, rt << 1, L, R, c);
if (R > mid)
add(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
void setmax (int l, int r, int rt, int L, int R, int c) {
if (tree[rt].valmin >= c)
return ;
if (L <= l && r <= R && tree[rt].secmin > c) {
lazy(r - l + 1, rt, 0, 0, 0, c - tree[rt].valmin, 0);
return ;
}
pushdown(l, r, rt);
int mid = l + r >> 1;
if (L <= mid)
setmax(l, mid, rt << 1, L, R, c);
if (R > mid)
setmax(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
void setmin (int l, int r, int rt, int L, int R, int c) {
if (tree[rt].valmax <= c)
return ;
if (L <= l && r <= R && tree[rt].secmax < c) {
lazy(r - l + 1, rt, c - tree[rt].valmax, 0, 0, 0, 0);
return ;
}
pushdown(l, r, rt);
int mid = l + r >> 1;
if (L <= mid)
setmin(l, mid, rt << 1, L, R, c);
if (R > mid)
setmin(mid + 1, r, rt << 1 | 1, L, R, c);
pushup(rt);
}
node query (int l, int r, int rt, int L, int R) {
if (L <= l && r <= R)
return tree[rt];
pushdown(l, r, rt);
int mid = l + r >> 1;
if (R <= mid)
return query(l, mid, rt << 1, L, R);
if (L > mid)
return query(mid + 1, r, rt << 1 | 1, L, R);
return query(l, mid, rt << 1, L, R) + query(mid + 1, r, rt << 1 | 1, L, R);
}
signed main (void) {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
build(1, n, 1);
cin >> m;
while (m--) {
int op, x, y, z;
cin >> op >> x >> y;
if (op == 1)
cin >> z, add(1, n, 1, x, y, z);
else if (op == 2)
cin >> z, setmax(1, n, 1, x, y, z);
else if (op == 3)
cin >> z, setmin(1, n, 1, x, y, z);
else {
node tmp = query(1, n, 1, x, y);
if (op == 4)
cout << tmp.sum << '\n';
else if (op == 5)
cout << tmp.valmax << '\n';
else
cout << tmp.valmin << '\n';
}
}
return 0;
}