CF1462-E1. Close Tuples (easy version)
题意:
给出一个由n个数字组成的数组,先让你找出符合下列条件的子集的数量:
- 每个子集包含的数字个数为m = 3
-
这三个数字中的最大值减去最小值不超过k = 2
思路:
首先对给出的数组进行排序,现在假设这个数组为\(a\),这个子集为\(\{A_1, A_2, A_3\}\),那么我们每次枚举\(A_1\),用一个指针记录数组中最后一个满足\(a[p] - A_1\)的位置,那么如果\(p\)和\(A_1\)之间元素的个数n再加上1大于等于2,那么答案的总数就加上\(C_n^2\)。
这里有个地方需要注意,由于指针p指向的位置只会越来越靠后,所以p不用每次都从\(A_1\)的位置开始找,只需要从上一次p的位置开始往后找就可以了。我不会说因为这个我T了好几次的 😦
AC代码:
#include <cstdio>
#include <algorithm>
typedef long long ll;
const int maxn = 2e5 + 5;
int a[maxn];
int main () {
int T, n;
scanf ("%d", &T);
while (T--) {
scanf ("%d", &n);
for (int i = 0; i < n; i++) {
scanf ("%d", &a[i]);
}
std::sort (a, a + n);
ll p = 0, ans = 0;
for (int i = 0; i < n; i++) {
while (a[p + 1] - a[i] <= 2 && p + 1 < n) {
p++;
}
if (p - i >= 2) {
ans = ans + (p - i) * (p - i - 1) / 2;
}
}
printf ("%lld\n", ans);
}
return 0;
}