#include #include #include #include #include using namespace std; typedef long long LL; const int N = 100010, INF_KEY = 2000000000; const LL INF_EXT = 1LL << 60; struct Node { LL mx; }; struct SegTree { Node seg[N << 2]; int sz, keys[N]; void Init(const vector &ks) { sz = ks.size(); for (int i = 0; i < sz; ++i) { keys[i] = ks[i]; } } void PushUp(int u) { seg[u].mx = max(seg[u << 1].mx, seg[u << 1 | 1].mx); } void Update(int u, int ul, int ur, int p, LL v) { if (ul == ur) { seg[u].mx = v; return; } int mid = ul + ur >> 1; if (p <= mid) Update(u << 1, ul, mid, p, v); else Update(u << 1 | 1, mid + 1, ur, p, v); PushUp(u); } void Update(int key, LL v) { auto it = lower_bound(keys, keys + sz, key); if (it == keys + sz || *it != key) return; Update(1, 1, sz, it - keys + 1, v); } LL Get(int u, int ul, int ur, int p) { if (ul == ur) return seg[u].mx; int mid = ul + ur >> 1; if (p <= mid) return Get(u << 1, ul, mid, p); return Get(u << 1 | 1, mid + 1, ur, p); } LL Get(int key) { auto it = lower_bound(keys, keys + sz, key); if (it == keys + sz || *it != key) return 0LL; return Get(1, 1, sz, it - keys + 1); } int QueryMin(int u, int ul, int ur, LL tgt) { if (seg[u].mx < tgt) return INF_KEY; if (ul == ur) return keys[ul - 1]; int mid = ul + ur >> 1; if (seg[u << 1].mx >= tgt) return QueryMin(u << 1, ul, mid, tgt); return QueryMin(u << 1 | 1, mid + 1, ur, tgt); } int QueryMin(LL tgt) { return sz ? QueryMin(1, 1, sz, tgt) : INF_KEY; } int QueryMax(int u, int ul, int ur, LL tgt) { if (seg[u].mx < tgt) return -1; if (ul == ur) return keys[ul - 1]; int mid = ul + ur >> 1; if (seg[u << 1 | 1].mx >= tgt) return QueryMax(u << 1 | 1, mid + 1, ur, tgt); return QueryMax(u << 1, ul, mid, tgt); } int QueryMax(LL tgt) { return sz ? QueryMax(1, 1, sz, tgt) : -1; } LL Sum(int u, int ul, int ur) { if (ul == ur) return seg[u].mx; int mid = ul + ur >> 1; return Sum(u << 1, ul, mid) + Sum(u << 1 | 1, mid + 1, ur); } LL Sum() { return sz ? Sum(1, 1, sz) : 0LL; } }; struct Op { int x, y, l; }; SegTree sgt[4]; int w, h, n; LL ans; void ProcessMin(int s, int o, int c1, int c2, int key, int add, int dim, int th1, int th2) { LL new_val = sgt[s].Get(key) + add; LL cand1 = (dim + 1) - sgt[o].Get(key); int k2 = sgt[c1].QueryMin(th1), k3 = sgt[c2].QueryMin(th2); LL cand2 = k2 == INF_KEY ? INF_EXT : k2; LL cand3 = k3 == INF_KEY ? INF_EXT : k3; LL safe = min({ cand1, cand2, cand3 }) - 1; if (new_val <= safe) { sgt[s].Update(key, new_val); } else { sgt[s].Update(key, 0); if (cand1 == safe + 1) sgt[o].Update(key, 0); if (cand2 == safe + 1) sgt[c1].Update(k2, 0); if (cand3 == safe + 1) sgt[c2].Update(k3, 0); } } void ProcessMax(int s, int o, int c1, int c2, int key, int add, int dim, int th1, int th2) { LL new_val = sgt[s].Get(key) + add; LL cand1 = (dim + 1) - sgt[o].Get(key); int k2 = sgt[c1].QueryMax(th1), k3 = sgt[c2].QueryMax(th2); LL cand2 = k2 == -1 ? INF_EXT : (dim + 1) - k2; LL cand3 = k3 == -1 ? INF_EXT : (dim + 1) - k3; LL safe = min({ cand1, cand2, cand3 }) - 1; if (new_val <= safe) { sgt[s].Update(key, new_val); } else { sgt[s].Update(key, 0); if (cand1 == safe + 1) sgt[o].Update(key, 0); if (cand2 == safe + 1) sgt[c1].Update(k2, 0); if (cand3 == safe + 1) sgt[c2].Update(k3, 0); } } int main() { scanf("%d%d%d", &h, &w, &n); vector ops(n); set sides[4]; for (auto &[x, y, l] : ops) { scanf("%d%d%d", &x, &y, &l); if (x == 0) sides[0].insert(y); else if (x == w + 1) sides[1].insert(y); else if (y == 0) sides[2].insert(x); else sides[3].insert(x); } for (int i = 0; i < 4; ++i) { sgt[i].Init(vector(sides[i].begin(), sides[i].end())); } for (auto [x, y, l] : ops) { if (x == 0) ProcessMin(0, 1, 2, 3, y, l, w, y, h + 1 - y); else if (x == w + 1) ProcessMax(1, 0, 2, 3, y, l, w, y, h + 1 - y); else if (y == 0) ProcessMin(2, 3, 0, 1, x, l, h, x, w + 1 - x); else ProcessMax(3, 2, 0, 1, x, l, h, x, w + 1 - x); } ans = 0LL; for (int i = 0; i < 4; ++i) { ans += sgt[i].Sum(); } printf("%lld\n", ans); return 0; }