Make Nonzero Sum (hard version) (Codeforces 1754C2)
Tags: Others, implementation

This is the hard version of the problem. The difference is that in this version the array contains zeros. You can make hacks only if both versions of the problem are solved.You are given an array $$$[a_1, a_2, \ldots a_n]$$$ consisting of integers $$$-1$$$, $$$0$$$ and $$$1$$$. You have to build a partition of this array into the set of segments $$$[l_1, r_1], [l_2, r_2], \ldots, [l_k, r_k]$$$ with the following property:  Denote the alternating sum of all elements of the $$$i$$$-th segment as $$$s_i$$$: $$$s_i$$$ = $$$a_{l_i} - a_{l_i+1} + a_{l_i+2} - a_{l_i+3} + \ldots \pm a_{r_i}$$$. For example, the alternating sum of elements of segment $$$[2, 4]$$$ in array $$$[1, 0, -1, 1, 1]$$$ equals to $$$0 - (-1) + 1 = 2$$$.  The sum of $$$s_i$$$ over all segments of partition should be equal to zero. Note that each $$$s_i$$$ does not have to be equal to zero, this property is about sum of $$$s_i$$$ over all segments of partition.The set of segments $$$[l_1, r_1], [l_2, r_2], \ldots, [l_k, r_k]$$$ is called a partition of the array $$$a$$$ of length $$$n$$$ if $$$1 = l_1 \le r_1, l_2 \le r_2, \ldots, l_k \le r_k = n$$$ and $$$r_i + 1 = l_{i+1}$$$ for all $$$i = 1, 2, \ldots k-1$$$. In other words, each element of the array must belong to exactly one segment.You have to build a partition of the given array with properties described above or determine that such partition does not exist.Note that it is not required to minimize the number of segments in the partition.

Input: Each test contains multiple test cases. The first line contains the number of test cases $$$t$$$ ($$$1 \le t \le 10\,000$$$). Description of the test cases follows.The first line of each test case contains an integer $$$n$$$ ($$$1 \le n \le 200\,000$$$) — the length of array $$$a$$$.The second line of each test case contains $$$n$$$ integers $$$a_1, a_2, \ldots, a_n$$$ ($$$a_i$$$ is $$$-1$$$, $$$0$$$, or $$$1$$$) — the elements of the given array.It's guaranteed that the sum of $$$n$$$ over all test cases does not exceed $$$200\,000$$$.

Output: For each test case print an integer $$$k$$$ — the number of segments in the partition. If required partition does not exist, print $$$-1$$$.If partition exists, in the $$$i$$$-th of the following $$$k$$$ lines print two integers $$$l_i$$$ and $$$r_i$$$ — description of the $$$i$$$-th segment. The following conditions should be satisfied:  $$$l_i \le r_i$$$ for each $$$i$$$ from $$$1$$$ to $$$k$$$.  $$$l_{i + 1} = r_i + 1$$$ for each $$$i$$$ from $$$1$$$ to $$$(k - 1)$$$.  $$$l_1 = 1, r_k = n$$$. If there are multiple correct partitions of the array, print any of them.

Note: In the first test case we can build a partition of $$$4$$$ segments — each of them will contain only one element of the array equals to $$$0$$$. So the sum will be equal to $$$0 + 0 + 0 + 0 = 0$$$.In the second test case we can build a partition of $$$4$$$ segments. The alternating sum of the first segment will be equal to $$$-1$$$, the alternating sum of the second segment will be equal to $$$1$$$, of the third segment — $$$0 - 1 + 0 = -1$$$, of the fourth segment — $$$1 - 0 = 1$$$. The sum will be equal to $$$-1 + 1 -1 + 1 = 0$$$.In the third test case it can be proved that the required partition does not exist.

Sample Inputs:
5
4
0 0 0 0
7
-1 1 0 1 0 1 0
5
0 -1 1 0 1
3
1 0 1
1
1

Sample Outputs:
4
1 1
2 2
3 3
4 4
4
1 1
2 2
3 5
6 7
-1
2
1 1
2 3
-1

Solution (Python):
import sys
INF = 10 ** 20
MOD = 10 ** 9 + 7
from math import gcd
from math import ceil, log2, factorial
from collections import defaultdict as dd, Counter
from bisect import bisect_left as bl, bisect_right as br

