题解:AT_abc403_d [ABC403D] Forbidden Difference
大概题意:
将一个整数序列删除至对于每个数都没有比它大
正式开始:
阅读完题我们可以发现:对于每个数,决定它是否被删除取决于比它大
对于一个数又要考虑比它大 v[1000005]
存储每个值在序列里出现的次数,为了优化,我们可以用
dp 转移方程也可以列出来了:
但是对于这道题有很坑的点:
最后要注意统计答案时要注意
//Just Sayori
#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
#define rnt register int
#define gr getchar
#define pr putchar
#define N 1000005
#define M 1000000007
using namespace std;
inline ll read()
{
ll x = 0, f = 1;
char ch = gr();
while (ch < '0' || ch > '9') ch == '-' ? f = -1, ch = gr() : ch = gr();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = gr();
return x * f;
}
inline void write(ll x, bool k)
{
static int sta[39], top = 0;
if (x < 0) pr('-'), x = -x;
do sta[++top] = x % 10, x /= 10;
while (x);
while (top) pr(sta[top--] + 48);
k ? pr(32) : pr(10);
}
ll a[N], v[N];
ll dp[N][2];//删前,删自
int main()
{
ll n = read(), d = read(), mx = 0, mn = M;
ll ans = 0;
for (rnt i = 1; i <= n; i++) a[i] = read(), v[a[i]]++, mx = max(mx, a[i]), mn = min(mn, a[i]);
if (!d)
{
for (rnt i = mn; i <= mx; i++) ans += v[i] ? v[i] - 1 : 0;
write(ans, 0);
}
else
{
for (rnt i = mn; i < mn + d; i++)
dp[i][1] = v[i];
for (rnt i = mn + d; i <= mx; i++)
{
dp[i][0] = min(dp[i - d][0] + v[i - d], dp[i - d][1]);
dp[i][1] = min(dp[i - d][0] + v[i], dp[i - d][1] + v[i]);
}
for (rnt i = mx; i >= max(0ll, mx - d + 1); i--)//这里要判断,防止越界
ans += min(dp[i][0], dp[i][1]);
write(ans, 0);
}
return 0;
}