专栏文章

题解:AT_abc403_d [ABC403D] Forbidden Difference

AT_abc403_d题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miph531h
此快照首次捕获于
2025/12/03 11:55
3 个月前
此快照最后确认于
2025/12/03 11:55
3 个月前
查看原文
先排序。
考虑到只有差为 dd 的两个数会被影响到,所以我们可以分别对模 dd 同余的这 dd 个集合分别统计答案。
题目要求删去最少的数,我们可以求保留最多的数,再去用 nn 去减,这个东西可以用线性 dp 求解。
我们用 dpi,0/1dp_{i,0/1} 表示这个位置删不删,则有以下 dp 式子: dpi,0=max(dpi1,0,dpi1,1)dp_{i,0}=\max(dp_{i-1,0},dp_{i-1,1}) dpi,1=max(dpi1,0+sumi,dpi1,1)dp_{i,1}=\max(dp_{i-1,0}+sum_i,dp_{i-1,1})
其中 sumisum_i 表示 aia_i 的数量。
注意特判 d=0d=0 的情况。
以下是赛时代码。
CPP
#include<bits/stdc++.h>

using namespace std;

int n,d;
int a[1000010];
int ans[2];
int sum;
int b[1000010];
int aaa;
int f[1000010][2];

vector<int>v[1000010];

signed main(){
	cin>>n>>d;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[a[i]]++;
	}
	sort(a+1,a+1+n);
	for(int i=0;i<=1000000;i++){
		if(b[i]) aaa+=b[i]-1;
	}
	if(d==0){
		cout<<aaa;
		//assert(d!=0);
		return 0;
	}
	n=unique(a+1,a+1+n)-a-1;
	//printf("aa %d\n",n);
	for(int i=1;i<=n;i++){
		v[a[i]%d].push_back(a[i]);
	}
	for(int x=0;x<d;x++){
		if(v[x].size()==0) continue;
		f[0][0]=0;
		f[0][1]=b[v[x][0]];
		int qsu=b[v[x][0]];
		for(int i=1;i<v[x].size();i++){
			if(v[x][i]-v[x][i-1]==d){
				f[i][0]=max(f[i-1][0],f[i-1][1]);
				if(i>=2) f[i][1]=max(f[i-1][0],f[i-2][1])+b[v[x][i]];
				else f[i][1]=f[i-1][0]+b[v[x][i]];
			}
			else{
				f[i][0]=max(f[i-1][0],f[i-1][1]);
				f[i][1]=f[i][0]+b[v[x][i]];
			}
			qsu+=b[v[x][i]];
		}
		int bbb=max(f[v[x].size()-1][1],f[v[x].size()-1][0]);
		sum+=qsu-bbb;
		//printf("qwqwqwq %d %d\n",qsu,bbb);
	}
	cout<<sum;
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...