Codeforces C Match Points(二分贪心)

题目描述:

Match Points

time limit per test

2 seconds

memory limit per test

256 mega bytes

input

standard input

output

standard output

You are given a set of points x1, , ..., x**n

Two points iand jcan be matched with each other if the following conditions hold:

  • neither i nor j is matched with any other point;
  • |x**ix**j|≥z.

What is the maximum number of pairs of points you can match with each other?

Input

The first line contains two integers n

and (2≤n≤2⋅105) — the number of points and the constraint on the distance between matched points, respectively.

The second line contains n integers , x2 (1≤x**i≤109

Output

Print one integer — the maximum number of pairs of points you can match with each other.

Examples

Input

Copy

4 2
1 3 3 7

Output

Copy

2

Input

Copy

5 5
10 9 5 8 7

Output

Copy

1

Note

In the first example, you may match point 1

with point (|3−1|≥2 with point 4).

In the second example, you may match point 1

with point (|5−10|≥5)

思路:

刚开始就想的是匹配嘛,一看到匹配想到二分图最大匹配,嗯~匈牙利算法,建个图,跑一下试试。不过看样子数据范围有点大,有超时的可能(必然)。不管了,想到这个先写写吧。怎么建图呢?把满足条件的两个点之间连一条边,等等,好像有重复啊,我一个数匹配了就不能再用了啊。我自以为可以解决问题的做法:对一个数来说枚举从他的下一个到末尾。是不是就可以了呢?

不是。我真的是,刚学了二分图就想什么都往上面套,明明怎么建图都还没学过,这样还是不可能建出正确的图。因为一个顶点被用了之后是不知道知道它已经被用了的,这就建不出二分图。

天真的我以为模板写错了,又用了最大流来了好几遍,一直WA,真好。

我就想到二分,然后有一种直觉告诉我,我把数组排个序,然后用lower_bound给每个数来一下查找满足条件的最小元素。但也是直觉产生怀疑,为什么,这样贪心正确吗?有没有可能这里lower_bound了配对以后就影响了后面元素的配对,而且是连环影响,本来可以产生更多配对,结果由于贪心配对数变少了。怀疑是正确的,比如一组例子:

4 2

1 3 4 5

如果找这种方法只能配出1,3一对来,实际上是两对:1,4和3,5

然后我想,那我统计一下元素可能配对的次数,从可能配对次数最小的开始配对,因为它们最不容易配对,优先满足它们可能会让总数大一些,于是又用了结构体排序什么的,也不正确。

眼看着我里正确的思路越来越远,也越来越想不到正确的解。知道是二分复杂度才能下去,知道是贪心才能得出正确解,但我的思路好像很奇怪?

现在来看看正确的思路,我们想最优的情况是什么?是每个元素都配了对,一共n/2对,是不是?那么这个时候配对情况是怎样的呢?是不是前一半小的配后一半大的?如果这点想到了,离正确二分就不远了。就是二分这个排序好的数组,用后一半跟前一半的元素配对,具体的,设中间为mid,最后一个从mid-1开始往前面配对,一旦出现配对元素,答案统计,并更新下一次配对开始的起点为当前位置的前一个位置。(为什么?因为当前如果配好了对,由于数组已经排好了序,下一次是比这次参加配对的后半段的元素更小的一个元素,这个位置及以后的位置上的元素明显不可能满足差值大于z的条件)。

代码:

#include <iostream>
#include <algorithm>
#define max_n 200005
using namespace std;
int n;
int z;
int a[max_n];
int ans = 0;
int main()
{
    cin >> n >> z;
    for(int i = 0;i<n;i++)
    {
        cin >> a[i];
    }
    sort(a,a+n);
    int mid=n/2;
    int l = mid-1;
    for(int i = n-1;i>=mid;i--)
    {
        while(l>=0)
        {
            if(abs(a[l]-a[i])>=z)
            {
                ans++;
                l--;
                break;
            }
            l--;

        }
    }
    cout << ans << endl;
    return 0;
}

后记:

学习模板固然有一定的作用,可是如果在学习过程中产生了依赖,什么都想套用模板而不去思考,后果是什么?什么题都想先百度题解,不认真思考的后果是什么?orz

我虽然菜,而且菜啊

posted @ 2019-08-10 20:35  小张人  阅读(349)  评论(0编辑  收藏  举报
分享到: