ACM模版

描述


题解

数轴上 n n 个不重叠的云,给坐标,长度都是 l ,有些云速度 1 1 ,有些云速度 1 ,现风速 w w ,问在风速不大于 w m a x 时,有几对云可能在 0 0 相遇。

对于会相遇的云,肯定一个是 v i = 1 ,一个是 vi=1 v i = − 1 ,所以我们首先可以根据 vi v i 将云分为两组,然后进行从小到大排序,接着枚举其中一组,去和另一组进行匹配。这里我们分组为 a[] a [ ] b[] b [ ] ,分别表示 v=1 v = 1 v=1 v = − 1 ,这里枚举 a[] a [ ] ,如果 a[i]>b[j] a [ i ] > b [ j ] ,那么他们是不可能相遇的,反之可能,但是必须满足 b[j]a[i]+l2w>|b[j]a[i]+l2+a[i]| b [ j ] − a [ i ] + l 2 ∗ w > | b [ j ] − a [ i ] + l 2 + a [ i ] | ,当我们匹配到这个云时,说明后边所有的云都是满足条件的,因为我们的云彩是按照位置从小到大进行排序的。当我们匹配到 j j 满足上述条件时,那么我们 a n s + = c n t _ b j + 1 ,如此这般,最后 ans a n s 即为正确结果。

代码

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 1e5 + 10;

int n, l, w;
int a[MAXN], b[MAXN];

int main()
{
    while (cin >> n >> l >> w)
    {
        long long ans = 0;

        int x, v, cnt_a = 0, cnt_b = 0;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d%d", &x, &v);

            if (v == 1)
            {
                a[++cnt_a] = x;
            }
            if (v == -1)
            {
                b[++cnt_b] = x;
            }
        }
        sort(a + 1, a + 1 + cnt_a);
        sort(b + 1, b + 1 + cnt_b);

        for (int i = 1, j = 1; i <= cnt_a; i++)
        {
            for (; j <= cnt_b; j++)
            {
                if (b[j] < a[i])
                {
                    continue;
                }

                double tmp = b[j] - a[i] + (double)l;
                double x = tmp / 2 + a[i];
                if (x < 0)
                {
                    x = -x;
                }

                if ((tmp / 2) * w > x)
                {
                    break;
                }
            }

            if (j > cnt_b)
            {
                break;
            }

            ans += cnt_b - j + 1;
        }

        printf("%lld\n", ans);
    }

    return 0;
}