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