Loading

【题解】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;
}

posted @ 2022-04-18 21:59  7KByte  阅读(156)  评论(0编辑  收藏  举报