This is the easy version of the problem. The difference between the versions is that the easy version does not require you to output the numbers of the rods to be removed. You can make hacks only if all versions of the problem are solved.

Stitch likes experimenting with different machines with his friend Sparky. Today they built another machine.

The main element of this machine are $n$ rods arranged along one straight line and numbered from $1$ to $n$ inclusive. Each of these rods must carry an electric charge quantitatively equal to either $1$ or $-1$ (otherwise the machine will not work). Another condition for this machine to work is that the sign-variable sum of the charge on all rods must be zero.

More formally, the rods can be represented as an array of $n$ numbers characterizing the charge: either $1$ or $-1$. Then the condition must hold: $a_1 - a_2 + a_3 - a_4 + \ldots = 0$, or $\sum\limits_{i=1}^n (-1)^{i-1} \cdot a_i = 0$.

Sparky charged all $n$ rods with an electric current, but unfortunately it happened that the rods were not charged correctly (the sign-variable sum of the charge is not zero). The friends decided to leave only some of the rods in the machine. Sparky has $q$ questions. In the $i$th question Sparky asks: if the machine consisted only of rods with numbers $l_i$ to $r_i$ inclusive, what minimal number of rods could be removed from the machine so that the sign-variable sum of charges on the remaining ones would be zero? Perhaps the friends got something wrong, and the sign-variable sum is already zero. In that case, you don't have to remove the rods at all.

If the number of rods is zero, we will assume that the sign-variable sum of charges is zero, that is, we can always remove all rods.

Help your friends and answer all of Sparky's questions!


-----Input-----

Each test contains multiple test cases.

The first line contains one positive integer $t$ ($1 \le t \le 10^3$), denoting the number of test cases. Description of the test cases follows.

The first line of each test case contains two positive integers $n$ and $q$ ($1 \le n, q \le 3 \cdot 10^5$) — the number of rods and the number of questions.

The second line of each test case contains a non-empty string $s$ of length $n$, where the charge of the $i$-th rod is $1$ if $s_i$ is the "+" symbol, or $-1$ if $s_i$ is the "-" symbol.

Each next line from the next $q$ lines contains two positive integers $l_i$ ans $r_i$ ($1 \le l_i \le r_i \le n$) — numbers, describing Sparky's questions.

It is guaranteed that the sum of $n$ over all test cases does not exceed $3 \cdot 10^5$, and the sum of $q$ over all test cases does not exceed $3 \cdot 10^5$.


-----Output-----

For each test case, print a single integer — the minimal number of rods that can be removed.


-----Examples-----

Input
3
14 1
+--++---++-++-
1 14
14 3
+--++---+++---
1 14
6 12
3 10
4 10
+-+-
1 1
1 2
1 3
1 4
2 2
2 3
2 4
3 3
3 4
4 4
Output
2
2
1
0
1
2
1
2
1
2
1
1
2
1


-----Note-----

In the first test case for the first query you can remove the rods numbered $5$ and $8$, then the following set of rods will remain: +--+--++-++-. It is easy to see that here the sign-variable sum is zero.

In the second test case:

For the first query, we can remove the rods numbered $1$ and $11$, then the following set of rods will remain: --++---++---. It is easy to see that here the sign-variable sum is zero.

For the second query we can remove the rod numbered $9$, then the following set of rods will remain: ---++-. It is easy to see that here the variable sum is zero.

For the third query we can not remove the rods at all.

Difficulty: MEDIUM_HARD
Tags: Dynamic programming

Data structures

Mathematics
Skill types: Dynamic programming

Data structures

Starter code:

Solutions:
import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	rod = input()
	dp = [0]
	for (i, j) in enumerate(rod):
		dp.append(dp[-1] + 1) if (j == '+') ^ (i % 2 == 0) else dp.append(dp[-1] - 1)
	for i in range(q):
		(l, r) = map(int, input().split())
		if dp[r] - dp[l - 1] == 0:
			print(0)
		elif (dp[r] - dp[l - 1]) % 2 == 1:
			print(1)
		else:
			print(2)


import os, sys
from io import BytesIO, IOBase

def main():
	for _ in range(int(input())):
		(n, Q) = map(int, input().split())
		s = input().strip()
		su = [0]
		for (idx, i) in enumerate(s):
			si = -1 if idx & 1 else 1
			num = 1 if i == '+' else -1
			su.append(su[-1] + num * si)
		for _ in range(Q):
			(l, r) = map(int, input().split())
			x = su[r] - su[l - 1]
			if not x:
				print(0)
			elif x & 1:
				print(1)
			else:
				print(2)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import sys
input = sys.stdin.readline
T = int(input())
for _ in range(T):
	(n, q) = map(int, input().split())
	s = input()
	pre_sum = [0]
	sign = 1
	for i in s:
		if i == '+':
			x = sign
		else:
			x = -sign
		pre_sum.append(pre_sum[-1] + x)
		sign *= -1
	for qq in range(q):
		(l, r) = map(int, input().split())
		sum = pre_sum[r] - pre_sum[l - 1]
		if sum == 0:
			print(0)
		elif sum & 1:
			print(1)
		else:
			print(2)


import sys
input = sys.stdin.readline
t = int(input())
for _ in range(t):
	(n, q) = map(int, input().split())
	s = list(input().rstrip())
	x = [0]
	for i in range(n):
		if i % 2:
			if s[i] == '+':
				x.append(x[-1] + 1)
			else:
				x.append(x[-1] - 1)
		elif s[i] == '-':
			x.append(x[-1] + 1)
		else:
			x.append(x[-1] - 1)
	for _ in range(q):
		(l, r) = map(int, input().split())
		c = x[r] - x[l - 1]
		d = r - l + 1
		if d % 2:
			ans = 1
		else:
			ans = 0 if c == 0 else 2
		print(ans)


from sys import stdin
input = stdin.readline
t = int(input())
for i in range(t):
	(n, q) = map(int, input().split())
	s = input()
	dp = [[0, 0] for i in range(n + 1)]
	for i in range(n):
		a = 0
		b = 0
		if s[i] == '+':
			if i % 2 == 0:
				a = a + 1
			else:
				b = b + 1
		elif i % 2 == 0:
			b = b + 1
		else:
			a = a + 1
		dp[i + 1][0] = dp[i][0] + a
		dp[i + 1][1] = dp[i][1] + b
	for i in range(q):
		(l, r) = map(int, input().split())
		a = dp[r][0] - dp[l - 1][0]
		b = dp[r][1] - dp[l - 1][1]
		if abs(a - b) <= 2:
			print(abs(a - b))
		elif abs(a - b) % 2 == 0:
			print(2)
		else:
			print(1)


import sys
input = sys.stdin.readline

def main():
	(n, q) = map(int, input().split())
	S = input().strip()
	cum = [0]
	for (i, s) in enumerate(S):
		if (s == '+') ^ (i % 2 == 0):
			cum.append(cum[-1] + 1)
		else:
			cum.append(cum[-1] - 1)
	for _ in range(q):
		(l, r) = map(int, input().split())
		d = cum[r] - cum[l - 1]
		if d == 0:
			print(0)
		elif d % 2 == 1:
			print(1)
		else:
			print(2)
for _ in range(int(input())):
	main()


import sys
input = sys.stdin.buffer.readline

def process(S, Q):
	odd_plus = [0]
	even_plus = [0]
	odd_minus = [0]
	even_minus = [0]
	n = len(S)
	for i in range(n):
		if S[i] == '+' and i % 2 == 0:
			odd_plus.append(odd_plus[-1])
			even_plus.append(even_plus[-1] + 1)
			odd_minus.append(odd_minus[-1])
			even_minus.append(even_minus[-1])
		elif S[i] == '+' and i % 2 == 1:
			odd_plus.append(odd_plus[-1] + 1)
			even_plus.append(even_plus[-1])
			odd_minus.append(odd_minus[-1])
			even_minus.append(even_minus[-1])
		elif S[i] == '-' and i % 2 == 0:
			odd_plus.append(odd_plus[-1])
			even_plus.append(even_plus[-1])
			odd_minus.append(odd_minus[-1])
			even_minus.append(even_minus[-1] + 1)
		elif S[i] == '-' and i % 2 == 1:
			odd_plus.append(odd_plus[-1])
			even_plus.append(even_plus[-1])
			odd_minus.append(odd_minus[-1] + 1)
			even_minus.append(even_minus[-1])
	answer = []
	for (l, r) in Q:
		m = r - l + 1
		my_oddplus = odd_plus[r] - odd_plus[l - 1]
		my_oddminus = odd_minus[r] - odd_minus[l - 1]
		my_evenplus = even_plus[r] - even_plus[l - 1]
		my_evenminus = even_minus[r] - even_minus[l - 1]
		if my_oddplus != my_evenplus or my_oddminus != my_evenminus:
			if m % 2 == 0:
				a = 2
			else:
				a = 1
		else:
			a = 0
		answer.append(a)
	return answer
t = int(input())
for i in range(t):
	(n, q) = [int(x) for x in input().split()]
	S = input().decode()
	Q = []
	for j in range(q):
		(l, r) = [int(x) for x in input().split()]
		Q.append([l, r])
	answer = process(S, Q)
	for x in answer:
		print(x)


import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def main(t):
	(n, q) = map(int, input().split())
	s = input()
	accu = [0] * (n + 1)
	for i in range(n):
		if i % 2 == 0:
			if s[i] == ord('+'):
				accu[i] = accu[i - 1] + 1
			else:
				accu[i] = accu[i - 1] - 1
		elif s[i] == ord('+'):
			accu[i] = accu[i - 1] - 1
		else:
			accu[i] = accu[i - 1] + 1
	for _ in range(q):
		(l, r) = map(int, input().split())
		l -= 1
		r -= 1
		if (r - l + 1) % 2 == 1:
			print(1)
		elif accu[r] == accu[l - 1]:
			print(0)
		else:
			print(2)
T = int(input())
t = 1
while t <= T:
	main(t)
	t += 1


from collections import defaultdict as dd
import math
import sys
input = sys.stdin.readline

def nn():
	return int(input())

def li():
	return list(input())

def mi():
	return map(int, input().split())

def lm():
	return list(map(int, input().split()))

def solve():
	(n, m) = mi()
	d = input()
	running = [0]
	tot = 0
	for i in range(n):
		if i % 2 == 0 and d[i] == '+':
			tot += 1
		if i % 2 == 0 and d[i] == '-':
			tot -= 1
		if i % 2 == 1 and d[i] == '+':
			tot -= 1
		if i % 2 == 1 and d[i] == '-':
			tot += 1
		running.append(tot)
	for i in range(m):
		(l, r) = mi()
		length = r - l + 1
		s = running[r] - running[l - 1]
		if s == 0:
			print(0)
		elif length % 2 == 0:
			print(2)
		else:
			print(1)
q = nn()
for _ in range(q):
	solve()


import math
import heapq
import string
from collections import deque
from bisect import bisect, bisect_left, bisect_right, insort
import sys
input = sys.stdin.readline
S = lambda : input().rstrip()
I = lambda : int(S())
M = lambda : map(int, S().split())
L = lambda : list(M())
H = 1000000000 + 7
for _ in range(I()):
	(n, q) = M()
	s = S()
	a = [0] * n
	for i in range(n):
		if s[i] == '+' and i % 2 == 0 or (s[i] == '-' and i % 2 == 1):
			a[i] = 1
		else:
			a[i] = -1
	dp = [0] * (n + 1)
	for i in range(n):
		dp[i + 1] = dp[i] + a[i]
	for i in range(q):
		(l, r) = M()
		if dp[r] - dp[l - 1] == 0:
			print(0)
		elif (r - l + 1) % 2 == 1:
			print(1)
		else:
			print(2)


from sys import stdin, gettrace
if gettrace():

	def inputi():
		return input()
else:

	def input():
		return next(stdin)[:-1]

	def inputi():
		return stdin.buffer.readline()

def solve():
	(n, q) = map(int, input().split())
	ss = input()
	rs = [0]
	for (i, r) in enumerate(ss):
		if i % 2 == 0 and r == '+' or (i % 2 == 1 and r == '-'):
			rs.append(rs[-1] + 1)
		else:
			rs.append(rs[-1] - 1)
	for _ in range(q):
		(l, r) = map(int, input().split())
		if (r - l) % 2 == 0:
			print(1)
		elif rs[r] == rs[l - 1]:
			print(0)
		else:
			print(2)

def main():
	t = int(input())
	for _ in range(t):
		solve()
main()


import sys
input = sys.stdin.readline
pre = [0] * (3 * int(100000.0) + 5)
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()
	for (i, c) in enumerate(s):
		base = 1 if i % 2 else -1
		if c == '+':
			pre[i + 1] = pre[i] + base
		else:
			pre[i + 1] = pre[i] - base
	for i in range(q):
		(l, r) = map(int, input().split())
		if pre[r] - pre[l - 1] == 0:
			print(0)
		elif (r - l + 1) % 2 == 1:
			print(1)
		else:
			print(2)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
print = lambda s: sys.stdout.write(str(s) + '\n')

def solve():
	(n, q) = map(int, input().split())
	a = input().strip()
	s = [0] * n
	if a[0] == '+':
		s[0] = 1
	else:
		s[0] = -1
	for i in range(1, n):
		sgn = -1 if i % 2 else 1
		num = 1 if a[i] == '+' else -1
		s[i] = s[i - 1] + sgn * num
	for _ in range(q):
		(l, r) = map(int, input().split())
		l -= 1
		r -= 1
		ss = s[r] - (s[l - 1] if l >= 1 else 0)
		if ss == 0:
			print(0)
		elif ss % 2 == 1:
			print(1)
		else:
			print(2)
for nt in range(int(input())):
	solve()


from sys import stdin
input = stdin.readline

def solution():
	(n, q) = map(int, input().split())
	S = input().rstrip()
	arr = [0] * (n + 1)
	sign = 1
	for i in range(1, n + 1):
		if S[i - 1] == '+':
			arr[i] = arr[i - 1] + 1 * sign
		else:
			arr[i] = arr[i - 1] - 1 * sign
		sign *= -1
	for _ in range(q):
		(l, r) = map(int, input().split())
		ans = arr[r] - arr[l - 1]
		if ans == 0:
			print(0)
		elif ans % 2 == 1:
			print(1)
		else:
			print(2)
