Design a stack which supports the following operations.
Implement the CustomStack class:

CustomStack(int maxSize) Initializes the object with maxSize which is the maximum number of elements in the stack or do nothing if the stack reached the maxSize.
void push(int x) Adds x to the top of the stack if the stack hasn't reached the maxSize.
int pop() Pops and returns the top of stack or -1 if the stack is empty.
void inc(int k, int val) Increments the bottom k elements of the stack by val. If there are less than k elements in the stack, just increment all the elements in the stack.

 
Example 1:
Input
["CustomStack","push","push","pop","push","push","push","increment","increment","pop","pop","pop","pop"]
[[3],[1],[2],[],[2],[3],[4],[5,100],[2,100],[],[],[],[]]
Output
[null,null,null,2,null,null,null,null,null,103,202,201,-1]
Explanation
CustomStack customStack = new CustomStack(3); // Stack is Empty []
customStack.push(1);                          // stack becomes [1]
customStack.push(2);                          // stack becomes [1, 2]
customStack.pop();                            // return 2 --> Return top of the stack 2, stack becomes [1]
customStack.push(2);                          // stack becomes [1, 2]
customStack.push(3);                          // stack becomes [1, 2, 3]
customStack.push(4);                          // stack still [1, 2, 3], Don't add another elements as size is 4
customStack.increment(5, 100);                // stack becomes [101, 102, 103]
customStack.increment(2, 100);                // stack becomes [201, 202, 103]
customStack.pop();                            // return 103 --> Return top of the stack 103, stack becomes [201, 202]
customStack.pop();                            // return 202 --> Return top of the stack 102, stack becomes [201]
customStack.pop();                            // return 201 --> Return top of the stack 101, stack becomes []
customStack.pop();                            // return -1 --> Stack is empty return -1.

 
Constraints:

1 <= maxSize <= 1000
1 <= x <= 1000
1 <= k <= 1000
0 <= val <= 100
At most 1000 calls will be made to each method of increment, push and pop each separately.

Difficulty: MEDIUM
Tags: Data structures
Skill types: Data structures

Starter code:
class CustomStack:
    def __init__(self, maxSize: int):
    def push(self, x: int) -> None:
    def pop(self) -> int:
    def increment(self, k: int, val: int) -> None:
# Your CustomStack object will be instantiated and called as such:
# obj = CustomStack(maxSize)
# obj.push(x)
# param_2 = obj.pop()
# obj.increment(k,val)

Solutions:
class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = []
		self.add = []
		self.limit = maxSize

	def push(self, x: int) -> None:
		if len(self.stack) < self.limit:
			self.stack.append(x)
			self.add.append(0)

	def pop(self) -> int:
		if len(self.stack) == 0:
			return -1
		result = self.stack.pop()
		left = self.add.pop()
		if len(self.add) > 0:
			self.add[-1] += left
		return result + left

	def increment(self, k: int, val: int) -> None:
		if len(self.stack) > 0:
			if k > len(self.stack):
				self.add[-1] += val
				return
			self.add[k - 1] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.maxSize = maxSize
		self.stack = []
		self.incre = []
		self.amount = 0

	def push(self, x: int) -> None:
		if len(self.stack) < self.maxSize:
			if self.amount:
				heapq.heappush(self.incre, (-len(self.stack), self.amount))
				self.amount = 0
			self.stack.append(x)

	def pop(self) -> int:
		if self.stack:
			while self.incre and len(self.stack) == -self.incre[0][0]:
				self.amount += heapq.heappop(self.incre)[1]
			return self.amount + self.stack.pop()
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		heapq.heappush(self.incre, (-min(k, len(self.stack)), val))


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = []
		self.len = maxSize

	def push(self, x: int) -> None:
		if len(self.stack) + 1 <= self.len:
			self.stack.append(x)

	def pop(self) -> int:
		if not self.stack:
			return -1
		last = self.stack[-1]
		self.stack = self.stack[:-1]
		return last

	def increment(self, k: int, val: int) -> None:
		if len(self.stack) < k:
			self.stack = [x + val for x in self.stack]
		else:
			self.stack[:k] = [x + val for x in self.stack[:k]]


