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;
}
posted @ 2020-12-21 12:03  牟翔宇  阅读(164)  评论(0编辑  收藏  举报