Submission #1328129

#TimeUsernameProblemLanguageResultExecution timeMemory
1328129model_codeCircuit 2 (JOI25_circuit2)C++20
100 / 100
56 ms824 KiB
#include "circuit.h"
#include <bits/stdc++.h>
using namespace std;

// HL 分解, 上から順に二分探索
string solve(int N, int R, vector<int> U, vector<int> V) {
    const int M = N * 2 + 1;
    string ans(N, '&');
    string s_(M, '0');

    auto Query = [&](string s) {
        assert((int)s.size() == M);
        for (int i = 0; i < M; i++) {
            s[i] ^= s_[i] & 1;
        }
        return query(s);
    };
    auto Flip = [&](int i) {
        ans[i] ^= '|' ^ '&';
        s_[i] ^= 1;
        s_[U[i]] ^= 1;
        s_[V[i]] ^= 1;
    };

    // HL 分解
    vector<int> siz(M, 0);
    for (int i = N; i--; ) {
        const int u = U[i], v = V[i];
        if (siz[u] < siz[v]) {
            swap(U[i], V[i]);
        }
        siz[i] = siz[u] + siz[v] + 1;
    }

    // light-edge の深さで頂点を分類
    vector<int> depth(M, 0);
    for (int i = 0; i < N; i++) {
        const int u = U[i], v = V[i];
        depth[u] = depth[i];
        depth[v] = depth[i] + 1;
    }

    // 深さごとに頂点のリストを作る
    const int D = ranges::max(depth | views::take(N)) + 1;
    vector<vector<int>> Chain(D);
    for (int i = 0; i < N; i++) {
        Chain[depth[i]].push_back(i);
    }
    
    // 深さごとに二分探索
    for (const auto& chain : Chain) {
        // chain[:r] に 1 個ずつ入力を与えて 1 が出力されるか
        auto check = [&](int r) {
            string s(M, '0');
            for (int i : chain | views::take(r)) {
                s[V[i]] = '1';
            }
            return Query(s);
        };
        // 二分探索の幅を 64 に制限
        const int w = 64;
        const int R = chain.size();
        for (int L0 = 0, R0 = w; L0 < R; L0 += w, R0 += w) {
            R0 = min(R0, R);
            while (check(R0)) {
                int zero = L0, one = R0;
                while (one - zero > 1) {
                    const int mid = (zero + one) / 2;
                    (check(mid) ? one : zero) = mid;
                }
                Flip(chain[zero]);
            }
        }
        // 全部 OR にする
        for (int i : chain) {
            s_[i] ^= 1;
            s_[U[i]] ^= 1;
            s_[V[i]] ^= 1;
        }
    }
    
    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...