class CustomStack:

	def __init__(self, maxSize):
		self.n = maxSize
		self.stack = []
		self.inc = []

	def push(self, x):
		if len(self.inc) < self.n:
			self.stack.append(x)
			self.inc.append(0)

	def pop(self):
		if not self.inc:
			return -1
		if len(self.inc) > 1:
			self.inc[-2] += self.inc[-1]
		return self.stack.pop() + self.inc.pop()

	def increment(self, k, val):
		if self.inc:
			self.inc[min(k, len(self.inc)) - 1] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = []
		self.maxsize = maxSize

	def push(self, x: int) -> None:
		if self.maxsize == 0:
			return
		self.stack.append(x)
		self.maxsize -= 1

	def pop(self) -> int:
		if len(self.stack) == 0:
			return -1
		val = self.stack[-1]
		self.stack = self.stack[:-1]
		self.maxsize += 1
		return val

	def increment(self, k: int, val: int) -> None:
		self.stack[:k] = [x + val for x in self.stack[:k]]


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = []
		self.cap = maxSize

	def push(self, x: int) -> None:
		if len(self.stack) < self.cap:
			self.stack.append(x)

	def pop(self) -> int:
		if self.stack:
			return self.stack.pop()
		return -1

	def increment(self, k: int, val: int) -> None:
		for i in range(min(k, len(self.stack))):
			self.stack[i] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.arr = []
		self.capacity = maxSize
		self.size = 0

	def push(self, x: int) -> None:
		if self.size < self.capacity:
			self.arr.append(x)
			self.size += 1

	def pop(self) -> int:
		if self.size > 0:
			ele = self.arr.pop()
			self.size -= 1
			return ele
		return -1

	def increment(self, k: int, val: int) -> None:
		k = min(k, self.size)
		for i in range(k):
			self.arr[i] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.maxSize = maxSize
		self.stack = []

	def push(self, x: int) -> None:
		if len(self.stack) + 1 > self.maxSize:
			return
		self.stack.append(x)

	def pop(self) -> int:
		if len(self.stack) == 0:
			return -1
		el = self.stack.pop()
		return el

	def increment(self, k: int, val: int) -> None:
		if len(self.stack) < k:
			self.stack = list([x + val for x in self.stack])
		else:
			beforek = list([x + val for x in self.stack[:k]])
			self.stack = beforek + self.stack[k:]


class CustomStack:

	def __init__(self, maxSize: int):
		self.origin_list = [0] * maxSize
		self.index = 0
		self.maxSize = maxSize

	def push(self, x: int) -> None:
		if self.index < self.maxSize:
			self.origin_list[self.index] = x
			self.index += 1

	def pop(self) -> int:
		if self.index == 0:
			return -1
		else:
			self.index -= 1
			return self.origin_list[self.index]

	def increment(self, k: int, val: int) -> None:
		num = min(k, self.index)
		for i in range(num):
			self.origin_list[i] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.size = maxSize
		self.arr = []
		self.currsize = 0

	def push(self, x: int) -> None:
		if self.currsize == self.size:
			return
		self.arr.append(x)
		self.currsize += 1

	def pop(self) -> int:
		if len(self.arr) == 0:
			return -1
		self.currsize -= 1
		return self.arr.pop()

	def increment(self, k: int, val: int) -> None:
		minsize = min(k, len(self.arr))
		for i in range(minsize):
			self.arr[i] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.items = []
		self.max = maxSize

	def push(self, x: int) -> None:
		if len(self.items) < self.max:
			self.items.append(x)

	def pop(self) -> int:
		return self.items.pop() if len(self.items) != 0 else -1

	def increment(self, k: int, val: int) -> None:
		k = k if k < len(self.items) else len(self.items)
		for i in range(k):
			self.items[i] = self.items[i] + val


class CustomStack:

	def __init__(self, maxSize: int):
		self.maxSize = maxSize
		self.stack = []
		self.incre = []

	def push(self, x: int) -> None:
		if len(self.stack) < self.maxSize:
			self.stack.append(x)
			self.incre.append(0)

	def pop(self) -> int:
		if self.stack:
			if len(self.incre) > 1:
				self.incre[-2] += self.incre[-1]
			return self.stack.pop() + self.incre.pop()
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		if self.incre:
			self.incre[min(len(self.incre), k) - 1] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = []
		self.size = maxSize

	def push(self, x: int) -> None:
		if len(self.stack) < self.size:
			self.stack.append(x)

	def pop(self) -> int:
		if len(self.stack) == 0:
			return -1
		else:
			item = self.stack.pop()
			return item

	def increment(self, k: int, val: int) -> None:
		l = len(self.stack)
		if l < k:
			for i in range(len(self.stack)):
				self.stack[i] = self.stack[i] + val
		else:
			for i in range(0, k):
				self.stack[i] = self.stack[i] + val


