ZYB的畫圖計劃

題目

題目描述
在20202020年22月1414日這一天,ZYBZYB終於找到了自己的妹子,可喜可賀可喜可賀。

找到妹子之後,ZYBZYB想做的第一件事情是給他的妹子畫一幅世界名畫。這副畫的長爲NN,寬爲11(清明上河圖?),ZYBZYB打算用MM種顏色來畫這幅畫,爲了方便,他將這副畫抽象成了NN個1×11×1的格子,每一個格子需要被塗成顏色cici.ZYBZYB有一支畫筆,可以隨時變換成任何顏色,但是這支畫筆在變換出一種顏色之後,之後就再也不能變換出這種顏色了(也就是說,每種顏色只能用一次)。每一次,ZYBZYB可以選擇連續的一段格子並將這段格子的顏色都塗成畫筆上的顏色,如果之前有顏色則會覆蓋之前的顏色。一開始所有的格子都是無色的。每塗一個格子就需要花費1單位的時間。

爲了彰顯出自己的努力,ZYBZYB希望能夠使得自己完成作品的時間儘量長。同時他可以自由調整選擇顏色的順序。你能幫幫他求出這個最長時間嗎?

輸入格式
一行兩個整數n,mn,m.

第二行NN個正整數cici,描述這張圖的顏色序列。

輸出格式
一行輸出最大值。

樣例1
輸入

5 2
1 1 2 2 3
輸出

11
解釋

有66種不同的顏色序列:

1 2 3:1先塗(1,5),2塗(3,5),3塗(5,5) 花費9單位時間。當然,1塗(1,2),2塗(3,4),3塗(5,5)也是合法解,但花費時間很少。

1 3 2:1先塗(1,5),3塗(3,5),2塗(3,4) 花費10單位時間

2 1 3:2先塗(1,5),1只能塗(1,2),3只能塗(5,5) 花費8單位時間

2 3 1:2先塗(1,5),3塗(5,5),1塗(1,2)花費8單位時間

3 1 2:3先塗(1,5),1塗(1,4),2塗(3,4)花費11單位時間

3 2 1:3先塗(1,5),2塗(1,4),1塗(1,2)花費11單位時間

樣例2
輸入

5 2
1 2 3 2 1
輸出

9
數據範圍
對於20%20%的數據,M≤8M≤8
對於40%40%的數據,M≤100M≤100
在所有數據中均勻分佈着50%50%的數據,cici是不降的

對於100%100%的數據,N≤100000,M≤5000,1≤ci≤MN≤100000,M≤5000,1≤ci≤M.數據保證所有顏色至少出現一次,同時存在一種合法畫法能夠畫出這張圖。

思路

暴力:
暴力枚舉顏色的先後順序,對於每種顏色,他能夠塗的範圍 是自己的從最左到最右,而如果中間有一個格子被之前的顏 色塗過且正好顏色相同,則這種方法無解。而其真正可以塗 的一段是包含自己的沒有被固定顏色的最長連續段,判斷一 下即可。時間複雜度O(M! * N)

正解:
若每種段只出現一次,可以注意到我們每塗完一種顏色,就 將整個序列分爲兩段,所以,我們不妨令fi,j表示塗完第i種 顏色到第j種顏色,最多可以塗多少。那麼我們 有dpl,r = maxl≤k≤rdpl,k 1 + dpk+1,r + costi,j,注意到該式 雖然與四邊形不等式稍有區別,但通過一樣的不等式分析仍 然可以得到dpi,j + dpi+1,j+1 ≥ dpi,j+1 + dpi + 1, j,故上式可 以直接用四邊形不等式優化。

代碼

#include<bits/stdc++.h>
#define N 100077
#define M 5077
#define pb push_back
using namespace std;
int A[N],m,n,p,k,aii[N],bz[N],st[N],ed[N],cnt,f[M][M],g[M][M],S[M],yjy; 
vector<int>v[N];
int solve(int x)
{
	if(!v[x].size()) return 0;
	int tp=v[x].size(),i,j;
	for(int i=1; i<=tp; i++) S[i]=v[x][i-1]; 
	for(int i=1; i<=tp; i++) S[i]+=S[i-1]; 
	for(int i=1; i<=tp; i++)
		for(int j=i; j<=tp; j++)
			f[i][j]=0;
	for(int i=1; i<=tp; i++) f[i][i]=S[i]-S[i-1],g[i][i]=i; 
	for(int l=2; l<=tp; l++)
		for(int i=1; i+l-1<=tp; i++)
		{
			int j=i+l-1; 
			for(int k=g[i][j-1]; k<=g[i][j]; ++k)
				if(f[i][k-1]+f[k+1][j]>=f[i][j])
					f[i][j]=f[i][k-1]+f[k+1][j],g[i][j]=k; 
			f[i][j]=max(f[i][j],f[i][j-1]);  f[i][j]=max(f[i][j],f[i+1][j]); 
			f[i][j]+=S[j]-S[i-1]; 
		}
	return f[1][tp]; 
}
int main()
{
	scanf("%d%d",&n,&m); 
	for(int i=1; i<=n; i++)
	{
		scanf("%d",&A[i]); 
		if(!bz[A[i]]) aii[++aii[0]]=A[i],bz[A[i]]=1,st[A[i]]=i,ed[A[i]]=i; 
		else 
		{
			++cnt; 
			ed[A[i]]=i; 
			while(aii[aii[0]]!=A[i]) 
			{
				int col=aii[aii[0]]; 
				v[cnt].pb(ed[col]-st[col]+1); 
				--aii[0]; 
			}
		}
	}
	++cnt;  
	while(aii[0])
	{
		int col=aii[aii[0]]; 
		v[cnt].pb(ed[col]-st[col]+1); 
		--aii[0]; 
	}
	for(int i=1; i<=cnt; i++) yjy+=solve(i); 
	printf("%d\n",yjy); 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章