You are given a program that consists of n instructions. Initially a single variable x is assigned to 0. Afterwards, the instructions are of two types: 

  * increase x by 1; 
  * decrease x by 1. 



You are given m queries of the following format: 

  * query l r — how many distinct values is x assigned to if all the instructions between the l-th one and the r-th one inclusive are ignored and the rest are executed without changing the order? 

Input

The first line contains a single integer t (1 ≤ t ≤ 1000) — the number of testcases.

Then the description of t testcases follows.

The first line of each testcase contains two integers n and m (1 ≤ n, m ≤ 2 ⋅ 10^5) — the number of instructions in the program and the number of queries.

The second line of each testcase contains a program — a string of n characters: each character is either '+' or '-' — increment and decrement instruction, respectively.

Each of the next m lines contains two integers l and r (1 ≤ l ≤ r ≤ n) — the description of the query.

The sum of n over all testcases doesn't exceed 2 ⋅ 10^5. The sum of m over all testcases doesn't exceed 2 ⋅ 10^5. 

Output

For each testcase print m integers — for each query l, r print the number of distinct values variable x is assigned to if all the instructions between the l-th one and the r-th one inclusive are ignored and the rest are executed without changing the order.

Example

Input


2
8 4
-+--+--+
1 8
2 8
2 5
1 1
4 10
+-++
1 1
1 2
2 2
1 3
2 3
3 3
1 4
2 4
3 4
4 4


Output


1
2
4
4
3
3
4
2
3
2
1
2
2
2

Note

The instructions that remain for each query of the first testcase are: 

  1. empty program — x was only equal to 0; 
  2. "-" — x had values 0 and -1; 
  3. "---+" — x had values 0, -1, -2, -3, -2 — there are 4 distinct values among them; 
  4. "+--+--+" — the distinct values are 1, 0, -1, -2. 
import java.io.*;
import java.util.*;

public class Equal {

	static ArrayList<Integer>[] adj;

	static boolean check(int[] arr) {
		boolean f = true;
		for (int i = 1; i < arr.length; i++) {
			f &= arr[i] >= arr[i - 1];
		}
		return f;
	}

	public static void main(String[] args) throws IOException {
		// BufferedReader br = new BufferedReader(new FileReader("name.in"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		PrintWriter pw = new PrintWriter(System.out);
		Scanner sc = new Scanner(System.in);

		int t = Integer.parseInt(br.readLine());
		while (t-- > 0) {
			st = new StringTokenizer(br.readLine());
			int n = Integer.parseInt(st.nextToken());
			int m = Integer.parseInt(st.nextToken());
			char[] a = br.readLine().toCharArray();
			int N = 1;
			while (N < n + 1) {
				N <<= 1;
			}

			int cummax[] = new int[N + 1];
			int cummin[] = new int[N + 1];
			Arrays.fill(cummin, 100000000);
			cummin[1] = 0;

			for (int i = 1; i <= a.length; i++) {
				cummax[i + 1] = cummax[i] + (a[i - 1] == '+' ? 1 : -1);
				cummin[i + 1] = cummin[i] + (a[i - 1] == '+' ? 1 : -1);
			}
			SegmentTree sgmax = new SegmentTree(cummax);
			SegmentTreeMin sgmin = new SegmentTreeMin(cummax);
//			System.out.println(Arrays.toString(cummax));
//			System.out.println(Arrays.toString(sgmin.sTree));
			while (m-- > 0) {
				st = new StringTokenizer(br.readLine());
				int l = Integer.parseInt(st.nextToken());
				int r = Integer.parseInt(st.nextToken());
				int max1 = sgmax.query(1, l);
				int min1 = sgmin.query(1, l);
//				System.out.println(max1+ " "+ min1);
				int dis = 0;
				if (r == n) {
					dis = max1 - min1 + 1;
				} else {
					int trans = cummax[r + 1] - cummax[l]; // doesn't matter with cum
					int max2 = sgmax.query(r + 2, n + 1) - trans;
					int min2 = sgmin.query(r + 2, n + 1) - trans;
//					System.out.println(max2+ " 2 "+ min2+" "+ trans);
					if (max2 < min1 || max1 < min2) {
						dis = max1 - min1 + max2 - min2 + 2;
					} else {
						int max = Math.max(max1, max2);
						int min = Math.min(min1, min2);
						dis = max - min + 1;
					}
				}
				pw.println(dis);
			}

		}

		pw.flush();
	}

	static int g[];
	static boolean[] vis;

	static int find(int u) {
		System.out.println(u);
		vis[u] = true;
		if (g[g[u]] == -1)
			return 0;
		if (vis[g[g[u]]])
			return 1;
		return 1 + find(g[g[u]]);

	}

	static long gcd(long a, long b) {
		if (a == 0)
			return b;
		return gcd(b % a, a);
	}

	static class SegmentTree { // 1-based DS, OOP

		int N; // the number of elements in the array as a power of 2 (i.e. after padding)
		int[] array, sTree, lazy;

		SegmentTree(int[] in) {
			array = in;
			N = in.length - 1;
			sTree = new int[N << 1]; // no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new int[N << 1];
			build(1, 1, N);
		}

