Description
有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000。现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k。那总的不河蟹度就是所有段的不河蟹度的总和。
Input
第一行:两个整数N,M
第2..N+1行:N个整数代表每个奶牛的编号
Output
一个整数,代表最小不河蟹度
Sample Input
13 4
1
2
1
3
2
2
3
4
3
4
3
1
4
1
2
1
3
2
2
3
4
3
4
3
1
4
Sample Output
11
首先有一个很显然的想法,就是任意一段区间的颜色个数不超过$sqrt(len)$个,否则不如$1$个$1$个直接拼
然后我们只要找如果用$k$种颜色,能从$i$点最远走到哪
很显然二分+主席树就可以解决了
我们设$f[i][j]$表示从$i$往只用$j$种颜色最多往前走到哪
然后讨论一下$C_i$上次出现的位置是否被包含即可转移
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #define M 40010 6 using namespace std; 7 int n,m,k; 8 int lst[M],a[M],dp[M],f[M][210]; 9 int main() 10 { 11 scanf("%d%d",&n,&m);k=min((int)sqrt(n),m); 12 memset(dp,1,sizeof(dp)),dp[0]=0; 13 scanf("%d",&a[1]);lst[a[1]]=1; 14 f[1][1]=1;f[1][0]=2;dp[1]=1;lst[a[1]]=1; 15 for(int i=2;i<=n;i++) 16 { 17 dp[i]=i,f[i][0]=i+1;scanf("%d",&a[i]); 18 for(int j=1;j<=k;j++) 19 { 20 if(lst[a[i]]>=f[i-1][j]&&f[i-1][j]) 21 f[i][j]=f[i-1][j]; 22 else f[i][j]=f[i-1][j-1]; 23 } 24 for(int j=1;j<=k;j++) 25 if(f[i][j]-1>=0) 26 dp[i]=min(dp[i],dp[f[i][j]-1]+j*j); 27 lst[a[i]]=i; 28 } 29 printf("%d ",dp[n]); 30 return 0; 31 }