[CF1481E] Sorting Books

前言

也许是不够专注,这种方法都没想到。

题目

CF

洛谷

题目大意:见洛谷

讲解

我们需要意识到这样一个事情:最小化移动次数相当于最大化不移动的书的数量。

这样就简单许多了。

我们定义每种书的区间为该种书最左边的书的位置到最右边的位置。

那么我们可以选择一些不相交的书,让它们不移动。而这个过程可以倒着 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;
}

后记

总感觉讲得不是很清楚。

原文地址:https://www.cnblogs.com/PPLPPL/p/14924673.html