import
java.util.*;
class
MultiStack<T> {
private
int
numberOfStacks;
private
ArrayList<T> values;
private
ArrayList<Integer> sizes, topIndex;
public
MultiStack(
int
k) {
numberOfStacks = k;
values =
new
ArrayList<>(numberOfStacks <<
1
);
sizes =
new
ArrayList<>(numberOfStacks);
topIndex =
new
ArrayList<>(numberOfStacks);
for
(
int
size =
2
, i =
0
; i < numberOfStacks; i++, size +=
2
) {
sizes.add(size);
topIndex.add(size -
2
);
}
}
public
void
push(
int
stackNum, T val) {
if
(isFull(stackNum))
Expand(stackNum);
values.add(topIndex.get(stackNum), val);
topIndex.set(stackNum, topIndex.get(stackNum) +
1
);
}
public
T pop(
int
stackNum) {
if
(empty(stackNum))
throw
new
RuntimeException(
"Empty Stack!"
);
T val = values.get(topIndex.get(stackNum) -
1
);
values.set(topIndex.get(stackNum) -
1
,
null
);
topIndex.set(stackNum, topIndex.get(stackNum) -
1
);
shrink(stackNum);
return
val;
}
public
T top(
int
stackNum) {
if
(empty(stackNum))
throw
new
RuntimeException(
"Empty Stack!"
);
return
values.get(topIndex.get(stackNum) -
1
);
}
public
int
size(
int
stackNum) {
if
(stackNum ==
0
)
return
topIndex.get(
0
);
return
topIndex.get(stackNum) - sizes.get(stackNum -
1
);
}
public
boolean
empty(
int
stackNum) {
int
offset;
if
(stackNum ==
0
)
offset =
0
;
else
offset = sizes.get(stackNum -
1
);
int
index = topIndex.get(stackNum);
return
index == offset;
}
public
boolean
isFull(
int
stackNum) {
int
offset = sizes.get(stackNum);
int
index = topIndex.get(stackNum);
return
index >= offset;
}
public
void
Expand(
int
stackNum) {
int
reserved_size = size(stackNum);
for
(
int
i = stackNum +
1
; i < numberOfStacks; i++) {
sizes.set(i, sizes.get(i) + reserved_size);
topIndex.set(i, topIndex.get(i) + reserved_size);
}
sizes.set(stackNum, sizes.get(stackNum) + reserved_size);
for
(
int
i =
0
; i < reserved_size; i++)
values.add(topIndex.get(stackNum),
null
);
}
void
shrink(
int
stackNum) {
int
reserved_size, current_size;
if
(stackNum ==
0
) {
reserved_size = sizes.get(
0
);
current_size = topIndex.get(
0
);
}
else
{
reserved_size = sizes.get(stackNum) - sizes.get(stackNum -
1
);
current_size = topIndex.get(stackNum) - sizes.get(stackNum -
1
);
}
if
(current_size *
4
> reserved_size || reserved_size ==
2
) {
return
;
}
int
dif = reserved_size /
2
;
for
(
int
i = stackNum +
1
; i < numberOfStacks; i++) {
sizes.set(i, sizes.get(i) - dif);
topIndex.set(i, topIndex.get(i) - dif);
}
sizes.set(stackNum, sizes.get(stackNum) - dif);
values.subList(topIndex.get(stackNum), topIndex.get(stackNum) + dif).clear();
}
public
static
void
main(String[] args) {
MultiStack<Integer> MStack =
new
MultiStack<>(
3
);
MStack.push(
0
,
21
);
MStack.push(
0
,
13
);
MStack.push(
0
,
14
);
MStack.push(
1
,
15
);
MStack.push(
2
,
1
);
MStack.push(
2
,
2
);
MStack.push(
2
,
3
);
System.out.println(MStack.top(
0
));
System.out.println(MStack.top(
1
));
System.out.println(MStack.top(
2
));
}
};