#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> #define kl (k<<1) #define kr ((k<<1)+1) #define mid ((l+r)>>1) using namespace std; const int maxn=35000+10, N=50+10; int n, k, a[maxn], f[N][maxn]; int pre[maxn], pos[maxn]; struct node { int ret, flag; }tr[maxn<<2]; void Push_down(int k) { tr[kl].ret+=tr[k].flag, tr[kl].flag+=tr[k].flag; tr[kr].ret+=tr[k].flag, tr[kr].flag+=tr[k].flag; tr[k].flag=0; return ; } void Push_up(int k) { tr[k].ret=max(tr[kl].ret, tr[kr].ret); return ; } void Build(int x, int k=1, int l=1, int r=n) { tr[k].flag=0; if(l==r) { tr[k].ret=f[x][l-1]; //注意是l-1 return ; } Build(x, kl, l, mid); Build(x, kr, mid+1, r); Push_up(k); return ; } void Update(int ll, int rr, int k=1, int l=1, int r=n) { if(rr< l || r <ll) return ; if(ll<=l && r<=rr) { tr[k].ret++, tr[k].flag++; return ; } Push_down(k); Update(ll, rr, kl, l, mid); Update(ll, rr, kr, mid+1, r); Push_up(k); return ; } int Query(int ll, int rr, int k=1, int l=1, int r=n) { if(rr< l || r <ll) return 0; if(ll<=l && r<=rr) return tr[k].ret; int tl=Query(ll, rr, kl, l, mid), tr=Query(ll, rr, kr, mid+1, r); Push_up(k); return max(tl, tr); } int main() { while(scanf("%d%d", &n, &k)!=EOF) { memset(pre, 0, sizeof pre); memset(pos, 0, sizeof pos); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); pre[i]=pos[a[i]]+1; pos[a[i]]=i; } for(int i=1; i<=k; i++) { Build(i-1); for(int j=1; j<=n; j++) { Update(pre[j], j); f[i][j]=Query(1, j); } } printf("%d\n", f[k][n]); } return 0; }
|