T = int(input())
for _ in range(T):
	solution()


import sys
import collections
import math
inf = sys.maxsize

def get_ints():
	return map(int, input().split())

def get_array():
	return list(map(int, input().split()))
mod = 1000000007
MOD = 998244353

def main():
	N = 3 * int(100000.0) + 1
	tree = [0] * (2 * N)

	def build(arr):
		n = len(arr)
		for i in range(n):
			tree[n + i] = arr[i]
		for i in range(n - 1, 0, -1):
			tree[i] = tree[i << 1] + tree[i << 1 | 1]

	def updateTreeNode(p, value, n):
		tree[p + n] = value
		p = p + n
		i = p
		while i > 1:
			tree[i >> 1] = tree[i] + tree[i ^ 1]
			i >>= 1

	def query(l, r, n):
		res = 0
		l += n
		r += n
		while l < r:
			if l & 1:
				res += tree[l]
				l += 1
			if r & 1:
				r -= 1
				res += tree[r]
			l >>= 1
			r >>= 1
		return res
	for _ in range(int(input())):
		(n, q) = get_ints()
		s = input()
		arr = []
		for i in range(n):
			if s[i] == '+':
				arr.append(1)
			else:
				arr.append(-1)
			if i & 1:
				arr[i] *= -1
		build(arr)
		for tt in range(q):
			(l, r) = get_ints()
			l -= 1
			ans = query(l, r, n)
			if ans == 0:
				print(0)
			else:
				rge = r - l
				if rge & 1:
					print(1)
				else:
					print(2)
py2 = round(0.5)
if py2:
	from future_builtins import ascii, filter, hex, map, oct, zip
	range = xrange
import os, sys
from io import IOBase, BytesIO
BUFSIZE = 8192

