description: You are given a 1 by n pixel image. The i-th pixel of the image has color a_i. For each color, the number of pixels of that color is at most 20.
  
  You can perform the following operation, which works like the bucket tool in paint programs, on this image: 
  
    * pick a color — an integer from 1 to n; 
    * choose a pixel in the image; 
    * for all pixels connected to the selected pixel, change their colors to the selected color (two pixels of the same color are considered connected if all the pixels between them have the same color as those two pixels). 
  
  
  
  Compute the minimum number of operations needed to make all the pixels in the image have the same color.
  
  Input
  
  Each test contains multiple test cases. The first line contains the number of test cases t (1 ≤ t ≤ 10^3).
  
  The first line of each test case contains a single integer n (1 ≤ n ≤ 3⋅10^3) — the number of pixels in the image.
  
  The second line of each test case contains n integers a_1, a_2, …, a_n (1 ≤ a_i ≤ n) — the colors of the pixels in the image.
  
  Note: for each color, the number of pixels of that color is at most 20.
  
  It is guaranteed that the sum of n over all test cases does not exceed 3⋅10^3.
  
  Output
  
  For each test case, print one integer: the minimum number of operations needed to make all the pixels in the image have the same color.
  
  Example
  
  Input
  
  
  3
  5
  1 2 3 2 1
  4
  1 1 2 2
  5
  1 2 1 4 2
  
  
  Output
  
  
  2
  1
  3
  
  Note
  
  In the first example, the optimal solution is to apply the operation on the third pixel changing its color to 2 and then to apply the operation on any pixel that has color 2 changing its color and the color of all pixels connected to it to 1. The sequence of operations is then: [1, 2, 3, 2, 1] → [1, 2, 2, 2, 1] → [1, 1, 1, 1, 1].
  
  In the second example, we can either change the 1s to 2s in one operation or change the 2s to 1s also in one operation.
  
  In the third example, one possible way to make all the pixels have the same color is to apply the operation on the first, third and the fourth pixel each time changing its color to 2.
