【题解】ABC248Ex - Beautiful Subsequences
给定一个排列和常数 \(K\le 3\),求有多少子区间满足区间 \(\max - \min \le R-L+K\)。
我们固定右端点统计有多少合法左端点的答案。观察到 \(K\) 很小,所以等价于对于每个 \(R\) 统计有多少 \(L\) 满足 \(R=\max - \min + L - w\),其中 \(w\in [0,K]\)。
也就是说我们只用支持更新 \(\max - \min\) 即可,而这是后缀最大值/最小值,直接用单调栈维护。那么问题就转化为支持区间加,查询区间中 \(=x\) 的数的个数,直接分块即可。
时间复杂度 \(\mathcal{O}(KN\sqrt N)\)。
#define N 140005
#define M 380
int n, k, a[N], len, t[M], m; LL ans;
int u[M][N];
#define ll(x) max(x * len, 1)
#define rr(x) min(x * len + len - 1, n)
void add(int l,int r,int val){
if(l / len == r / len){
int id = l / len;
rep(i, l, r)a[i] <= m && u[id][a[i]]--, a[i] += val, a[i] <= m && u[id][a[i]]++;
}
else{
int ld = l / len, rd = r / len, lc = rr(ld), rc = ll(rd);
rep(i, ld + 1, rd - 1)t[i] += val;
rep(i, l, lc)a[i] <= m && u[ld][a[i]]--, a[i] += val, a[i] <= m && u[ld][a[i]]++;
rep(i, rc, r)a[i] <= m && u[rd][a[i]]--, a[i] += val, a[i] <= m && u[rd][a[i]]++;
}
}
int ask(int r,int val){
int id = r / len, sum = 0, l = ll(id);
rep(i, 0, id - 1)if(val - t[i] > 0)sum += u[i][val - t[i]];
rep(i, l, r)sum += (a[i] + t[id] == val);
return sum;
}
int mx[N], mn[N], lt, rt, v[N];
int main() {
read(n, k), len = sqrt(n) + 0.5, m = n + k;
rp(i, n)a[i] = i, u[i / len][i] = 1;
rp(i, n){
int x; read(x), v[i] = x;
while(lt && v[mx[lt]] < x){
add(mx[lt - 1] + 1, mx[lt], x - v[mx[lt]]), lt--;
}mx[++lt] = i;
while(rt && v[mn[rt]] > x){
add(mn[rt - 1] + 1, mn[rt], v[mn[rt]] - x), rt--;
}mn[++rt] = i;
rep(w, 0, k)ans += ask(i, i + w);
}
printf("%lld\n", ans);
return 0;
}