Skip to content

Commit 31e4d96

Browse files
committed
Tetris 3d
1 parent 67b0325 commit 31e4d96

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

POI/POI 06-tetris3d.cpp

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
POI 2006 Tetris3D
3+
- Firstly, realize that we can't do lazy propagation on a 2D segtree and cry a bit
4+
- Next, notice that heights only ever increase
5+
- This is similar to the 1D version of range updates/queries where we can't
6+
use lazy propagation
7+
- Basically, for each node, we store 2 values:
8+
- The maximum of that range (max[i])
9+
- The maximum of the last time every value in that range was equal (all[i])
10+
- Since the values only ever increase, we know that if we have a segment (l, r)
11+
and the query range intersects it, the answer to the query is always >= all[i]
12+
- We can apply this idea to our 2D segtree, but the inner 1D segtrees do support lazy
13+
propagation
14+
- Each node of the 2D segtree stores 2 1D segtrees: range_max and range_all
15+
- Complexity: O(N log S log D)
16+
*/
17+
18+
#include <bits/stdc++.h>
19+
#define FOR(i, x, y) for (int i = x; i < y; i++)
20+
typedef long long ll;
21+
using namespace std;
22+
23+
struct Segtree {
24+
int seg_val[2048], lazy[2048];
25+
26+
void push_lazy(int node, int l, int r) {
27+
seg_val[node] = max(seg_val[node], lazy[node]);
28+
if (l != r) {
29+
lazy[node * 2] = max(lazy[node * 2], lazy[node]);
30+
lazy[node * 2 + 1] = max(lazy[node * 2 + 1], lazy[node]);
31+
}
32+
lazy[node] = 0;
33+
}
34+
35+
void update(int yl, int yr, int val, int node = 1, int l = 0, int r = 999) {
36+
push_lazy(node, l, r);
37+
if (l > yr || r < yl) return;
38+
if (l >= yl && r <= yr) {
39+
lazy[node] = val;
40+
push_lazy(node, l, r);
41+
} else {
42+
int mid = (l + r) / 2;
43+
update(yl, yr, val, node * 2, l, mid);
44+
update(yl, yr, val, node * 2 + 1, mid + 1, r);
45+
seg_val[node] = max(seg_val[node * 2], seg_val[node * 2 + 1]);
46+
}
47+
}
48+
49+
int query(int yl, int yr, int node = 1, int l = 0, int r = 999) {
50+
push_lazy(node, l, r);
51+
if (l > yr || r < yl) return 0;
52+
if (l >= yl && r <= yr) return seg_val[node];
53+
int mid = (l + r) / 2;
54+
return max(query(yl, yr, node * 2, l, mid),
55+
query(yl, yr, node * 2 + 1, mid + 1, r));
56+
}
57+
};
58+
59+
struct Lazy2dSegtree {
60+
Segtree range_all[2048], range_max[2048];
61+
62+
void update(int xl, int xr, int yl, int yr, int val, int node = 1, int l = 0, int r = 999) {
63+
if (l > xr || r < xl) return;
64+
if (l >= xl && r <= xr) {
65+
range_all[node].update(yl, yr, val);
66+
range_max[node].update(yl, yr, val);
67+
} else {
68+
int mid = (l + r) / 2;
69+
update(xl, xr, yl, yr, val, node * 2, l, mid);
70+
update(xl, xr, yl, yr, val, node * 2 + 1, mid + 1, r);
71+
range_max[node].update(yl, yr, val);
72+
}
73+
}
74+
75+
int query(int xl, int xr, int yl, int yr, int node = 1, int l = 0, int r = 999) {
76+
if (l > xr || r < xl) return 0;
77+
if (l >= xl && r <= xr) return range_max[node].query(yl, yr);
78+
int mid = (l + r) / 2;
79+
return max(max(query(xl, xr, yl, yr, node * 2, l, mid),
80+
query(xl, xr, yl, yr, node * 2 + 1, mid + 1, r)),
81+
range_all[node].query(yl, yr));
82+
}
83+
} board;
84+
85+
int main() {
86+
ios_base::sync_with_stdio(0);
87+
cin.tie(0);
88+
int D, S, N;
89+
cin >> D >> S >> N;
90+
91+
while (N--) {
92+
int d, s, w, x, y;
93+
cin >> d >> s >> w >> x >> y;
94+
int mx = board.query(x, x + d - 1, y, y + s - 1);
95+
board.update(x, x + d - 1, y, y + s - 1, mx + w);
96+
}
97+
cout << board.query(0, D - 1, 0, S - 1);
98+
return 0;
99+
}

0 commit comments

Comments
 (0)