class FastIO(BytesIO):
	newlines = 0

	def __init__(self, file):
		self._file = file
		self._fd = file.fileno()
		self.writable = 'x' in file.mode or 'w' in file.mode
		self.write = super(FastIO, self).write if self.writable else None

	def _fill(self):
		s = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
		self.seek((self.tell(), self.seek(0, 2), super(FastIO, self).write(s))[0])
		return s

	def read(self):
		while self._fill():
			pass
		return super(FastIO, self).read()

	def readline(self):
		while self.newlines == 0:
			s = self._fill()
			self.newlines = s.count(b'\n') + (not s)
		self.newlines -= 1
		return super(FastIO, self).readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.getvalue())
			(self.truncate(0), self.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		if py2:
			self.write = self.buffer.write
			self.read = self.buffer.read
			self.readline = self.buffer.readline
		else:
			self.write = lambda s: self.buffer.write(s.encode('ascii'))
			self.read = lambda : self.buffer.read().decode('ascii')
			self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import sys
input = sys.stdin.readline
t = int(input())
for _ in range(t):
	(n, q) = map(int, input().split())
	s = list(str(input()))
	if n % 2:
		cur = 1
	else:
		cur = -1
	sums = []
	sums.append(0)
	for i in range(n - 1, -1, -1):
		if s[i] == '+':
			sums.append(sums[-1] + cur)
		else:
			sums.append(sums[-1] - cur)
		cur *= -1
	for _ in range(q):
		(a, b) = map(int, input().split())
		if sums[n - b] - sums[n - a + 1] == 0:
			print(0)
		elif (b - a + 1) % 2:
			print(1)
		else:
			print(2)


import sys
from math import factorial, gcd
from collections import Counter, deque, defaultdict
from bisect import bisect_left, bisect_right
from heapq import heappop, heappush, heapify, nlargest, nsmallest
from itertools import groupby
from copy import deepcopy
MOD = 10 ** 9 + 7
INF = float('inf')
rl = lambda : list(map(int, sys.stdin.readline().split()))
rs = lambda : sys.stdin.readline().strip()

def getSum(l, r):
	if l > r:
		return 0
	if l % 2:
		return p[r] - p[l - 1]
	return p[l - 1] - p[r]
for _ in range(int(input())):
	(n, q) = rl()
	s = rs()
	a = [0] * (n + 1)
	p = [0] * (n + 1)
	for i in range(1, n + 1):
		a[i] += 1 if s[i - 1] == '+' else -1
	for i in range(1, n + 1):
		p[i] = p[i - 1] + (a[i] if i % 2 == 0 else -a[i])
	for _ in range(q):
		(l, r) = rl()
		if getSum(l, r) == 0:
			print(0)
		elif (r - l + 1) % 2 == 1:
			print(1)
		else:
			print(2)


I = lambda : map(int, input().split())
(k,) = I()
for i in range(k):
	(n, q) = I()
	(s, a, y, z, o, p, r) = (input(), [], 1, {0: (0, 0)}, 0, 0, '')
	for i in range(n):
		if s[i] == '+':
			a += [y]
		else:
			a += [-1 * y]
		y *= -1
	for i in range(1, n + 1):
		if a[i - 1] == 1:
			o += 1
		else:
			p += 1
		z[i] = (o, p)
	for i in range(q):
		(c, v) = I()
		w = abs(z[v][0] - z[c - 1][0] - z[v][1] + z[c - 1][1])
		r += str(w if w == 0 else 1 if w % 2 else 2) + '\n'
	print(r)


import sys
import io, os
input = sys.stdin.readline
t = int(input())
from itertools import accumulate
for _ in range(t):
	(n, q) = map(int, input().split())
	s = str(input().rstrip())
	A = [0] * n
	for (i, c) in enumerate(s):
		if c == '+':
			A[i] = 1
		else:
			A[i] = -1
	C = [0] * (n + 1)
	for i in range(n):
		if i % 2 == 0:
			C[i + 1] = C[i] + A[i]
		else:
			C[i + 1] = C[i] - A[i]
	for i in range(q):
		(l, r) = map(int, input().split())
		(l, r) = (l - 1, r - 1)
		if l % 2 == 0:
			x = C[r + 1] - C[l]
		else:
			x = -(C[r + 1] - C[l])
		if x == 0:
			print(0)
		elif (r - l + 1) % 2 == 0:
			print(2)
		else:
			print(1)


from sys import stdin
input = stdin.readline

def answer():
	(pos, neg) = ([0], [0])
	for i in range(n):
		pos.append(pos[-1])
		neg.append(neg[-1])
		if i & 1 == 0:
			if s[i] == '+':
				pos[-1] += 1
			else:
				neg[-1] += 1
		elif s[i] == '-':
			pos[-1] += 1
		else:
			neg[-1] += 1
	for i in range(m):
		(l, r) = map(int, input().split())
		positive = pos[r] - pos[l - 1]
		negitive = neg[r] - neg[l - 1]
		if positive - negitive == 0:
			print(0)
		elif l & 1 == r & 1:
			print(1)
		else:
			print(2)
for T in range(int(input())):
	(n, m) = map(int, input().split())
	s = input().strip()
	answer()


import os, sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
try:
	(sys.stdin, sys.stdout) = (open('in.txt', 'r'), open('out.txt', 'w'))
except:
	pass
ii1 = lambda : int(sys.stdin.readline().strip())
is1 = lambda : sys.stdin.readline().strip()
iia = lambda : list(map(int, sys.stdin.readline().strip().split()))
isa = lambda : sys.stdin.readline().strip().split()
mod = int(1000000000.0 + 7)
for _ in range(ii1()):
	(n, q) = iia()
	s = is1()
	arr = [0]
	for i in range(n):
		v = s[i]
		if i % 2:
			sign = -1
		else:
			sign = 1
		if v == '+':
			put = 1
		else:
			put = -1
		arr.append(put * sign)
	for i in range(1, n + 1):
		arr[i] += arr[i - 1]
	for _ in range(q):
		(l, r) = sorted(iia())
		ans = arr[r] - arr[l - 1]
		ans = abs(ans)
		if ans == 0:
			print(ans)
		elif (r - l) % 2:
			print(2)
		else:
			print(1)


import sys
input = sys.stdin.readline
for __ in range(int(input())):
	(n, t) = map(int, input().split())
	s = input()
	z = [0]
	a = 0
	x = 1
	for i in range(n):
		if s[i] == '+':
			a = 1
		else:
			a = -1
		a = a * x
		x = x * -1
		z.append(z[-1] + a)
	for _ in range(t):
		(s1, s2) = map(int, input().split())
		s_ = z[s2] - z[s1 - 1]
		if s_ == 0:
			print(0)
		elif s_ % 2 == 1:
			print(1)
		else:
			print(2)


import sys
import getpass
import math, random
import functools, itertools, collections, heapq, bisect
from collections import Counter, defaultdict, deque
input = sys.stdin.readline
M9 = 10 ** 9 + 7
(yes, no) = ('YES', 'NO')
MAXINT = sys.maxsize
OFFLINE_TEST = getpass.getuser() == 'hkmac'

def log(*args):
	if OFFLINE_TEST:
		print('\x1b[36m', *args, '\x1b[0m', file=sys.stderr)

def solve(*args):
	if OFFLINE_TEST:
		log('----- solving ------')
		log(*args)
		log('----- ------- ------')
	return solve_(*args)

def read_matrix(rows):
	return [list(map(int, input().split())) for _ in range(rows)]

def read_strings(rows):
	return [input().strip() for _ in range(rows)]

def minus_one(arr):
	return [x - 1 for x in arr]

def minus_one_matrix(mrr):
	return [[x - 1 for x in row] for row in mrr]

def solve_(srr, qrr):
	arr = [1 if x == '+' else -1 for x in srr]
	brr = [x if i % 2 else -x for (i, x) in enumerate(arr)]
	log(brr)
	log(arr)
	psum = [0]
	for x in brr:
		psum.append(psum[-1] + x)
	log(psum)
	res = []
	for (a, b) in qrr:
		a -= 1
		if psum[a] == psum[b]:
			res.append(0)
			continue
		if (b - a) % 2:
			res.append(1)
			continue
		res.append(2)
	return res
for case_num in range(int(input())):
	(_, k) = list(map(int, input().split()))
	srr = input().strip()
	qrr = read_matrix(k)
	res = solve(srr, qrr)
	res = '\n'.join((str(x) for x in res))
	print(res)


from sys import stdin, setrecursionlimit, maxsize
from collections import deque
from heapq import *
from math import sqrt, gcd
input = stdin.readline
setrecursionlimit(10 ** 5)

def get_sum(l, r):
	if l > r:
		return 0
	return p[r] - p[l - 1] if l % 2 else p[l - 1] - p[r]
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input().strip()
	a = [0] * (n + 1)
	p = [0] * (n + 1)
	for i in range(1, n + 1):
		a[i] = 1 if s[i - 1] == '+' else -1
	for i in range(1, n + 1):
		p[i] = p[i - 1] + (a[i] if i % 2 == 1 else -a[i])
	for _ in range(q):
		(l, r) = map(int, input().split())
		if get_sum(l, r) == 0:
			print(0)
			continue
		if (r - l + 1) % 2 == 0:
			print(2)
		else:
			print(1)


import sys
ii = 0
inp = sys.stdin.read().split()
out = []
t = int(inp[ii])
ii += 1
for _ in range(t):
	n = int(inp[ii])
	ii += 1
	q = int(inp[ii])
	ii += 1
	s = inp[ii]
	ii += 1
	a = 0
	p = [0]
	for (i, j) in enumerate(s):
		a += 1 if (j == '+') ^ i & 1 else -1
		p.append(a)
	for _ in range(q):
		l = int(inp[ii])
		ii += 1
		r = int(inp[ii])
		ii += 1
		a = p[r] - p[l - 1]
		out.append('1' if a % 2 else '2' if a else '0')
print('\n'.join(out))


test = int(input())
for _ in range(test):
	(n, q) = map(int, input().split())
	s = input()
	sumi = 0
	rangesumi = [0] * (n + 1)
	for i in range(len(s)):
		if i % 2 == 0:
			if s[i] == '+'[0]:
				sumi += 1
			else:
				sumi -= 1
		elif s[i] == '+'[0]:
			sumi -= 1
		else:
			sumi += 1
		rangesumi[i + 1] = sumi
	ans = ''
	for i in range(q):
		(l, r) = map(int, input().split())
		sumi = rangesumi[r] - rangesumi[l - 1]
		if sumi == 0:
			ans += '0'
		elif (r - l + 1) % 2 == 1:
			ans += '1'
		else:
			ans += '2'
	for i in ans:
		print(i)


import sys, os, io
import math
from collections import defaultdict
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def ii():
	return int(input())

def li():
	return list(map(int, input().split()))
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
t = 1
t = ii()
for _ in range(t):
	(n, q) = li()
	s = list(input())
	prep = [0] * (n + 1)
	prem = [0] * (n + 1)
	for i in range(1, n + 1):
		prep[i] += prep[i - 1]
		prem[i] += prem[i - 1]
		if s[i - 1] == '+':
			if i % 2 == 0:
				prep[i] += 1
			else:
				prem[i] += 1
		elif i % 2 == 0:
			prem[i] += 1
		else:
			prep[i] += 1
	for i in range(q):
		(l, r) = li()
		p = prep[r] - prep[l - 1]
		m = prem[r] - prem[l - 1]
		if (r - l + 1) % 2 == 1:
			print(1)
			continue
		if abs(p - m) == 0:
			print(0)
		else:
			print(2)


import sys
import math
input = lambda : sys.stdin.readline().strip()
t = int(input())
while t:
	t -= 1
	(n, q) = map(int, input().split())
	s = input()
	arr = [0]
	for i in range(n):
		if i & 1:
			if s[i] == '+':
				arr.append(arr[-1] - 1)
			else:
				arr.append(arr[-1] + 1)
		elif s[i] == '-':
			arr.append(arr[-1] - 1)
		else:
			arr.append(arr[-1] + 1)
	while q:
		q -= 1
		(l, r) = map(int, input().split())
		l -= 1
		su = abs(arr[r] - arr[l])
		ans = 0
		if su % 2:
			ans = 1
		elif su > 0:
			ans = 2
		print(ans)


import sys

def main():
	t = int(input())
	for _ in range(t):
		(n, q) = map(int, input().split())
		ar = []
		s = input()
		pre = [0]
		presum = [0]
		for (i, x) in enumerate(s):
			if x == '+':
				ar.append(1)
				pre.append(1 - pre[-1])
			if x == '-':
				ar.append(-1)
				pre.append(pre[-1])
			if i % 2:
				presum.append(presum[-1] + ar[i])
			else:
				presum.append(presum[-1] - ar[i])
		for _ in range(q):
			(l, r) = map(int, input().split())
			if presum[r] - presum[l - 1] == 0:
				print(0)
			else:
				ones = pre[r] - pre[l - 1]
				zeroes = r - l + 1 - ones
				if ones % 2:
					if zeroes % 2:
						print(2)
					else:
						print(1)
				elif zeroes % 2:
					print(1)
				else:
					print(2)
import os
import sys
from io import BytesIO, IOBase
_str = str
str = lambda x=b'': x if type(x) is bytes else _str(x).encode()
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


from itertools import combinations, permutations
from sys import path_hooks, stdin, stdout
from collections import Counter, deque
import math
from copy import deepcopy
import random
import heapq
import sys
sys.setrecursionlimit(10 ** 5)

def mapinput():
	return map(int, stdin.readline().split())

def strinput():
	return stdin.readline().strip()

def listinput():
	return list(map(int, stdin.readline().split()))

def intinput():
	return int(stdin.readline().strip())

def gcd(a, b):
	if b == 0:
		return a
	else:
		return gcd(b, a % b)

def SieveOfEratosthenes(n):
	prime = [True for i in range(n + 1)]
	p = 2
	while p * p <= n:
		if prime[p] == True:
			for i in range(p * 2, n + 1, p):
				prime[i] = False
		p += 1
	prime[0] = False
	prime[1] = False
	ans = []
	for p in range(n + 1):
		if prime[p]:
			ans.append(p)
	return ans
primes = set(SieveOfEratosthenes(1000))

def writ(ss):
	stdout.write(str(ss) + '\n')
mod = 998244353

def sumn(n):
	return n * (n + 1) // 2

def overlap(s1, s2):
	j = 0
	for i in s1:
		if j < len(s2) and s2[j] == i:
			j += 1
	if j == len(s2):
		return True
	return False

def perm(lis):
	if len(lis) < 2:
		return lis
	anss = []
	for i in range(len(lis)):
		ele = lis[i]
		liss = lis[:i] + lis[i + 1:]
		for j in perm(liss):
			anss.append(ele + j)
	return anss
for test in range(intinput()):

	def solve():
		(n, q) = mapinput()
		s = strinput()
		arr = []
		for i in range(n):
			if s[i] == '+':
				ele = 1
			else:
				ele = -1
			if i & 1 == 1:
				ele = -ele
			arr.append(ele)
		pref = [0]
		su = 0
		for i in arr:
			su += i
			pref.append(su)
		for ttt in range(q):
			(l, r) = mapinput()
			ans = abs(pref[r] - pref[l - 1])
			if ans == 0:
				print(0)
			elif ans % 2 == 0:
				print(2)
			else:
				print(1)
	solve()


import sys
input = sys.stdin.readline
T = int(input())
for iii in range(T):
	(n, q) = map(int, input().split())
	a = [0] + list(input()[:-1])
	for i in range(1, n + 1):
		if a[i] == '+':
			a[i] = 1
		else:
			a[i] = -1
	s = [0] * (n + 1)
	for i in range(1, n + 1):
		if i % 2 == 1:
			s[i] = s[i - 1] + a[i]
		else:
			a[i] *= -1
			s[i] = s[i - 1] + a[i]
	for _ in range(q):
		(l, r) = map(int, input().split())
		res = s[r] - s[l - 1]
		if res == 0:
			print(0)
		elif res % 2 == 1:
			print(1)
		else:
			print(2)


def divisors(M):
	d = []
	i = 1
	while M >= i ** 2:
		if M % i == 0:
			d.append(i)
			if i ** 2 != M:
				d.append(M // i)
		i = i + 1
	return d

def popcount(x):
	x = x - (x >> 1 & 1431655765)
	x = (x & 858993459) + (x >> 2 & 858993459)
	x = x + (x >> 4) & 252645135
	x = x + (x >> 8)
	x = x + (x >> 16)
	return x & 127

def eratosthenes(n):
	res = [0 for i in range(n + 1)]
	prime = set([])
	for i in range(2, n + 1):
		if not res[i]:
			prime.add(i)
			for j in range(1, n // i + 1):
				res[i * j] = 1
	return prime

def factorization(n):
	res = []
	for p in prime:
		if n % p == 0:
			while n % p == 0:
				n //= p
			res.append(p)
	if n != 1:
		res.append(n)
	return res

def euler_phi(n):
	res = n
	for x in range(2, n + 1):
		if x ** 2 > n:
			break
		if n % x == 0:
			res = res // x * (x - 1)
			while n % x == 0:
				n //= x
	if n != 1:
		res = res // n * (n - 1)
	return res

def ind(b, n):
	res = 0
	while n % b == 0:
		res += 1
		n //= b
	return res

def isPrimeMR(n):
	d = n - 1
	d = d // (d & -d)
	L = [2, 3, 5, 7, 11, 13, 17]
	for a in L:
		t = d
		y = pow(a, t, n)
		if y == 1:
			continue
		while y != n - 1:
			y = y * y % n
			if y == 1 or t == n - 1:
				return 0
			t <<= 1
	return 1

def findFactorRho(n):
	from math import gcd
	m = 1 << n.bit_length() // 8
	for c in range(1, 99):
		f = lambda x: (x * x + c) % n
		(y, r, q, g) = (2, 1, 1, 1)
		while g == 1:
			x = y
			for i in range(r):
				y = f(y)
			k = 0
			while k < r and g == 1:
				ys = y
				for i in range(min(m, r - k)):
					y = f(y)
					q = q * abs(x - y) % n
				g = gcd(q, n)
				k += m
			r <<= 1
		if g == n:
			g = 1
			while g == 1:
				ys = f(ys)
				g = gcd(abs(x - ys), n)
		if g < n:
			if isPrimeMR(g):
				return g
			elif isPrimeMR(n // g):
				return n // g
			return findFactorRho(g)

def primeFactor(n):
	i = 2
	ret = {}
	rhoFlg = 0
	while i * i <= n:
		k = 0
		while n % i == 0:
			n //= i
			k += 1
		if k:
			ret[i] = k
		i += 1 + i % 2
		if i == 101 and n >= 2 ** 20:
			while n > 1:
				if isPrimeMR(n):
					(ret[n], n) = (1, 1)
				else:
					rhoFlg = 1
					j = findFactorRho(n)
					k = 0
					while n % j == 0:
						n //= j
						k += 1
					ret[j] = k
	if n > 1:
		ret[n] = 1
	if rhoFlg:
		ret = {x: ret[x] for x in sorted(ret)}
	return ret

def divisors(n):
	res = [1]
	prime = primeFactor(n)
	for p in prime:
		newres = []
		for d in res:
			for j in range(prime[p] + 1):
				newres.append(d * p ** j)
		res = newres
	res.sort()
	return res

def xorfactorial(num):
	if num == 0:
		return 0
	elif num == 1:
		return 1
	elif num == 2:
		return 3
	elif num == 3:
		return 0
	else:
		x = baseorder(num)
		return 2 ** x * ((num - 2 ** x + 1) % 2) + function(num - 2 ** x)

def xorconv(n, X, Y):
	if n == 0:
		res = [X[0] * Y[0] % mod]
		return res
	x = [X[i] + X[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	y = [Y[i] + Y[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	z = [X[i] - X[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	w = [Y[i] - Y[i + 2 ** (n - 1)] for i in range(2 ** (n - 1))]
	res1 = xorconv(n - 1, x, y)
	res2 = xorconv(n - 1, z, w)
	former = [(res1[i] + res2[i]) * inv for i in range(2 ** (n - 1))]
	latter = [(res1[i] - res2[i]) * inv for i in range(2 ** (n - 1))]
	former = list(map(lambda x: x % mod, former))
	latter = list(map(lambda x: x % mod, latter))
	return former + latter

def merge_sort(A, B):
	(pos_A, pos_B) = (0, 0)
	(n, m) = (len(A), len(B))
	res = []
	while pos_A < n and pos_B < m:
		(a, b) = (A[pos_A], B[pos_B])
		if a < b:
			res.append(a)
			pos_A += 1
		else:
			res.append(b)
			pos_B += 1
	res += A[pos_A:]
	res += B[pos_B:]
	return res

class UnionFindVerSize:

	def __init__(self, N):
		self._parent = [n for n in range(0, N)]
		self._size = [1] * N
		self.group = N

	def find_root(self, x):
		if self._parent[x] == x:
			return x
		self._parent[x] = self.find_root(self._parent[x])
		stack = [x]
		while self._parent[stack[-1]] != stack[-1]:
			stack.append(self._parent[stack[-1]])
		for v in stack:
			self._parent[v] = stack[-1]
		return self._parent[x]

	def unite(self, x, y):
		gx = self.find_root(x)
		gy = self.find_root(y)
		if gx == gy:
			return
		self.group -= 1
		if self._size[gx] < self._size[gy]:
			self._parent[gx] = gy
			self._size[gy] += self._size[gx]
		else:
			self._parent[gy] = gx
			self._size[gx] += self._size[gy]

	def get_size(self, x):
		return self._size[self.find_root(x)]

	def is_same_group(self, x, y):
		return self.find_root(x) == self.find_root(y)

class WeightedUnionFind:

	def __init__(self, N):
		self.parent = [i for i in range(N)]
		self.size = [1 for i in range(N)]
		self.val = [0 for i in range(N)]
		self.flag = True
		self.edge = [[] for i in range(N)]

	def dfs(self, v, pv):
		stack = [(v, pv)]
		new_parent = self.parent[pv]
		while stack:
			(v, pv) = stack.pop()
			self.parent[v] = new_parent
			for (nv, w) in self.edge[v]:
				if nv != pv:
					self.val[nv] = self.val[v] + w
					stack.append((nv, v))

	def unite(self, x, y, w):
		if not self.flag:
			return
		if self.parent[x] == self.parent[y]:
			self.flag = self.val[x] - self.val[y] == w
			return
		if self.size[self.parent[x]] > self.size[self.parent[y]]:
			self.edge[x].append((y, -w))
			self.edge[y].append((x, w))
			self.size[x] += self.size[y]
			self.val[y] = self.val[x] - w
			self.dfs(y, x)
		else:
			self.edge[x].append((y, -w))
			self.edge[y].append((x, w))
			self.size[y] += self.size[x]
			self.val[x] = self.val[y] + w
			self.dfs(x, y)

class Dijkstra:

	class Edge:

		def __init__(self, _to, _cost):
			self.to = _to
			self.cost = _cost

	def __init__(self, V):
		self.G = [[] for i in range(V)]
		self._E = 0
		self._V = V

	@property
	def E(self):
		return self._E

	@property
	def V(self):
		return self._V

	def add_edge(self, _from, _to, _cost):
		self.G[_from].append(self.Edge(_to, _cost))
		self._E += 1

	def shortest_path(self, s):
		import heapq
		que = []
		d = [10 ** 15] * self.V
		d[s] = 0
		heapq.heappush(que, (0, s))
		while len(que) != 0:
			(cost, v) = heapq.heappop(que)
			if d[v] < cost:
				continue
			for i in range(len(self.G[v])):
				e = self.G[v][i]
				if d[e.to] > d[v] + e.cost:
					d[e.to] = d[v] + e.cost
					heapq.heappush(que, (d[e.to], e.to))
		return d

def Z_algorithm(s):
	N = len(s)
	Z_alg = [0] * N
	Z_alg[0] = N
	i = 1
	j = 0
	while i < N:
		while i + j < N and s[j] == s[i + j]:
			j += 1
		Z_alg[i] = j
		if j == 0:
			i += 1
			continue
		k = 1
		while i + k < N and k + Z_alg[k] < j:
			Z_alg[i + k] = Z_alg[k]
			k += 1
		i += k
		j -= k
	return Z_alg

class BIT:

	def __init__(self, n, mod=0):
		self.BIT = [0] * (n + 1)
		self.num = n
		self.mod = mod

	def query(self, idx):
		res_sum = 0
		mod = self.mod
		while idx > 0:
			res_sum += self.BIT[idx]
			if mod:
				res_sum %= mod
			idx -= idx & -idx
		return res_sum

	def update(self, idx, x):
		mod = self.mod
		while idx <= self.num:
			self.BIT[idx] += x
			if mod:
				self.BIT[idx] %= mod
			idx += idx & -idx
		return

class dancinglink:

	def __init__(self, n, debug=False):
		self.n = n
		self.debug = debug
		self._left = [i - 1 for i in range(n)]
		self._right = [i + 1 for i in range(n)]
		self.exist = [True for i in range(n)]

	def pop(self, k):
		if self.debug:
			assert self.exist[k]
		L = self._left[k]
		R = self._right[k]
		if L != -1:
			if R != self.n:
				(self._right[L], self._left[R]) = (R, L)
			else:
				self._right[L] = self.n
		elif R != self.n:
			self._left[R] = -1
		self.exist[k] = False

	def left(self, idx, k=1):
		if self.debug:
			assert self.exist[idx]
		res = idx
		while k:
			res = self._left[res]
			if res == -1:
				break
			k -= 1
		return res

	def right(self, idx, k=1):
		if self.debug:
			assert self.exist[idx]
		res = idx
		while k:
			res = self._right[res]
			if res == self.n:
				break
			k -= 1
		return res

class SparseTable:

	def __init__(self, A, merge_func, ide_ele):
		N = len(A)
		n = N.bit_length()
		self.table = [[ide_ele for i in range(n)] for i in range(N)]
		self.merge_func = merge_func
		for i in range(N):
			self.table[i][0] = A[i]
		for j in range(1, n):
			for i in range(0, N - 2 ** j + 1):
				f = self.table[i][j - 1]
				s = self.table[i + 2 ** (j - 1)][j - 1]
				self.table[i][j] = self.merge_func(f, s)

	def query(self, s, t):
		b = t - s + 1
		m = b.bit_length() - 1
		return self.merge_func(self.table[s][m], self.table[t - 2 ** m + 1][m])

class BinaryTrie:

	class node:

		def __init__(self, val):
			self.left = None
			self.right = None
			self.max = val

	def __init__(self):
		self.root = self.node(-10 ** 15)

	def append(self, key, val):
		pos = self.root
		for i in range(29, -1, -1):
			pos.max = max(pos.max, val)
			if key >> i & 1:
				if pos.right is None:
					pos.right = self.node(val)
					pos = pos.right
				else:
					pos = pos.right
			elif pos.left is None:
				pos.left = self.node(val)
				pos = pos.left
			else:
				pos = pos.left
		pos.max = max(pos.max, val)

	def search(self, M, xor):
		res = -10 ** 15
		pos = self.root
		for i in range(29, -1, -1):
			if pos is None:
				break
			if M >> i & 1:
				if xor >> i & 1:
					if pos.right:
						res = max(res, pos.right.max)
					pos = pos.left
				else:
					if pos.left:
						res = max(res, pos.left.max)
					pos = pos.right
			elif xor >> i & 1:
				pos = pos.right
			else:
				pos = pos.left
		if pos:
			res = max(res, pos.max)
		return res

def solveequation(edge, ans, n, m):
	x = [0] * m
	used = [False] * n
	for v in range(n):
		if used[v]:
			continue
		y = dfs(v)
		if y != 0:
			return False
	return x

	def dfs(v):
		used[v] = True
		r = ans[v]
		for (to, dire, id) in edge[v]:
			if used[to]:
				continue
			y = dfs(to)
			if dire == -1:
				x[id] = y
			else:
				x[id] = -y
			r += y
		return r

class SegmentTree:

	def __init__(self, init_val, segfunc, ide_ele):
		n = len(init_val)
		self.segfunc = segfunc
		self.ide_ele = ide_ele
		self.num = 1 << (n - 1).bit_length()
		self.tree = [ide_ele] * 2 * self.num
		self.size = n
		for i in range(n):
			self.tree[self.num + i] = init_val[i]
		for i in range(self.num - 1, 0, -1):
			self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

	def update(self, k, x):
		k += self.num
		self.tree[k] = x
		while k > 1:
			self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
			k >>= 1

	def query(self, l, r):
		if r == self.size:
			r = self.num
		res = self.ide_ele
		l += self.num
		r += self.num
		while l < r:
			if l & 1:
				res = self.segfunc(res, self.tree[l])
				l += 1
			if r & 1:
				res = self.segfunc(res, self.tree[r - 1])
			l >>= 1
			r >>= 1
		return res

	def bisect_l(self, l, r, x):
		l += self.num
		r += self.num
		Lmin = -1
		Rmin = -1
		while l < r:
			if l & 1:
				if self.tree[l] <= x and Lmin == -1:
					Lmin = l
				l += 1
			if r & 1:
				if self.tree[r - 1] <= x:
					Rmin = r - 1
			l >>= 1
			r >>= 1
		if Lmin != -1:
			pos = Lmin
			while pos < self.num:
				if self.tree[2 * pos] <= x:
					pos = 2 * pos
				else:
					pos = 2 * pos + 1
			return pos - self.num
		elif Rmin != -1:
			pos = Rmin
			while pos < self.num:
				if self.tree[2 * pos] <= x:
					pos = 2 * pos
				else:
					pos = 2 * pos + 1
			return pos - self.num
		else:
			return -1
import sys, random, bisect
from collections import deque, defaultdict
from heapq import heapify, heappop, heappush
from itertools import permutations
from math import gcd, log
input = lambda : sys.stdin.readline().rstrip()
mi = lambda : map(int, input().split())
li = lambda : list(mi())
c = {'+': 1, '-': -1}
for _ in range(int(input())):
	(n, q) = mi()
	S = input()
	A = [0]
	for i in range(n):
		if i & 1:
			A.append(-c[S[i]])
		else:
			A.append(c[S[i]])
	for i in range(1, n + 1):
		A[i] += A[i - 1]
	for i in range(q):
		(l, r) = mi()
		if r - l + 1 & 1:
			print(1)
		else:
			tmp = A[r] - A[l - 1]
			if tmp == 0:
				print(0)
			else:
				print(2)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input().strip()
	a = 0
	p = [0] * (n + 1)
	for (i, j) in enumerate(s):
		a += 1 if (j == '+') ^ i % 2 else -1
		p[i + 1] = a
	for _ in range(q):
		(l, r) = map(int, input().split())
		a = p[r] - p[l - 1]
		print(1 if a % 2 else 2 if a else 0)


import os
import sys
import math
from io import BytesIO, IOBase
import io
from fractions import Fraction
import collections
from itertools import permutations
from collections import defaultdict
from collections import deque
from collections import Counter
import threading
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class SegmentTree:

	def __init__(self, data, default=0, func=lambda a, b: math.gcd(a, b)):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree1:

	def __init__(self, data, default=0, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)
MOD = 10 ** 9 + 7

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD
mod = 10 ** 9 + 7
omod = 998244353
prime = [True for i in range(11)]
prime[0] = prime[1] = False

def SieveOfEratosthenes(n=10):
	p = 2
	c = 0
	while p <= n:
		if prime[p] == True:
			c += 1
			for i in range(p, n + 1, p):
				prime[i] = False
		p += 1

class DSU:

	def __init__(self, R, C):
		self.par = range(R * C + 1)
		self.rnk = [0] * (R * C + 1)
		self.sz = [1] * (R * C + 1)

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return
		if self.rnk[xr] < self.rnk[yr]:
			(xr, yr) = (yr, xr)
		if self.rnk[xr] == self.rnk[yr]:
			self.rnk[xr] += 1
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]

	def size(self, x):
		return self.sz[self.find(x)]

	def top(self):
		return self.size(len(self.sz) - 1) - 1

class LazySegTree:

	def __init__(self, _op, _e, _mapping, _composition, _id, v):

		def set(p, x):
			assert 0 <= p < _n
			p += _size
			for i in range(_log, 0, -1):
				_push(p >> i)
			_d[p] = x
			for i in range(1, _log + 1):
				_update(p >> i)

		def get(p):
			assert 0 <= p < _n
			p += _size
			for i in range(_log, 0, -1):
				_push(p >> i)
			return _d[p]

		def prod(l, r):
			assert 0 <= l <= r <= _n
			if l == r:
				return _e
			l += _size
			r += _size
			for i in range(_log, 0, -1):
				if l >> i << i != l:
					_push(l >> i)
				if r >> i << i != r:
					_push(r >> i)
			sml = _e
			smr = _e
			while l < r:
				if l & 1:
					sml = _op(sml, _d[l])
					l += 1
				if r & 1:
					r -= 1
					smr = _op(_d[r], smr)
				l >>= 1
				r >>= 1
			return _op(sml, smr)

		def apply(l, r, f):
			assert 0 <= l <= r <= _n
			if l == r:
				return
			l += _size
			r += _size
			for i in range(_log, 0, -1):
				if l >> i << i != l:
					_push(l >> i)
				if r >> i << i != r:
					_push(r - 1 >> i)
			l2 = l
			r2 = r
			while l < r:
				if l & 1:
					_all_apply(l, f)
					l += 1
				if r & 1:
					r -= 1
					_all_apply(r, f)
				l >>= 1
				r >>= 1
			l = l2
			r = r2
			for i in range(1, _log + 1):
				if l >> i << i != l:
					_update(l >> i)
				if r >> i << i != r:
					_update(r - 1 >> i)

		def _update(k):
			_d[k] = _op(_d[2 * k], _d[2 * k + 1])

		def _all_apply(k, f):
			_d[k] = _mapping(f, _d[k])
			if k < _size:
				_lz[k] = _composition(f, _lz[k])

		def _push(k):
			_all_apply(2 * k, _lz[k])
			_all_apply(2 * k + 1, _lz[k])
			_lz[k] = _id
		_n = len(v)
		_log = _n.bit_length()
		_size = 1 << _log
		_d = [_e] * (2 * _size)
		_lz = [_id] * _size
		for i in range(_n):
			_d[_size + i] = v[i]
		for i in range(_size - 1, 0, -1):
			_update(i)
		self.set = set
		self.get = get
		self.prod = prod
		self.apply = apply
MIL = 1 << 20

def makeNode(total, count):
	return total * MIL + count

def getTotal(node):
	return math.floor(node / MIL)

def getCount(node):
	return node - getTotal(node) * MIL
nodeIdentity = makeNode(0.0, 0.0)

def nodeOp(node1, node2):
	return node1 + node2
	return makeNode(getTotal(node1) + getTotal(node2), getCount(node1) + getCount(node2))
identityMapping = -1

def mapping(tag, node):
	if tag == identityMapping:
		return node
	count = getCount(node)
	return makeNode(tag * count, count)

def composition(mapping1, mapping2):
	return mapping1 if mapping1 != identityMapping else mapping2

def memodict(f):

	class memodict(dict):

		def __missing__(self, key):
			ret = self[key] = f(key)
			return ret
	return memodict().__getitem__

def pollard_rho(n):
	if n & 1 == 0:
		return 2
	if n % 3 == 0:
		return 3
	s = (n - 1 & 1 - n).bit_length() - 1
	d = n >> s
	for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
		p = pow(a, d, n)
		if p == 1 or p == n - 1 or a % n == 0:
			continue
		for _ in range(s):
			prev = p
			p = p * p % n
			if p == 1:
				return math.gcd(prev - 1, n)
			if p == n - 1:
				break
		else:
			for i in range(2, n):
				(x, y) = (i, (i * i + 1) % n)
				f = math.gcd(abs(x - y), n)
				while f == 1:
					(x, y) = ((x * x + 1) % n, (y * y + 1) % n)
					y = (y * y + 1) % n
					f = math.gcd(abs(x - y), n)
				if f != n:
					return f
	return n

@memodict
def prime_factors(n):
	if n <= 1:
		return Counter()
	f = pollard_rho(n)
	return Counter([n]) if f == n else prime_factors(f) + prime_factors(n // f)

def distinct_factors(n):
	factors = [1]
	for (p, exp) in prime_factors(n).items():
		factors += [p ** i * factor for factor in factors for i in range(1, exp + 1)]
	return factors

def all_factors(n):
	(small, large) = ([], [])
	for i in range(1, int(n ** 0.5) + 1, 2 if n & 1 else 1):
		if not n % i:
			small.append(i)
			large.append(n // i)
	if small[-1] == large[-1]:
		large.pop()
	large.reverse()
	small.extend(large)
	return small

def binarySearch(arr, n, key):
	left = 0
	right = n - 1
	mid = 0
	res = n
	while left <= right:
		mid = (right + left) // 2
		if arr[mid] > key:
			res = mid
			right = mid - 1
		else:
			left = mid + 1
	return res

def binarySearch1(arr, n, key):
	left = 0
	right = n - 1
	mid = 0
	res = -1
	while left <= right:
		mid = (right + left) // 2
		if arr[mid] > key:
			right = mid - 1
		else:
			res = mid
			left = mid + 1
	return res
t = 1
t = int(input())
for _ in range(t):
	(n, q) = map(int, input().split())
	s = input()
	pre = [0] * (n + 1)
	m = 1
	for i in range(n):
		if s[i] == '+':
			pre[i + 1] = pre[i] + m
		else:
			pre[i + 1] = pre[i] - m
		m *= -1
	for i in range(q):
		(l, r) = map(int, input().split())
		l -= 1
		parity = (r - l) % 2
		sm = pre[r] - pre[l]
		if sm == 0:
			print(0)
		elif parity:
			print(1)
		else:
			print(2)


from __future__ import division, print_function
import math
import sys
import os
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def inp():
	return int(input())

def inps():
	return input().strip()

def inlt():
	return list(map(int, input().split()))

def insr():
	s = input().strip()
	return list(s[:len(s)])

def invr():
	return map(int, input().split())

def mdn(v):
	if v == 0:
		return 0
	if v % 2:
		return 1
	return 2
for _ in range(inp()):
	(n, q) = invr()
	s = insr()
	d = {'+': 1, '-': -1}
	l = [0]
	for i in range(n):
		if i % 2:
			l.append(l[-1] - d[s[i]])
		else:
			l.append(l[-1] + d[s[i]])
	for i in range(q):
		(lf, rt) = invr()
		print(mdn(l[rt] - l[lf - 1]))


from sys import stdin, stdout

def INPUT():
	return list((int(i) for i in stdin.readline().split()))

def inp():
	return stdin.readline()

def out(x):
	return stdout.write(x)
from math import *
from decimal import *
INT_MAX = 10 ** 13
from bisect import bisect_left
import sys
MOD = 10 ** 9 + 7
from random import randint as R
from heapq import heappush, heappop, heapify
for _ in range(int(input())):
	(n, q) = map(int, stdin.readline().split())
	s = inp()
	A = []
	for i in range(n):
		if s[i] == '+':
			if i % 2 == 0:
				A.append(1)
			else:
				A.append(-1)
		elif i % 2 == 0:
			A.append(-1)
		else:
			A.append(1)
	S = [0]
	for i in range(n):
		S.append(S[-1] + A[i])
	for _ in range(q):
		(l, r) = map(int, stdin.readline().split())
		if S[r] - S[l - 1] == 0:
			print(0)
		elif (r - l + 1) % 2 == 0:
			out(str(2) + '\n')
		else:
			out(str(1) + '\n')


from sys import stdin, stdout, setrecursionlimit
from io import BytesIO, IOBase
setrecursionlimit(10000)

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None
		self.BUFSIZE = 8192

	def read(self):
		while True:
			a = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, self.BUFSIZE))
			if not a:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(a), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			a = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, self.BUFSIZE))
			self.newlines = a.count(b'\n') + (not a)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(a), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(stdin, stdout) = (IOWrapper(stdin), IOWrapper(stdout))
input = lambda : stdin.readline().rstrip('\r\n')
inp = lambda : int(input())
st = lambda : input().strip()
jn = lambda x, l: x.join(map(str, l))
int_arr = lambda : list(map(int, input().strip().split()))
str_arr = lambda : list(map(str, input().split()))
get_str = lambda : map(str, input().strip().split())
get_int = lambda : map(int, input().strip().split())
get_float = lambda : map(float, input().strip().split())
mod = 1000000007
for _ in range(inp()):
	(n, q) = get_int()
	s = st()
	dp = [0] * n
	dp[0] = 1 if s[0] == '+' else -1
	for i in range(1, n):
		c1 = -1 if i % 2 else 1
		c2 = 1 if s[i] == '+' else -1
		dp[i] = dp[i - 1] + c1 * c2
	for i in range(q):
		(l, r) = get_int()
		l -= 1
		r -= 1
		ans = dp[r] - (dp[l - 1] if l >= 1 else 0)
		if not ans:
			print(0)
		else:
			print(1 if ans % 2 else 2)


import sys
import math
from bisect import bisect_right as br
from itertools import combinations as cb

def int_arr():
	return list(map(int, sys.stdin.readline().strip().split()))

def str_arr():
	return list(map(str, sys.stdin.readline().strip().split()))

def input():
	return sys.stdin.readline().strip()
for _ in range(int(input())):
	(n, q) = int_arr()
	st = input()
	pref = [0]
	lst = 0
	for i in range(n):
		if i % 2 == 0:
			lst += 1 if st[i] == '+' else -1
			pref.append(lst)
		else:
			lst += -1 if st[i] == '+' else 1
			pref.append(lst)
	for i in range(q):
		(l, r) = int_arr()
		if pref[r] - pref[l - 1] == 0:
			print(0)
		elif (r - l) % 2 == 0:
			print(1)
		else:
			print(2)


import sys
input = sys.stdin.buffer.readline
from itertools import accumulate
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	arr = list(input())
	for i in range(n):
		arr[i] = chr(arr[i])
	for i in range(n):
		if arr[i] == '+':
			arr[i] = 1
		else:
			arr[i] = -1
	for i in range(n):
		if (i - n) % 2 == 0:
			arr[i] = arr[i] * 1
		else:
			arr[i] = arr[i] * -1
	brr = list(accumulate(arr))
	for i in range(q):
		(l, r) = map(int, input().split())
		r -= 1
		l -= 1
		c = 0
		if l == 0:
			c = brr[r]
		else:
			c = brr[r] - brr[l - 1]
		if c == 0:
			print(0)
		elif c % 2 == 1:
			print(1)
		else:
			print(2)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import ceil

def prod(a, mod=10 ** 9 + 7):
	ans = 1
	for each in a:
		ans = ans * each % mod
	return ans

def gcd(x, y):
	while y:
		(x, y) = (y, x % y)
	return x

def lcm(a, b):
	return a * b // gcd(a, b)

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y
from bisect import bisect_left, bisect_right

class Result:

	def __init__(self, index, value):
		self.index = index
		self.value = value

class BinarySearch:

	def __init__(self):
		pass

	@staticmethod
	def greater_than(num: int, func, size: int=1):
		if isinstance(func, list):
			index = bisect_right(func, num)
			if index == len(func):
				return Result(None, None)
			else:
				return Result(index, func[index])
		else:
			(alpha, omega) = (0, size - 1)
			if func(omega) <= num:
				return Result(None, None)
			while alpha < omega:
				if func(alpha) > num:
					return Result(alpha, func(alpha))
				if omega == alpha + 1:
					return Result(omega, func(omega))
				mid = (alpha + omega) // 2
				if func(mid) > num:
					omega = mid
				else:
					alpha = mid

	@staticmethod
	def less_than(num: int, func, size: int=1):
		if isinstance(func, list):
			index = bisect_left(func, num) - 1
			if index == -1:
				return Result(None, None)
			else:
				return Result(index, func[index])
		else:
			(alpha, omega) = (0, size - 1)
			if func(alpha) >= num:
				return Result(None, None)
			while alpha < omega:
				if func(omega) < num:
					return Result(omega, func(omega))
				if omega == alpha + 1:
					return Result(alpha, func(alpha))
				mid = (alpha + omega) // 2
				if func(mid) < num:
					alpha = mid
				else:
					omega = mid
bs = BinarySearch()
for _ in range(int(input()) if True else 1):
	(n, q) = map(int, input().split())
	s = input()
	di = {}
	pre = [0]
	for i in range(n):
		pre += [pre[-1] + (1 if i % 2 == 0 and s[i] == '+' or (i % 2 and s[i] == '-') else -1)]
		ch = (pre[-2], pre[-1])
		if ch not in di:
			di[ch] = []
		di[ch] += [i]

	def get(x, y):
		diff = pre[y + 1] - pre[x]
		final = pre[y + 1]
		t1 = pre[x] + (-(-diff // 2) if diff < 0 else diff // 2)
		t2 = t1 + 1 if final > pre[x] else t1 - 1
		assert final == pre[y + 1]
		return bs.greater_than(x - 1, di[t1, t2]).value + 1
	for __ in range(q):
		(x, y) = map(int, input().split())
		x -= 1
		y -= 1
		if pre[y + 1] - pre[x] == 0:
			print(0)
			continue
		elif (y - x + 1) % 2:
			print(1)
		else:
			print(2)


class SegmentTree:

	def __init__(self, n, oper, e):
		self.n = n
		self.oper = oper
		self.e = e
		self.log = (n - 1).bit_length()
		self.size = 1 << self.log
		self.data = [e] * (2 * self.size)

	def update(self, k):
		self.data[k] = self.oper(self.data[2 * k], self.data[2 * k + 1])

	def build(self, arr):
		for i in range(self.n):
			self.data[self.size + i] = arr[i]
		for i in range(self.size - 1, 0, -1):
			self.update(i)

	def set(self, p, x):
		p += self.size
		self.data[p] = x
		for i in range(self.log):
			p >>= 1
			self.update(p)

	def get(self, p):
		return self.data[p + self.size]

	def prod(self, l, r):
		sml = smr = self.e
		l += self.size
		r += self.size
		while l < r:
			if l & 1:
				sml = self.oper(sml, self.data[l])
				l += 1
			if r & 1:
				r -= 1
				smr = self.oper(self.data[r], smr)
			l >>= 1
			r >>= 1
		return self.oper(sml, smr)

	def all_prod(self):
		return self.data[1]

class S:

	def __init__(self, m, s):
		self.m = m
		self.s = s
		self.e = s ^ m + 1 & 1

def op(x, y):
	if x.m == 0:
		return S(y.m, y.s)
	if y.m == 0:
		return S(x.m, x.s)
	if x.e != y.s:
		return S(x.m + y.m, x.s)
	if x.m >= y.m:
		return S(x.m - y.m, x.s)
	return S(y.m - x.m, 1 - x.s)
e = S(0, 1)
e1 = S(1, 1)
e0 = S(1, 0)

def solve():
	(n, q) = map(int, input().split())
	s = input()
	arr = [S(1, 1) if c == '+' else S(1, 0) for c in s]
	seg = SegmentTree(n, op, e)
	seg.build(arr)
	for _ in range(q):
		(x, y) = map(int, input().split())
		k = seg.prod(x - 1, y).m
		if k == 0:
			print(0)
		else:
			print(2 - k % 2)
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
t = int(input())
for i in range(t):
	solve()


import itertools as _itertools
import sys as _sys

def which_rods_should_remove_to_make_machine_charged_correctly(rods, queries):
	rods = [+x if i % 2 == 0 else -x for (i, x) in enumerate(rods)]
	prefix_sums = tuple(_itertools.accumulate(rods))
	for query in queries:
		yield tuple(_process_query(query, prefix_sums))

def _process_query(query, prefix_sums):

	def get_prefix_sum(i):
		return prefix_sums[i] if i >= 0 else 0
	(l, r) = query
	sum_before_prefix = get_prefix_sum(l - 1)
	initial_sum = get_prefix_sum(r) - sum_before_prefix
	if initial_sum == 0:
		return
	if (initial_sum - 1) % 2 != 0:
		yield from _process_query((l, r - 1), prefix_sums)
		yield r
		return

	def get_sum_by_deletion(i):
		sum_before_deletion = get_prefix_sum(i - 1) - sum_before_prefix
		sum_after_deletion = get_prefix_sum(r) - get_prefix_sum(i)
		return sum_before_deletion - sum_after_deletion
	first_sum = get_sum_by_deletion(r)
	if first_sum == 0:
		yield r
		return
	min_i_to_del = l
	max_i_to_del = r
	while min_i_to_del != max_i_to_del:
		i = (min_i_to_del + max_i_to_del) // 2
		current_sum = get_sum_by_deletion(i)
		if current_sum * first_sum < 0:
			min_i_to_del = i + 1
		else:
			max_i_to_del = i
	i_to_del = min_i_to_del
	yield i_to_del

def _main():
	output = []
	[tests_n] = _read_ints()
	for i_test in range(tests_n):
		[rods_n, queries_n] = _read_ints()
		rods = _read_string()
		assert len(rods) == rods_n and set(rods).issubset({'+', '-'})
		rods = [+1 if ch == '+' else -1 for ch in rods]
		queries = [_read_query() for i_query in range(queries_n)]
		results = which_rods_should_remove_to_make_machine_charged_correctly(rods, queries)
		for result in results:
			output.append(str(len(result)))
	_sys.stdout.write('\n'.join(output))
	_sys.stdout.write('\n')

def _read_query(file=_sys.stdin):
	[l, r] = _read_ints(file)
	l -= 1
	r -= 1
	return (l, r)

def _read_ints(file=_sys.stdin):
	return map(int, _read_string(file).split())

def _read_string(file=_sys.stdin):
	[result] = file.readline().splitlines()
	return result
_main()


import sys
input = sys.stdin.readline
for i in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()
	if n == 1:
		l = [0, [1, -1][s == '-']]
	else:
		l = [[1, -1][s[0] == '-'], [1, -1][s[0] == '-'] - [1, -1][s[1] == '-']]
		for i in range(2, n):
			f = [1, -1][s[i] == '-']
			if i % 2 != 0:
				l.append(l[-2] + ([1, -1][s[i - 1] == '-'] - f))
			else:
				l.append(l[-1] + f)
		l = [0] + l
	for i in range(q):
		(k, r) = map(int, input().split())
		ff = abs(l[r] - l[k - 1])
		if ff == 0:
			print(0)
		elif ff % 2 == 0:
			print(2)
		else:
			print(1)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = [i for i in input()]
	for i in range(n):
		if s[i] == '+':
			s[i] = 1
		else:
			s[i] = -1
	pre = [0] * (n + 1)
	for i in range(n):
		curr = 0
		if i & 1:
			curr = -1 * s[i]
		else:
			curr = s[i]
		pre[i + 1] = pre[i] + curr
	for i in range(q):
		(l, r) = map(int, input().split())
		l -= 1
		if r - l & 1:
			print(1)
		elif pre[r] == pre[l]:
			print(0)
		else:
			print(2)


answer = []
for i in range(int(input())):
	(_, question_count) = map(int, input().split(' '))
	sums = [0]
	sign = 1
	for charge in input():
		change = sign if charge == '+' else -sign
		sign *= -1
		sums.append(sums[-1] + change)
	for _ in range(question_count):
		(mn, mx) = map(int, input().split(' '))
		sm = sums[mx] - sums[mn - 1]
		if sm == 0:
			answer.append(0)
		elif sm % 2:
			answer.append(1)
		else:
			answer.append(2)
for i in answer:
	print(i)


from itertools import accumulate
from sys import stdin, stdout
input = stdin.readline

def print(x):
	return stdout.write(str(x) + '\n')
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()
	nums = []
	for i in range(n):
		if s[i] == '+' and i % 2 == 0 or (s[i] == '-' and i % 2 == 1):
			nums.append(1)
		else:
			nums.append(0)
	a = list(accumulate(nums))
	for _ in range(q):
		(li, ri) = map(int, input().split())
		if (ri - li) % 2 == 0:
			print(1)
		elif li == 1 and a[ri - 1] == ri // 2:
			print(0)
		elif li != 1 and a[ri - 1] - a[li - 2] == (ri - li + 1) // 2:
			print(0)
		else:
			print(2)


import sys, math
input = sys.stdin.readline
INF = int(1000000000.0) + 7

def solve():
	(n, q) = map(int, input().split())
	s = input().rstrip()
	cache = [0] * (n + 1)
	summ = 0
	k = 0
	for i in range(n):
		if s[i] == '+':
			k = 1
		else:
			k = -1
		if i % 2 == 0:
			summ += k
		else:
			summ -= k
		cache[i + 1] = summ
	for _ in range(q):
		(a, b) = map(int, input().split())
		k = abs(cache[b] - cache[a - 1])
		if k == 0:
			print(0)
		elif k % 2 == 0:
			print(2)
		else:
			print(1)
t = int(input())
while t:
	t -= 1
	solve()


import os, sys, math
from io import BytesIO, IOBase
ip = lambda : input()
it = lambda : int(input())
ma = lambda : map(int, input().split(' '))
li = lambda : list(map(int, input().split(' ')))
mod = 10 ** 9 + 7

def f(a, n, s):
	for i in range(1 - s, n - 1, 2):
		if a[i] > a[i + 1]:
			(a[i], a[i + 1]) = (a[i + 1], a[i])
	return a

def main():
	for _ in range(int(input())):
		(n, q) = ma()
		s = ip()
		c = [0] * (n + 1)
		x = 0
		for i in range(1, n + 1):
			if s[i - 1] == '+':
				if i % 2:
					x += 1
				else:
					x -= 1
			elif i % 2:
				x -= 1
			else:
				x += 1
			c[i] = x
		for i in range(q):
			(l, r) = ma()
			z = c[r] - c[l - 1]
			if z == 0:
				print(0)
				continue
			if (r - l + 1) % 2:
				print(1)
				continue
			print(2)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


from sys import stdin
input = stdin.readline

def f(s):
	s = list(s)
	d = {'+': 1, '-': -1}
	d2 = {1: '+', -1: '-'}
	d3 = {'+': 0, '-': 1}
	pref = []
	for i in range(len(s)):
		pp = d2[d[s[i]] * pow(-1, i)]
		if i == 0:
			ll = [0, 0]
			ll[d3[pp]] += 1
			pref.append(ll)
		else:
			ll = pref[-1].copy()
			ll[d3[pp]] += 1
			pref.append(ll)
	return pref
for t in range(int(input())):
	(n, m) = map(int, input().strip().split())
	s = input().strip()
	pref = f(s)
	for i in range(m):
		(l, r) = map(int, input().strip().split())
		l -= 1
		r -= 1
		ll = r - l + 1
		lr = [0, 0]
		if l != 0:
			lr = pref[l - 1]
		rr = pref[r]
		cp = rr[0] - lr[0]
		cp2 = rr[1] - lr[1]
		if cp == cp2:
			print(0)
		elif ll % 2 == 0:
			print(2)
		else:
			print(1)


from itertools import product
import itertools
import math
import sys
import heapq
from collections import deque
MOD = 1000000000007

def find(parent, i):
	if parent[i] != i:
		parent[i] = find(parent, parent[i])
	return parent[i]

def union(parent, rank, xx, yy):
	x = find(parent, xx)
	y = find(parent, yy)
	if rank[x] > rank[y]:
		parent[y] = x
	elif rank[y] > rank[x]:
		parent[x] = y
	else:
		parent[y] = x
		rank[x] += 1
ans = 0
K = int(sys.stdin.readline().strip())
x = 0
y = 0
np = {1, 4, 6, 8, 9}
p = {2, 3, 5, 7}
for _ in range(K):
	(n, q) = list(map(int, sys.stdin.readline().strip().split()))
	ss = sys.stdin.readline().strip()
	r = 0
	s = []
	pre = [0]
	for i in range(n):
		c = ss[i]
		if c == '+':
			s.append(1)
		else:
			s.append(-1)
		if i % 2 == 1:
			r -= s[-1]
		else:
			r += s[-1]
		pre.append(r)
	for _ in range(q):
		ans = 0
		l = []
		(ll, rr) = list(map(int, sys.stdin.readline().strip().split()))
		r = pre[rr] - pre[ll - 1]
		if r == 0:
			print(0)
		elif r % 2 == 1:
			print(1)
		else:
			print(2)


import sys
input = sys.stdin.readline
for nt in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()
	a = []
	for i in range(n):
		if i % 2:
			if s[i] == '+':
				a.append(-1)
			else:
				a.append(1)
		elif s[i] == '+':
			a.append(1)
		else:
			a.append(-1)
	p = [0]
	for i in range(n):
		p.append(p[-1] + a[i])
	for i in range(q):
		(l, r) = map(int, input().split())
		if p[r] - p[l - 1] == 0:
			print(0)
			continue
		if (r - l + 1) % 2:
			print(1)
		else:
			print(2)


import sys
input = sys.stdin.readline

def inp():
	return int(input())

def st():
	return input().rstrip('\n')

def lis():
	return list(map(int, input().split()))

def ma():
	return map(int, input().split())
t = inp()
while t:
	t -= 1
	(n, q) = ma()
	s = st()
	pos = [0]
	neg = [0]
	npos = [0]
	nneg = [0]
	for i in range(n):
		if s[i] == '-' and i % 2 == 0:
			npos.append(1 + npos[-1])
			nneg.append(1 + nneg[-1])
		elif s[i] == '-' and i % 2:
			nneg.append(1 + nneg[-1])
			npos.append(npos[-1])
		else:
			nneg.append(nneg[-1])
			npos.append(npos[-1])
		if s[i] == '+' and i % 2 == 0:
			pos.append(pos[-1] + 1)
			neg.append(neg[-1])
		elif s[i] == '-' and i % 2:
			pos.append(pos[-1] + 1)
			neg.append(neg[-1])
		else:
			neg.append(neg[-1] + 1)
			pos.append(pos[-1])
	for i in range(q):
		(l, r) = ma()
		cur1 = pos[r] - pos[l - 1]
		cur2 = neg[r] - neg[l - 1]
		if (r - l) % 2 == 0:
			print(1)
		elif cur1 == cur2:
			print(0)
		else:
			print(2)


import sys
input = lambda : sys.stdin.readline()
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()
	a = [0]
	t = -1
	for i in s:
		t *= -1
		if i == '+':
			t1 = 1
		else:
			t1 = -1
		a.append(t1 * t)
	sm = [0, a[1]]
	for i in range(2, n + 1):
		sm.append(sm[i - 1] + a[i])
	ans = []
	for i in range(q):
		(l, r) = map(int, input().split())
		if (r - l) % 2 == 0:
			ans.append('1')
		elif sm[r] - sm[l - 1] == 0:
			ans.append('0')
		else:
			ans.append('2')
	print('\n'.join(ans))


import itertools
import operator

def main():
	n = int(input())
	for _ in range(n):
		(k, q) = [int(num_str) for num_str in input().split()[:2]]
		seq = input()[:k]
		questions = []
		for qi in range(q):
			questions.append(tuple((int(num_str) for num_str in input().split())))
		solve(seq, questions)

def solve(seq, questions):
	seq = [1 if s == '+' else -1 for s in seq]
	seq = [elem if i % 2 == 0 else -elem for (i, elem) in enumerate(seq)]
	cumsum = list(itertools.accumulate(seq, func=operator.add, initial=0))
	for (l, r) in questions:
		if (r - l + 1) % 2 == 1:
			print(1)
		elif cumsum[r] - cumsum[l - 1] == 0:
			print(0)
		else:
			print(2)
main()


import sys

def fun(s, i, n, x, arr):
	if i == n:
		if s == 0:
			return 0
		return 100
	elif x == 0:
		return min(fun(s + arr[i], i + 1, n, 1, arr), 1 + fun(s, i + 1, n, 0, arr))
	else:
		return min(fun(s - arr[i], i + 1, n, 0, arr), 1 + fun(s, i + 1, n, 1, arr))
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	arr = [0] * n
	s = sys.stdin.readline()
	pref = [0] * (n + 1)
	st = 0
	for i in range(n):
		if s[i] == '+':
			arr[i] = 1
		else:
			arr[i] = -1
	st = 0
	for i in range(n):
		if i % 2 == 0:
			st += arr[i]
		else:
			st += -arr[i]
		pref[i] = st
	for i in range(q):
		(x, y) = map(int, sys.stdin.readline().split())
		if pref[y - 1] - pref[x - 2] == 0:
			ans = 0
		elif (pref[y - 1] - pref[x - 2]) % 2 == 0:
			ans = 2
		else:
			ans = 1
		sys.stdout.write(str(ans) + '\n')


class Dsu:

	def __init__(self, n):
		self.parent = list(range(n))
		self.rank = [1] * n

	def find(self, x):
		while x != self.parent[x]:
			self.parent[x] = self.parent[self.parent[x]]
			x = self.parent[x]
		return x

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return 0
		if self.rank[py] > self.rank[px]:
			(px, py) = (py, px)
		self.parent[py] = px
		self.rank[px] += self.rank[py]
		return 1

	def get_size(self, x):
		return self.rank[self.find(x)]

class SegTree:

	def __init__(self, n, array):
		self.n = n
		self.tree = [0] * (2 * n)
		for i in range(n, 2 * n):
			self.tree[i] = array[i - n]
		for i in range(n - 1, -1, -1):
			self.tree[i] = self.tree[2 * i] + self.tree[2 * i + 1]

	def update(self, i, val):
		self.tree[i] = val
		while i:
			self.tree[i] = self.tree[i * 2] + self.tree[i * 2 + 1]
			i //= 2

	def query(self):
		pass

	def top(self):
		return self.tree[0]
from sys import stdin, stdout
from bisect import bisect_left, bisect_right
from math import ceil, floor, log, gcd, sqrt
from collections import Counter, deque
from heapq import heappush, heappop, heapify

def re():
	return stdin.readline().rstrip()

def ints():
	return map(int, stdin.readline().split())

def test(tc):
	for _ in range(tc):
		solve()
mod = 1000000007
nl = '\n'

def solve():
	(n, q) = ints()
	s = 'z' + re()
	pref = [0] * (n + 1)
	for i in range(1, n + 1):
		if i & 1:
			if s[i] == '+':
				pref[i] = 1
			else:
				pref[i] = -1
		elif s[i] == '+':
			pref[i] = -1
		else:
			pref[i] = 1
		pref[i] += pref[i - 1]
	for i in range(q):
		(l, r) = ints()
		ans = pref[r] - pref[l - 1]
		if ans == 0:
			print(0)
		elif ans % 2:
			print(1)
		else:
			print(2)
	return
test(int(re()))


import sys, os, io
input = sys.stdin.readline
from math import sqrt
for _ in range(int(input())):
	(n, q) = [int(i) for i in input().split()]
	s = input().strip()
	cnt1 = [0] * n
	cnt2 = [0] * n
	for i in range(n):
		if s[i] == '+' and i % 2 == 0:
			cnt1[i] += 1
		elif s[i] == '+' and i % 2 == 1:
			cnt2[i] += 1
		elif s[i] == '-' and i % 2 == 0:
			cnt2[i] += 1
		else:
			cnt1[i] += 1
	for i in range(1, n):
		cnt1[i] += cnt1[i - 1]
		cnt2[i] += cnt2[i - 1]
	cnt1.append(0)
	cnt2.append(0)
	for qi in range(q):
		(l, r) = [int(i) - 1 for i in input().split()]
		diff = abs(cnt1[r] - cnt1[l - 1] - cnt2[r] + cnt2[l - 1])
		if (l - r + 1) % 2 == 1:
			print(1)
		elif diff:
			print(2)
		else:
			print(0)


import os
import sys
from io import BytesIO, IOBase

def main():
	pass
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()
T = int(input())
for _ in range(T):
	(n, q) = map(int, input().split())
	s = list(input())
	pre = [0 for i in range(n + 1)]
	for i in range(n):
		if s[i] == '+':
			if i % 2 == 0:
				pre[i + 1] = pre[i] + 1
			else:
				pre[i + 1] = pre[i] - 1
		elif i % 2 == 0:
			pre[i + 1] = pre[i] - 1
		else:
			pre[i + 1] = pre[i] + 1
	for i in range(q):
		(l, r) = map(int, input().split())
		v = pre[r] - pre[l - 1]
		if v == 0:
			print(0)
		elif v % 2 == 0:
			print(2)
		else:
			print(1)


from sys import stdin
input = lambda : stdin.readline().strip()
lin = lambda : list(map(int, input().split()))
iin = lambda : int(input())
main = lambda : map(int, input().split())
from math import ceil, sqrt, factorial, log
from collections import deque
from bisect import bisect_left
mod = 998244353
mod = 1000000007

def solve(we):
	(n, q) = main()
	s = input()
	z = [0]
	for i in range(n):
		x = 1
		if s[i] == '-':
			x = -1
		if i % 2 == 0:
			z.append(z[-1] + x)
		else:
			z.append(z[-1] - x)
	for i in range(q):
		(a, b) = main()
		t = z[b] - z[a - 1]
		if t == 0:
			print(0)
			continue
		if t % 2 == 0:
			print(2)
		else:
			print(1)
qwe = 1
qwe = iin()
for _ in range(qwe):
	solve(_ + 1)


import sys
input = sys.stdin.readline

def inp():
	return int(input())

def input_list():
	return list(map(int, input().split()))

def input_string():
	s = input()
	return list(s[:len(s) - 1])

def input_int_gen():
	return map(int, input().split())
tests = inp()
charge_dict = {'+': 1, '-': -1}
for _ in range(tests):
	(n, q) = input_int_gen()
	s = input_string()
	s = [charge_dict[k] for k in s]
	ps = [0]
	for (i, k) in enumerate(s):
		ps.append(ps[-1] + k * (-1 if i % 2 else 1))
	for i in range(q):
		(l, r) = input_int_gen()
		charge = (ps[r] - ps[l - 1]) * (1 if l % 2 else -1)
		if ps[r] - ps[l - 1] == 0:
			print(0)
			continue
		print(1 if (r - l + 1) % 2 else 2)


import sys, math
input = lambda : sys.stdin.readline().rstrip('\r\n')
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()
	pre = [0] * (n + 1)
	for i in range(n):
		if s[i] == '+' and i % 2 == 0 or (s[i] == '-' and i % 2 == 1):
			pre[i + 1] = pre[i] + 1
		else:
			pre[i + 1] = pre[i] - 1
	ans = []
	for i in range(q):
		(x, y) = map(int, input().split())
		if (y - x + 1) % 2 == 1:
			print(1)
		elif pre[y] - pre[x - 1] == 0:
			print(0)
		else:
			print(2)


n = int(input())
i = 0
lo = []

def C(Q):
	w = r = 0
	at = [0]
	while w < len(Q):
		if Q[w] == '+':
			r = r + 1 - 2 * (w % 2)
		else:
			r = r - 1 + 2 * (w % 2)
		at.append(r)
		w += 1
	return at
while i < n:
	i1 = input().split()
	Q = input()
	sp = C(Q)
	u = 0
	while u < int(i1[1]):
		Z = list(map(int, input().split()))
		z1 = Z[0]
		z2 = Z[1]
		s = sp[z2] - sp[z1 - 1]
		if s == 0:
			d = 0
		else:
			d = 2 - s % 2
		lo.append(d)
		u += 1
	i += 1
i = 0
while i < len(lo):
	print(lo[i])
	i += 1


import sys
from math import sqrt, ceil, floor, gcd
from collections import Counter
input = lambda : sys.stdin.readline()

def int_arr():
	return list(map(int, input().split()))

def str_arr():
	return list(map(str, input().split()))

def get_str():
	return map(str, input().split())

def get_int():
	return map(int, input().split())

def get_flo():
	return map(float, input().split())

def lcm(a, b):
	return a * b // gcd(a, b)
mod = 1000000007

def solve(n, s):
	dp = [0] * n
	dp[0] = 1 if s[0] == '+' else -1
	for i in range(1, n):
		a = -1 if i % 2 else 1
		b = 1 if s[i] == '+' else -1
		dp[i] = dp[i - 1] + a * b
	return dp
for _ in range(int(input())):
	(n, q) = get_int()
	s = str(input())[:-1]
	dp = solve(n, s)
	for i in range(q):
		(a, b) = get_int()
		a -= 1
		b -= 1
		ans = dp[b] - (dp[a - 1] if a >= 1 else 0)
		if not ans:
			print(0)
		else:
			print(1 if ans % 2 else 2)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input().strip()
	psum = [0] * (n + 1)
	for i in range(n):
		psum[i] = psum[i - 1] + (-1 + 2 * (i & 1 ^ 1)) * (-1 + 2 * (s[i] == '+'))
	for i in range(q):
		(l, r) = map(int, input().split())
		r -= 1
		l -= 1
		if psum[r] - psum[l - 1] == 0:
			print(0)
		else:
			print(1 + (r - l + 1 & 1 ^ 1))


import sys
from heapq import heappush, heappop, heapify
from math import ceil

def get_ints():
	return map(int, sys.stdin.readline().strip().split())

def get_array():
	return list(get_ints())

def input():
	return sys.stdin.readline().strip()
T = int(input())
while T > 0:
	(n, q) = get_ints()
	s = input()
	Arr = []
	for i in s:
		if i == '+':
			Arr.append(1)
		else:
			Arr.append(-1)
	for i in range(n):
		if i & 1:
			Arr[i] *= -1
	pos = [0] * n
	neg = [0] * n
	if Arr[0] == -1:
		neg[0] = 1
	else:
		pos[0] = 1
	for i in range(1, n):
		if Arr[i] == 1:
			pos[i] = pos[i - 1] + 1
			neg[i] = neg[i - 1]
		else:
			neg[i] = neg[i - 1] + 1
			pos[i] = pos[i - 1]
	while q > 0:
		(l, r) = get_ints()
		l -= 1
		r -= 1
		plus = 0
		minus = 0
		if l == 0:
			plus = pos[r]
			minus = neg[r]
		else:
			plus = pos[r] - pos[l - 1]
			minus = neg[r] - neg[l - 1]
		if abs(plus - minus) == 0:
			print(0)
		elif abs(plus - minus) & 1:
			print(1)
		else:
			print(2)
		q -= 1
	T -= 1


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()[:-1]
	(A, B) = ([0], [0])
	for (i, c) in enumerate(s):
		if not i % 2:
			A.append(A[-1] + (1 if c == '+' else -1))
			B.append(B[-1])
		else:
			A.append(A[-1])
			B.append(B[-1] + (1 if c == '+' else -1))
	for _ in range(q):
		(l, r) = map(int, input().split())
		x = A[r] - A[l - 1]
		y = B[r] - B[l - 1]
		if x == y:
			print(0)
		elif abs(x - y) % 2:
			print(1)
		else:
			print(2)


import sys
input = sys.stdin.readline
t = int(input())
for tests in range(t):
	(n, q) = map(int, input().split())
	S = input().strip()
	A = []
	for i in range(n):
		if S[i] == '+':
			x = 1
		else:
			x = -1
		if i % 2 == 0:
			A.append(x)
		else:
			A.append(-x)
	S = [0]
	for a in A:
		S.append(S[-1] + a)
	for queries in range(q):
		(l, r) = map(int, input().split())
		k = abs(S[r] - S[l - 1])
		if k == 0:
			print(0)
		elif k % 2 == 0:
			print(2)
		else:
			print(1)


def naiveSolve():
	return

def solve():
	return

def main():
	t = int(input())
	allans = []
	for _ in range(t):
		(n, q) = readIntArr()
		s = input()
		evenPlusP = [0] * n
		oddPlusP = [0] * n
		evenMinusP = [0] * n
		oddMinusP = [0] * n
		for (i, c) in enumerate(s):
			if c == '+':
				if i % 2 == 0:
					evenPlusP[i] += 1
				else:
					oddPlusP[i] += 1
			elif i % 2 == 0:
				evenMinusP[i] += 1
			else:
				oddMinusP[i] += 1
		for i in range(1, n):
			evenPlusP[i] += evenPlusP[i - 1]
			oddPlusP[i] += oddPlusP[i - 1]
			evenMinusP[i] += evenMinusP[i - 1]
			oddMinusP[i] += oddMinusP[i - 1]
		for __ in range(q):
			(l, r) = readIntArr()
			l -= 1
			r -= 1
			totalCnts = r - l + 1
			score = 0
			score += evenPlusP[r] - oddPlusP[r]
			if l - 1 >= 0:
				score -= evenPlusP[l - 1] - oddPlusP[l - 1]
			ans = 0
			if totalCnts % 2 == 1:
				ans += 1
			elif score != 0:
				ans += 2
			allans.append(ans)
	multiLineArrayPrint(allans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
	dv = defaultValFactory
	da = dimensionArr
	if len(da) == 1:
		return [dv() for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(x):
	print('{}'.format(x))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ans):
	print('! {}'.format(ans))
	sys.stdout.flush()
inf = float('inf')
from math import gcd, floor, ceil
for _abc in range(1):
	main()


import sys

def get_ints():
	return map(int, sys.stdin.readline().strip().split())

def get_list():
	return list(map(int, sys.stdin.readline().strip().split()))

def get_string():
	return sys.stdin.readline().strip()

def get_int():
	return int(sys.stdin.readline().strip())

def get_list_strings():
	return list(map(str, sys.stdin.readline().strip().split()))

def solve(n, s, q, arr):
	store = []
	for (i, ele) in enumerate(s):
		if ele == '+':
			val = 1
		else:
			val = -1
		if i % 2 == 1:
			val *= -1
		store.append(val)
	final = [0]
	final.extend(store)
	for i in range(1, n + 1):
		final[i] += final[i - 1]
	for ele in arr:
		left = ele[0]
		right = ele[1]
		if final[right] == final[left - 1]:
			print(0)
			continue
		l = right - left + 1
		if l % 2 == 1:
			print(1)
		else:
			print(2)
T = get_int()
while T:
	(n, q) = get_ints()
	s = get_string()
	tempQ = q
	arr = []
	while tempQ:
		(li, ri) = get_ints()
		arr.append([li, ri])
		tempQ -= 1
	solve(n, s, q, arr)
	T -= 1


import sys
import math
t = int(sys.stdin.readline())
for _ in range(t):
	line = []
	(n, q) = [int(i) for i in sys.stdin.readline().split()]
	line = sys.stdin.readline()
	s = [0] * (n + 2)
	for (i, c) in enumerate(line):
		if (c == '-') ^ (i % 2 == 0):
			s[i + 1] = s[i] + 1
		else:
			s[i + 1] = s[i] - 1
	for i in range(q):
		(l, r) = [int(i) for i in sys.stdin.readline().split()]
		cur = abs(s[r] - s[l - 1])
		if cur == 0:
			print(0)
		elif (r - l + 1) % 2 == 1:
			print(1)
		else:
			print(2)


import sys
read = lambda : sys.stdin.readline()
for _ in range(int(read())):
	(n, q) = map(int, read().split())
	s = read()
	s = s[:len(s) - 1]
	pre = [0 for i in range(n + 1)]
	val = {'+': 1, '-': -1}
	for i in range(n):
		if i % 2 == 0:
			pre[i + 1] = pre[i] + val[s[i]]
		else:
			pre[i + 1] = pre[i] - val[s[i]]
	for i in range(q):
		(l, r) = map(int, read().split())
		tot = -1 * (pre[r] - pre[l - 1]) if l % 2 == 0 else pre[r] - pre[l - 1]
		if (r - l + 1) % 2 == 1:
			print(1)
			continue
		elif tot == 0:
			print(0)
			continue
		else:
			print(2)
			continue


import os, sys
from io import BytesIO, IOBase

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, 8192))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, 8192))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

class dict(dict):

	def __missing__(self, key):
		return 0
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
inp = lambda dtype: [dtype(x) for x in input().split()]
inp_2d = lambda dtype, n: [dtype(input()) for _ in range(n)]
inp_2ds = lambda dtype, n: [inp(dtype) for _ in range(n)]
inp_enu = lambda dtype: [(i, x) for (i, x) in enumerate(inp(dtype))]
inp_enus = lambda dtype, n: [[i] + [inp(dtype)] for i in range(n)]
ceil1 = lambda a, b: (a + b - 1) // b
for _ in range(int(input())):
	(n, q) = inp(int)
	s = input()
	(cum0, cum1) = ([0], [0, 0])
	for i in range(n):
		sign = -1 if i & 1 else 1
		if s[i] == '+':
			cum0.append(cum0[-1] + sign)
		else:
			cum0.append(cum0[-1] + sign * -1)
	for i in range(1, n):
		sign = 1 if i & 1 else -1
		if s[i] == '+':
			cum1.append(cum1[-1] + sign)
		else:
			cum1.append(cum1[-1] + sign * -1)
	for _ in range(q):
		(l, r) = inp(int)
		d = 0
		if l & 1:
			d = abs(cum0[r] - cum0[l - 1])
		else:
			d = abs(cum1[r] - cum1[l - 1])
		if d & 1:
			print(1)
		elif d > 1:
			print(2)
		else:
			print(d)


import sys
input = sys.stdin.readline

def solve():
	(n, q) = map(int, input().split())
	s = input()
	l = [0] * n
	for i in range(n):
		if s[i] == '+':
			l[i] = 1
		else:
			l[i] = -1
	ssum1 = [0] * (n + 1)
	ssum1[1] = l[0]
	for i in range(1, n):
		ssum1[i + 1] = ssum1[i] + l[i] * (-1) ** i
	for _ in range(q):
		(l, r) = map(int, input().split())
		k = ssum1[r] - ssum1[l - 1]
		print(0 if k == 0 else 2 if k % 2 == 0 else 1)
t = int(input())
for i in range(t):
	solve()


import os, sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import ceil
mod = 10 ** 9 + 7
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input()
	arr = [0 for i in range(n)]
	for i in range(n):
		if s[i] == '+':
			arr[i] = 1
		else:
			arr[i] = -1
		if i % 2:
			arr[i] = -arr[i]
	for i in range(1, n):
		arr[i] += arr[i - 1]
	ans = [0 for i in range(q)]
	for i in range(q):
		(l, r) = map(int, input().split())
		l -= 1
		r -= 1
		if l == 0:
			value = arr[r]
		else:
			value = arr[r] - arr[l - 1]
		if abs(value) == 0:
			ans[i] = 0
		elif (r - l + 1) % 2 == 0:
			ans[i] = 2
		else:
			ans[i] = 1
	for i in ans:
		print(i)


import sys
input = lambda : sys.stdin.readline().strip()
mp = {'+': 1, '-': -1}

def solve():
	(n, m) = map(int, input().split())
	s = input()
	u = [0] + [mp[c] * (1 if i & 1 else -1) for (i, c) in enumerate(s)]
	for i in range(1, n + 1):
		u[i] += u[i - 1]
	for _ in range(m):
		(l, r) = map(int, input().split())
		x = u[r] - u[l - 1]
		if x == 0:
			print(0)
		elif r - l + 1 & 1:
			print(1)
		else:
			print(2)
	return
for _ in range(int(input())):
	solve()


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def value(e):
	return 1 if e == '+' else -1
T = int(input())
for _ in range(T):
	(n, q) = map(int, input().split(' '))
	A = input()
	sign = 1
	prefix = [sign * value(A[0])]
	for a in A[1:]:
		sign *= -1
		prefix.append(prefix[-1] + sign * value(a))
	for _ in range(q):
		(l, r) = map(int, input().split(' '))
		l -= 1
		r -= 1
		s = prefix[r] - (prefix[l - 1] if l > 0 else 0)
		if s == 0:
			k = 0
		else:
			k = (r - l) % 2 + 1
		print(k)


from sys import stdin
input = stdin.readline
rn = lambda : int(input())
rns = lambda : map(int, input().split())
rl = lambda : list(map(int, input().split()))
rs = lambda : input().strip()
YN = lambda x: print('YES') if x else print('NO')
mod = 10 ** 9 + 7
for _ in range(rn()):
	(n, q) = rns()
	s = rs()
	suff = [0 for i in range(n)]
	for i in range(n - 1, -1, -1):
		suff[i] += s[i] == ['+', '-'][i % 2]
		if i != n - 1:
			suff[i] += suff[i + 1]
	suff.append(0)
	for __ in range(q):
		(l, r) = rns()
		l -= 1
		mis = suff[l] - suff[r]
		diff = r - l
		if mis == diff / 2:
			print(0)
		elif diff % 2 == 1:
			print(1)
		else:
			print(2)


TL = 1.5
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
input = lambda : sys.stdin.readline().rstrip()
import bisect, string, math, time, functools, random, fractions
st = time.time()
from bisect import *
from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
from itertools import permutations, combinations, groupby
rep = range
R = range

def I():
	return int(input())

def LI():
	return [int(i) for i in input().split()]

def LI_():
	return [int(i) - 1 for i in input().split()]

def S_():
	return input()

def IS():
	return input().split()

def LS():
	return [i for i in input().split()]

def NI(n):
	return [int(input()) for i in range(n)]

def NI_(n):
	return [int(input()) - 1 for i in range(n)]

def NLI(n):
	return [[int(i) for i in input().split()] for i in range(n)]

def NLI_(n):
	return [[int(i) - 1 for i in input().split()] for i in range(n)]

def StoLI():
	return [ord(i) - 97 for i in input()]

def ItoS(n):
	return chr(n + 97)

def LtoS(ls):
	return ''.join([chr(i + 97) for i in ls])

def RLI(n=8, a=1, b=10):
	return [random.randint(a, b) for i in range(n)]

def RI(a=1, b=10):
	return random.randint(a, b)

def INP():
	N = 8
	n = random.randint(2, N)
	n = 6
	a = [(random.randint(1, 9), random.randint(1, 9)) for i in range(n)]
	return a

def Rtest(T):
	(case, err) = (0, 0)
	for i in range(T):
		inp = INP()
		a1 = naive(inp)
		a2 = solve(inp)
		if a1 != a2:
			print(inp)
			print('naive', a1)
			print('solve', a2)
			err += 1
		case += 1
	print('Tested', case, 'case with', err, 'errors')

def GI(V, E, ls=None, Directed=False, index=1):
	org_inp = []
	g = [[] for i in range(V)]
	FromStdin = True if ls == None else False
	for i in range(E):
		if FromStdin:
			inp = LI()
			org_inp.append(inp)
		else:
			inp = ls[i]
		if len(inp) == 2:
			(a, b) = inp
			c = 1
		else:
			(a, b, c) = inp
		if index == 1:
			a -= 1
			b -= 1
		aa = (a, c)
		bb = (b, c)
		g[a].append(bb)
		if not Directed:
			g[b].append(aa)
	return (g, org_inp)

def GGI(h, w, search=None, replacement_of_found='.', mp_def={'#': 1, '.': 0}, boundary=1):
	mp = [boundary] * (w + 2)
	found = {}
	for i in R(h):
		s = input()
		for char in search:
			if char in s:
				found[char] = (i + 1) * (w + 2) + s.index(char) + 1
				mp_def[char] = mp_def[replacement_of_found]
		mp += [boundary] + [mp_def[j] for j in s] + [boundary]
	mp += [boundary] * (w + 2)
	return (h + 2, w + 2, mp, found)

def TI(n):
	return GI(n, n - 1)

def accum(ls):
	rt = [0]
	for i in ls:
		rt += [rt[-1] + i]
	return rt

def bit_combination(n, base=2):
	rt = []
	for tb in R(base ** n):
		s = [tb // base ** bt % base for bt in R(n)]
		rt += [s]
	return rt

def gcd(x, y):
	if y == 0:
		return x
	if x % y == 0:
		return y
	while x % y != 0:
		(x, y) = (y, x % y)
	return y

def YN(x):
	print(['NO', 'YES'][x])

def Yn(x):
	print(['No', 'Yes'][x])

def show(*inp, end='\n'):
	if show_flg:
		print(*inp, end=end)
mo = 10 ** 9 + 7
inf = float('inf')
FourNb = [(-1, 0), (1, 0), (0, 1), (0, -1)]
EightNb = [(-1, 0), (1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)]
compas = dict(zip('WENS', FourNb))
cursol = dict(zip('LRUD', FourNb))
alp = [chr(ord('a') + i) for i in range(26)]
show_flg = False
show_flg = True
for _ in range(I()):
	(n, q) = LI()
	s = input()
	a = [1 if i == '+' else -1 for i in s]
	ac = [0]
	for i in range(n):
		ac += (ac[-1] + a[i] * (-1) ** (i % 2),)
	p = []
	for i in range(q):
		(l, r) = LI_()
		p += ((l, r),)
		if (r - l + 1) % 2 == 1:
			ans = 1
		elif ac[l] == ac[r + 1]:
			ans = 0
		else:
			ans = 2
		print(ans)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from bisect import bisect_left, bisect_right
t = int(input())
for _ in range(t):
	(n, q) = map(int, input().split())
	get = input()
	rod = [1 if get[i] == '+' and i % 2 == 0 or (get[i] == '-' and i % 2 == 1) else -1 for i in range(n)]
	pre = [rod[0]]
	for i in range(1, n):
		pre.append(pre[i - 1] + rod[i])
	for i in range(q):
		(l, r) = map(int, input().split())
		if l == 1:
			subsum = pre[r - 1]
		else:
			subsum = pre[r - 1] - pre[l - 2]
		if subsum == 0:
			print(0)
		elif subsum % 2 == 1:
			print(1)
		else:
			print(2)


import sys, io, os
try:
	input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
except:
	input = lambda : sys.stdin.readline().encode()
read = lambda : map(int, input().split())
from collections import defaultdict as dd
O = []
neg = [1, -1]
for _ in range(int(input())):
	(n, q) = read()
	s = input().strip()
	p = [0]
	for i in range(n):
		p.append(p[-1] + (44 - s[i]) * neg[i & 1])
	for i in range(q):
		(l, r) = read()
		if r - l & 1:
			if p[r] - p[l - 1] == 0:
				O.append('0')
			else:
				O.append('2')
		else:
			O.append('1')
print('\n'.join(O))


import sys, os, io
input = sys.stdin.readline
PI = 3.141592653589793
INF = float('inf')
MOD = 1000000007

def bin32(num):
	return '{0:032b}'.format(num)

def add(x, y):
	return (x + y) % MOD

def sub(x, y):
	return (x - y + MOD) % MOD

def mul(x, y):
	return x * y % MOD

def gcd(x, y):
	if y == 0:
		return x
	return gcd(y, x % y)

def lcm(x, y):
	return x * y // gcd(x, y)

def power(x, y):
	res = 1
	x %= MOD
	while y != 0:
		if y & 1:
			res = mul(res, x)
		y >>= 1
		x = mul(x, x)
	return res

def mod_inv(n):
	return power(n, MOD - 2)

def prob(p, q):
	return mul(p, power(q, MOD - 2))

def ii():
	return int(input())

def li():
	return [int(i) for i in input().split()]

def ls():
	return [i for i in input().split()]
for t in range(ii()):
	t += 1
	(n, q) = li()
	s = input().strip()
	s = '&' + s
	a = [0]
	for i in range(1, n + 1):
		if s[i] == '+':
			a.append(1)
		else:
			a.append(-1)
	odd = [0 for i in range(n + 1)]
	even = [0 for i in range(n + 1)]
	for i in range(1, n + 1):
		if i % 2:
			even[i] = even[i - 1]
			odd[i] = odd[i - 2] + a[i]
		else:
			odd[i] = odd[i - 1]
			even[i] = even[i - 2] + a[i]
	for _ in range(q):
		(l, r) = li()
		if (r - l + 1) % 2:
			print(1)
		else:
			x = odd[r] - odd[l - 1]
			y = even[r] - even[l - 1]
			y *= -1
			if x + y == 0:
				print(0)
			else:
				print(2)


from sys import stdin, stdout
ip = lambda : stdin.readline().rstrip('\r\n')
ips = lambda : ip().split()
out = lambda x, end='\n': stdout.write(str(x) + end)
inf = float('inf')
for _ in range(int(ip())):
	(n, q) = map(int, ips())
	s = ip()
	np = nn = 0
	a = [None] * n
	b = [None] * n
	c = [None] * n
	d = [None] * n
	for i in range(n):
		if i % 2 == 0:
			if s[i] == '+':
				np += 1
			else:
				nn += 1
		elif s[i] == '+':
			nn += 1
		else:
			np += 1
		a[i] = np
		b[i] = nn
	for i in range(q):
		(l, r) = map(int, ips())
		l -= 1
		r -= 1
		if l == r:
			out(1)
			continue
		nph = a[r]
		nnh = b[r]
		if l - 1 >= 0:
			nph -= a[l - 1]
			nnh -= b[l - 1]
		if abs(nph - nnh) == 0:
			out(0)
			continue
		if abs(nph - nnh) % 2 == 0:
			out(2)
		else:
			out(1)


from sys import stdin
input = stdin.readline
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	s = input().rstrip()
	ps = [0]
	for x in range(n):
		if x % 2 == 0:
			if s[x] == '+':
				ps.append(ps[-1] + 1)
			else:
				ps.append(ps[-1] - 1)
		elif s[x] == '+':
			ps.append(ps[-1] - 1)
		else:
			ps.append(ps[-1] + 1)
	for x in range(q):
		(l, r) = map(int, input().split())
		now = ps[r] - ps[l - 1]
		if now == 0:
			print(0)
		elif now % 2 == 0:
			print(2)
		else:
			print(1)


from __future__ import print_function
from math import *
from collections import deque
import os
import sys
from io import BytesIO, IOBase

def main():
	pass
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
mod = 10 ** 9 + 7

def inp():
	return int(input())

def inlt():
	return list(map(int, input().split()))

def insr():
	s = input()
	return list(s[:len(s)])

def invr():
	return map(int, input().split())
for _ in range(inp()):
	(n, q) = invr()
	ps = [0]
	l = input()
	for i in range(n):
		if l[i] == '+':
			ps.append(ps[-1] + 1 * (-1) ** i)
		else:
			ps.append(ps[-1] - 1 * (-1) ** i)
	for i in range(q):
		(a, b) = invr()
		if ps[b] - ps[a - 1] == 0:
			print(0)
		else:
			diff = ps[b] - ps[a - 1]
			if diff % 2 == 1:
				print(1)
			else:
				print(2)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, q) = map(int, input().split())
	arr = input()
	pl = 0
	mns = 0
	F = [(0, 0)]
	for x in range(n):
		if arr[x] == '+':
			pl += (-1) ** x
		else:
			mns += (-1) ** x
		F.append((pl, mns))
	for _ in range(q):
		(l, r) = map(int, input().split())
		(pl, mns) = (F[r][0] - F[l - 1][0], F[r][1] - F[l - 1][1])
		if pl == mns == 0:
			print(0)
		elif pl % 2 and mns % 2 or not (pl % 2 or mns % 2):
			print(2)
		else:
			print(1)


import sys
import math
import random
import heapq
input = sys.stdin.readline

def pow(a, n, m):
	if n == 0:
		return 1
	x = pow(a, n // 2, m)
	if n % 2 == 0:
		return x * x % m
	else:
		return x * x * a % m

def gcd(a, b):
	while b != 0:
		(a, b) = (b, a % b)
	return a

def bs(arr, le, ri):
	l = 0
	arr.sort()
	r = len(arr) - 1
	ans = 10000000
	while l <= r:
		m = (l + r) // 2
		if arr[m] >= le and arr[m] <= ri:
			ans = arr[m]
			r = m - 1
		elif arr[m] < le:
			l = m + 1
		else:
			r = m - 1
	return ans
t = int(input())
while t > 0:
	(n, q) = map(int, input().split())
	s = input().strip()
	l = [0]
	for i in range(n):
		if i % 2 == 0:
			if s[i] == '+':
				l.append(l[-1] + 1)
			else:
				l.append(l[-1] - 1)
		elif s[i] == '-':
			l.append(l[-1] + 1)
		else:
			l.append(l[-1] - 1)
	for i in range(q):
		(li, ri) = map(int, input().split())
		x = abs(l[ri] - l[li - 1])
		if x % 2 == 1:
			print(1)
		elif x == 0:
			print(0)
		else:
			print(2)
	t -= 1


import bisect
import heapq
import math
import collections
import sys
import copy
from functools import reduce
import decimal
from io import BytesIO, IOBase
import os
import itertools
import functools
from types import GeneratorType
sys.setrecursionlimit(10 ** 9)
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
graphDict = collections.defaultdict
queue = collections.deque

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		to = f(*args, **kwargs)
		if stack:
			return to
		else:
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						return to
					to = stack[-1].send(to)
	return wrappedfunc

class Graphs:

	def __init__(self):
		self.graph = graphDict(set)

	def add_edge(self, u, v):
		self.graph[u].add(v)
		self.graph[v].add(u)

	def dfs_utility(self, nodes, visited_nodes, psf):
		global ans
		if len(visited_nodes.keys()) == n:
			ans = psf
			return
		visited_nodes[nodes] = None
		for neighbour in self.graph[nodes]:
			if neighbour not in visited_nodes:
				self.dfs_utility(neighbour, visited_nodes, psf + [neighbour])
		visited_nodes.pop(nodes)
		return

	def dfs(self, node):
		global ans
		Visited = collections.OrderedDict()
		self.dfs_utility(node, Visited, [node])

	def bfs(self, node):
		visited = set()
		if node not in visited:
			queue.append(node)
			visited.add(node)
		while queue:
			parent = queue.popleft()
			print(parent)
			for item in self.graph[parent]:
				if item not in visited:
					queue.append(item)
					visited.add(item)

class Tree:

	def __init__(self, data):
		self.data = data
		self.left = None
		self.right = None

def inorder(node, lis):
	if node:
		inorder(node.left, lis)
		lis.append(node.data)
		inorder(node.right, lis)
	return lis

def leaf_node_sum(root):
	if root is None:
		return 0
	if root.left is None and root.right is None:
		return root.data
	return leaf_node_sum(root.left) + leaf_node_sum(root.right)

def hight(root):
	if root is None:
		return -1
	if root.left is None and root.right is None:
		return 0
	return max(hight(root.left), hight(root.right)) + 1

def rounding(n):
	return int(decimal.Decimal(f'{n}').to_integral_value())

def factors(n):
	return set(reduce(list.__add__, ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0), []))

def p_sum(array):
	return list(itertools.accumulate(array))
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self, **kwargs):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def inp():
	return sys.stdin.readline().strip()

def map_inp(v_type):
	return map(v_type, inp().split())

def list_inp(v_type):
	return list(map_inp(v_type))
for _ in range(int(inp())):
	(n, q) = map_inp(int)
	s = [int(item + '1') for item in inp()]
	start = 1
	for i in range(n):
		s[i] *= start
		start *= -1
	dp = [[0 for col in range(n + 1)] for row in range(2)]
	for i in range(1, n + 1):
		if s[i - 1] == 1:
			dp[0][i] += dp[0][i - 1] + 1
			dp[1][i] = dp[1][i - 1]
		else:
			dp[1][i] += dp[1][i - 1] + 1
			dp[0][i] = dp[0][i - 1]
	for i in range(q):
		(l, r) = map_inp(int)
		ans = abs(dp[0][r] - dp[0][l - 1] - (dp[1][r] - dp[1][l - 1]))
		if ans % 2:
			print(1)
		elif ans == 0:
			print(0)
		else:
			print(2)


import sys
input = sys.stdin.readline
tests = int(input())
for test in range(tests):
	(n, q) = map(int, input().split())
	s = str.rstrip(input())
	sum_list = [0]
	oddeven = 1
	sum = 0
	for char in s:
		if char == '+':
			sum += oddeven
		else:
			sum -= oddeven
		oddeven *= -1
		sum_list.append(sum)
	for question in range(q):
		(l, r) = map(int, input().split())
		if (r - l) % 2 == 0:
			print(1)
		elif sum_list[r] - sum_list[l - 1] == 0:
			print(0)
		else:
			print(2)