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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章