#线性dp#CF1110D Jongmah

题目


分析

考虑三个 \((i,i+1,i+2)\) 可以用 \((i,i,i)\)\((i+1,i+1,i+1)\)\((i+2,i+2,i+2)\) 代替,

所以这样的三元组本质上最多出现两次,设 \(dp[n][i][j]\) 表示

\(n\) 个其中 \(i\) 个作为 \((n-1,n,n+1)\)\(j\) 个作为 \((n,n+1,n+2)\) 的最多三元组个数,

那么 \(dp[n][i][j]=\sum_{k=0}^2 dp[n-1][j][k]+i+\lfloor\frac{a_n-i-j-k}{3}\rfloor\)

最后答案为 \(dp[n][0][0]\)


代码

#include <cstdio>
#include <cstring>
#include <cctype>
#define rr register
using namespace std;
const int N=1000011;
int n,m,a[N],dp[3][3],f[3][3];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline signed max(int a,int b){return a>b?a:b;}
signed main(){
	n=iut(); m=iut();
	for (rr int i=1;i<=n;++i) ++a[iut()];
	for (rr int P=1;P<=m;++P){
		memset(f,0,sizeof(f));
		for (rr int j=0;j<3;++j)
		for (rr int i=0;i<3;++i)
		for (rr int k=0;k<3;++k)
		if (a[P]>=k+j+i)
		    f[j][i]=max(f[j][i],dp[k][j]+i+(a[P]-k-j-i)/3);
		memcpy(dp,f,sizeof(dp));
	}
	return !printf("%d",dp[0][0]);
}
posted @ 2021-09-27 16:34  lemondinosaur  阅读(23)  评论(0编辑  收藏  举报