#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int MAXN = 2e5 + 10;
struct Node {
  vector<int> x;
  Node() { x.resize(6); }
  void init_open() { x = {1, 1, -2, -MAXN, -MAXN, -MAXN}; };
  void init_closed() { x = {-1, -1, 2, -MAXN, -MAXN, -MAXN}; };
};
struct Tournament {
  int offset;
  vector<Node> T;
  Tournament(int n) {
    for (offset = 1; offset <= n; offset *= 2)
      ;
    T.resize(2 * offset);
  }
  void merge(int i) {
    const auto &L = T[2 * i];
    const auto &R = T[2 * i + 1];
    T[i].x[0] = L.x[0] + R.x[0];
    T[i].x[1] = max(L.x[1], L.x[0] + R.x[1]);
    T[i].x[2] = max(L.x[2], -2 * L.x[0] + R.x[2]);
    T[i].x[3] =
        max(L.x[3], max(-1 * L.x[0] + R.x[3], L.x[1] - 2 * L.x[0] + R.x[2]));
    T[i].x[4] =
        max(L.x[4], max(-1 * L.x[0] + R.x[4], L.x[2] + L.x[0] + R.x[1]));
    T[i].x[5] = max(L.x[5], max(R.x[5], max(L.x[1] - L.x[0] + R.x[4],
                                            L.x[3] + L.x[0] + R.x[1])));
  }
  void add_node(int i, Node val) {
    i += offset;
    T[i] = val;
    i /= 2;
    for (; i > 0; i /= 2) merge(i);
  }
  int diameter() { return max(T[1].x[1], max(T[1].x[3], T[1].x[5])); }
  int debug() {
    for (int i = 1; i < 2 * offset; ++i) {
      if (__builtin_popcount(i) == 1) printf("\n");
      printf("( ");
      for (int j = 0; j < 6; ++j) printf("%d ", T[i].x[j]);
      printf(") | ");
    }
    printf("\n");
  }
};
int n, q;
char s[MAXN];
void insert(int i, Tournament *T) {
  Node node;
  if (s[i] == '(')
    node.init_open();
  else
    node.init_closed();
  T->add_node(i, node);
}
int main(void) {
  scanf("%d%d", &n, &q);
  scanf("%s", s);
  Tournament T(2 * (n - 1));
  for (int i = 0; i < 2 * (n - 1); ++i) insert(i, &T);
  printf("%d\n", T.diameter());
  for (int i = 0; i < q; ++i) {
    int a, b;
    scanf("%d%d", &a, &b);
    --a;
    --b;
    swap(s[a], s[b]);
    insert(a, &T);
    insert(b, &T);
    printf("%d\n", T.diameter());
  }
  return 0;
}
