Double Knapsack (Codeforces 618F)
Tags: Others, two pointers

You are given two multisets A and B. Each multiset has exactly n integers each between 1 and n inclusive. Multisets may contain multiple copies of the same number.You would like to find a nonempty subset of A and a nonempty subset of B such that the sum of elements in these subsets are equal. Subsets are also multisets, i.e. they can contain elements with equal values.If no solution exists, print  - 1. Otherwise, print the indices of elements in any such subsets of A and B that have the same sum.

Input: The first line of the input contains a single integer n (1 ≤ n ≤ 1 000 000) — the size of both multisets.The second line contains n integers, denoting the elements of A. Each element will be between 1 and n inclusive.The third line contains n integers, denoting the elements of B. Each element will be between 1 and n inclusive.

Output: If there is no solution, print a single integer  - 1. Otherwise, your solution should be printed on four lines.The first line should contain a single integer ka, the size of the corresponding subset of A. The second line should contain ka distinct integers, the indices of the subset of A.The third line should contain a single integer kb, the size of the corresponding subset of B. The fourth line should contain kb distinct integers, the indices of the subset of B.Elements in both sets are numbered from 1 to n. If there are multiple possible solutions, print any of them.


Sample Inputs:
10
10 10 10 10 10 10 10 10 10 10
10 9 8 7 6 5 4 3 2 1

5
4 4 3 3 3
2 2 2 2 5

Sample Outputs:
1
2
3
5 8 10

2
2 3
2
3 5

Solution (Python):
n = int(input())
arr1 = list(map(int, input().split()))
arr2 = list(map(int, input().split()))
visited = [0] * (2 * n + 1)
result = []
result1 = []
result2 = []
x = 1
while not visited[x]:
    visited[x] = 1
    result.append(x)
    if x <= n:
        x += arr1[x - 1]
    else:
        x -= arr2[x - n - 1]
len_result = len(result)
for i in range(len_result):
    if result[i] == x:
        break
    visited[result[i]] = 0
for i in range(1, n + 1):
    if visited[i]:
        result1.append(i)
    if visited[i + n]:
        result2.append(i)
print(len(result1))
print(' '.join(map(str, result1)))
print(len(result2))
print(' '.join(map(str, result2)))

Solution (Python):
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
if sum(a) == sum(b):
    print(n)
    print(list(range(1, n + 1)))
    print(n)
    print(list(range(1, n + 1)))
else:
    z = 0
    if sum(a) < sum(b):
        (a, b) = (b, a)
        z = 1
    i = 0
    s = [0, 0]
    l = [-1] * n
    ans = [-1, -1]
    for j in range(n):
        s[1] += b[j]
        while s[0] < s[1]:
            s[0] += a[i]
            i += 1
        if s[0] == s[1]:
            l[0] = (i, j + 1)
            break
        if l[s[1] - s[0]] != -1:
            ans[0] = l[s[1] - s[0]]
            ans[1] = (i, j + 1)
            break
        l[s[1] - s[0]] = (i, j + 1)
    if l[0] != -1:
        a1 = list(range(1, l[0][0] + 1))
        b1 = list(range(1, l[0][1] + 1))
    else:
        a1 = list(range(ans[0][0] + 1, ans[1][0] + 1))
        b1 = list(range(ans[0][1] + 1, ans[1][1] + 1))
    if z == 1:
        print(len(b1))
        print(*b1)
        print(len(a1))
        print(*a1)
    else:
        print(len(a1))
        print(*a1)
        print(len(b1))
        print(*b1)

Solution (Python):
from io import BytesIO, IOBase
import sys
import os
import bisect
import math
import random
from collections import Counter, defaultdict, deque
from copy import deepcopy
from functools import cmp_to_key, lru_cache, reduce
from heapq import heapify, heappop, heappush, heappushpop, nlargest, nsmallest
from itertools import accumulate, combinations, permutations
from operator import add, iand, ior, itemgetter, mul, xor
from string import ascii_lowercase, ascii_uppercase
from typing import *

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')
BUFSIZE = 4096

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

    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()
sys.stdin = IOWrapper(sys.stdin)
sys.stdout = IOWrapper(sys.stdout)
input = lambda : sys.stdin.readline().rstrip('\r\n')

def I():
    return input()

def II():
    return int(input())

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

def LI():
    return list(input().split())

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

def GMI():
    return map(lambda x: int(x) - 1, input().split())

def LGMI():
    return list(map(lambda x: int(x) - 1, input().split()))
inf = float('inf')
n = II()
v1 = [0] + LII()
v2 = [0] + LII()
for i in range(n):
    v1[i + 1] += v1[i]
    v2[i + 1] += v2[i]
flag = True
if v1[-1] < v2[-1]:
    (v1, v2) = (v2, v1)
    flag = False
pt = 0
note = [None] * (n + 1)
for i in range(n + 1):
    while pt < n and v1[pt + 1] <= v2[i]:
        pt += 1
    note[i] = pt
saved_val = [None] * (n + 1)
for i in range(n + 1):
    v = v2[i] - v1[note[i]]
    if saved_val[v] is not None:
        i1 = saved_val[v]
        i2 = i
        (j1, j2) = (note[i1], note[i2])
        if flag:
            print(j2 - j1)
            print(*range(j1 + 1, j2 + 1))
            print(i2 - i1)
            print(*range(i1 + 1, i2 + 1))
        else:
            print(i2 - i1)
            print(*range(i1 + 1, i2 + 1))
            print(j2 - j1)
            print(*range(j1 + 1, j2 + 1))
        exit()
    saved_val[v] = i