import
java.util.*;
class
Compressed2DBIT {
int
n, m;
List<List<Integer>> bit, tree;
public
Compressed2DBIT(
int
n,
int
m) {
this
.n = n;
this
.m = m;
bit =
new
ArrayList<>(n +
1
);
for
(
int
i =
0
; i <= n; i++) {
bit.add(
new
ArrayList<>(m +
1
));
for
(
int
j =
0
; j <= m; j++) {
bit.get(i).add(
0
);
}
}
tree =
new
ArrayList<>(n);
for
(
int
i =
0
; i < n; i++) {
tree.add(
new
ArrayList<>(m));
for
(
int
j =
0
; j < m; j++) {
tree.get(i).add(
0
);
}
}
}
public
void
update(
int
x,
int
y,
int
val) {
while
(x <= n) {
int
y1 = y;
while
(y1 <= m) {
bit.get(x).set(y1, bit.get(x).get(y1) + val);
y1 += y1 & -y1;
}
x += x & -x;
}
}
public
int
query(
int
x,
int
y) {
int
s =
0
;
while
(x >
0
) {
int
y1 = y;
while
(y1 >
0
) {
s += bit.get(x).get(y1);
y1 -= y1 & -y1;
}
x -= x & -x;
}
return
s;
}
public
void
compress() {
for
(
int
i =
1
; i <= n; i++) {
for
(
int
j =
1
; j <= m; j++) {
tree.get(i -
1
).set(j -
1
, query(i, j)
- query(i -
1
, j)
- query(i, j -
1
)
+ query(i -
1
, j -
1
));
}
}
bit.clear();
}
public
List<List<Integer>> getCompressedTree() {
return
tree;
}
}
public
class
Main {
public
static
void
main(String[] args) {
List<List<Integer>> arr =
new
ArrayList<>(Arrays.asList(
Arrays.asList(
1
,
2
,
3
,
4
,
5
),
Arrays.asList(
6
,
7
,
8
,
9
,
10
),
Arrays.asList(
11
,
12
,
13
,
14
,
15
),
Arrays.asList(
16
,
17
,
18
,
19
,
20
)
));
Compressed2DBIT bit =
new
Compressed2DBIT(
4
,
5
);
for
(
int
i =
0
; i <
4
; i++) {
for
(
int
j =
0
; j <
5
; j++) {
bit.update(i +
1
, j +
1
, arr.get(i).get(j));
}
}
bit.compress();
List<List<Integer>> compressedTree = bit.getCompressedTree();
for
(
int
i =
0
; i < compressedTree.size(); i++) {
for
(
int
j =
0
; j < compressedTree.get(i).size(); j++) {
System.out.print(compressedTree.get(i).get(j) +
" "
);
}
System.out.println();
}
}
}