首页 > 其他 > 详细

CF1481E Sorting Books

时间:2021-02-07 00:05:43      阅读:42      评论:0      收藏:0      [点我收藏+]

E. Sorting Books

这个官方题解只讲了转移方程,根本没讲原理,这里全部重新做个解释。

我们先考虑答案的范围。如果我们贪心,那么最多操作次数为 \(n\) 次,且一本书最多会被移动一次。

定状态

我们令 \(l_i,r_i\) 分别为第 \(i\) 种颜色从左往右数最早出现/最晚出现的位置。令 \(f_i\) 为在最后将所有书归好类后,\([i,n]\) 内最多有多少本书无需移动。明显,我们需要倒序枚举。最后的答案为 \(n-f_1\)

我们记 \(tot_{i,j}\) 为在 \([j,n]\) 中,颜色为 \(i\) 的书本有多少本。

列状态转移方程

\[f_i=\max\begin{cases} f_{i+1}&1\leq i<n\tot_{a_i,i}&i\neq l_{a_i}\tot_{a_i,i}+f_{r_{a_i}+1}&i=l_{a_i} \end{cases}\]

  • 首先我们考虑的是 \(i\) 这本书要移动,那么此时最多可以保留不动的就是 \(f_{i+1}\) 本。
  • 如果 \(i\) 这本书不移动,那么显然颜色为 \(a_i\) 的书都不要动,即 \(tot_{a_i,i}\) 本。那为什么在 \(i\neq l_{a_i}\),不加上 \(f_{r_{a_i}+1}\) 呢?我们可以重点关注一下样例:
5
1 2 2 1 3

若加上了,我们得到的 \(f\) 数组为 \(4,4,3,2,1\)(下标从 \(1\) 开始)。明显是错误的,应该为 \(3\)。为什么会错呢?我们来具体分析发生了甚么。

从本质出发,为什么可以保持颜色为 \(a_i\) 的书不移动,就是因为把 \([i,r_{a_i}]\) 中颜色不为 \(a_i\) 的全部移走。如果过早地进行了与有区间的合并,可能就会有两个区间有部分重叠。只有等所有颜色为 \(a_i\) 的数都出现过了,才可以进行区间的合并。

那上面那个样例说事,我们来理清关系:

  • \(f_1=f_2\)
  • \(f_2=f_4+1\)
  • \(f_4=f_5+1\)

好,到这里,就出现了问题。我们已经将 \([4,4],[5,5]\) 合并为了 \([4,5]\)。而在 \([2,3]\) 出现后,我们又进行了合并,有区间 \([2,5]\)。说明我们不可能将 \(2\) 移走了。我饿么您此时为了做出最优决策,只能将第一个 \(1\) 移走。明显是错误的。因为在 \([1,4]\) 区间可以被计算时,\([4,4]\) 已经“名花有主”了。

边界&初值

无。好干脆啊。

//Don‘t act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you‘ll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
#define int long long
using namespace std;

int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch<‘0‘||ch>‘9‘) {
		if(ch==‘-‘)
			f=-1;
		ch=getchar();
	}
	while(ch>=‘0‘&&ch<=‘9‘) {
		x=x*10+ch-‘0‘;
		ch=getchar();
	}
	return f*x;
}

const int MAXN=5e5+10; 

int n;
int a[MAXN],l[MAXN],r[MAXN],f[MAXN],tot[MAXN];

signed main() {
	cin>>n;
	for(int i=1;i<=n;i++) {
		a[i]=read();
		if(!l[a[i]]) {
			l[a[i]]=i;
		}
	}
	for(int i=n;i;i--) {
		if(!r[a[i]]) {
			r[a[i]]=i;
		}
	}
	
	for(int i=n;i;i--) {
		tot[a[i]]++;
		if(i==l[a[i]]) {
			f[i]=max(tot[a[i]]+f[r[a[i]]+1],f[i+1]);
		}
		else {
			f[i]=max(f[i+1],tot[a[i]]);//正确
		//	f[i]=max(tot[a[i]]+f[r[a[i]]+1],f[i+1];//错误
		}
	}
	
	cout<<n-f[1]<<endl;
	return 0;
}

CF1481E Sorting Books

原文:https://www.cnblogs.com/huayucaiji/p/CF1481E.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!