ABC 338

A. Capitalized?

https://atcoder.jp/contests/abc338/tasks/abc338_a

B. Frequency

https://atcoder.jp/contests/abc338/tasks/abc338_b

C. Leftover Recipes

https://atcoder.jp/contests/abc338/tasks/abc338_c

D. Island Tour

https://atcoder.jp/contests/abc338/tasks/abc338_d

解説 AC

void solve() {
    ll n, m;
    cin >> n >> m;
    vll x(m);
    rep(i, m) {
        cin >> x[i];
        x[i]--;
    }

    vll cumsum(n * 2 + 1, 0);

    rep(i, m - 1) {
        ll mi = min(x[i], x[i + 1]);
        ll mx = max(x[i], x[i + 1]);

        ll dr = mx - mi;
        ll dl = n - dr;
        cumsum[mi] += dl;
        cumsum[mx] -= dl;
        cumsum[0] += dr;
        cumsum[mi] -= dr;
        cumsum[mx] += dr;
        cumsum[n] -= dr;
    }

    rep(i, n * 2) cumsum[i + 1] += cumsum[i];

    ll ans = INF;
    rep(i, n) chmin(ans, cumsum[i]);
    cout << ans << endl;
}

E. Chords

https://atcoder.jp/contests/abc338/tasks/abc338_e

https://atcoder.jp/contests/abc405/editorial/13011 での方式と同じ実装して通った。

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    cin >> N;

    vector<pair<int, int>> ps;
    rep(i, N) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        if (a > b)
            swap(a, b);
        ps.emplace_back(a, b);
    }

    sort(all(ps), [](auto a, auto b) -> bool {
        return a.second < b.second;
    });

    auto op = [](ll a, ll b) -> ll { return a + b; };
    auto e = []() -> ll { return 0ll; };

    segtree<ll, op, e> seg(N * 2);
    rep(i, N) {
        seg.set(ps[i].first, 1);
    }

    bool ans = false;
    for (auto [a, b] : ps) {
        int sum = seg.prod(a + 1, b);
        if (sum > 0)
            ans = true;
        seg.set(a, -1);
        seg.set(b, 1);
    }
    yesno(ans);
}

2026/1/18 解説 AC

頂点 $2N$ に対して辺の数が $N$ だからすべての辺が並行のときしか交差しないと思ったが $2i, 2i+1$ のように順番に辺を張ると交差しない例があるので間違い。

カッコ列の問題として解けるらしい。ref: https://drken1215.hatenablog.com/entry/2024/11/02/202502

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N;
    cin >> N;
    vint P(N * 2);
    rep(i, N) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        P[a] = i;
        P[b] = i;
    }

    stack<int> st;
    rep(i, N * 2) {
        if (st.size() && st.top() == P[i]) {
            st.pop();
        } else {
            st.push(P[i]);
        }
    }

    yesno(st.size());
}

$A_i < A_j < B_i < B_j$ を満たす $(i, j)$ の組が存在するかどうかを判定する問題として解く方法。

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N;
    cin >> N;

    using P = pair<ll, ll>;
    vector<P> ps;
    rep(i, N) {
        ll a, b;
        cin >> a >> b;
        if (a > b) swap(a, b);
        a--, b--;
        ps.emplace_back(a, b);
    }

    fenwick_tree<ll> fw(N * 2);
    for (auto [a, b] : ps) fw.add(a, 1);

    sort(all(ps), [](P a, P b) -> bool {
        return a.second < b.second;
    });

    int cross = 0;
    for (auto [a, b] : ps) {
        ll sum = fw.sum(a + 1, b);
        if (sum > 0) cross = 1;
        fw.add(a, -1);
    }
    yesno(cross);
}

2026/2/23 カッコ列の類似問題と知った状態で自力 AC

https://atcoder-novisteps.vercel.app/workbooks/141

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    cin >> N;

    vint chords(N * 2, -1);
    rep(i, N) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        chords[u] = chords[v] = i;
    }

    vint st, appear(N);

    for (int x : chords) {
        if (appear[x]) {
            if (st.back() != x) {
                Yes();
                return;
            }
            st.pop_back();
        } else {
            st.pb(x);
            appear[x] = 1;
        }
    }
    No();
}

F. Negative Traveling Salesman

https://atcoder.jp/contests/abc338/tasks/abc338_f

G. evall

https://atcoder.jp/contests/abc338/tasks/abc338_g