import java.util.Scanner;
/**
* 线段树维护区间的前后缀不下降子数组的长度
* 在合并左子树和右子树时
* 通过比较左子树的后缀和右子树的前缀来判断是否可以为答案多贡献,合并逻辑在push方法中
*/
public class Main {
static final int N = 200010;
static int[] a = new int[N];
static Pair[] tree = new Pair[N * 4];
static int n, m;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
for (int i = 1; i <= n; i++) {
a[i] = sc.nextInt();
}
build(1, 1, n);
for (int i = 1; i <= m; i++) {
int op = sc.nextInt();
if (op == 1) {
int l = sc.nextInt(), r = sc.nextInt(), k = sc.nextInt();
update(1, 1, n, l, r, k);
} else {
int l = sc.nextInt(), r = sc.nextInt();
System.out.println(query(1, 1, n, l, r).cnt);
}
}
}
static void build(int u, int l, int r) {
tree[u] = new Pair();
if (l == r) {
tree[u].cnt = tree[u].prec = tree[u].sufc = 1;
tree[u].x = tree[u].y = a[l];
tree[u].l = tree[u].r = l;
return;
}
int mid = l + r >> 1;
build(u * 2, l, mid);
build(u * 2 + 1, mid + 1, r);
pushup(u);
}
static void update(int u, int L, int R, int l, int r, int k) {
if (l <= L && r >= R) {
/**
* 所有元素都是k
* 那么前缀和后缀的长度都是R-L+1
* 那么不下降子数组的个数就是1+2+...+len即len*(len+1)/2
*/
upLazy(u, k);
return;
}
pushdown(u);
int mid = L + R >> 1;
if (l <= mid) {
update(u * 2, L, mid, l, r, k);
}
if (r > mid) {
update(u * 2 + 1, mid + 1, R, l, r, k);
}
pushup(u);
}
static Pair query(int u, int L, int R, int l, int r) {
if (l <= L && r >= R) {
return tree[u];
}
pushdown(u);
int mid = L + R >> 1;
Pair qL = null, qR = null;
if (l <= mid) {
qL = query(u * 2, L, mid, l, r);
}
if (r > mid) {
qR = query(u * 2 + 1, mid + 1, R, l, r);
}
if (qL == null || qR == null) {
return qL == null ? qR : qL;//返回不为null的
} else {
return push(qL, qR);//合并返回
}
}
static void pushdown(int u) {
if (tree[u].lazy == 0) return;
upLazy(u * 2, tree[u].lazy);
upLazy(u * 2 + 1, tree[u].lazy);
tree[u].lazy = 0;
}
static void upLazy(int u, int k) {
int len = tree[u].r - tree[u].l + 1;
tree[u].lazy = k;
tree[u].prec = tree[u].sufc = len;
tree[u].x = tree[u].y = k;
tree[u].cnt = (long) len * (len + 1) / 2;
}
static Pair push(Pair L, Pair R) {
Pair res = new Pair();
//拿到左子树的最后一个元素,和右子树的第一个元素
int s = L.y, e = R.x;
res.x = L.x;
res.y = R.y;
res.l = L.l;
res.r = R.r;
res.cnt = L.cnt + R.cnt;
//不能接
res.prec = L.prec;
res.sufc = R.sufc;
if (s <= e) {
//可以接
int Llen = L.r - L.l + 1, Rlen = R.r - R.l + 1;
res.prec = (L.prec == Llen ? Llen + R.prec : L.prec);
res.sufc = (R.sufc == Rlen ? Rlen + L.sufc : R.sufc);
res.cnt += (long) L.sufc * R.prec;
}
return res;
}
static void pushup(int u) {
Pair L = tree[u * 2], R = tree[u * 2 + 1];
tree[u] = push(L, R);
}
}
class Pair {
long cnt;//long防止爆
int prec, sufc;//前缀和后缀的不下降序列的长度
//第一个元素x是pre的第一个
int x, y;//第一个元素和最后一个元素
int l, r;//记录该元素的管理范围
int lazy = 0;
public Pair() {
}
}