BerSU Ball(贪心)

111 阅读2分钟

Problem - 489B - Codeforces

原题题面

image.png

题目描述

给定两个数组 a,ba,b,现在从 aa 数组中取出一个元素 xx,从 bb 数组中取出一个元素 yy,若 xxyy 的差值小于等于 11,则这两个数可以凑成一对。

现在要求输出这两个数组可以挑出的最大的元素对数。

输入格式为:

首先输入 nn ,代表 aa 数组的元素总数,然后下一行为 nnaa 数组中的元素。

然后输入 mm ,代表 bb 数组的元素总数,然后下一行为 mmbb 数组中的元素。

输出格式为一个数,代表两个数组最大的匹配对数。

题目分析

这是一道简单的贪心题。

首先我们先将两个数组从小到大进行排序,然后用两个指针分别指向两个数组的第一个元素。

然后我们比较当前两个指针所指向的元素的大小,选择较小的指针指向的元素与另一个元素的大小进行比较,若这个元素与较大元素的差值小于等于 11,则其对最终答案的贡献加一,否则答案无变动。然后无论比较的结果如何,将较小的指针向后移动一位,并进行下一次比较。循环往复直至某个指针越界。

由于我们一开始便将数组元素排序,且每个元素对答案最多产生一的贡献,所以不存在对答案的少算和漏算现象。

最终时间复杂度为 O(n+m)O(n+m)

Accept代码

#include <bits/stdc++.h>

using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n; cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i ++) cin >> a[i];
    int m; cin >> m;
    vector<int> b(m);
    for (int i = 0; i < m; i ++) cin >> b[i];
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    int ans = 0;
    for (int i = 0, j = 0; i < n && j < m; )
    {
        if (a[i] > b[j])
        {
            if (a[i] - b[j] <= 1) ans ++, i ++;
            j ++;
        }
        else
        {
            if (b[j] - a[i] <= 1) ans ++, j ++;
            i ++;
        }
    }
    cout << ans;
    return 0;
}