CF1178F Long Colorful Strip


F1

首先\(n\)这个小看上去就是区间dp
我们设\(dp_{i,j}\)表示染色区间\([i,j]\)的方案数。
然后因为是从小往大染,所以这个区间内第一步染色的肯定是最小的颜色,记为\(Mi\)
然后找到这个数的位置两边分别转移一下最后乘起来就好了,时间复杂度\(O(n^3)\)

F2

一开始想了个巨大多麻烦的做法然后不想写萎掉了。
然后瞄了一眼题解才发现我是sb
首先我们将同色的缩成一段,因为染色不可能从中间开始染色。
然后我们发现一次染色最多只能增加2个不同色段,所以如果最后的色段超过\(2n\)个直接无解。
然后就剩下\(O(n)\)级别的颜色了,直接像F1一样dp就好了。
code:

#include
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 1000
#define K 1000000
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*x+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
int n,m,B[N+5],x,Bh,Mi,L,R;ll dp[N+5][N+5],T1,T2;vector S[N+5];
int main(){
	freopen("1.in","r",stdin);
	RI i,j,h;scanf("%d%d",&n,&m);for(i=1;i<=m;i++) {scanf("%d",&x);if(!Bh||B[Bh]^x) B[++Bh]=x;if(Bh>2*m){Pc('0');return 0;}}
	for(i=1;i<=Bh;i++) S[B[i]].push_back(i);for(i=1;i<=Bh+1;i++) dp[i][i-1]=1;
	for(i=Bh;i;i--){
		for(j=i;j<=Bh;j++){
			Mi=1e9;for(h=i;h<=j;h++) Mi=min(Mi,B[h]);L=S[Mi][0];R=S[Mi][S[Mi].size()-1];if(Lj) continue;
			dp[i][j]=1;for(h=1;h