[LuoguP3668][USACO17OPEN]現代藝術2
阿新 • • 發佈:2019-01-04
[LuoguP3668][USACO17OPEN]Modern Art2(Link)
現在你有一塊長為\(N\)的畫布,每次可以選擇一段連續的區間進行顏色填塗,新顏色會覆蓋舊顏色。每一次填塗都要耗費一天時間。在所有的填塗中每一種顏色只能用1次。求將畫布變為目標序列的最小天數。如果不能完成填塗那麼輸出\(-1\)。
首先我們要知道填塗的方式以及什麼叫做填塗不合法。
上面的這個方案明顯是合法的,我們先塗上“底色”\(Green\)然後再塗\(Red\)就好。
上面的這個情況,你發現無論怎麼塗都是不合法。那麼我們找到了一個顯然的規律:有交叉的顏色就不合法。
於是問題變得簡單了,我們用一個棧直接記錄一下花費時間就可以了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; const int MAXN = 100010 ; const int MAXM = 100010 ; int N, Line[MAXN], S[MAXN], S1[MAXN], Top, S2[MAXN], Sum ; inline int Read() { int X = 0, F = 1 ; char ch = getchar() ; while (ch > '9' || ch < '0') F = (ch == '-' ? - 1 : 1), ch = getchar() ; while (ch >= '0' && ch <= '9') X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ; return X * F ; } int main() { N = Read() ; for (int i = 1 ; i <= N ; i ++) { Line[i] = Read() ; S2[Line[i]] = i ; if (! S1[Line[i]]) S1[Line[i]] = i ; } S2[Line[N + 1]] = N + 1 ; for (int i = 0 ; i <= N + 1 ; i ++) { if (i == S1[Line[i]]) S[++ Top] = Line[i], Sum = max(Top, Sum) ; if (Line[i] != S[Top]) { printf("-1") ; return 0 ; } if (i == S2[Line[i]]) Top -- ; } printf("%d", Sum) ; }