1. 程式人生 > >hdu 5009 dp + 優化

hdu 5009 dp + 優化

Paint Pearls Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 3620 Accepted Submission(s): 1196

Problem Description Lee has a string of n pearls. In the beginning, all the pearls have no color. He plans to color the pearls to make it more fascinating. He drew his ideal pattern of the string on a paper and asks for your help.

In each operation, he selects some continuous pearls and all these pearls will be painted to their target colors. When he paints a string which has k different target colors, Lee will cost k2 points.

Now, Lee wants to cost as few as possible to get his ideal string. You should tell him the minimal cost.

Input There are multiple test cases. Please process till EOF.

For each test case, the first line contains an integer n(1 ≤ n ≤ 5×104), indicating the number of pearls. The second line contains a1,a2,…,an (1 ≤ ai ≤ 109) indicating the target color of each pearl.

Output For each test case, output the minimal cost in a line.

Sample Input

3 1 3 3 10 3 4 2 4 4 2 4 3 2 2

Sample Output

2 7

Source 2014 ACM/ICPC Asia Regional Xi’an Online

考慮dp[ i ] 表示前 i 個花費的最小值,自然轉移方程: dp[ i ] = Min { dp[ j ] + cnt( j+1, i ) }; 很顯然,這是n^2 的轉移; 所以應考慮降低複雜度; 可以發現: 當有重複的時候,我們可以跳過,比如樣例2,因為cost 僅是不同的顏色數量,所以我們應當去重; ---------> 連結串列優化; 改變相應的前驅和後繼可以實現刪除操作;

但是極端資料還是會T; 設法將一個變為 sqrt or log ; 明顯,最大的 Maxcost =n ; 所以不能連續 sqrt(n) 不同的顏色塗在一起; 那麼此時複雜度就降了;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
#include<cctype>
//#pragma GCC optimize("O3")
using namespace std;
#define maxn 200005
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const int mod = 1e9 + 7;
#define Mod 20100403
#define sq(x) (x)*(x)
#define eps 1e-10
const int N = 1505;

inline int rd() {
	int x = 0;
	char c = getchar();
	bool f = false;
	while (!isdigit(c)) {
		if (c == '-') f = true;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return f ? -x : x;
}

ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
ll sqr(ll x) { return x * x; }

int dp[maxn];
int n;
int a[maxn];
int pre[maxn], nxt[maxn];
map<int, int>Map;

int main()
{
	//ios::sync_with_stdio(false);
	while (rdint(n) != EOF) {
		int i, j; 
		Map.clear();
		for ( i = 1; i <= n; i++) {
			rdint(a[i]);
			pre[i] = i - 1; nxt[i] = i + 1;
		}
		for (i = 0; i <= n+2; i++)dp[i] = INF;
		dp[0] = 0;
		pre[0] = -1;
		for ( i = 1; i <= n; i++) {
			if (Map.count(a[i]) == 0)Map[a[i]] = i;
			else {
				int pos = Map[a[i]];
				nxt[pre[pos]] = nxt[pos]; pre[nxt[pos]] = pre[pos];
				Map[a[i]] = i;
				// 連結串列去重
			}
			int tot = 0;
			for (int j = pre[i]; j != -1; j = pre[j]) {
				tot++;
				dp[i] = min(dp[i], dp[j] + tot * tot);
				if (tot*tot >= i)break;
			}
		}
		cout << dp[n] << endl;
	}
	return 0;
}