洛谷P1102 A-B數對

Gold_stein發表於2024-03-31

雙指標做法:

反過來,從後往前看也是一樣的:

#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