solution: import java.io.OutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Arrays;
  import java.io.OutputStream;
  import java.io.PrintStream;
  import java.io.IOException;
  import java.lang.reflect.Field;
  import java.nio.charset.StandardCharsets;
  import java.io.UncheckedIOException;
  import java.io.Closeable;
  import java.io.InputStream;
  
  /**
   * Built using CHelper plug-in
   * Actual solution is at the top
   */
  public class Main {
      public static void main(String[] args) throws Exception {
          Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 29);
          thread.start();
          thread.join();
      }
  
      static class TaskAdapter implements Runnable {
          @Override
          public void run() {
              InputStream inputStream = System.in;
              OutputStream outputStream = System.out;
              FastInput in = new FastInput(inputStream);
              FastOutput out = new FastOutput(outputStream);
              CPaint solver = new CPaint();
              int testCount = Integer.parseInt(in.next());
              for (int i = 1; i <= testCount; i++)
                  solver.solve(i, in, out);
              out.close();
          }
      }
  
      static class CPaint {
          int n;
          int[] next;
          int[][] dp;
          Debug debug = new Debug(false);
  
          public void solve(int testNumber, FastInput in, FastOutput out) {
              n = in.ri();
              IntegerArrayList list = new IntegerArrayList(n);
              for (int i = 0; i < n; i++) {
                  int x = in.ri() - 1;
                  if (!list.isEmpty() && list.tail() == x) {
                      continue;
                  }
                  list.add(x);
              }
              int[] a = list.toArray();
              int m = a.length;
              next = new int[m];
              int[] reg = new int[n];
              Arrays.fill(reg, m);
              for (int i = m - 1; i >= 0; i--) {
                  next[i] = reg[a[i]];
                  reg[a[i]] = i;
              }
              dp = new int[m][m];
              SequenceUtils.deepFill(dp, -1);
              int ans = dp(0, m - 1);
              debug.debug("ans", ans);
              out.println(m - 1 - ans);
          }
  
          public int dp(int l, int r) {
              if (l >= r) {
                  return 0;
              }
              if (dp[l][r] == -1) {
                  int ans = dp(l + 1, r);
                  int iter = l;
                  while (next[iter] <= r) {
                      iter = next[iter];
                      ans = Math.max(ans, dp(l + 1, iter - 1) + dp(iter, r) + 1);
                  }
                  dp[l][r] = ans;
              }
              return dp[l][r];
          }
  
      }
  
      static class SequenceUtils {
          public static void deepFill(Object array, int val) {
              if (array == null) {
                  return;
              }
              if (!array.getClass().isArray()) {
                  throw new IllegalArgumentException();
              }
              if (array instanceof int[]) {
                  int[] intArray = (int[]) array;
                  Arrays.fill(intArray, val);
              } else {
                  Object[] objArray = (Object[]) array;
                  for (Object obj : objArray) {
                      deepFill(obj, val);
                  }
              }
          }
  
          public static boolean equal(int[] a, int al, int ar, int[] b, int bl, int br) {
              if ((ar - al) != (br - bl)) {
                  return false;
              }
              for (int i = al, j = bl; i <= ar; i++, j++) {
                  if (a[i] != b[j]) {
                      return false;
                  }
              }
              return true;
          }
  
      }
  
      static class FastInput {
          private final InputStream is;
          private StringBuilder defaultStringBuf = new StringBuilder(1 << 13);
          private byte[] buf = new byte[1 << 13];
          private int bufLen;
          private int bufOffset;
          private int next;
  
          public FastInput(InputStream is) {
              this.is = is;
          }
  
          private int read() {
              while (bufLen == bufOffset) {
                  bufOffset = 0;
                  try {
                      bufLen = is.read(buf);
                  } catch (IOException e) {
                      bufLen = -1;
                  }
                  if (bufLen == -1) {
                      return -1;
                  }
              }
              return buf[bufOffset++];
          }
  
          public void skipBlank() {
              while (next >= 0 && next <= 32) {
                  next = read();
              }
          }
  
          public String next() {
              return readString();
          }
  
          public int ri() {
              return readInt();
          }
  
          public int readInt() {
              boolean rev = false;
  
              skipBlank();
              if (next == '+' || next == '-') {
                  rev = next == '-';
                  next = read();
              }
  
              int val = 0;
              while (next >= '0' && next <= '9') {
                  val = val * 10 - next + '0';
                  next = read();
              }
  
              return rev ? val : -val;
          }
  
          public String readString(StringBuilder builder) {
              skipBlank();
  
              while (next > 32) {
                  builder.append((char) next);
                  next = read();
              }
  
              return builder.toString();
          }
  
          public String readString() {
              defaultStringBuf.setLength(0);
              return readString(defaultStringBuf);
          }
  
      }
  
      static class FastOutput implements AutoCloseable, Closeable, Appendable {
          private static final int THRESHOLD = 32 << 10;
          private OutputStream writer;
          private StringBuilder cache = new StringBuilder(THRESHOLD * 2);
          private static Field stringBuilderValueField;
          private char[] charBuf = new char[THRESHOLD * 2];
          private byte[] byteBuf = new byte[THRESHOLD * 2];
  
          static {
              try {
                  stringBuilderValueField = StringBuilder.class.getSuperclass().getDeclaredField("value");
                  stringBuilderValueField.setAccessible(true);
              } catch (Exception e) {
                  stringBuilderValueField = null;
              }
              stringBuilderValueField = null;
          }
  
          public FastOutput append(CharSequence csq) {
              cache.append(csq);
              return this;
          }
  
          public FastOutput append(CharSequence csq, int start, int end) {
              cache.append(csq, start, end);
              return this;
          }
  
          private void afterWrite() {
              if (cache.length() < THRESHOLD) {
                  return;
              }
              flush();
          }
  
          public FastOutput(OutputStream writer) {
              this.writer = writer;
          }
  
          public FastOutput append(char c) {
              cache.append(c);
              afterWrite();
              return this;
          }
  
          public FastOutput append(int c) {
              cache.append(c);
              afterWrite();
              return this;
          }
  
          public FastOutput println(int c) {
              return append(c).println();
          }
  
          public FastOutput println() {
              return append('\n');
          }
  
          public FastOutput flush() {
              try {
                  if (stringBuilderValueField != null) {
                      try {
                          byte[] value = (byte[]) stringBuilderValueField.get(cache);
                          writer.write(value, 0, cache.length());
                      } catch (Exception e) {
                          stringBuilderValueField = null;
                      }
                  }
                  if (stringBuilderValueField == null) {
                      int n = cache.length();
                      if (n > byteBuf.length) {
                          //slow
                          writer.write(cache.toString().getBytes(StandardCharsets.UTF_8));
  //                writer.append(cache);
                      } else {
                          cache.getChars(0, n, charBuf, 0);
                          for (int i = 0; i < n; i++) {
                              byteBuf[i] = (byte) charBuf[i];
                          }
                          writer.write(byteBuf, 0, n);
                      }
                  }
                  writer.flush();
                  cache.setLength(0);
              } catch (IOException e) {
                  throw new UncheckedIOException(e);
              }
              return this;
          }
  
          public void close() {
              flush();
              try {
                  writer.close();
              } catch (IOException e) {
                  throw new UncheckedIOException(e);
              }
          }
  
          public String toString() {
              return cache.toString();
          }
  
      }
  
      static class Debug {
          private boolean offline;
          private PrintStream out = System.err;
  
          public Debug(boolean enable) {
              offline = enable && System.getSecurityManager() == null;
          }
  
          public Debug debug(String name, int x) {
              if (offline) {
                  debug(name, "" + x);
              }
              return this;
          }
  
          public Debug debug(String name, String x) {
              if (offline) {
                  out.printf("%s=%s", name, x);
                  out.println();
              }
              return this;
          }
  
      }
  
      static class IntegerArrayList implements Cloneable {
          private int size;
          private int cap;
          private int[] data;
          private static final int[] EMPTY = new int[0];
  
          public IntegerArrayList(int cap) {
              this.cap = cap;
              if (cap == 0) {
                  data = EMPTY;
              } else {
                  data = new int[cap];
              }
          }
  
          public IntegerArrayList(int[] data) {
              this(0);
              addAll(data);
          }
  
          public IntegerArrayList(IntegerArrayList list) {
              this.size = list.size;
              this.cap = list.cap;
              this.data = Arrays.copyOf(list.data, size);
          }
  
          public IntegerArrayList() {
              this(0);
          }
  
          public void ensureSpace(int req) {
              if (req > cap) {
                  while (cap < req) {
                      cap = Math.max(cap + 10, 2 * cap);
                  }
                  data = Arrays.copyOf(data, cap);
              }
          }
  
          private void checkRange(int i) {
              if (i < 0 || i >= size) {
                  throw new ArrayIndexOutOfBoundsException("Access [" + i + "]");
              }
          }
  
          public void add(int x) {
              ensureSpace(size + 1);
              data[size++] = x;
          }
  
          public void addAll(int[] x) {
              addAll(x, 0, x.length);
          }
  
          public void addAll(int[] x, int offset, int len) {
              ensureSpace(size + len);
              System.arraycopy(x, offset, data, size, len);
              size += len;
          }
  
          public void addAll(IntegerArrayList list) {
              addAll(list.data, 0, list.size);
          }
  
          public int tail() {
              checkRange(0);
              return data[size - 1];
          }
  
          public int[] toArray() {
              return Arrays.copyOf(data, size);
          }
  
          public boolean isEmpty() {
              return size == 0;
          }
  
          public String toString() {
              return Arrays.toString(toArray());
          }
  
          public boolean equals(Object obj) {
              if (!(obj instanceof IntegerArrayList)) {
                  return false;
              }
              IntegerArrayList other = (IntegerArrayList) obj;
              return SequenceUtils.equal(data, 0, size - 1, other.data, 0, other.size - 1);
          }
  
          public int hashCode() {
              int h = 1;
              for (int i = 0; i < size; i++) {
                  h = h * 31 + Integer.hashCode(data[i]);
              }
              return h;
          }
  
          public IntegerArrayList clone() {
              IntegerArrayList ans = new IntegerArrayList();
              ans.addAll(this);
              return ans;
          }
  
      }
  }
  
  