結果

問題 No.855 ヘビの日光浴
コンテスト
ユーザー 梧桐
提出日時 2026-05-19 14:24:11
言語 C++14
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++14 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 121 ms / 3,153 ms
コード長 4,672 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 785 ms
コンパイル使用メモリ 100,636 KB
実行使用メモリ 12,032 KB
最終ジャッジ日時 2026-05-19 14:24:20
合計ジャッジ時間 8,701 ms
ジャッジサーバーID
(参考情報)
judge3_0 / judge1_0
純コード判定待ち
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 92
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: In function 'int main()':
main.cpp:120:16: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17' [-Wc++17-extensions]
  120 |     for (auto &[x, y, l] : ops) {
      |                ^
main.cpp:132:15: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17' [-Wc++17-extensions]
  132 |     for (auto [x, y, l] : ops) {
      |               ^

ソースコード

diff #
raw source code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>

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<int> &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<Op> ops(n);
    set<int> 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<int>(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;
}
0