#include <bits/stdc++.h>
using namespace std;
using namespace std;
const int NMAX = 40666;
const int INF = 1000000666;
const long long maxv = 100000;
int arr[NMAX];
int sol[NMAX];
int tree[4 * NMAX];
int lazy[4 * NMAX];
int prec[NMAX], prv[NMAX];
int A[NMAX];
int n, k;
mt19937_64 rang(
    chrono::high_resolution_clock::now().time_since_epoch().count());
int rng(int lim) {
  uniform_int_distribution<int> uid(0, lim - 1);
  return uid(rang);
}
long long fact(long long n, long long mod) {
  if (n <= 1) return 1;
  long long res = 1;
  for (long long i = 2; i <= n; i++) res = (i * res) % mod;
  return res;
}
long long power(long long base, long long pow, long long mod) {
  long long res = 1;
  base %= mod;
  while (pow > 0) {
    if ((pow & 1) == 1) res = (res * base) % mod;
    base = (base * base) % mod;
    pow >>= 1;
  }
  return res;
}
long long modInverse(long long first, long long mod) {
  return power(first, mod - 2, mod);
}
template <typename T>
void swap(T* first, T* second) {
  T temp = *first;
  *first = *second;
  *second = temp;
}
void build_tree(int node, int a, int b) {
  if (a > b) return;
  if (a == b) {
    tree[node] = arr[a];
    return;
  }
  build_tree(node * 2, a, (a + b) / 2);
  build_tree(node * 2 + 1, 1 + (a + b) / 2, b);
  tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
void update_tree(int node, int a, int b, int i, int j, int value) {
  if (lazy[node] != 0) {
    tree[node] += lazy[node];
    if (a != b) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2 + 1] += lazy[node];
    }
    lazy[node] = 0;
  }
  if (a > b || a > j || b < i) return;
  if (a >= i && b <= j) {
    tree[node] += value;
    if (a != b) {
      lazy[node * 2] += value;
      lazy[node * 2 + 1] += value;
    }
    return;
  }
  update_tree(node * 2, a, (a + b) / 2, i, j, value);
  update_tree(1 + node * 2, 1 + (a + b) / 2, b, i, j, value);
  tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}
int query_tree(int node, int a, int b, int i, int j) {
  if (a > b || a > j || b < i) return -INF;
  if (lazy[node] != 0) {
    tree[node] += lazy[node];
    if (a != b) {
      lazy[node * 2] += lazy[node];
      lazy[node * 2 + 1] += lazy[node];
    }
    lazy[node] = 0;
  }
  if (a >= i && b <= j) return tree[node];
  int q1 = query_tree(node * 2, a, (a + b) / 2, i, j);
  int q2 = query_tree(1 + node * 2, 1 + (a + b) / 2, b, i, j);
  int res = max(q1, q2);
  return res;
}
void solve() {
  cin >> n >> k;
  for (int i = 1; i <= n; ++i) {
    cin >> A[i];
  }
  for (int i = 1; i <= n; ++i) {
    prec[i] = 0;
  }
  for (int i = 1; i <= n; ++i) {
    prv[i] = prec[A[i]];
    prec[A[i]] = i;
  }
  for (int i = 1; i <= n; ++i) {
    sol[i] = 0;
  }
  for (int kk = 1; kk <= k; ++kk) {
    for (int i = 0; i < n; ++i) {
      arr[i] = sol[i];
    }
    memset(lazy, 0, sizeof(lazy));
    build_tree(1, 0, n - 1);
    for (int i = 1; i <= n; ++i) {
      if (prv[i] != 0) {
        update_tree(1, 0, n - 1, prv[i], i - 1, 1);
      } else {
        update_tree(1, 0, n - 1, 0, i - 1, 1);
      }
      sol[i] = query_tree(1, 0, n - 1, 0, i - 1);
    }
  }
  cout << query_tree(1, 0, n - 1, 0, n - 1);
}
int main() {
  solve();
  cout << "\n";
  return 0;
}