		void build(int node, int b, int e) // O(n)
		{
			if (b == e)
				sTree[node] = array[b];
			else {
				int mid = b + e >> 1;
				build(node << 1, b, mid);
				build(node << 1 | 1, mid + 1, e);
				sTree[node] = Math.max(sTree[node << 1], sTree[node << 1 | 1]);
			}
		}

		void update_point(int index, int val) // O(log n)
		{
			index += N - 1;
			sTree[index] += val;
			while (index > 1) {
				index >>= 1;
				sTree[index] = Math.max(sTree[index << 1], sTree[index << 1 | 1]);
			}
		}

		void update_range(int i, int j, int val) // O(log n)
		{
			update_range(1, 1, N, i, j, val);
		}

		void update_range(int node, int b, int e, int i, int j, int val) {
			if (i > e || j < b)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;
			} else {
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}

		}

		void propagate(int node, int b, int mid, int e) {
			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			lazy[node] = 0;
		}

		int query(int i, int j) {
			return query(1, 1, N, i, j);
		}

		int query(int node, int b, int e, int i, int j) // O(log n)
		{
			if (i > e || j < b)
				return -10000000;
			if (b >= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			propagate(node, b, mid, e);
			int q1 = query(node << 1, b, mid, i, j);
			int q2 = query(node << 1 | 1, mid + 1, e, i, j);
			return Math.max(q1, q2);

		}

	}

	static class SegmentTreeMin { // 1-based DS, OOP

		int N; // the number of elements in the array as a power of 2 (i.e. after padding)
		int[] array, sTree, lazy;

		SegmentTreeMin(int[] in) {
			array = in;
			N = in.length - 1;
			sTree = new int[N << 1]; // no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new int[N << 1];
			build(1, 1, N);
		}

		void build(int node, int b, int e) // O(n)
		{
			if (b == e)
				sTree[node] = array[b];
			else {
				int mid = b + e >> 1;
				build(node << 1, b, mid);
				build(node << 1 | 1, mid + 1, e);
				sTree[node] = Math.min(sTree[node << 1], sTree[node << 1 | 1]);
			}
		}

		void update_point(int index, int val) // O(log n)
		{
			index += N - 1;
			sTree[index] += val;
			while (index > 1) {
				index >>= 1;
				sTree[index] = Math.max(sTree[index << 1], sTree[index << 1 | 1]);
			}
		}

		void update_range(int i, int j, int val) // O(log n)
		{
			update_range(1, 1, N, i, j, val);
		}

		void update_range(int node, int b, int e, int i, int j, int val) {
			if (i > e || j < b)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;
			} else {
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}

		}

		void propagate(int node, int b, int mid, int e) {
			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			lazy[node] = 0;
		}

		int query(int i, int j) {
			return query(1, 1, N, i, j);
		}

		int query(int node, int b, int e, int i, int j) // O(log n)
		{
			if (i > e || j < b)
				return 100000000;
			if (b >= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			propagate(node, b, mid, e);
			int q1 = query(node << 1, b, mid, i, j);
			int q2 = query(node << 1 | 1, mid + 1, e, i, j);
			return Math.min(q1, q2);

		}

	}

	static int mod = 1000000007;

	static int[][] matMul(int[][] A, int[][] B, int p, int q, int r) // C(p x r) = A(p x q) x (q x r) -- O(p x q x r)
	{
		int[][] C = new int[p][r];
		for (int i = 0; i < p; ++i)
			for (int j = 0; j < r; ++j)
				for (int k = 0; k < q; ++k) {
					C[i][j] += (A[i][k] * 1l * B[k][j]) % mod;
					C[i][j] %= mod;
				}
		return C;
	}

	/*
	 * 4. Square Matrix Exponentiation
	 */
	static int[][] matPow(int[][] base, long p) {
		int n = base.length;
		int[][] ans = new int[n][n];
		for (int i = 0; i < n; i++)
			ans[i][i] = 1;
		while (p != 0) {
			if ((p & 1) == 1)
				ans = matMul(ans, base, n, n, n);
			base = matMul(base, base, n, n, n);
			p >>= 1;
		}

		return ans;
	}

	static class triple implements Comparable<triple> {
		long x;
		long y;
		int z;

		public triple(long a, long b, int c) {
			x = a;
			y = b;
			z = c;
		}

		@Override
		public int compareTo(triple o) {
			// TODO Auto-generated method stub
			return (int) (x - o.x);
		}

		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return x + " " + y + " " + z;
		}
	}

	static long powmod(long r, long e, long mod) {
		long ans = 1;
		r %= mod;
		while (e > 0) {
			if ((e & 1) == 1)
				ans = (int) ((ans * 1l * r) % mod);
			e >>= 1;
			r = (int) ((r * 1l * r) % mod);
		}
		return ans;
	}

	static class pair implements Comparable<pair> {
		int x;
		int y;

		public pair(int d, int u) {
			x = d;
			y = u;
		}

		@Override
		public int compareTo(pair o) {
			// TODO Auto-generated method stub
			return x - o.x;
		}

		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return x + " " + y;
		}

	}

}