T604061 禁止的差值
这道题目要求我们从一个整数序列中删除最少数量的元素,使得剩下的序列中任意两个元素的差值都不等于给定的D值。我们可以采用以下策略:
- 
统计频率:首先统计每个数字在序列中出现的次数。 
- 
处理特殊情况:当D=0时,需要确保每个数字最多只出现一次。 
- 
双指针扫描:对于D≠0的情况,使用双指针(l和r=l+D)扫描整个数值范围,处理所有可能产生差值D的数字对。 
- 
贪心删除:对于每对可能产生差值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; }
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号