class CustomStack:

	def __init__(self, maxSize: int):
		self.n = maxSize
		self.s = []

	def push(self, x: int) -> None:
		if len(self.s) < self.n:
			self.s.append(x)

	def pop(self) -> int:
		if len(self.s) == 0:
			return -1
		return self.s.pop()

	def increment(self, k: int, val: int) -> None:
		for i in range(0, k):
			if i >= len(self.s):
				break
			self.s[i] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.maxSize = maxSize
		self.stack = []

	def push(self, x: int) -> None:
		if len(self.stack) < self.maxSize:
			self.stack.append(x)

	def pop(self) -> int:
		if len(self.stack) == 0:
			return -1
		else:
			return self.stack.pop(-1)

	def increment(self, k: int, val: int) -> None:
		i = 0
		if k <= len(self.stack):
			while i < k:
				self.stack[i] += val
				i += 1
		else:
			while i < len(self.stack):
				self.stack[i] += val
				i += 1


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = [0] * maxSize
		self.top = -1

	def push(self, x: int) -> None:
		if self.top + 1 < len(self.stack):
			self.top += 1
			self.stack[self.top] = x

	def pop(self) -> int:
		if self.top < 0:
			return -1
		n = self.stack[self.top]
		self.top -= 1
		return n

	def increment(self, k: int, val: int) -> None:
		for i in range(k):
			if i <= self.top:
				self.stack[i] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.increament_at = collections.defaultdict(lambda : 0)
		self.stack = []
		self.max_size = maxSize

	def push(self, x: int) -> None:
		if len(self.stack) < self.max_size:
			self.stack.append(x)

	def pop(self) -> int:
		if not self.stack:
			return -1
		tmp = self.increament_at[len(self.stack) - 1]
		self.increament_at[len(self.stack) - 2] += tmp
		self.increament_at[len(self.stack) - 1] = 0
		return self.stack.pop() + tmp

	def increment(self, k: int, val: int) -> None:
		if len(self.stack) < k:
			self.increament_at[len(self.stack) - 1] += val
		else:
			self.increament_at[k - 1] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self._max_size = maxSize
		self._len = 0
		self._stack = []

	def push(self, x: int) -> None:
		if self._len < self._max_size:
			self._stack.insert(0, x)
			self._len += 1

	def pop(self) -> int:
		if self._len > 0:
			self._len -= 1
			ret = self._stack.pop(0)
		else:
			ret = -1
		return ret

	def increment(self, k: int, val: int) -> None:
		i = 0
		while i < k and i < self._len:
			self._stack[self._len - i - 1] += val
			i += 1


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = []
		self.maxSize = maxSize

	def push(self, x: int) -> None:
		if len(self.stack) < self.maxSize:
			self.stack.append(x)
		else:
			pass

	def pop(self) -> int:
		if self.stack:
			return self.stack.pop()
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		for i in range(k):
			try:
				self.stack[i] += val
			except:
				pass


class CustomStack:

	def __init__(self, maxSize: int):
		self.maxsize = maxSize
		self.currentsize = 0
		self._list = []

	def push(self, x: int) -> None:
		if self.currentsize < self.maxsize:
			self._list.append(x)
			self.currentsize += 1

	def pop(self) -> int:
		if self.currentsize > 0:
			lastelem = self._list.pop(-1)
			self.currentsize -= 1
			return lastelem
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		for idx in range(k):
			if idx < len(self._list):
				self._list[idx] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = []
		self.maxSize = maxSize
		self.curSize = 0

	def push(self, x: int) -> None:
		if self.curSize < self.maxSize:
			self.stack.append(x)
			self.curSize += 1

	def pop(self) -> int:
		if self.stack:
			self.curSize -= 1
			return self.stack.pop()
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		cur = 0
		while cur < k and cur < self.curSize:
			self.stack[cur] += val
			cur += 1


from collections import deque

class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = deque()
		self.max_size = maxSize

	def push(self, x: int) -> None:
		if len(self.stack) < self.max_size:
			self.stack.append(x)

	def pop(self) -> int:
		if self.stack:
			return self.stack.pop()
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		for i in range(k):
			if i < len(self.stack):
				self.stack[i] += val


class CustomStack:

	def __init__(self, maxSize: int):
		self.maxSize = maxSize
		self.stack = []

	def push(self, x: int) -> None:
		if len(self.stack) < self.maxSize:
			self.stack.append(x)

	def pop(self) -> int:
		return -1 if not self.stack else self.stack.pop()

	def increment(self, k: int, val: int) -> None:
		if k > len(self.stack):
			self.stack = list([x + val for x in self.stack])
		else:
			temp = []
			m = len(self.stack) - k
			while m:
				temp.append(self.stack.pop())
				m -= 1
			self.stack = [x + val for x in self.stack]
			while temp:
				self.stack.append(temp.pop())


