#include <bits/stdc++.h>   using namespace std;   using LL = long long;   template <typename T>   using V = vector<T>;   template <typename T, typename S>   using P = pair<T, S>;   template <class T>   using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;   using LD = long double;   template <typename T, typename S>   void check(T& a, S& b) {     if (a >= b) {       a %= b;     }   }   template <typename T>   T gcd(T u, T v) {     if (u == v) return u;     if (u == 0) return v;     if (v == 0) return u;     if (~u & 1) {       if (v & 1)         return gcd(u >> 1, v);       else         return gcd(u >> 1, v >> 1) << 1;     }     if (~v & 1) return gcd(u, v >> 1);     if (u > v) return gcd((u - v) >> 1, v);     return gcd((v - u) >> 1, u);   }   const int N = 35001;   int n, k;   int dp[N][51];   class SegmentTree {    public:     int n;     V<int> arr, lazy;     SegmentTree() {}     SegmentTree(int n) {       this->n = n;       this->arr = V<int>(n << 2, 0);       this->lazy = V<int>(n << 2, 0);     }     void propogate(int node, int s, int e) {       if (lazy[node]) {         arr[node] += lazy[node];         if (s != e) {           lazy[node << 1] += lazy[node];           lazy[node << 1 | 1] += lazy[node];         }       }       lazy[node] = 0;     }     void update(int node, int s, int e, int l, int r, int val) {       propogate(node, s, e);       if (l > r || s > r || e < l) return;       if (s >= l && e <= r) {         lazy[node] += val;         propogate(node, s, e);         return;       }       int mid = (s + e) >> 1;       update(node << 1, s, mid, l, r, val);       update(node << 1 | 1, mid + 1, e, l, r, val);       arr[node] = max(arr[node << 1], arr[node << 1 | 1]);     }     void upd(int node, int s, int e, int l, int val) {       propogate(node, s, e);       if (s == e) {         arr[node] = max(arr[node], val);         return;       }       int mid = (s + e) >> 1;       if (l <= mid)         upd(node << 1, s, mid, l, val);       else         upd(node << 1 | 1, mid + 1, e, l, val);       propogate(node << 1, s, mid);       propogate(node << 1 | 1, mid + 1, e);       arr[node] = max(arr[node << 1], arr[node << 1 | 1]);       return;     }     int get(int node, int s, int e, int l, int r) {       propogate(node, s, e);       if (l > r || s > r || e < l) return 0;       if (s >= l && e <= r) {         return arr[node];       }       int mid = (s + e) >> 1;       return max(get(node << 1, s, mid, l, r),                  get(node << 1 | 1, mid + 1, e, l, r));     }   };   int32_t main() {     ios_base::sync_with_stdio(false);     cin.tie(NULL);     cerr.tie(NULL);     ;     cin >> n >> k;     V<int> a, f(n + 1, n);     a.resize(n);     for (int i = 0; i < (int)n; i++) cin >> a[i], a[i]--;     SegmentTree seg[51];     for (int i = 0; i < k; i++) seg[i] = SegmentTree(n);     for (int i = n - 1; i >= 0; i--) {       dp[i][0] = dp[i + 1][0];       if (f[a[i]] == n) dp[i][0]++;       seg[0].upd(1, 0, n - 1, i, dp[i][0]);       for (int j = 1; j < min(n - i, k); j++) {         seg[j - 1].update(1, 0, n - 1, i + 1, min(f[a[i]], n - 1), 1);         dp[i][j] = seg[j - 1].get(1, 0, n - 1, i + 1, n - 1);         seg[j].upd(1, 0, n - 1, i, dp[i][j]);       }       f[a[i]] = i;     }     cout << dp[0][k - 1] <<   n ;     cerr <<  Time elapsed :  << clock() * 1000.0 / CLOCKS_PER_SEC <<   ms           <<   n ;     return 0;   }