转化一下询问即为区间$max - min + 1 = cnt$,其中$cnt$表示区间内数的种类数。
即求有多少区间$max - min - cnt=-1$,注意到任意区间的$max-min-cnt \geq -1$,那么即维护区间$max-min-cnt$的最小值和最小值的个数,再看最小值等不等于$-1$就行了。
那么可以用扫描线扫右端点$r$,线段树维护左端点为$1, 2,\dots,r-1$的区间最小值和最小值的个数。每加入一个数,$r$这里必定为$-1$,所以当前区间最小值的个数就是答案了。
对于区间种类数就$[last[a[i]], i - 1]$多了$1$,那么要减去$1$,因为在式子里$cnt$,前面是负号。
然后最大值最小值就用两个单调栈搞一下就好了。区间加上对应的差值即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 7;
int top1, top2, a[N], st1[N], st2[N];
map<int, int> pos;
struct Seg {
#define lp p << 1
#define rp p << 1 | 1
int tree[N << 2], lazy[N << 2], sum[N << 2];
inline void init() {
memset(tree, 0, sizeof(tree));
memset(lazy, 0, sizeof(lazy));
memset(sum, 0x3f, sizeof(sum));
}
inline void pushdown(int p) {
if (lazy[p] == 0) return;
lazy[lp] += lazy[p];
lazy[rp] += lazy[p];
sum[lp] += lazy[p];
sum[rp] += lazy[p];
lazy[p] = 0;
}
inline void pushup(int p) {
sum[p] = min(sum[lp], sum[rp]);
if (sum[lp] == sum[rp]) tree[p] = tree[lp] + tree[rp];
else if (sum[lp] < sum[rp]) tree[p] = tree[lp];
else tree[p] = tree[rp];
}
void update(int p, int l, int r, int pos) {
if (l == r) {
tree[p] = 1;
sum[p] = -1;
return;
}
pushdown(p);
int mid = l + r >> 1;
if (pos <= mid) update(lp, l, mid, pos);
else update(rp, mid + 1, r, pos);
pushup(p);
}
void update(int p, int l, int r, int x, int y, int val) {
if (x > y) return;
if (x <= l && y >= r) {
sum[p] += val;
lazy[p] += val;
return;
}
pushdown(p);
int mid = l + r >> 1;
if (x <= mid) update(lp, l, mid, x, y, val);
if (y > mid) update(rp, mid + 1, r, x, y, val);
pushup(p);
}
} seg;
inline void init() {
top1 = top2 = 0;
seg.init();
pos.clear();
}
int main() {
int T;
int kase = 0;
scanf("%d", &T);
while (T--) {
init();
ll ans = 0;
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
seg.update(1, 1, n, i);
scanf("%d", &a[i]);
while (top1 && a[st1[top1]] <= a[i]) {
int p = st1[top1], key = a[st1[top1]];
top1--;
seg.update(1, 1, n, st1[top1] + 1, p, a[i] - key);
}
st1[++top1] = i;
while (top2 && a[st2[top2]] >= a[i]) {
int p = st2[top2], key = a[st2[top2]];
top2--;
seg.update(1, 1, n, st2[top2] + 1, p, key - a[i]);
}
st2[++top2] = i;
int l = pos[a[i]];
seg.update(1, 1, n, l + 1, i - 1, -1);
pos[a[i]] = i;
ans += seg.tree[1];
}
printf("Case #%d: %lld\n", ++kase, ans);
}
return 0;
}
