T604061 禁止的差值

这道题目要求我们从一个整数序列中删除最少数量的元素,使得剩下的序列中任意两个元素的差值都不等于给定的D值。我们可以采用以下策略:

  1. 统计频率:首先统计每个数字在序列中出现的次数。

  2. 处理特殊情况:当D=0时,需要确保每个数字最多只出现一次。

  3. 双指针扫描:对于D≠0的情况,使用双指针(l和r=l+D)扫描整个数值范围,处理所有可能产生差值D的数字对。

  4. 贪心删除:对于每对可能产生差值D的数字,删除出现次数较少的一方,这样可以最小化删除数量。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;  // 定义足够大的数组大小,覆盖所有可能的数值范围
int vis[N];              // 用于统计每个数字出现的次数
int n,d,x;               // n-序列长度,d-禁止的差值,x-临时变量

int main()
{
    // 输入处理
    cin >> n >> d;  // 读取序列长度n和禁止的差值d
    
    // 统计每个数字出现的次数
    for(int i = 1; i <= n; i++){
        cin >> x;        // 读取序列中的数字
        vis[x]++;       // 统计该数字出现的次数
    }
    
    int ans = 0;  // 记录需要删除的元素数量
    
    // 处理所有可能的数字对(l,r),其中r = l + d
    for(int l = 0, r = d; r <= 1e6; l++, r++) {
        // 特殊情况:当d=0时,需要确保每个数字最多出现1次
        if(d == 0){
            if(vis[l] >= 2){  // 如果数字l出现超过1次
                ans += vis[l] - 1;  // 需要删除多余的次数
                vis[l] = 1;         // 保留1个
            }
            continue;  // 跳过后续处理
        }
        
        // 一般情况:处理数字对(l,r)
        if(vis[l] && vis[r]){  // 如果两个数字都存在
            int k = min(vis[l], vis[r]);  // 取两个数字出现次数的较小值
            ans += k;           // 需要删除k个数字对
            vis[l] -= k;        // 更新剩余数字l的数量
            vis[r] -= k;        // 更新剩余数字r的数量
        }
    }
    
    // 输出结果
    cout << ans;
    return 0;
}

 

posted @ 2025-04-28 18:27  CRt0729  阅读(10)  评论(0)    收藏  举报