CF1257E The Contest

洛谷题目链接

题目分析

只要保证\(a_1\)\(a_3\)满足条件即可,所以我们几乎可以忽略\(a_2\).

为了方便下面讲解,简化一下题面.

将每个元素想象成一棵棵带有编号的树,要通过一系列的操作,

将树种在上方(\(a_1\)处),或种在下方(\(a_3\)处),或因生长发育不合格而被扔掉(\(a_2\)处),然后求最少次数使满足题目要求.

(读者看到此处可根据简化题面再独立思考一下如何解题)

思路解析

最优答案一类的问题,想到DP.

\(F_{i,0/1/2}\)表示所有树里到第i课时扔掉/种在上方/种在下方    的最少操作次数,接下来要分情况讨论(第i棵树的原始状态):

1.在上方

\(F_{i,0}=min(F_{i-1,1},F_{i-1,0})+ 1\)  如果这棵树被扔掉,那前面一棵一定不是种在下面

\(F_{i,1}=F_{i-1,1}\)  这棵树不动,对答案没贡献

\(F_{i,2}=min\) { \(F_{i-1,2},F_{i-1}{1},F_{i-1,0}\)} \(+1\)  如果这棵树被种在下面,则前面树的状态无所谓

2.在下方

\(F_{i,0}=min(F_{i-1,1},F_{i-1,0})+ 1\)

\(F_{i,1}=F_{i-1,1} + 1\)

\(F_{i,2}=min\) { \(F_{i-1,2},F_{i-1}{1},F_{i-1,0}\)}

理解同第一种情况,但要注意是否+1的问题

3.在\(a_2\)垃圾箱

方程思路与1,2种情况相同,请读者自行推理

4.端点

第一棵树比较特殊,无法从第0棵树转移过来,需要初始化处理一下.

另外说一下时间复杂度,状态转移方程的复杂度是\(O(n)\)但是所有的树需要按照编号从小到大排序,所以时间复杂度为\(O(nlogn)\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int n,m,t,a[200001],b[200001],c[200001],f[200001][3],d[200001],mx,oo;

inline int pd(int x,int y) {
	if(b[x] >= c[y]) return y;
	return x;
}

inline bool cmp(int x,int y) {
	return x < y;
}

int main() {
	scanf("%d%d%d",&n,&m,&t);
	for(int i = 1;i <= n; i++) {
		int u;
		scanf("%d",&u);
		d[++mx] = u;
		a[u] = 1;
		++oo;
	}
	for(int i = 1;i <= m; i++) {//因为a2可以被忽略,所以不做任何处理 
		int x;
		scanf("%d",&x);
	}
	for(int j = 1;j <= t; j++)  {
		int x;
		scanf("%d",&x);
		d[++mx] = x;
		a[x] = 2;
	}
	n = n + m + t;
	sort(d+1,d+mx+1,cmp);
	if(a[1] == 1) f[1][0] = f[1][2] = 1;
	if(a[1] == 0) f[1][1] = f[1][2] = 1;
	if(a[1] == 2) f[1][1] = f[1][0] = 1;
	for(int i = 2;i <= n; i++) {
		if(a[i] == 0) {
			f[i][0] = min(f[i-1][1],f[i-1][0]);
			f[i][1] = f[i-1][1] + 1;
			f[i][2] = min(f[i-1][2],min(f[i-1][0],f[i-1][1])) + 1;
		}
		if(a[i] == 2) {
			f[i][0] = min(f[i-1][1],f[i-1][0]) + 1;
			f[i][1] = f[i-1][1] + 1;
			f[i][2] = min(f[i-1][2],min(f[i-1][1],f[i-1][0]));
		}
		if(a[i] == 1) {
			f[i][0] = min(f[i-1][1],f[i-1][0]) + 1;
			f[i][1] = f[i-1][1];
			f[i][2] = min(f[i-1][2],min(f[i-1][1],f[i-1][0])) + 1;
		}
	}
	printf("%d",min(f[n][1],min(f[n][0],f[n][2])));
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章