前言
也许是不够专注,这种方法都没想到。
题目
题目大意:见洛谷。
讲解
我们需要意识到这样一个事情:最小化移动次数相当于最大化不移动的书的数量。
这样就简单许多了。
我们定义每种书的区间为该种书最左边的书的位置到最右边的位置。
那么我们可以选择一些不相交的书,让它们不移动。而这个过程可以倒着 dp 实现。
具体转移参考代码,很容易理解。
代码
它真的很短。
//12252024832524
#include <cstdio>
#include <cstring>
#include <algorithm>
#define TT template<typename T>
using namespace std;
typedef long long LL;
const int MAXN = 500005;
int n;
int a[MAXN],l[MAXN],r[MAXN],dp[MAXN],cnt[MAXN];
LL Read()
{
LL x = 0,f = 1;char c = getchar();
while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
return x * f;
}
TT void Put1(T x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = Read();
for(int i = 1;i <= n;++ i)
{
a[i] = Read();
if(!l[a[i]]) l[a[i]] = i;
r[a[i]] = i;
}
for(int i = n;i >= 1;-- i)
{
dp[i] = dp[i+1];
cnt[a[i]]++;
if(i == l[a[i]]) dp[i] = Max(dp[i],dp[r[a[i]]+1]+cnt[a[i]]);
else dp[i] = Max(dp[i],cnt[a[i]]);
}
Put(n-dp[1]);
return 0;
}
后记
总感觉讲得不是很清楚。