洛谷P1102 A-B数对

双指针做法:

 

 反过来,从后往前看也是一样的:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cmath>
#define For(i, j, n) for (int i = j; i <= n; ++i)
using namespace std;

const int N = 2e5 + 5;

int n, c;
int a[N];

int main()
{
    scanf("%d%d", &n, &c);
    For(i, 1, n)
        scanf("%d", a + i);
    sort(a + 1, a + n + 1);
    /*for (int i = 1; i <= n; i++)
        cout << i << " ";
    puts("");
    for (int i = 1; i <= n; i++)
        cout << a[i] << " ";
    cout << endl;*/
    // int r1 = 1, r2 = 1;
    long long ans = 0;
    /*for(int i = 1; i <= n; i++)
    {
        int k = a[i] + c;
        while(r1 <= n && a[r1] < k) r1++;
        while(r2 <= n && a[r2] <= k) r2++;
        if(a[r1] == k && a[r2 - 1] == k)
            ans += r2 - r1;
    }*/
    int l1 = 1, l2 = 1;
    for(int i = 1; i <= n; i++)
    {
        int k = a[i] - c;
        while(l1 <= n && a[l1] < k) l1++;
        while(l2 <= n && a[l2] <= k) l2++;
        if(a[l1] == k && l2 >= 2 && a[l2 - 1] == k)
            ans += l2 - l1; 
    }
    printf("%lld\n", ans);
    return 0;
}

另外要注意的是,这道题虽然N只有1e5数量级,但ans还是需要开long long的,我们可以分析一下ans的范围:

考虑最极端的情况:

a[]由一系列相等的部分连接而成:

如1 1 1 1 1 …… 2 2 2 2 2 

我们简化一下情况,假设每一段数字的数量都相同且为k,那么ans就是:

$\frac{n}{k} \times k^{2} = nk $

(为了方便,不考虑向下取整)

我们令k=n/2,就可以让ans来到n^2数量级,从而爆int

 

posted @ 2024-03-31 19:15  Gold_stein  阅读(3)  评论(0编辑  收藏  举报