def fastio():
    import sys
    from io import StringIO
    from atexit import register
    global input
    sys.stdin = StringIO(sys.stdin.read())
    input = lambda : sys.stdin.readline().rstrip('\r\n')
    sys.stdout = StringIO()
    register(lambda : sys.__stdout__.write(sys.stdout.getvalue()))
fastio()
I = lambda : list(map(int, input().split()))
TESTS = 1
''

def solve():
    (n,) = I()
    a = I()
    s = sum(a)
    if s % 2:
        print(-1)
        return
    ok = -1
    if s < 0:
        need = -s // 2
    else:
        need = s // 2
        ok = 1
    idx = []
    i = 1
    while i < n and len(idx) < need:
        if a[i] == ok:
            idx.append(i)
            i += 2
            continue
        i += 1
    assert len(idx) == need
    idx = idx[:need] + [MOD]
    cur = 0
    i = 0
    ans = []
    while i < n:
        if i == idx[cur]:
            ans[-1][-1] = i + 1
            i += 1
            cur += 1
            continue
        ans.append([i + 1, i + 1])
        i += 1
    print(len(ans))
    for i in ans:
        print(*i)

def main():
    if not TESTS:
        solve()
        return
    (t,) = I()
    while t:
        solve()
        t -= 1
if __name__ == '__main__':
    main()

Solution (Python):
def sign(x: int) -> int:
    if x > 0:
        return 1
    elif x < 0:
        return -1
    else:
        return 0
for i in range(int(input())):
    n = int(input())
    a = [int(x) for x in input().split()]
    s = sum(a)
    if s == 0:
        print(n)
        for i in range(1, n + 1):
            print(f'{i} {i}')
    elif s & 1:
        print(-1)
    else:
        res = []
        i = n - 1
        while i > 0:
            if sign(s) == sign(a[i]):
                res.append((i, i + 1))
                i -= 2
                s -= 2 * sign(s)
            else:
                res.append((i + 1, i + 1))
                i -= 1
            if s == 0:
                break
        for i in range(i, -1, -1):
            res.append((i + 1, i + 1))
        res = res[::-1]
        print(len(res))
        for (a, b) in res:
            print(f'{a} {b}')

Solution (Python):
from operator import le
import sys
import os
from math import ceil, floor, sqrt, gcd, factorial, log, log2
from io import BytesIO, IOBase
from collections import Counter, deque
from itertools import permutations, combinations
from bisect import bisect, insort, bisect_left
yes = 'YES'
no = 'NO'
Yes = 'Yes'
No = 'No'
inf = int(10000000000.0) + 7
BUFSIZE = 8192

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

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

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

def main():
    for _ in range(inp()):
        n = inp()
        a = lst()
        one = 0
        mone = 0
        ans = []
        i = 0
        while i < n:
            if a[i] == 1 and mone > one:
                one += 1
                ans.append((i + 1, i + 1))
                i += 1
            elif a[i] == -1 and one > mone:
                mone += 1
                ans.append((i + 1, i + 1))
                i += 1
            elif i + 1 >= n:
                if a[i] == 1:
                    one += 1
                elif a[i] == -1:
                    mone += 1
                ans.append((i + 1, i + 1))
                i += 1
            elif a[i] == a[i + 1]:
                if a[i] == 0:
                    ans.append((i + 1, i + 1))
                    i += 1
                else:
                    ans.append((i + 1, i + 2))
                    i += 2
            elif a[i:i + 2] == [0, 1] and one > mone:
                mone += 1
                ans.append((i + 1, i + 2))
                i += 2
            elif a[i:i + 2] == [0, -1] and mone > one:
                one += 1
                ans.append((i + 1, i + 2))
                i += 2
            else:
                if a[i] == 1:
                    one += 1
                elif a[i] == -1:
                    mone += 1
                ans.append((i + 1, i + 1))
                i += 1
        if one == mone:
            print(len(ans))
            for (i, j) in ans:
                print(i, j)
        else:
            print(-1)

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))

def input():
    return sys.stdin.readline().rstrip('\r\n')
if __name__ == '__main__':
    main()