专栏文章

题解:CF2128D Sum of LDS

CF2128D题解参与者 5已保存评论 4

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
4 条
当前快照
1 份
快照标识符
@miodhcps
此快照首次捕获于
2025/12/02 17:25
3 个月前
此快照最后确认于
2025/12/02 17:25
3 个月前
查看原文

简要题意

给定一个长度为 nn 的排列 p1,p2,,pnp_1, p_2, \ldots, p_n,并且对所有 1in21 \le i \le n-2 都满足 max(pi,pi+1)>pi+2\max(p_i, p_{i+1}) > p_{i+2}
请计算:对所有满足 1lrn1 \le l \le r \le n 的子数组 (pl,pl+1,,pr)(p_l, p_{l+1}, \ldots, p_r),其最长严格下降子序列(LDS)的长度之和。

思路

pn+1=pn+2=pn+3=p_{n+1} = p_{n+2} = p_{n+3} = -\infty{i1,,im}\{i_1, \ldots, i_m\} 为所有满足 pi>pi+1p_i > p_{i+1}i[n]i \in [n] 组成的集合。
可以分两步证明,序列 (i1,,im)(i_1, \ldots, i_m)pp 的一个 LDS。

它是单调递减的

k[m]k \in [m]

情况 1:(ik)+1=ik+1(i_k) + 1 = i_{k+1}

按照集合构造规则,直接有 pik>p(ik)+1=pik+1p_{i_k} > p_{(i_k) + 1} = p_{i_{k+1}}

情况 2:(ik)+1<ik+1(i_k) + 1 < i_{k+1}

此时,根据题意,有 max(pik,p(ik)+1)>p(ik)+2\max(p_{i_k}, p_{(i_k) + 1}) > p_{(i_k) + 2}
(ik)+1<ik+1(i_k) + 1 < i_{k+1},说明 (ik)+1(i_k) + 1 没有被选入集合,又说明 p(ik)+1<p(ik)+2p_{(i_k) + 1} < p_{(i_k) + 2},所以 pik>p(ik)+2p_{i_k} > p_{(i_k) + 2} 只能成立,否则 max(pik,p(ik)+1)>p(ik)+2\max(p_{i_k}, p_{(i_k) + 1}) > p_{(i_k) + 2} 不成立。
别忘了,根据规则,现在不仅有 pik>p(ik)+2p_{i_k} > p_{(i_k) + 2},还有 pik>p(ik)+1p_{i_k} > p_{(i_k) + 1}。根据题意,又有 pik>max(p(ik)+1,p(ik)+2)>p(ik)+3)p_{i_k} > \max(p_{(i_k) + 1}, p_{(i_k) + 2}) > p_{(i_k) + 3)},于是就有了传递性,可以一路传出去了。
综上所述,pik>max(p(ik)+1,p(ik)+2,,pn)p_{i_k} > \max(p_{(i_k) + 1}, p_{(i_k) + 2}, \ldots, p_{n}) 恒成立,单调性得证。

它是最长的

注意到,若 pi<pi+1p_i < p_{i + 1},那么 iii+1i + 1 至多只能选择其中一个存在于 LDS 中。
因此答案的上界为 ni=1n1[pi<pi+1]n - \sum_{i=1}^{n-1} \left[p_i < p_{i+1}\right],即 n(nm)=mn - (n - m) = m,注意到 {i1,,im}=m|\{i_1, \ldots, i_m\}| = m,正好达到上界,最优性得证。

综上所述,(i1,,im)(i_1, \ldots, i_m)pp 的一个 LDS。
因此原问题被转换成了:计算 l=1nr=ln1+k=lr1[pk>pk+1]\sum_{l=1}^{n} \sum_{r=l}^n 1 + \sum_{k=l}^{r-1} [p_k > p_{k+1}] 的值。
相信有良好普及组基础的同学,可以轻松地在 Θ(n)\Theta(n) 的时空复杂度下解决此问题。

实现

CPP
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

constexpr int N = 500000 + 1;

int a[N];

void solve() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i];
	}
	ll ans = 0;
	for (int i = 1; i < n; ++i) if (a[i] > a[i + 1]) {
		ans += (ll)i * (n - i);
	}
	cout << ans + ((ll)n * (n + 1) >> 1) << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}
时空复杂度:均为 Θ(n)\Theta(n)

评论

4 条评论,欢迎与作者交流。

正在加载评论...