1 条题解
-
0
首先,我们可以将给定的数字映射到 范围内的整数。设 ,,我们想要找到满足 且 的数对 的数量。
为了计算 ,我们可以维护一个名为 的数组,用来记录每个值出现的次数。具体做法是:从左到右遍历数组,并更新 数组;在位置 处, 就等于 的值( 可以用类似的方法计算)。
除此之外,我们还可以借助树状数组(Fenwick Tree)来解决。我们使用一个树状数组,并从右到左遍历。在每一步中,我们将树状数组中小于 的元素个数累加到答案中,然后将 加入到树状数组里。
总时间复杂度:。
此外,我们也可以使用分治法(divide and conquer)来解决这个问题。你可以参考第二个示例解法来了解具体的实现方式。
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1000 * 1000 + 10; int fen[MAXN]; void add(int x, int val) { for (int i = x + 1; i < MAXN; i += i & (-i)) fen[i] += val; } int get(int x) { int ans = 0; for (int i = x; i > 0; i -= i & (-i)) ans += fen[i]; return ans; } int sum(int x, int y) { return get(y) - get(x); } int rem[MAXN], cnt[MAXN], a[MAXN], tot[MAXN], sz; int main() { ios::sync_with_stdio(false); int n; cin >> n; for (int i = 0; i < n; i ++) cin >> a[i], tot[sz++] = a[i]; sort(tot, tot + sz); sz = unique(tot, tot + sz) - tot; for (int i = 0; i < n; i ++) a[i] = lower_bound(tot, tot + sz, a[i]) - tot; for (int i = n - 1; i >= 0; i --) { cnt[a[i]] ++; add(cnt[a[i]], 1); rem[i] = cnt[a[i]]; } memset(cnt, 0, sizeof cnt); long long ans = 0; for (int i = 0; i < n; i ++) { add(rem[i], -1); cnt[a[i]] ++; ans += sum(1, cnt[a[i]]); } cout << ans << endl; return 0; }
- 1
信息
- ID
- 6768
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者