• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
对局匹配 线性DP-分块

对局匹配 线性DP-分块

题目链接

对局匹配

思路

​ 当\(num = 0\)时, 答案为不重复的数字数量之和。

​ 当\(num > 0\)时, 我们以模数不同将该序列划分成不同的块,即构造\(x + tk, (t = 0, 1, 2, \dots), x \in [0, k)\), 以\(x\)来划分不同的块,这样不同的块一定能够保证他们之间不会差\(k\), 因为相差等于\(k\)一定同余, 所以我们只考虑组内相差等于\(k\), 这时就可以当成线性\(dp\)来做了, 对于组内我们用下列式子:

\[dp[j] = std::max(dp[j - 1], dp[j - 2] + count[j]) \]

​ 复杂度\(O(n)\)

Code

#include <bits/stdc++.h>

using i64 = long long;

const int N = 1e5 + 10;

int n, k;

int a[N], count[N], dp[N], val[N];

int main() {
	std::cin >> n >> k;

	for (int i = 1; i <= n; i ++) std::cin >> a[i], count[a[i]] ++;

	int ans = 0;

	if (!k) {
		for (int i = 1; i <= 1e5; i ++) {
			ans += (count[i] >= 1);
		}
	} else {
		for (int i = 0; i < k; i ++) {
			memset(dp, 0, sizeof dp);
			int cnt = 1;

			for (int j = i; j <= 1e5; j += k) {
				val[++ cnt] = count[j];
			}

			for (int j = 2; j <= cnt; j ++) {
				dp[j] = std::max(dp[j - 1], dp[j - 2] + val[j]);
			}

			ans += dp[cnt];
		}

	}

	std::cout << ans;
}
posted on 2023-06-07 16:02  Jack404  阅读(22)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3