洛谷 P3668 [USACO17OPEN]Modern Art 2 現代藝術2 棧

solution:棧

本篇題解是受到大佬qiianr的啓發,如果侵權,請聯繫刪除

  1. 爲了保證最優解,我們必須要先塗最外層,舉個例子:AAABCBBBA,(A,B,C分別代表一種顏色)我們先把這些都塗上A,然後中間都塗上B,最後再在最上面那一個塗上C,這就是最優解的情況

  2. 對於每個顏色,我們記錄這個顏色的開始位置和結束位置,我們可以很清楚的看到越到最外層塗的顏色,開始位置越晚,結束位置越早,所以我們可以用一個棧來維護當前棧頂的顏色

  3. 並且我們塗的區間不能重疊,舉個例子,A和B分別代表一種顏色:AABBAAB,根據上面所推得,我們應該找最外層的顏色,但是因爲A和B重疊,所以這種情況是不合法的

  4. 枚舉畫條上的每一個點,對於一個顏色如果這個顏色的開始位置等於現在枚舉的位置,那麼我們就把這個顏色壓入棧,如果當前顏色和棧頂顏色不同,那麼我們直接輸出無解即可

  5. 如何尋找答案,因爲我們都把顏色放進棧中,所以我們只需要比較答案和棧內的元素個數,最後取最大值即可

  6. 如果當前枚舉的點等於這個元素的結束位置,那麼我們直接彈出棧頂即可

  7. 後一點,也沒什麼可說的,加一些優化,手打max,加個位運算快讀,隨手加個register,開O2 38ms,不開47ms,處於最優解第一頁

AC代碼

#include<cstdio>
#define si 100005
#define re register int
using namespace std;
int n,ans,tp,a[si],st[si],ed[si],sta[si];
inline int read() {
	int x=0,cf=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-') cf=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=(x<<3)+(x<<1)+(ch^48);
		ch=getchar();
	}
	return x*cf;
}
inline int max(int A,int B) { return A>B?A:B; }
int main() {
	n=read();
	for(re i=1;i<=n;i++) {
		a[i]=read();
		if(!st[a[i]]) st[a[i]]=i;//如果這個元素還沒有開始位置,記錄開始位置
		ed[a[i]]=i;//隨時記錄結束位置
	}
	ed[0]=n+1,a[n+1]=0;
	for(re i=0;i<=n+1;i++) {
		int x=a[i];
		if(i==st[x]) {//當前枚舉等於開始位置,推入棧
			sta[++tp]=x;
			ans=max(ans,tp);//取最大值
		}
		if(x!=sta[tp]) {//當前元素和棧頂元素顏色不同,輸出無解
			printf("-1");
			return 0;
		}
		if(i==ed[x]) tp--;//等於結束位置,彈出
	}
	printf("%d",ans-1);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章