Loading

abc 252 d 题解

abc 252 d

AT 链接

洛谷链接

题意

给定长度为 \(n\) 的序列 \(a = (a_1, a_2, \dots, a_n)\),请你求出满足以下条件的三元组的数量:

  • \(1 \le i < j < k \le n\)

  • \(a_i, a_j, a_k\) 均不相同。

\(3 \le n \le 2 \times 10 ^ 5\)

\(1 \le a_i \le 2 \times 10 ^ 5\)

思路

这道题目可以转换成这样:

求出满足 \(1 \le i, j, k \le n\)\(a_i < a_j < a_k\) 的三元组数量。

那么,我们可以直接枚举中间的 \(a_j\) 的值。

\(s_i\) 表示在序列 \(a\) 中,小于等于 \(i\) 的数字数量,\(cnt_i\) 表示在序列 \(a\) 中,\(i\) 的出现次数,\(V\) 表示最大的 \(a_i\)

那么对于每个 \(a_j\),它对答案的贡献就是 \(cnt_i \times s_{i - 1} \times (s_{V} - s_i)\)

统计答案即可。

时间复杂度为 \(O(n + V)\)\(V\) 表示最大的 \(a_i\)

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10, INF = 2e5;

int n, a[N], cnt[N], s[N];
long long ans;

int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
    cnt[a[i]]++;  // 统计出现次数
  }
  for (int i = 1; i <= INF; i++) {
    s[i] = s[i - 1] + cnt[i];  // 前缀和
  }
  for (int i = 1; i <= INF; i++) {
    ans += 1ll * cnt[i] * s[i - 1] * (s[INF] - s[i]);  // 统计答案
  }
  cout << ans;
  return 0;
}
posted @ 2024-09-20 17:09  chengning0909  阅读(5)  评论(0编辑  收藏  举报