class CustomStack:

	def __init__(self, maxSize: int):
		self.stack = deque()
		self.limit = maxSize
		self.count = 0

	def push(self, x: int) -> None:
		if self.count < self.limit:
			self.count += 1
			self.stack.append(x)

	def pop(self) -> int:
		if not self.stack:
			return -1
		else:
			self.count -= 1
			return self.stack.pop()

	def increment(self, k: int, val: int) -> None:
		tstack = []
		while self.stack and k > 0:
			tstack.append(self.stack.popleft() + val)
			k -= 1
		while tstack:
			self.stack.appendleft(tstack.pop())


class CustomStack:

	def __init__(self, maxSize: int):
		self.max = maxSize
		self.array = []
		self.size = 0

	def push(self, x: int) -> None:
		if self.size == self.max:
			pass
		else:
			self.array.append(x)
			self.size += 1

	def pop(self) -> int:
		if self.size == 0:
			return -1
		self.size -= 1
		temp = self.array.pop()
		return temp

	def increment(self, k: int, val: int) -> None:
		self.array[0:k] = list([x + val for x in self.array[0:k]])


class CustomStack:

	def __init__(self, maxSize: int):
		self.maxSize = maxSize
		self.stack = []

	def push(self, x: int) -> None:
		if len(self.stack) < self.maxSize:
			self.stack.append(x)

	def pop(self) -> int:
		if len(self.stack) >= 1:
			return self.stack.pop()
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		import numpy as np
		if k >= len(self.stack):
			self.stack = (np.array(self.stack) + np.array([val] * len(self.stack))).tolist()
		if k < len(self.stack):
			t = [val] * k
			t.extend([0] * (len(self.stack) - k))
			self.stack = (np.array(self.stack) + np.array(t)).tolist()


class CustomStack:

	def __init__(self, maxSize: int):
		self.max = maxSize
		self.stack = []
		self.inc_stack = []
		self.index = 0

	def push(self, x: int) -> None:
		self.index += 1
		if len(self.stack) != self.max:
			self.stack.append((self.index, x))

	def pop(self) -> int:
		self.index += 1
		if not self.stack:
			return -1
		height = len(self.stack)
		(index_x, x) = self.stack.pop()
		for i in range(len(self.inc_stack) - 1, -1, -1):
			(index, val, h) = self.inc_stack[i]
			if index < index_x:
				break
			if h >= height:
				x += val
		return x

	def increment(self, k: int, val: int) -> None:
		self.index += 1
		self.inc_stack.append((self.index, val, min(k, len(self.stack))))


class CustomStack:

	def __init__(self, maxSize: int):
		self.arr = []
		self.size = maxSize

	def push(self, x: int) -> None:
		if len(self.arr) == self.size:
			pass
		else:
			self.arr.append(x)

	def pop(self) -> int:
		try:
			return self.arr.pop()
		except:
			return -1

	def increment(self, k: int, val: int) -> None:
		ctr = 0
		for i in self.arr:
			self.arr[ctr] += val
			ctr += 1
			if ctr == k:
				break


import numpy

class CustomStack:

	def __init__(self, maxSize: int):
		self.sz = maxSize
		self.vals = []

	def push(self, x: int) -> None:
		if len(self.vals) < self.sz:
			self.vals.append(x)

	def pop(self) -> int:
		if len(self.vals) > 0:
			return self.vals.pop()
		return -1

	def increment(self, k: int, val: int) -> None:
		tmp = numpy.array(self.vals)
		tmp[:k] += val
		self.vals = list(tmp)


class CustomStack:

	def __init__(self, maxSize: int):
		self.m = maxSize
		self.lst = []

	def push(self, x: int) -> None:
		if len(self.lst) < self.m:
			self.lst.append(x)

	def pop(self) -> int:
		if len(self.lst) == 0:
			return -1
		ret = self.lst[-1]
		self.lst = self.lst[0:-1]
		return ret

	def increment(self, k: int, val: int) -> None:
		i = 0
		while i < len(self.lst) and i < k:
			self.lst[i] += val
			i += 1


class CustomStack:

	def __init__(self, maxSize: int):
		self.max = maxSize
		self.stack = list()

	def push(self, x: int) -> None:
		if len(self.stack) < self.max:
			self.stack.append([x, 0])

	def pop(self) -> int:
		if self.stack:
			(value, increment) = self.stack.pop()
			if self.stack:
				self.stack[-1][1] += increment
			return value + increment
		else:
			return -1

	def increment(self, k: int, val: int) -> None:
		if k <= len(self.stack):
			self.stack[k - 1][1] += val
		elif self.stack:
			self.stack[-1][1] += val