{"model_name":"deepseek-v4-flash-high","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Rect { int a, b, c, d; }; // [a,c) x [b,d)\nstruct Region { int x0, y0, x1, y1; vector<int> ids; };\nstruct SplitResult { int axis; int s; vector<int> left, right; };\n\nint n;\nvector<int> xi, yi, ri;\n\ndouble calc_p(int idx, long long area) {\n    long long r = ri[idx];\n    long long s = area;\n    long long mn = min(r, s);\n    long long mx = max(r, s);\n    double ratio = (double)mn / mx;\n    return ratio * (2.0 - ratio);\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return max(a.a, b.a) < min(a.c, b.c) && max(a.b, b.b) < min(a.d, b.d);\n}\nbool contains(const Rect& rect, int xi, int yi) {\n    return rect.a <= xi && xi < rect.c && rect.b <= yi && yi < rect.d;\n}\n\ndouble total_score(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; ++i) {\n        long long area = (long long)(rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        sum += calc_p(i, area);\n    }\n    return sum;\n}\n\nSplitResult choose_split(const Region& reg) {\n    int m = reg.ids.size();\n    const auto& ids = reg.ids;\n    int x0 = reg.x0, y0 = reg.y0, x1 = reg.x1, y1 = reg.y1;\n    vector<SplitResult> candidates;\n\n    // ---- vertical split (axis 0) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, xi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, xi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int height = y1 - y0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / height + x0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - x0) * height;\n            long long right_area = (long long)(x1 - s) * height;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({0, s, move(left_ids), move(right_ids)});\n        }\n    }\n\n    // ---- horizontal split (axis 1) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return yi[i] < yi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, yi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, yi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int width = x1 - x0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / width + y0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - y0) * width;\n            long long right_area = (long long)(y1 - s) * width;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({1, s, move(left_ids), move(right_ids)});\n        }\n    }\n\n    if (candidates.empty()) {\n        // fallback: split vertically at median\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        int mid = m / 2;\n        int split_x = (xi[order[mid-1]] + xi[order[mid]] + 1) / 2;\n        if (split_x <= x0) split_x = x0+1;\n        if (split_x >= x1) split_x = x1-1;\n        vector<int> left(order.begin(), order.begin()+mid);\n        vector<int> right(order.begin()+mid, order.end());\n        return {0, split_x, move(left), move(right)};\n    }\n\n    // stochastic selection with softmax\n    double temperature = 0.02;\n    double max_metric = 1e100;\n    for (auto& c : candidates) if (c.metric < max_metric) max_metric = c.metric;\n    vector<double> weights(candidates.size());\n    double sum_weights = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        weights[i] = exp(- (candidates[i].metric - max_metric) * temperature);\n        sum_weights += weights[i];\n    }\n    uniform_real_distribution<double> dist(0.0, sum_weights);\n    double r = dist(rng);\n    double cum = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        cum += weights[i];\n        if (r <= cum) return move(candidates[i]);\n    }\n    return move(candidates.back());\n}\n\nvoid recursive_split(const Region& reg, vector<Rect>& rects) {\n    if (reg.ids.size() == 1) {\n        int idx = reg.ids[0];\n        rects[idx] = {reg.x0, reg.y0, reg.x1, reg.y1};\n        return;\n    }\n    SplitResult split = choose_split(reg);\n    if (split.axis == 0) {\n        Region left{reg.x0, reg.y0, split.s, reg.y1, move(split.left)};\n        Region right{split.s, reg.y0, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    } else {\n        Region left{reg.x0, reg.y0, reg.x1, split.s, move(split.left)};\n        Region right{reg.x0, split.s, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    }\n}\n\nvoid improve(vector<Rect>& rects) {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < n; ++i) {\n            Rect cur = rects[i];\n            // try expand in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c >= 10000) continue;\n                    newr.c++;\n                } else if (dir == 1) { // left\n                    if (newr.a <= 0) continue;\n                    newr.a--;\n                } else if (dir == 2) { // top\n                    if (newr.d >= 10000) continue;\n                    newr.d++;\n                } else { // bottom\n                    if (newr.b <= 0) continue;\n                    newr.b--;\n                }\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n            // try shrink in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c - 1 <= newr.a) continue;\n                    newr.c--;\n                } else if (dir == 1) { // left\n                    if (newr.a + 1 >= newr.c) continue;\n                    newr.a++;\n                } else if (dir == 2) { // top\n                    if (newr.d - 1 <= newr.b) continue;\n                    newr.d--;\n                } else { // bottom\n                    if (newr.b + 1 >= newr.d) continue;\n                    newr.b++;\n                }\n                // must still contain the point\n                if (!contains(newr, xi[i], yi[i])) continue;\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(15);\n\n    cin >> n;\n    xi.resize(n); yi.resize(n); ri.resize(n);\n    for (int i = 0; i < n; ++i) cin >> xi[i] >> yi[i] >> ri[i];\n\n    vector<Rect> best_rects(n);\n    double best_score = -1.0;\n\n    const int TRIALS = 200; // number of random constructions\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        vector<int> all_ids(n);\n        iota(all_ids.begin(), all_ids.end(), 0);\n        Region full{0, 0, 10000, 10000, move(all_ids)};\n        vector<Rect> rects(n);\n        recursive_split(full, rects);\n        double score = total_score(rects);\n        if (score > best_score) {\n            best_score = score;\n            best_rects = move(rects);\n        }\n    }\n\n    // post-processing on best solution\n    improve(best_rects);\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n             << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\n// constants\nconst int N = 50;\nconst int MAX_TILES = 2500;\nusing Bitset = array<uint64_t, 40>; // 2500 bits = 40 * 64 bits\n\nstruct State {\n    int r, c;\n    Bitset vis;\n    int sum;\n    string path;\n};\n\n// direction characters\nconst char dir_chars[] = {'U', 'D', 'L', 'R'};\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    int si, sj;\n    cin >> si >> sj;\n\n    int tile[N][N];\n    int p[N][N];\n    int max_tile_id = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tile[i][j];\n            max_tile_id = max(max_tile_id, tile[i][j]);\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> p[i][j];\n        }\n    }\n    int M = max_tile_id + 1; // number of tiles\n\n    // precompute valid moves for each cell (neighbor with different tile)\n    vector<tuple<int,int,char>> moves[N][N];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dr[d];\n                int nj = j + dc[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (tile[i][j] != tile[ni][nj]) {\n                    moves[i][j].emplace_back(ni, nj, dir_chars[d]);\n                }\n            }\n        }\n    }\n\n    // helper to set and check bits in Bitset\n    auto set_bit = [](Bitset &bs, int id) {\n        bs[id / 64] |= (1ULL << (id % 64));\n    };\n    auto test_bit = [](const Bitset &bs, int id) -> bool {\n        return (bs[id / 64] >> (id % 64)) & 1;\n    };\n\n    // beam search parameters\n    const int K = 50;\n    const int TIME_LIMIT_MS = 1900;\n\n    auto start_time = chrono::high_resolution_clock::now();\n\n    // initial state\n    State start;\n    start.r = si;\n    start.c = sj;\n    fill(start.vis.begin(), start.vis.end(), 0);\n    set_bit(start.vis, tile[si][sj]);\n    start.sum = p[si][sj];\n    start.path = \"\";\n\n    vector<State> beam;\n    beam.push_back(start);\n\n    string best_path = \"\";\n    int best_sum = 0;\n\n    while (!beam.empty()) {\n        // check time\n        auto now = chrono::high_resolution_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > TIME_LIMIT_MS) break;\n\n        vector<State> candidates;\n        candidates.reserve(beam.size() * 4);\n\n        for (const auto &s : beam) {\n            int r = s.r, c = s.c;\n            for (auto [nr, nc, dir] : moves[r][c]) {\n                int nt = tile[nr][nc];\n                if (test_bit(s.vis, nt)) continue; // tile already visited\n                // create new state\n                State ns;\n                ns.r = nr;\n                ns.c = nc;\n                ns.vis = s.vis;\n                set_bit(ns.vis, nt);\n                ns.sum = s.sum + p[nr][nc];\n                ns.path = s.path + dir;\n                candidates.push_back(move(ns));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        // sort by sum descending\n        sort(candidates.begin(), candidates.end(),\n             [](const State &a, const State &b) { return a.sum > b.sum; });\n\n        // keep top K\n        if (candidates.size() > K) candidates.resize(K);\n\n        // update best\n        if (candidates[0].sum > best_sum) {\n            best_sum = candidates[0].sum;\n            best_path = candidates[0].path;\n        }\n\n        beam = move(candidates);\n    }\n\n    // if no path (should not happen), output empty string\n    cout << best_path << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n#include <sstream>\n#include <iomanip>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int H_EDGES = 29; // number of horizontal edges per row\nconst int V_EDGES = 29; // number of vertical edges per column (30 rows -> 29 vertical edges per column)\n\nconst double INIT_EST = 4500.0;\nconst double MIN_EDGE = 1000.0;\nconst double MAX_EDGE = 9000.0;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // estimates, counts, and sum of squared gradients for AdaGrad\n    vector<vector<double>> h_est(GRID_SIZE, vector<double>(H_EDGES, INIT_EST));\n    vector<vector<int>> h_cnt(GRID_SIZE, vector<int>(H_EDGES, 0));\n    vector<vector<double>> h_grad_sq(GRID_SIZE, vector<double>(H_EDGES, 0.0));\n\n    vector<vector<double>> v_est(V_EDGES, vector<double>(GRID_SIZE, INIT_EST));\n    vector<vector<int>> v_cnt(V_EDGES, vector<int>(GRID_SIZE, 0));\n    vector<vector<double>> v_grad_sq(V_EDGES, vector<double>(GRID_SIZE, 0.0));\n\n    // hyperparameters\n    const double lr0 = 0.5;\n    const double C_explore = 500.0;\n    const int explore_until = 400;\n\n    int T = 1000;\n    for (int k = 0; k < T; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        // exploration factor: decays linearly to 0 over first explore_until queries\n        double explore_factor = max(0.0, 1.0 - (double)k / explore_until);\n        double t_weight = sqrt(log(k + 1.0) + 1.0); // UCB time factor\n\n        // ----------------------- Dijkstra with UCB-adjusted weights -----------------------\n        const double INF = 1e18;\n        vector<vector<double>> dist(GRID_SIZE, vector<double>(GRID_SIZE, INF));\n        vector<vector<pair<int,int>>> prev(GRID_SIZE, vector<pair<int,int>>(GRID_SIZE, {-1, -1}));\n        // priority queue: (distance, (i,j))\n        priority_queue<pair<double, pair<int,int>>, vector<pair<double, pair<int,int>>>, greater<>> pq;\n        dist[si][sj] = 0.0;\n        pq.push({0.0, {si, sj}});\n\n        while (!pq.empty()) {\n            auto [d, node] = pq.top(); pq.pop();\n            int i = node.first, j = node.second;\n            if (d > dist[i][j] + 1e-9) continue;\n            if (i == ti && j == tj) break; // reached target\n\n            // neighbor: up (i-1, j) -> vertical edge (i-1, j)\n            if (i > 0) {\n                double w = v_est[i-1][j] - C_explore * t_weight / sqrt(v_cnt[i-1][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i-1][j] - 1e-9) {\n                    dist[i-1][j] = d + w;\n                    prev[i-1][j] = {i, j};\n                    pq.push({dist[i-1][j], {i-1, j}});\n                }\n            }\n            // neighbor: down (i+1, j) -> vertical edge (i, j)\n            if (i < GRID_SIZE - 1) {\n                double w = v_est[i][j] - C_explore * t_weight / sqrt(v_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i+1][j] - 1e-9) {\n                    dist[i+1][j] = d + w;\n                    prev[i+1][j] = {i, j};\n                    pq.push({dist[i+1][j], {i+1, j}});\n                }\n            }\n            // neighbor: left (i, j-1) -> horizontal edge (i, j-1)\n            if (j > 0) {\n                double w = h_est[i][j-1] - C_explore * t_weight / sqrt(h_cnt[i][j-1] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j-1] - 1e-9) {\n                    dist[i][j-1] = d + w;\n                    prev[i][j-1] = {i, j};\n                    pq.push({dist[i][j-1], {i, j-1}});\n                }\n            }\n            // neighbor: right (i, j+1) -> horizontal edge (i, j)\n            if (j < GRID_SIZE - 1) {\n                double w = h_est[i][j] - C_explore * t_weight / sqrt(h_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j+1] - 1e-9) {\n                    dist[i][j+1] = d + w;\n                    prev[i][j+1] = {i, j};\n                    pq.push({dist[i][j+1], {i, j+1}});\n                }\n            }\n        }\n\n        // backtrack to retrieve the path\n        vector<pair<int,int>> path;\n        int ci = ti, cj = tj;\n        while (!(ci == si && cj == sj)) {\n            path.push_back({ci, cj});\n            auto p = prev[ci][cj];\n            ci = p.first;\n            cj = p.second;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n\n        // construct output string (moves)\n        string out;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int di = path[idx].first - path[idx-1].first;\n            int dj = path[idx].second - path[idx-1].second;\n            if (di == -1) out += 'U';\n            else if (di == 1) out += 'D';\n            else if (dj == -1) out += 'L';\n            else if (dj == 1) out += 'R';\n        }\n        cout << out << endl; // flush included\n\n        // read feedback: observed (noisy) path length\n        int feedback;\n        cin >> feedback;\n\n        // ----------------------- Update estimates -----------------------\n        // compute predicted length using current (unadjusted) estimates\n        double L_pred = 0.0;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                L_pred += h_est[i1][jmin];\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                L_pred += v_est[imin][j1];\n            }\n        }\n\n        double error = feedback - L_pred;\n        double rel_error = error / max(L_pred, 1.0);\n        // clamp to avoid extreme updates from large mispredictions\n        rel_error = clamp(rel_error, -3.0, 3.0);\n\n        // update each edge on the path\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                // accumulate squared gradient\n                h_grad_sq[i1][jmin] += rel_error * rel_error;\n                double lr = lr0 / sqrt(h_grad_sq[i1][jmin] + 1e-8);\n                double new_val = h_est[i1][jmin] + lr * rel_error;\n                h_est[i1][jmin] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                h_cnt[i1][jmin]++;\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                v_grad_sq[imin][j1] += rel_error * rel_error;\n                double lr = lr0 / sqrt(v_grad_sq[imin][j1] + 1e-8);\n                double new_val = v_est[imin][j1] + lr * rel_error;\n                v_est[imin][j1] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                v_cnt[imin][j1]++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPH = 8;\n\nint M;\nvector<string> strs;\nvector<uint64_t> hashes;\nunordered_map<uint64_t, vector<int>> hash_to_ids;\n\nvector<string> mat; // current matrix\nvector<int> occ;    // occurrences per input string\nint matched = 0;    // number of input strings with occ>0\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// encode a string to a 64-bit integer (3 bits per character)\nuint64_t encode(const string &s) {\n    uint64_t h = 0;\n    for (char c : s) {\n        h = (h << 3) | (c - 'A');\n    }\n    return h;\n}\n\n// generate all substrings that include cell (r,c) under the assumption that\n// mat[r][c] has the given character (used for delta computation)\nvoid collect_hashes(int r, int c, char cell_char, vector<uint64_t> &hashes) {\n    hashes.clear();\n    // helper lambda: get character of a cell, possibly with override\n    auto get_char = [&](int i, int j) -> char {\n        if (i == r && j == c) return cell_char;\n        return mat[i][j];\n    };\n    // horizontal substrings\n    for (int len = 2; len <= 12; ++len) {\n        // starting columns that include (r,c)\n        for (int offset = 0; offset < len; ++offset) {\n            int start_col = (c - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int col = (start_col + t) % N;\n                char ch = get_char(r, col);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) hashes.push_back(h);\n        }\n    }\n    // vertical substrings\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_row = (r - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int row = (start_row + t) % N;\n                char ch = get_char(row, c);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) hashes.push_back(h);\n        }\n    }\n}\n\n// compute the change in 'matched' if we set (r,c) from old_char to new_char\nint compute_delta(int r, int c, char old_char, char new_char) {\n    static vector<uint64_t> old_hashes, new_hashes;\n    static vector<int> delta_occ(M, 0);\n    static vector<int> affected_ids;\n    affected_ids.clear();\n\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]--;\n            }\n        }\n    }\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]++;\n            }\n        }\n    }\n\n    int delta_matched = 0;\n    for (int id : affected_ids) {\n        int new_occ = occ[id] + delta_occ[id];\n        if (occ[id] == 0 && new_occ > 0) delta_matched++;\n        if (occ[id] > 0 && new_occ == 0) delta_matched--;\n    }\n    // clean up\n    for (int id : affected_ids) delta_occ[id] = 0;\n    return delta_matched;\n}\n\n// apply the change: update matrix and global occ/matched\nvoid apply_change(int r, int c, char new_char) {\n    char old_char = mat[r][c];\n    if (old_char == new_char) return;\n    static vector<uint64_t> old_hashes, new_hashes;\n    // remove old substrings\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                occ[id]--;\n                if (occ[id] == 0) matched--;\n            }\n        }\n    }\n    // set new character\n    mat[r][c] = new_char;\n    // add new substrings\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (occ[id] == 0) matched++;\n                occ[id]++;\n            }\n        }\n    }\n}\n\n// compute initial occ and matched by scanning the whole matrix\nvoid compute_initial_state() {\n    fill(occ.begin(), occ.end(), 0);\n    matched = 0;\n    // scan all substrings\n    for (int r = 0; r < N; ++r) {\n        for (int len = 2; len <= 12; ++len) {\n            // horizontal\n            for (int start_col = 0; start_col < N; ++start_col) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int col = (start_col + t) % N;\n                    char ch = mat[r][col];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n            // vertical\n            for (int start_row = 0; start_row < N; ++start_row) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int row = (start_row + t) % N;\n                    char ch = mat[row][start_row]; // column is start_row? actually vertical: column fixed\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// structure for a placement (for greedy)\nstruct Placement {\n    vector<int> cells;   // linear indices (r*20 + c)\n    vector<char> letters;\n};\n\n// greedy initialisation: fill matrix with as many strings as possible\nvoid greedy_initialization(vector<vector<Placement>> &placements) {\n    mat.assign(N, string(N, '.'));\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int idx : order) {\n        int best_score = -1;\n        int best_p = -1;\n        for (int p = 0; p < (int)placements[idx].size(); ++p) {\n            auto &pl = placements[idx][p];\n            int score = 0;\n            bool ok = true;\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                char cur = mat[r][c];\n                if (cur == '.') {\n                    // fine\n                } else if (cur != pl.letters[t]) {\n                    ok = false;\n                    break;\n                } else {\n                    score++;\n                }\n            }\n            if (ok && score > best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        if (best_p != -1) {\n            auto &pl = placements[idx][best_p];\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                mat[r][c] = pl.letters[t];\n            }\n        }\n    }\n    compute_initial_state();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    if (N != 20) { // just in case\n        cerr << \"N is not 20\" << endl;\n        return 1;\n    }\n    strs.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n    }\n\n    // compute hashes and mapping\n    hashes.resize(M);\n    for (int i = 0; i < M; ++i) {\n        hashes[i] = encode(strs[i]);\n        hash_to_ids[hashes[i]].push_back(i);\n    }\n\n    // Precompute all placements for each string\n    vector<vector<Placement>> placements(M);\n    for (int i = 0; i < M; ++i) {\n        const string &s = strs[i];\n        int len = s.size();\n        placements[i].reserve(800);\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // horizontal\n                Placement ph;\n                ph.cells.reserve(len);\n                ph.letters.reserve(len);\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int col = (c + t) % N;\n                    ph.cells.push_back(r * N + col);\n                    ph.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(ph));\n                // vertical\n                Placement pv;\n                pv.cells.reserve(len);\n                pv.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int row = (r + t) % N;\n                    pv.cells.push_back(row * N + c);\n                    pv.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(pv));\n            }\n        }\n    }\n\n    // Try several greedy initializations and keep the best one\n    const int TRIES = 5; // adjust as needed\n    int best_matched = -1;\n    vector<string> best_mat;\n    for (int t = 0; t < TRIES; ++t) {\n        greedy_initialization(placements);\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n        if (best_matched == M) break; // already perfect\n    }\n    // set state to best found\n    mat = best_mat;\n    compute_initial_state();\n\n    // Simulated Annealing\n    const int MAX_ITER = 100000;\n    double T = 1.0;\n    const double COOLING = 0.99999;\n    const double MIN_T = 1e-4;\n    int iter = 0;\n    while (matched < M && iter < MAX_ITER && T > MIN_T) {\n        // pick random cell\n        int r = uniform_int_distribution<int>(0, N-1)(rng);\n        int c = uniform_int_distribution<int>(0, N-1)(rng);\n        char oldc = mat[r][c];\n        // pick random new letter\n        char newc;\n        do {\n            newc = 'A' + uniform_int_distribution<int>(0, ALPH-1)(rng);\n        } while (newc == oldc);\n\n        int delta = compute_delta(r, c, oldc, newc);\n        if (delta > 0) {\n            apply_change(r, c, newc);\n        } else if (delta == 0) {\n            // accept with some probability to escape plateaus\n            if (uniform_real_distribution<double>(0,1)(rng) < 0.1) {\n                apply_change(r, c, newc);\n            }\n        } else {\n            // accept worse with probability exp(delta / T), delta negative\n            double prob = exp(delta / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                apply_change(r, c, newc);\n            }\n        }\n        T *= COOLING;\n        iter++;\n        // update best if improved\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n    }\n\n    // If we have all strings, try to remove cells to increase score\n    if (best_matched == M) {\n        mat = best_mat;\n        compute_initial_state();\n        // greedy removal: try to set each cell to '.' and keep if still all matched\n        vector<int> cell_order(N*N);\n        iota(cell_order.begin(), cell_order.end(), 0);\n        shuffle(cell_order.begin(), cell_order.end(), rng);\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int cell : cell_order) {\n                int r = cell / N, c = cell % N;\n                if (mat[r][c] == '.') continue;\n                int delta = compute_delta(r, c, mat[r][c], '.');\n                if (delta == 0) { // still all strings present\n                    apply_change(r, c, '.');\n                    changed = true;\n                }\n            }\n        }\n        best_mat = mat;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << best_mat[i] << \"\\n\";\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint16 = unsigned short;\nconst uint16 INF16 = UINT16_MAX;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int,int>> pos;       // coordinates of each road square\nvector<int> weight;              // time cost of each road square\nvector<vector<int>> adj;         // adjacency list (neighbor indices)\nint R;                           // number of road squares\n\n// map (i,j) -> id\nint id[70][70];\n\nvoid read_input() {\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    // assign ids to road squares\n    R = 0;\n    memset(id, -1, sizeof(id));\n    pos.clear();\n    weight.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R;\n                pos.emplace_back(i, j);\n                weight.push_back(grid[i][j] - '0');\n                ++R;\n            }\n        }\n    }\n    // build adjacency\n    adj.assign(R, vector<int>());\n    int di[] = {-1,1,0,0};\n    int dj[] = {0,0,-1,1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == '#') continue;\n            int u = id[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && grid[ni][nj] != '#') {\n                    int v = id[ni][nj];\n                    adj[u].push_back(v);\n                }\n            }\n        }\n    }\n}\n\n// Precompute all-pair shortest paths (distance matrix)\nvector<vector<uint16>> precompute_all_pairs() {\n    vector<vector<uint16>> dist(R, vector<uint16>(R, INF16));\n    for (int src = 0; src < R; ++src) {\n        vector<uint16> d(R, INF16);\n        d[src] = 0;\n        priority_queue<pair<uint16,int>, vector<pair<uint16,int>>, greater<pair<uint16,int>>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top(); pq.pop();\n            if (cd != d[u]) continue;\n            for (int v : adj[u]) {\n                uint16 nd = cd + weight[v];\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n        dist[src] = d;\n    }\n    return dist;\n}\n\n// Get horizontal segments\npair<vector<vector<int>>, vector<int>> get_h_segments() {\n    vector<int> h_id(R, -1);\n    vector<vector<int>> h_nodes;\n    int hcnt = 0;\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') { ++j; continue; }\n            int start = j;\n            while (j < N && grid[i][j] != '#') ++j;\n            vector<int> seg;\n            for (int k = start; k < j; ++k) {\n                int uid = id[i][k];\n                h_id[uid] = hcnt;\n                seg.push_back(uid);\n            }\n            h_nodes.push_back(seg);\n            ++hcnt;\n        }\n    }\n    return {move(h_nodes), move(h_id)};\n}\n\n// Build groups (start group + all H-segments except start's)\nvector<vector<int>> build_groups(const vector<vector<int>> &h_nodes, const vector<int> &h_id, int start_id) {\n    vector<vector<int>> groups;\n    // group 0 = start\n    groups.push_back({start_id});\n    int start_h = h_id[start_id];\n    for (size_t g = 0; g < h_nodes.size(); ++g) {\n        if ((int)g == start_h) continue;\n        groups.push_back(h_nodes[g]);\n    }\n    return groups;\n}\n\n// Compute segment distance matrix\nvector<vector<uint16>> segment_dist_matrix(const vector<vector<int>> &groups, const vector<vector<uint16>> &dist) {\n    int G = groups.size();\n    vector<vector<uint16>> D(G, vector<uint16>(G, INF16));\n    for (int i = 0; i < G; ++i) {\n        D[i][i] = 0;\n        for (int j = i+1; j < G; ++j) {\n            uint16 best = INF16;\n            for (int u : groups[i]) {\n                for (int v : groups[j]) {\n                    best = min(best, dist[u][v]);\n                }\n            }\n            D[i][j] = D[j][i] = best;\n        }\n    }\n    return D;\n}\n\n// TSP on groups with 2-opt (fix start group 0)\nvector<int> solve_tsp(const vector<vector<uint16>> &D) {\n    int G = D.size();\n    if (G <= 1) return {0};\n    vector<int> tour(G);\n    // nearest neighbour\n    vector<bool> visited(G, false);\n    tour[0] = 0;\n    visited[0] = true;\n    for (int k = 1; k < G; ++k) {\n        int cur = tour[k-1];\n        int best = -1;\n        uint16 bestDist = INF16;\n        for (int i = 0; i < G; ++i) {\n            if (!visited[i] && D[cur][i] < bestDist) {\n                bestDist = D[cur][i];\n                best = i;\n            }\n        }\n        tour[k] = best;\n        visited[best] = true;\n    }\n    // 2-opt improvement (cycle)\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i < G-1; ++i) {\n            for (int j = i+1; j < G; ++j) {\n                int a = tour[i-1];\n                int b = tour[i];\n                int c = tour[j];\n                int d = (j+1 < G) ? tour[j+1] : tour[0];\n                uint16 old = D[a][b] + D[c][d];\n                uint16 nw = D[a][c] + D[b][d];\n                if (nw < old) {\n                    reverse(tour.begin() + i, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    return tour;\n}\n\n// DP to select one node per group given a fixed order\nvector<int> select_nodes(const vector<int> &order, const vector<vector<int>> &groups, const vector<vector<uint16>> &dist) {\n    int G = order.size();\n    if (G == 1) return {groups[0][0]}; // only start\n    vector<unordered_map<int,uint16>> dp_cost(G);\n    vector<unordered_map<int,int>> dp_prev(G);\n    // initialize start group (order[0] should be 0)\n    int start_id = groups[0][0];\n    dp_cost[0][start_id] = 0;\n    for (int pos = 1; pos < G; ++pos) {\n        int g = order[pos];\n        int prev_g = order[pos-1];\n        for (int v : groups[g]) {\n            uint16 best = INF16;\n            int best_u = -1;\n            for (int u : groups[prev_g]) {\n                auto it = dp_cost[pos-1].find(u);\n                if (it != dp_cost[pos-1].end()) {\n                    uint16 cand = it->second + dist[u][v];\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n            }\n            if (best != INF16) {\n                dp_cost[pos][v] = best;\n                dp_prev[pos][v] = best_u;\n            }\n        }\n    }\n    // final step: return to start\n    uint16 total_best = INF16;\n    int last_node = -1;\n    for (int u : groups[order[G-1]]) {\n        auto it = dp_cost[G-1].find(u);\n        if (it != dp_cost[G-1].end()) {\n            uint16 cand = it->second + dist[u][start_id];\n            if (cand < total_best) {\n                total_best = cand;\n                last_node = u;\n            }\n        }\n    }\n    // backtrace\n    vector<int> selected(G);\n    selected[G-1] = last_node;\n    for (int pos = G-1; pos >= 1; --pos) {\n        int v = selected[pos];\n        int u = dp_prev[pos][v];\n        selected[pos-1] = u;\n    }\n    return selected;\n}\n\n// Reconstruct path string between two nodes\nstring get_path(int from, int to, const vector<vector<uint16>> &dist) {\n    if (from == to) return \"\";\n    // Dijkstra from 'from' to 'to'\n    vector<uint16> d(R, INF16);\n    vector<int> parent(R, -1);\n    vector<char> move_char(R, 0);\n    d[from] = 0;\n    priority_queue<pair<uint16,int>, vector<pair<uint16,int>>, greater<pair<uint16,int>>> pq;\n    pq.emplace(0, from);\n    while (!pq.empty()) {\n        auto [cd, u] = pq.top(); pq.pop();\n        if (cd != d[u]) continue;\n        if (u == to) break;\n        for (int v : adj[u]) {\n            uint16 nd = cd + weight[v];\n            if (nd < d[v]) {\n                d[v] = nd;\n                parent[v] = u;\n                // direction\n                int dx = pos[v].first - pos[u].first;\n                int dy = pos[v].second - pos[u].second;\n                if (dx == -1) move_char[v] = 'U';\n                else if (dx == 1) move_char[v] = 'D';\n                else if (dy == -1) move_char[v] = 'L';\n                else if (dy == 1) move_char[v] = 'R';\n                pq.emplace(nd, v);\n            }\n        }\n    }\n    // backtrack\n    string path;\n    int cur = to;\n    while (cur != from) {\n        path.push_back(move_char[cur]);\n        cur = parent[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n\n    // precompute all-pair distances\n    auto dist = precompute_all_pairs();\n\n    // get horizontal segments\n    auto [h_nodes, h_id] = get_h_segments();\n    int start_id = id[si][sj];\n\n    // build groups (start + all H-segments except start's)\n    auto groups = build_groups(h_nodes, h_id, start_id);\n    int G = groups.size();\n\n    // segment distance matrix\n    auto D = segment_dist_matrix(groups, dist);\n\n    // TSP on groups\n    auto order = solve_tsp(D);\n    // for each group index in order, the actual group id is order[i]\n    // Now select nodes with DP\n    vector<int> selected = select_nodes(order, groups, dist);\n\n    // build final path\n    string ans;\n    for (int i = 0; i < G-1; ++i) {\n        ans += get_path(selected[i], selected[i+1], dist);\n    }\n    ans += get_path(selected[G-1], selected[0], dist);\n\n    cout << ans << endl;\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst double INF = 1e9;\nconst double SKILL_INIT = 100.0;\nconst double LR = 0.1;\n\nint N, M, K, R;\nvector<vector<int>> d; // N x K\nvector<vector<int>> preds, succs;\nvector<int> remaining_preds; // for dependency counting\n\n// task state\nvector<int> task_status; // -1: not started, 0: in progress, 1: completed\nvector<int> start_day;\nvector<int> assigned_worker;\nvector<int> actual_dur; // only valid when completed\n\n// worker state\nvector<int> worker_status; // -1: idle, else task id\nvector<vector<double>> skill_est; // M x K\n\n// helpers\ndouble predicted_duration(int task, int worker) {\n    double w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        if (d[task][k] > skill_est[worker][k])\n            w += d[task][k] - skill_est[worker][k];\n    }\n    if (w == 0.0) return 1.0;\n    else return 1.0 + w;\n}\n\nvoid update_skill(int worker, int task, int dur) {\n    int actual_w = max(0, dur - 1);\n    double w_pred = 0.0;\n    for (int k = 0; k < K; ++k) {\n        if (d[task][k] > skill_est[worker][k])\n            w_pred += d[task][k] - skill_est[worker][k];\n    }\n    if (actual_w == 0) {\n        // task completed in 1 day -> no deficiency\n        if (w_pred > 0) {\n            // we predicted deficiency, but actual none -> increase skills\n            double error = w_pred - 0; // positive\n            double step = 2.0 * LR * error;\n            for (int k = 0; k < K; ++k) {\n                if (d[task][k] > skill_est[worker][k]) {\n                    skill_est[worker][k] += step;\n                }\n            }\n            // clamp\n            for (int k = 0; k < K; ++k) {\n                if (skill_est[worker][k] < 0) skill_est[worker][k] = 0;\n                if (skill_est[worker][k] > 100) skill_est[worker][k] = 100;\n            }\n        }\n        // else w_pred also 0 -> no update\n    } else {\n        // actual_w > 0\n        double error = w_pred - actual_w;\n        double step = 2.0 * LR * error;\n        // apply gradient where gap exists\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                skill_est[worker][k] += step;\n            }\n        }\n        // clamp\n        for (int k = 0; k < K; ++k) {\n            if (skill_est[worker][k] < 0) skill_est[worker][k] = 0;\n            if (skill_est[worker][k] > 100) skill_est[worker][k] = 100;\n        }\n        // special case: we predicted no deficiency but actual deficiency exists\n        if (w_pred == 0.0 && actual_w > 0) {\n            // decrease skills that are above the requirement\n            for (int k = 0; k < K; ++k) {\n                if (skill_est[worker][k] > d[task][k])\n                    skill_est[worker][k] = max(0.0, skill_est[worker][k] - 1.0);\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ========== read prior information ==========\n    cin >> N >> M >> K >> R;\n    d.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < K; ++j) {\n            cin >> d[i][j];\n        }\n    }\n    preds.assign(N, vector<int>());\n    succs.assign(N, vector<int>());\n    remaining_preds.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        preds[v].push_back(u);\n        succs[u].push_back(v);\n        remaining_preds[v]++;\n    }\n\n    // ========== initialize state ==========\n    task_status.assign(N, -1);\n    start_day.assign(N, 0);\n    assigned_worker.assign(N, -1);\n    actual_dur.assign(N, 0);\n    worker_status.assign(M, -1);\n    skill_est.assign(M, vector<double>(K, SKILL_INIT));\n\n    // initial ready tasks (no predecessors)\n    vector<int> ready;\n    for (int i = 0; i < N; ++i) {\n        if (remaining_preds[i] == 0) ready.push_back(i);\n    }\n\n    int day = 1;\n    while (true) {\n        // ---- compute CPM for this day ----\n        // estimate durations for all tasks\n        vector<double> dur_est(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == 1) {\n                dur_est[i] = actual_dur[i];\n            } else if (task_status[i] == 0) {\n                dur_est[i] = predicted_duration(i, assigned_worker[i]);\n            } else {\n                double best = INF;\n                for (int j = 0; j < M; ++j) {\n                    double pd = predicted_duration(i, j);\n                    if (pd < best) best = pd;\n                }\n                dur_est[i] = best;\n            }\n        }\n\n        // forward pass (topological order is by increasing index because u<v)\n        vector<double> EST(N);\n        for (int i = 0; i < N; ++i) {\n            double max_est = 1.0; // project starts day 1\n            for (int p : preds[i]) {\n                double finish = EST[p] + dur_est[p];\n                if (finish > max_est) max_est = finish;\n            }\n            EST[i] = max_est;\n        }\n\n        // project deadline estimate\n        double D_est = 1.0;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] != 1) {\n                double finish = EST[i] + dur_est[i];\n                if (finish > D_est) D_est = finish;\n            }\n        }\n\n        // backward pass\n        vector<double> LST(N);\n        for (int i = N - 1; i >= 0; --i) {\n            double min_lst = D_est;\n            for (int s : succs[i]) {\n                double lst_s = LST[s];\n                double lft_i = lst_s - 1.0;\n                double lst_i_candidate = lft_i - dur_est[i] + 1.0;\n                if (lst_i_candidate < min_lst) min_lst = lst_i_candidate;\n            }\n            if (succs[i].empty() && task_status[i] == 1) {\n                LST[i] = EST[i]; // not needed\n            } else {\n                double lst_calc = min_lst;\n                if (lst_calc < EST[i]) lst_calc = EST[i];\n                LST[i] = lst_calc;\n            }\n        }\n\n        // ---- gather ready tasks ----\n        vector<int> ready;\n        for (int i = 0; i < N; ++i) {\n            if (task_status[i] == -1 && remaining_preds[i] == 0) {\n                ready.push_back(i);\n            }\n        }\n\n        // ---- compute slack for ready tasks ----\n        vector<pair<double, int>> slack_ready;\n        for (int i : ready) {\n            double slack = LST[i] - EST[i];\n            slack_ready.emplace_back(slack, i);\n        }\n        sort(slack_ready.begin(), slack_ready.end());\n\n        // ---- idle workers ----\n        vector<int> idle;\n        for (int j = 0; j < M; ++j) {\n            if (worker_status[j] == -1) idle.push_back(j);\n        }\n\n        // ---- assign tasks ----\n        vector<int> assign_out; // flattened list: worker, task pairs\n        vector<int> avail = idle;\n        for (auto &p : slack_ready) {\n            if (avail.empty()) break;\n            int task = p.second;\n            // find best worker among avail\n            int best_w = -1;\n            double best_pred = INF;\n            for (int j : avail) {\n                double pd = predicted_duration(task, j);\n                if (pd < best_pred) {\n                    best_pred = pd;\n                    best_w = j;\n                }\n            }\n            // assign\n            assign_out.push_back(best_w);\n            assign_out.push_back(task);\n            worker_status[best_w] = task;\n            start_day[task] = day;\n            assigned_worker[task] = best_w;\n            task_status[task] = 0;\n            // remove best_w from avail\n            auto it = find(avail.begin(), avail.end(), best_w);\n            if (it != avail.end()) {\n                *it = avail.back();\n                avail.pop_back();\n            }\n        }\n\n        // ---- output ----\n        int m = assign_out.size() / 2;\n        cout << m;\n        for (int idx = 0; idx < (int)assign_out.size(); ++idx) {\n            // convert to 1-indexed\n            if (idx % 2 == 0) cout << ' ' << assign_out[idx] + 1;\n            else cout << ' ' << assign_out[idx] + 1;\n        }\n        cout << '\\n';\n        cout.flush();\n\n        // ---- read input ----\n        int dummy;\n        cin >> dummy;\n        if (dummy == -1) {\n            break; // all tasks completed or day 2000 over\n        }\n\n        // process completions\n        int n_completed = dummy;\n        for (int i = 0; i < n_completed; ++i) {\n            int worker;\n            cin >> worker;\n            --worker; // 0-indexed\n            int task = worker_status[worker];\n            int duration = day - start_day[task] + 1;\n            // mark completed\n            task_status[task] = 1;\n            actual_dur[task] = duration;\n            worker_status[worker] = -1; // worker becomes idle\n            // update skill estimates\n            update_skill(worker, task, duration);\n            // update remaining predecessors for successors\n            for (int s : succs[task]) {\n                remaining_preds[s]--;\n                // note: readiness will be re-scanned later\n            }\n        }\n\n        ++day;\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nconst int DEPOT_ID = 2000;\nconst int NUM_ORDERS = 1000;\nconst int NUM_SELECT = 50;\nconst int COORD_MAX = 800;\nconst int CENTER = 400;\n\n// Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(time(0));\n\n    // Read input\n    vector<pair<int,int>> pickup(NUM_ORDERS), delivery(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int a,b,c,d;\n        cin >> a >> b >> c >> d;\n        pickup[i] = {a,b};\n        delivery[i] = {c,d};\n    }\n\n    // Node coordinates: for order i: pickup node = 2*i, delivery node = 2*i+1, depot = DEPOT_ID\n    vector<int> node_x(2001), node_y(2001);\n    node_x[DEPOT_ID] = node_y[DEPOT_ID] = CENTER;\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        node_x[2*i] = pickup[i].first;\n        node_y[2*i] = pickup[i].second;\n        node_x[2*i+1] = delivery[i].first;\n        node_y[2*i+1] = delivery[i].second;\n    }\n\n    // Precompute distance matrix (2001 x 2001)\n    vector<vector<int>> dist(2001, vector<int>(2001));\n    for (int i = 0; i < 2001; ++i) {\n        for (int j = 0; j < 2001; ++j) {\n            dist[i][j] = manhattan(node_x[i], node_y[i], node_x[j], node_y[j]);\n        }\n    }\n\n    // ----- Construction: cheapest insertion (pickup+delivery as a block) -----\n    vector<int> route = {DEPOT_ID, DEPOT_ID}; // start and end\n    int total_dist = 0; // sum of distances along the route\n    vector<bool> selected(NUM_ORDERS, false);\n    int selected_cnt = 0;\n\n    while (selected_cnt < NUM_SELECT) {\n        int best_order = -1;\n        int best_pos = -1;\n        int best_inc = INT_MAX;\n        for (int i = 0; i < NUM_ORDERS; ++i) {\n            if (selected[i]) continue;\n            int p = 2*i;   // pickup node id\n            int d = 2*i+1; // delivery node id\n            int L = route.size();\n            for (int pos = 0; pos < L-1; ++pos) {\n                int left = route[pos];\n                int right = route[pos+1];\n                // increase if we insert [p, d] between left and right\n                int inc = -dist[left][right] + dist[left][p] + dist[p][d] + dist[d][right];\n                if (inc < best_inc) {\n                    best_inc = inc;\n                    best_order = i;\n                    best_pos = pos;\n                }\n            }\n        }\n        // Insert the best order\n        selected[best_order] = true;\n        int p = 2*best_order;\n        int d = 2*best_order+1;\n        int pos = best_pos;\n        route.insert(route.begin() + pos + 1, {p, d}); // insert after pos\n        total_dist += best_inc;\n        ++selected_cnt;\n    }\n\n    // Now route has 2 depots and 100 customer nodes -> size = 102\n    // total_dist is sum of edge lengths\n\n    // ----- Local Search: Simulated Annealing -----\n    vector<int> best_route = route;\n    int best_total = total_dist;\n\n    auto start_time = chrono::steady_clock::now();\n    double elapsed_time = 0.0;\n    double temperature = 1000.0;\n    const double cooling_rate = 0.999;\n    const int max_iter = 300000; // safety limit\n\n    // Helper function to compute total distance of a route (O(n))\n    auto compute_total = [&](const vector<int>& r) {\n        int n = r.size();\n        int tot = 0;\n        for (int i = 0; i < n-1; ++i) {\n            tot += dist[r[i]][r[i+1]];\n        }\n        return tot;\n    };\n\n    // Helper function to check precedence constraints for all orders\n    auto is_feasible = [&](const vector<int>& r) {\n        // For each order, find positions of pickup and delivery\n        vector<int> first_occur(2*NUM_ORDERS, -1);\n        vector<int> second_occur(2*NUM_ORDERS, -1);\n        int n = r.size();\n        for (int i = 0; i < n; ++i) {\n            int node = r[i];\n            if (node == DEPOT_ID) continue;\n            int order = node / 2;\n            int type = node % 2; // 0=pickup, 1=delivery\n            if (type == 0) {\n                // pickup\n                if (first_occur[node] == -1) first_occur[node] = i;\n                else return false; // duplicate pickup? not possible\n            } else {\n                // delivery\n                if (second_occur[node] == -1) second_occur[node] = i;\n                else return false;\n            }\n        }\n        // Check each order\n        for (int i = 0; i < NUM_ORDERS; ++i) {\n            int p = 2*i;\n            int d = 2*i+1;\n            if (first_occur[p] == -1 || second_occur[d] == -1) continue; // not selected? but all selected in our route\n            if (first_occur[p] > second_occur[d]) return false;\n        }\n        return true;\n    };\n\n    // SA loop\n    for (int iter = 0; iter < max_iter; ++iter) {\n        auto now = chrono::steady_clock::now();\n        elapsed_time = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n        if (elapsed_time > 1.9) break;\n\n        // Generate random move type: 0=relocate, 1=swap\n        int move_type = rand() % 2;\n        vector<int> new_route = route;\n        int delta = 0;\n        bool feasible = false;\n\n        if (move_type == 0) {\n            // Relocate: pick a random non-depot node and move it to another position\n            int n = new_route.size();\n            int idx = rand() % (n-2) + 1; // 1..n-2\n            int new_pos = rand() % (n-1); // insert before new_pos (0..n-2)\n            // ensure new_pos != idx (difficult after removal, so we generate and later adjust)\n            int node = new_route[idx];\n            new_route.erase(new_route.begin() + idx);\n            // now size = n-1\n            // new_pos must be in 0..new_size\n            if (new_pos > new_route.size()) new_pos = new_route.size();\n            // avoid inserting at same position? if new_pos == idx after removal, it's okay but trivial\n            new_route.insert(new_route.begin() + new_pos, node);\n            // compute total distance quickly? We'll just compute full\n            int new_total = compute_total(new_route);\n            delta = new_total - total_dist;\n            feasible = is_feasible(new_route);\n        } else {\n            // Swap two non-depot nodes\n            int n = new_route.size();\n            int i = rand() % (n-2) + 1;\n            int j = rand() % (n-2) + 1;\n            if (i == j) continue;\n            swap(new_route[i], new_route[j]);\n            int new_total = compute_total(new_route);\n            delta = new_total - total_dist;\n            feasible = is_feasible(new_route);\n        }\n\n        if (feasible) {\n            double accept_prob = 1.0;\n            if (delta > 0) {\n                accept_prob = exp(-delta / temperature);\n            }\n            if ((double)rand() / RAND_MAX < accept_prob) {\n                route = new_route;\n                total_dist = compute_total(route); // update\n                if (total_dist < best_total) {\n                    best_total = total_dist;\n                    best_route = route;\n                }\n            }\n        }\n        temperature *= cooling_rate;\n    }\n\n    // Build output: list of selected orders (in some order; we can output in the order they appear in route)\n    // Find selected orders from the best route\n    vector<int> selected_orders;\n    for (int node : best_route) {\n        if (node == DEPOT_ID) continue;\n        int order = node / 2;\n        if (selected_orders.empty() || selected_orders.back() != order) {\n            selected_orders.push_back(order);\n        }\n    }\n    // double-check size\n    if (selected_orders.size() != NUM_SELECT) {\n        // should not happen, but fallback: use construction order\n        for (int i = 0; i < NUM_ORDERS; ++i) if (selected[i]) selected_orders.push_back(i);\n    }\n\n    // Output final result\n    cout << NUM_SELECT;\n    for (int o : selected_orders) cout << \" \" << o+1; // 1-indexed output\n    cout << '\\n';\n\n    int n = best_route.size();\n    cout << n;\n    for (int node : best_route) {\n        cout << \" \" << node_x[node] << \" \" << node_y[node];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Disjoint Set Union (Union-Find)\nstruct DSU {\n    vector<int> parent, rank;\n    DSU(int n) {\n        parent.resize(n);\n        rank.resize(n, 0);\n        for (int i = 0; i < n; ++i) parent[i] = i;\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) swap(x, y);\n        parent[y] = x;\n        if (rank[x] == rank[y]) ++rank[x];\n        return true;\n    }\n};\n\n// edge information\nstruct Edge {\n    int u, v, d;   // endpoints and rounded Euclidean distance\n    int id;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    // read vertex coordinates\n    vector<pair<int,int>> coord(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coord[i].first >> coord[i].second;\n    }\n\n    // read edges (only endpoints)\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = coord[u].first - coord[v].first;\n        int dy = coord[u].second - coord[v].second;\n        double dist = sqrt(dx*dx + dy*dy);\n        int d = round(dist);\n        edges[i] = {u, v, d, i};\n    }\n\n    // ---------- compute the first MST (T1) using d ----------\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return edges[a].d < edges[b].d;\n    });\n\n    DSU dsu_mst(N);\n    vector<bool> in_mst(M, false);\n    vector<int> mst_edges;          // original indices of tree edges\n    for (int idx : order) {\n        auto &e = edges[idx];\n        if (dsu_mst.unite(e.u, e.v)) {\n            in_mst[idx] = true;\n            mst_edges.push_back(idx);\n            if ((int)mst_edges.size() == N-1) break;\n        }\n    }\n\n    // ---------- build T1 adjacency and compute LCA info ----------\n    vector<vector<pair<int,int>>> adj(N);   // (neighbor, edge id)\n    for (int idx : mst_edges) {\n        auto &e = edges[idx];\n        adj[e.u].push_back({e.v, idx});\n        adj[e.v].push_back({e.u, idx});\n    }\n\n    vector<int> parent(N, -1), depth(N, 0), parent_edge(N, -1);\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [v, eid] : adj[u]) {\n            if (v == parent[u]) continue;\n            parent[v] = u;\n            depth[v] = depth[u] + 1;\n            parent_edge[v] = eid;\n            q.push(v);\n        }\n    }\n\n    // ---------- compute best alternative (lower bound) for each tree edge ----------\n    vector<int> best_alt(M, INT_MAX);   // only used for tree edges\n    for (int i = 0; i < M; ++i) {\n        if (in_mst[i]) continue;        // only non\u2011tree edges are candidates\n        auto &e = edges[i];\n        int u = e.u, v = e.v;\n        int d_val = e.d;\n\n        // gather all tree edges on the path between u and v\n        vector<int> path_edges;\n        int uu = u, vv = v;\n        while (depth[uu] > depth[vv]) {\n            path_edges.push_back(parent_edge[uu]);\n            uu = parent[uu];\n        }\n        while (depth[vv] > depth[uu]) {\n            path_edges.push_back(parent_edge[vv]);\n            vv = parent[vv];\n        }\n        while (uu != vv) {\n            path_edges.push_back(parent_edge[uu]);\n            path_edges.push_back(parent_edge[vv]);\n            uu = parent[uu];\n            vv = parent[vv];\n        }\n\n        for (int eid : path_edges) {\n            if (d_val < best_alt[eid]) best_alt[eid] = d_val;\n        }\n    }\n\n    // ---------- online phase ----------\n    DSU dsu_online(N);\n    int accepted = 0;          // number of adopted edges\n    int comp = N;              // number of connected components\n\n    for (int i = 0; i < M; ++i) {\n        int l; cin >> l;      // true length\n        auto &e = edges[i];\n        int u = e.u, v = e.v;\n\n        // already have a spanning tree\n        if (accepted == N-1) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        // already connected\n        if (dsu_online.find(u) == dsu_online.find(v)) {\n            cout << 0 << endl;\n            continue;\n        }\n\n        int needed = comp - 1;\n        int rem = M - i;               // remaining edges (including current)\n\n        // base threshold factor\n        double factor;\n        if (in_mst[i]) {\n            double alt_factor = (best_alt[i] == INT_MAX) ? 3.0 : (2.0 * best_alt[i] / e.d);\n            factor = min(2.0, alt_factor);\n        } else {\n            factor = 1.5;\n        }\n\n        // urgency adjustment\n        if (needed * 2 > rem) factor *= 1.5;\n        if (needed > rem) factor = 3.0;\n\n        double threshold = factor * e.d;\n\n        if (l <= threshold) {\n            cout << 1 << endl;\n            dsu_online.unite(u, v);\n            --comp;\n            ++accepted;\n        } else {\n            cout << 0 << endl;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N_MAX = 20;\nconst int M_MAX = 10;\nconst int TURN_MAX = 300;\nconst int GRID_SIZE = 30;\n\n// directions\nconst int dx[4] = { -1, 1, 0, 0 };\nconst int dy[4] = { 0, 0, -1, 1 };\nconst char move_char[4] = { 'U', 'D', 'L', 'R' };\nconst char block_char[4] = { 'u', 'd', 'l', 'r' };\n\n// global state\nint N, M;\nint pet_x[N_MAX], pet_y[N_MAX], pet_type[N_MAX];\nint human_x[M_MAX], human_y[M_MAX];\nbool impassable[31][31]; // 1-indexed, true = impassable\nint turn; // 0-indexed\n\n// check if a cell is inside grid\ninline bool inside(int x, int y) {\n    return 1 <= x && x <= GRID_SIZE && 1 <= y && y <= GRID_SIZE;\n}\n\n// BFS: return (area, number of pets inside)\npair<int,int> bfs(int sx, int sy, const bool tmp_impassable[31][31], const int pet_pos_x[], const int pet_pos_y[]) {\n    bool visited[31][31] = {};\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    visited[sx][sy] = true;\n    int area = 1;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_impassable[nx][ny]) continue;\n            if (visited[nx][ny]) continue;\n            visited[nx][ny] = true;\n            q.push({nx, ny});\n            ++area;\n        }\n    }\n    int pet_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        if (visited[pet_pos_x[i]][pet_pos_y[i]]) ++pet_cnt;\n    }\n    return {area, pet_cnt};\n}\n\n// evaluate a candidate action for a single human\ndouble evaluate_action(int human_idx, char action,\n                       const int start_human_x[], const int start_human_y[],\n                       const int start_pet_x[], const int start_pet_y[],\n                       const bool cur_impassable[31][31],\n                       int cur_human_x[], int cur_human_y[]) {\n    // make copies\n    bool tmp_impassable[31][31];\n    memcpy(tmp_impassable, cur_impassable, sizeof(tmp_impassable));\n    int tmp_human_x[M_MAX], tmp_human_y[M_MAX];\n    memcpy(tmp_human_x, cur_human_x, sizeof(int)*M);\n    memcpy(tmp_human_y, cur_human_y, sizeof(int)*M);\n\n    int x = cur_human_x[human_idx], y = cur_human_y[human_idx];\n    int nx, ny;\n    if (action == '.') {\n        // stay: do nothing\n        // evaluate BFS from current position\n    } else {\n        // determine if it's a move or block\n        bool is_move = false;\n        int d = -1;\n        for (int k = 0; k < 4; ++k) {\n            if (action == move_char[k]) { is_move = true; d = k; break; }\n            if (action == block_char[k]) { d = k; break; }\n        }\n        nx = x + dx[d];\n        ny = y + dy[d];\n        if (!inside(nx, ny)) return -1e18; // invalid\n        if (is_move) {\n            // move: check target cell is not impassable (including temp blocks from previous humans)\n            if (tmp_impassable[nx][ny]) return -1e18;\n            // update position\n            tmp_human_x[human_idx] = nx;\n            tmp_human_y[human_idx] = ny;\n        } else {\n            // block: check conditions\n            // cannot block cell that already impassable (nop, but we can treat as stay)\n            if (tmp_impassable[nx][ny]) return -1e18; // skip nop\n            // cannot block cell containing any start human or start pet\n            bool occupied = false;\n            for (int i = 0; i < M; ++i) {\n                if (start_human_x[i] == nx && start_human_y[i] == ny) { occupied = true; break; }\n            }\n            if (!occupied) {\n                for (int i = 0; i < N; ++i) {\n                    if (start_pet_x[i] == nx && start_pet_y[i] == ny) { occupied = true; break; }\n                }\n            }\n            if (occupied) return -1e18;\n            // cannot block cell adjacent to any pet (only start pets)\n            bool adj_pet = false;\n            for (int i = 0; i < N; ++i) {\n                int px = start_pet_x[i], py = start_pet_y[i];\n                for (int k = 0; k < 4; ++k) {\n                    if (nx + dx[k] == px && ny + dy[k] == py) { adj_pet = true; break; }\n                }\n                if (adj_pet) break;\n            }\n            if (adj_pet) return -1e18;\n            // valid block\n            tmp_impassable[nx][ny] = true;\n        }\n    }\n\n    // now BFS from the human's position (after action)\n    int sx = tmp_human_x[human_idx], sy = tmp_human_y[human_idx];\n    auto [area, pet_cnt] = bfs(sx, sy, tmp_impassable, start_pet_x, start_pet_y);\n    double heuristic = area * pow(0.5, pet_cnt);\n    // optional small penalty if a pet is adjacent (already in BFS area if adjacent)\n    return heuristic;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    cin >> N;\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_x[i] >> pet_y[i] >> pet_type[i];\n    }\n    cin >> M;\n    for (int i = 0; i < M; ++i) {\n        cin >> human_x[i] >> human_y[i];\n    }\n\n    // initialize state\n    memset(impassable, 0, sizeof(impassable));\n    // outer borders are already impassable by problem, but we handle via inside() check\n\n    // main loop\n    for (turn = 0; turn < TURN_MAX; ++turn) {\n        // record positions at start of this turn\n        int start_human_x[M_MAX], start_human_y[M_MAX];\n        memcpy(start_human_x, human_x, sizeof(int)*M);\n        memcpy(start_human_y, human_y, sizeof(int)*M);\n        int start_pet_x[N_MAX], start_pet_y[N_MAX];\n        memcpy(start_pet_x, pet_x, sizeof(int)*N);\n        memcpy(start_pet_y, pet_y, sizeof(int)*N);\n\n        // current mutable state for this turn (will be updated per human)\n        int cur_human_x[M_MAX], cur_human_y[M_MAX];\n        memcpy(cur_human_x, start_human_x, sizeof(int)*M);\n        memcpy(cur_human_y, start_human_y, sizeof(int)*M);\n        bool cur_impassable[31][31];\n        memcpy(cur_impassable, impassable, sizeof(impassable));\n\n        char actions[M_MAX];\n        // process humans sequentially\n        for (int i = 0; i < M; ++i) {\n            double best_heuristic = -1e18;\n            char best_action = '.';\n            // consider all possible actions: stay, 4 moves, 4 blocks\n            // . \n            double val = evaluate_action(i, '.', start_human_x, start_human_y, start_pet_x, start_pet_y, cur_impassable, cur_human_x, cur_human_y);\n            if (val > best_heuristic) {\n                best_heuristic = val;\n                best_action = '.';\n            }\n            // moves U D L R\n            for (int d = 0; d < 4; ++d) {\n                val = evaluate_action(i, move_char[d], start_human_x, start_human_y, start_pet_x, start_pet_y, cur_impassable, cur_human_x, cur_human_y);\n                if (val > best_heuristic) {\n                    best_heuristic = val;\n                    best_action = move_char[d];\n                }\n            }\n            // blocks u d l r\n            for (int d = 0; d < 4; ++d) {\n                val = evaluate_action(i, block_char[d], start_human_x, start_human_y, start_pet_x, start_pet_y, cur_impassable, cur_human_x, cur_human_y);\n                if (val > best_heuristic) {\n                    best_heuristic = val;\n                    best_action = block_char[d];\n                }\n            }\n\n            // execute chosen action on the mutable state (so later humans see it)\n            int x = cur_human_x[i], y = cur_human_y[i];\n            if (best_action == '.') {\n                // do nothing\n            } else {\n                bool is_move = false;\n                int d = -1;\n                for (int k = 0; k < 4; ++k) {\n                    if (best_action == move_char[k]) { is_move = true; d = k; break; }\n                    if (best_action == block_char[k]) { d = k; break; }\n                }\n                int nx = x + dx[d], ny = y + dy[d];\n                if (is_move) {\n                    cur_human_x[i] = nx;\n                    cur_human_y[i] = ny;\n                } else {\n                    cur_impassable[nx][ny] = true;\n                }\n            }\n            actions[i] = best_action;\n        }\n\n        // output actions\n        for (int i = 0; i < M; ++i) cout << actions[i];\n        cout << endl;\n        // flush\n        cout.flush();\n\n        // read pet movements\n        string line;\n        getline(cin, line); // may have leftover newline\n        // Actually after output, there will be a line containing N strings separated by spaces.\n        // We need to read that line.\n        // Use getline to read the whole line, then split.\n        getline(cin, line);\n        stringstream ss(line);\n        vector<string> moves(N);\n        for (int i = 0; i < N; ++i) ss >> moves[i];\n\n        // update pet positions\n        for (int i = 0; i < N; ++i) {\n            const string &s = moves[i];\n            if (s == \".\") continue;\n            int x = pet_x[i], y = pet_y[i];\n            for (char c : s) {\n                int d;\n                if (c == 'U') d = 0;\n                else if (c == 'D') d = 1;\n                else if (c == 'L') d = 2;\n                else if (c == 'R') d = 3;\n                else continue; // shouldn't happen\n                x += dx[d];\n                y += dy[d];\n            }\n            pet_x[i] = x;\n            pet_y[i] = y;\n        }\n\n        // update global impassable to reflect block actions of this turn\n        memcpy(impassable, cur_impassable, sizeof(impassable));\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(20);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    vector<string> v(19);\n    for (int i = 0; i < 19; ++i) cin >> v[i];\n\n    // BFS to find the shortest path from start to goal\n    const int INF = 1e9;\n    vector<vector<int>> dist(20, vector<int>(20, INF));\n    vector<vector<pair<int, int>>> parent(20, vector<pair<int, int>>(20, {-1, -1}));\n    queue<pair<int, int>> q;\n    dist[si][sj] = 0;\n    q.emplace(si, sj);\n\n    // directions: D, R, U, L\n    const int dr[] = {1, 0, -1, 0};\n    const int dc[] = {0, 1, 0, -1};\n    const char dirs[] = {'D', 'R', 'U', 'L'};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        if (i == ti && j == tj) break;\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + dr[d], nj = j + dc[d];\n            if (ni < 0 || ni >= 20 || nj < 0 || nj >= 20) continue;\n            bool ok = false;\n            if (d == 0) { // down\n                if (i < 19 && v[i][j] == '0') ok = true;\n            } else if (d == 1) { // right\n                if (j < 19 && h[i][j] == '0') ok = true;\n            } else if (d == 2) { // up\n                if (i > 0 && v[i-1][j] == '0') ok = true;\n            } else { // left\n                if (j > 0 && h[i][j-1] == '0') ok = true;\n            }\n            if (ok && dist[ni][nj] > dist[i][j] + 1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                parent[ni][nj] = {i, j};\n                q.emplace(ni, nj);\n            }\n        }\n    }\n\n    // Reconstruct the path as a string of moves\n    string path;\n    int ci = ti, cj = tj;\n    while (!(ci == si && cj == sj)) {\n        auto [pi, pj] = parent[ci][cj];\n        if (pi == -1) break; // should not happen\n        int d = -1;\n        if (pi + 1 == ci && pj == cj) d = 0;       // down\n        else if (pi - 1 == ci && pj == cj) d = 2; // up\n        else if (pi == ci && pj + 1 == cj) d = 1; // right\n        else if (pi == ci && pj - 1 == cj) d = 3; // left\n        path.push_back(dirs[d]);\n        ci = pi; cj = pj;\n    }\n    reverse(path.begin(), path.end());\n\n    // Build the final string of length exactly 200 by repeating the path\n    string ans;\n    int L = (int)path.size();\n    if (L > 0) {\n        int repeat = 200 / L;\n        int rem = 200 % L;\n        for (int i = 0; i < repeat; ++i) ans += path;\n        ans += path.substr(0, rem);\n    }\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstring>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst int N = 30;\nconst int M = N * N; // 900\n\n// direction arrays: 0:left, 1:up, 2:right, 3:down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to[t][d] = exit direction when entering tile t from direction d, -1 if invalid\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0\n    {3, -1, -1, 0},  // 1\n    {-1, -1, 3, 2},  // 2\n    {-1, 2, 1, -1},  // 3\n    {1, 0, 3, 2},    // 4\n    {3, 2, 1, 0},    // 5\n    {2, -1, 0, -1},  // 6\n    {-1, 3, -1, 1}   // 7\n};\n\n// rotate function: given original type t and rotation r (0..3), return the effective state\ninline int rotate(int t, int r) {\n    if (t < 4) return (t + r) % 4;                     // single curve\n    if (t < 6) return 4 + ((t - 4 + r) % 2);          // double curve (4<->5)\n    return 6 + ((t - 6 + r) % 2);                     // straight (6<->7)\n}\n\n// evaluate the board state and return L1 * L2\nint evaluate(const int* state) {\n    // visited flags for each half-edge (tile, direction)\n    char visited[M * 4] = {0};\n\n    int best = 0, second = 0;\n\n    for (int idx = 0; idx < M; ++idx) {\n        int i = idx / N;\n        int j = idx % N;\n        int s = state[idx];\n\n        for (int d = 0; d < 4; ++d) {\n            if (to[s][d] == -1) continue;\n            int vidx = idx * 4 + d;\n            if (visited[vidx]) continue;\n\n            // start tracing\n            int ci = i, cj = j, cd = d;\n            int len = 0;\n            bool is_cycle = false;\n\n            while (true) {\n                visited[(ci * N + cj) * 4 + cd] = 1;\n                int d2 = to[state[ci * N + cj]][cd];\n                if (d2 == -1) break;                     // broken track (should not happen)\n                int ni = ci + di[d2];\n                int nj = cj + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) break; // out of board\n                cd = (d2 + 2) & 3;                      // opposite direction at neighbour\n                ci = ni;\n                cj = nj;\n                len++;\n                if (ci == i && cj == j && cd == d) {\n                    is_cycle = true;\n                    break;\n                }\n            }\n\n            if (is_cycle) {\n                if (len > best) {\n                    second = best;\n                    best = len;\n                } else if (len > second) {\n                    second = len;\n                }\n            }\n            // non\u2011cycle paths are also marked visited (they cannot be part of a cycle)\n        }\n    }\n\n    return best * second;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read original tile types\n    vector<int> orig(M);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            orig[i * N + j] = s[j] - '0';\n        }\n    }\n\n    // random number generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist4(0, 3);\n    uniform_int_distribution<int> dist900(0, M - 1);\n\n    // current state and rotation\n    vector<int> state(M), rot(M);\n    // best found\n    vector<int> best_rot(M);\n    int best_score = 0;\n\n    auto start_time = chrono::steady_clock::now();\n    long long step = 0;\n\n    // initial random state\n    for (int i = 0; i < M; ++i) {\n        rot[i] = dist4(rng);\n        state[i] = rotate(orig[i], rot[i]);\n    }\n    int cur_score = evaluate(state.data());\n    if (cur_score > best_score) {\n        best_score = cur_score;\n        best_rot = rot;\n    }\n\n    // hill\u2011climbing loop\n    while (true) {\n        // time check every 1000 steps\n        if (step % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n            if (elapsed >= 1900) break;\n        }\n\n        // choose a random tile and a new rotation\n        int idx = dist900(rng);\n        int r_old = rot[idx];\n        int r_new = (r_old + 1 + (rng() % 3)) % 4; // guarantee different\n        int old_state = state[idx];\n        int new_state = rotate(orig[idx], r_new);\n\n        // apply candidate\n        state[idx] = new_state;\n        rot[idx] = r_new;\n        int new_score = evaluate(state.data());\n\n        if (new_score > cur_score) {\n            cur_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                best_rot = rot;\n            }\n        } else {\n            // revert\n            state[idx] = old_state;\n            rot[idx] = r_old;\n        }\n\n        ++step;\n\n        // periodic restart to escape local optima\n        if (step % 200000 == 0) {\n            for (int i = 0; i < M; ++i) {\n                rot[i] = dist4(rng);\n                state[i] = rotate(orig[i], rot[i]);\n            }\n            cur_score = evaluate(state.data());\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_rot = rot;\n            }\n        }\n    }\n\n    // output the best rotation string\n    for (int i = 0; i < M; ++i) {\n        cout << best_rot[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- union-find with edge count ----------\nstruct DSU {\n    vector<int> parent, sz, edges;\n    DSU(int n) : parent(n), sz(n, 1), edges(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (x != parent[x]) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) {\n            edges[a]++;  // extra edge, cycle\n            return;\n        }\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        edges[a] += edges[b] + 1;\n    }\n};\n\n// ---------- compute size of largest tree ----------\nint largest_tree(const vector<vector<int>>& board, int N) {\n    DSU dsu(N * N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            if (board[i][j] == 0) continue;\n            // right\n            if (j + 1 < N && board[i][j+1] != 0 &&\n                (board[i][j] & 4) && (board[i][j+1] & 1)) {\n                dsu.unite(id, id + 1);\n            }\n            // down\n            if (i + 1 < N && board[i+1][j] != 0 &&\n                (board[i][j] & 8) && (board[i+1][j] & 2)) {\n                dsu.unite(id, id + N);\n            }\n        }\n    }\n    int best = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            if (board[i][j] == 0) continue;\n            if (dsu.find(id) == id) {\n                if (dsu.edges[id] == dsu.sz[id] - 1) {\n                    best = max(best, dsu.sz[id]);\n                }\n            }\n        }\n    }\n    return best;\n}\n\n// ---------- apply a move ----------\npair<vector<vector<int>>, pair<int,int>> apply_move(\n    const vector<vector<int>>& board, int ei, int ej, char dir) {\n    int di = 0, dj = 0;\n    if (dir == 'U') di = -1;\n    else if (dir == 'D') di = 1;\n    else if (dir == 'L') dj = -1;\n    else if (dir == 'R') dj = 1;\n    int ni = ei + di, nj = ej + dj;\n    auto b2 = board;\n    swap(b2[ei][ej], b2[ni][nj]);\n    return {b2, {ni, nj}};\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    vector<string> raw(N);\n    vector<vector<int>> board(N, vector<int>(N));\n    int empty_i = -1, empty_j = -1;\n    for (int i = 0; i < N; ++i) {\n        cin >> raw[i];\n        for (int j = 0; j < N; ++j) {\n            char c = raw[i][j];\n            int val;\n            if (isdigit(c)) val = c - '0';\n            else val = 10 + (c - 'a');\n            board[i][j] = val;\n            if (val == 0) {\n                empty_i = i; empty_j = j;\n            }\n        }\n    }\n\n    int full = N * N - 1;\n    string moves;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // possible directions\n    const string dirs = \"UDLR\";\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n\n    int stagnation = 0;\n    int cur_best = largest_tree(board, N);\n\n    while ((int)moves.size() < T) {\n        if (cur_best == full) break;\n\n        vector<pair<int, char>> cand; // (value after 2 moves, direction)\n        for (int d = 0; d < 4; ++d) {\n            int ni = empty_i + di[d];\n            int nj = empty_j + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            char dir = dirs[d];\n            auto [b1, e1] = apply_move(board, empty_i, empty_j, dir);\n            int best_after2 = largest_tree(b1, N);\n\n            // lookahead second move\n            for (int d2 = 0; d2 < 4; ++d2) {\n                int ni2 = e1.first + di[d2];\n                int nj2 = e1.second + dj[d2];\n                if (ni2 < 0 || ni2 >= N || nj2 < 0 || nj2 >= N) continue;\n                char dir2 = dirs[d2];\n                auto [b2, _] = apply_move(b1, e1.first, e1.second, dir2);\n                int val2 = largest_tree(b2, N);\n                best_after2 = max(best_after2, val2);\n            }\n\n            cand.emplace_back(best_after2, dir);\n        }\n\n        // choose best\n        int best_val = -1;\n        char best_dir = '?';\n        for (auto [val, dir] : cand) {\n            if (val > best_val) {\n                best_val = val;\n                best_dir = dir;\n            }\n        }\n\n        // if no improvement for a while, random move\n        if (best_val <= cur_best) {\n            stagnation++;\n        } else {\n            stagnation = 0;\n        }\n        if (stagnation > 3 * N) {\n            // random move\n            vector<char> valid_dirs;\n            for (int d = 0; d < 4; ++d) {\n                int ni = empty_i + di[d];\n                int nj = empty_j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N)\n                    valid_dirs.push_back(dirs[d]);\n            }\n            best_dir = valid_dirs[rng() % valid_dirs.size()];\n            stagnation = 0;\n        }\n\n        // apply chosen move\n        auto [b_new, e_new] = apply_move(board, empty_i, empty_j, best_dir);\n        board = move(b_new);\n        empty_i = e_new.first;\n        empty_j = e_new.second;\n        moves.push_back(best_dir);\n        cur_best = best_val; // actually after this move it's the immediate value, but we recompute later\n        // recompute to be safe\n        cur_best = largest_tree(board, N);\n    }\n\n    cout << moves << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nusing ll = long long;\nusing i128 = __int128_t;\nconst ll R = 10000;\n\nstruct Line {\n    ll px, py, qx, qy;\n};\n\n// Check if line cuts the circle (distance from origin < R)\nbool lineCutsCircle(const Line& l) {\n    ll dx = l.qx - l.px;\n    ll dy = l.qy - l.py;\n    if (dx == 0 && dy == 0) return false;\n    i128 cross = (i128)dx * l.py - (i128)dy * l.px;\n    i128 dsq = (i128)dx * dx + (i128)dy * dy;\n    i128 left = cross * cross;\n    i128 right = (i128)R * R * dsq;\n    return left < right;\n}\n\n// Generate a random line that cuts the circle\nLine genRandomLine(mt19937& rng) {\n    uniform_int_distribution<ll> dist(-20000, 20000);\n    while (true) {\n        ll px = dist(rng), py = dist(rng);\n        ll qx = dist(rng), qy = dist(rng);\n        if (px == qx && py == qy) continue;\n        Line l{px, py, qx, qy};\n        if (lineCutsCircle(l)) return l;\n    }\n}\n\n// Evaluate a set of lines, return total min(a_d, b_d)\nint evaluate(const vector<Line>& lines, const vector<pair<int,int>>& points, const int a[11]) {\n    int n = points.size();\n    int k = lines.size();\n    unordered_map<bitset<100>, int> cell_counts;\n    for (int i = 0; i < n; ++i) {\n        ll x = points[i].first, y = points[i].second;\n        bitset<100> key;\n        bool active = true;\n        for (int j = 0; j < k; ++j) {\n            ll dx = lines[j].qx - lines[j].px;\n            ll dy = lines[j].qy - lines[j].py;\n            ll cross = dx * (y - lines[j].py) - dy * (x - lines[j].px);\n            if (cross == 0) { active = false; break; }\n            if (cross > 0) key.set(j);\n        }\n        if (active) cell_counts[key]++;\n    }\n    int b[11] = {0};\n    for (auto& p : cell_counts) {\n        int c = p.second;\n        if (c >= 1 && c <= 10) b[c]++;\n    }\n    int total = 0;\n    for (int d = 1; d <= 10; ++d) {\n        total += min(a[d], b[d]);\n    }\n    return total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<pair<int,int>> points(N);\n    for (int i = 0; i < N; ++i) cin >> points[i].first >> points[i].second;\n\n    // Random engine\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Greedy construction\n    vector<Line> lines;\n    int currentScore = evaluate(lines, points, a);\n    const int TRIALS_PER_STEP = 300;\n    for (int step = 0; step < K; ++step) {\n        int bestScore = currentScore;\n        Line bestLine;\n        bool found = false;\n        for (int t = 0; t < TRIALS_PER_STEP; ++t) {\n            Line cand = genRandomLine(rng);\n            lines.push_back(cand);\n            int sc = evaluate(lines, points, a);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestLine = cand;\n                found = true;\n            }\n            lines.pop_back();\n        }\n        if (found && bestScore > currentScore) {\n            lines.push_back(bestLine);\n            currentScore = bestScore;\n        } else {\n            break;\n        }\n    }\n\n    // Simulated Annealing\n    auto bestLines = lines;\n    int bestScore = currentScore;\n    double T = 100.0;\n    auto start = clock();\n    const double TIME_LIMIT = 2.8; // seconds\n    while ( (clock() - start) / (double)CLOCKS_PER_SEC < TIME_LIMIT ) {\n        // propose new state\n        vector<Line> newLines = lines;\n        int action = uniform_int_distribution<int>(0,2)(rng); // 0:add, 1:remove, 2:modify\n        if (action == 0 && newLines.size() < K) {\n            newLines.push_back(genRandomLine(rng));\n        } else if (action == 1 && newLines.size() > 0) {\n            int idx = uniform_int_distribution<int>(0, newLines.size()-1)(rng);\n            newLines.erase(newLines.begin() + idx);\n        } else if (action == 2 && newLines.size() > 0) {\n            int idx = uniform_int_distribution<int>(0, newLines.size()-1)(rng);\n            const int DELTA = 100;\n            auto& l = newLines[idx];\n            l.px += uniform_int_distribution<int>(-DELTA, DELTA)(rng);\n            l.py += uniform_int_distribution<int>(-DELTA, DELTA)(rng);\n            l.qx += uniform_int_distribution<int>(-DELTA, DELTA)(rng);\n            l.qy += uniform_int_distribution<int>(-DELTA, DELTA)(rng);\n            // avoid degenerate line\n            if (l.px == l.qx && l.py == l.qy) {\n                // revert? just skip this iteration\n                continue;\n            }\n        } else {\n            continue; // no change\n        }\n\n        int newScore = evaluate(newLines, points, a);\n        // update best\n        if (newScore > bestScore) {\n            bestLines = newLines;\n            bestScore = newScore;\n        }\n        // accept / reject\n        if (newScore > currentScore || \n            (double)rand() / RAND_MAX < exp((newScore - currentScore) / T)) {\n            lines = newLines;\n            currentScore = newScore;\n        }\n        T *= 0.9995; // cooling\n    }\n\n    // Output the best solution\n    cout << bestLines.size() << \"\\n\";\n    for (const auto& l : bestLines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 61;\nint N, M;\nbool dot[MAXN][MAXN]; // true if dot present\nvector<int> rowDots[MAXN]; // for each y, sorted x\nvector<int> colDots[MAXN]; // for each x, sorted y\nvector<int> diag1Dots[2*MAXN]; // (y-x) + (N-1) -> sorted x\nvector<int> diag2Dots[2*MAXN]; // (y+x) -> sorted x\n\n// used unit edges\nbool usedH[MAXN-1][MAXN]; // horizontal (x,y) -> (x+1,y)\nbool usedV[MAXN][MAXN-1]; // vertical (x,y) -> (x,y+1)\nbool usedD1[MAXN-1][MAXN-1]; // diagonal (1,1): (x,y)->(x+1,y+1), x in [0,N-2], y in [0,N-2]\nbool usedD2[MAXN-1][MAXN-1]; // diagonal (1,-1): (x,y)->(x+1,y-1), store as (x, y-1) for y>=1\n\nint64_t weight[MAXN][MAXN]; // w(x,y)\nvector<pair<int,int>> sortedPoints; // by weight descending\n\n// Interval helpers: check if any dot in open interval (l+1 .. r-1)\ninline bool hasDotRow(int y, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = rowDots[y];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotCol(int x, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = colDots[x];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotDiag1(int c, int lx, int rx) { // c = y-x + (N-1)\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag1Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\ninline bool hasDotDiag2(int c, int lx, int rx) { // c = y+x\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag2Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\n\n// Check unit edges on axis-aligned rectangle\nbool checkUnitEdgesAxis(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {\n    // (x1,y1) -> (x2,y2) horizontal\n    int stepx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += stepx) {\n        int ux = min(x, x+stepx);\n        if (usedH[ux][y1]) return false;\n    }\n    // (x2,y2) -> (x3,y3) vertical\n    int stepy = (y3 > y2) ? 1 : -1;\n    for (int y = y2; y != y3; y += stepy) {\n        int uy = min(y, y+stepy);\n        if (usedV[x2][uy]) return false;\n    }\n    // (x3,y3) -> (x4,y4) horizontal (same y as y3)\n    stepx = (x4 > x3) ? 1 : -1;\n    for (int x = x3; x != x4; x += stepx) {\n        int ux = min(x, x+stepx);\n        if (usedH[ux][y3]) return false;\n    }\n    // (x4,y4) -> (x1,y1) vertical\n    stepy = (y1 > y4) ? 1 : -1;\n    for (int y = y4; y != y1; y += stepy) {\n        int uy = min(y, y+stepy);\n        if (usedV[x4][uy]) return false;\n    }\n    return true;\n}\n\n// Check unit edges on diagonal rectangle (type1: (a,a) and (b,-b))\nbool checkUnitEdgesDiag1(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {\n    // edge p1->p2: slope1 (dx positive assumed, but we handle direction\n    int stepx = (x2 > x1) ? 1 : -1;\n    int dx = x2 - x1;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x1 + t * stepx;\n        int y = y1 + t * stepx; // since dy=dx for slope1\n        if (usedD1[x][y]) return false; // x in [0,N-2], y in [0,N-2] should hold\n    }\n    // edge p2->p3: slope -1\n    stepx = (x3 > x2) ? 1 : -1;\n    dx = x3 - x2;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x2 + t * stepx;\n        int y = y2 - t * stepx; // dy = -dx\n        // usedD2[x][y-1] if y>0\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    // edge p3->p4: slope1 (reverse direction: p4->p3 is slope1, but going p3->p4 is opposite direction, same line)\n    int stepx2 = (x4 > x3) ? 1 : -1;\n    dx = x4 - x3;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x3 + t * stepx2;\n        int y = y3 + t * stepx2;\n        if (usedD1[x][y]) return false;\n    }\n    // edge p4->p1: slope -1\n    stepx = (x1 > x4) ? 1 : -1;\n    dx = x1 - x4;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x4 + t * stepx;\n        int y = y4 - t * stepx;\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    return true;\n}\n// similar for type2: (a,-a) and (b,b)\nbool checkUnitEdgesDiag2(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {\n    // edge p1->p2: slope -1\n    int stepx = (x2 > x1) ? 1 : -1;\n    int dx = x2 - x1;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x1 + t * stepx;\n        int y = y1 - t * stepx;\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    // edge p2->p3: slope1\n    stepx = (x3 > x2) ? 1 : -1;\n    dx = x3 - x2;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x2 + t * stepx;\n        int y = y2 + t * stepx;\n        if (usedD1[x][y]) return false;\n    }\n    // edge p3->p4: slope -1\n    stepx = (x4 > x3) ? 1 : -1;\n    dx = x4 - x3;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x3 + t * stepx;\n        int y = y3 - t * stepx;\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    // edge p4->p1: slope1\n    stepx = (x1 > x4) ? 1 : -1;\n    dx = x1 - x4;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x4 + t * stepx;\n        int y = y4 + t * stepx;\n        if (usedD1[x][y]) return false;\n    }\n    return true;\n}\n\n// try to place a dot at (x,y) by finding a valid rectangle\nbool tryPlace(int x, int y, int rect[4][2]) {\n    // axis-aligned\n    const auto& row = rowDots[y];\n    const auto& col = colDots[x];\n    for (int x2 : row) {\n        if (x2 == x) continue;\n        int xmin = min(x,x2), xmax = max(x,x2);\n        for (int y4 : col) {\n            if (y4 == y) continue;\n            if (!dot[x2][y4]) continue;\n            int ymin = min(y,y4), ymax = max(y,y4);\n            // check dots on edges\n            if (hasDotRow(y, xmin, xmax)) continue;\n            if (hasDotRow(y4, xmin, xmax)) continue;\n            if (hasDotCol(x, ymin, ymax)) continue;\n            if (hasDotCol(x2, ymin, ymax)) continue;\n            // check unit edges\n            if (!checkUnitEdgesAxis(x,y, x2,y, x2,y4, x,y4)) continue;\n            // found\n            rect[0][0]=x; rect[0][1]=y;\n            rect[1][0]=x2; rect[1][1]=y;\n            rect[2][0]=x2; rect[2][1]=y4;\n            rect[3][0]=x; rect[3][1]=y4;\n            return true;\n        }\n    }\n    // diagonal type1: p2 on diag1 (y-x constant), p4 on diag2 (y+x constant)\n    int c1 = y - x + N-1; // index for diag1\n    int c2 = y + x; // index for diag2\n    for (int x2 : diag1Dots[c1]) {\n        if (x2 == x) continue;\n        int y2 = x2 + (y-x); // because y2-x2 = y-x\n        int dx = x2 - x; // a = dx = dy\n        for (int x4 : diag2Dots[c2]) {\n            if (x4 == x) continue;\n            int y4 = c2 - x4; // y4 = (y+x) - x4\n            int db = x4 - x;\n            // check if p3 exists: (x2 + db, y2 - db)\n            int x3 = x2 + db;\n            int y3 = y2 - db;\n            if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n            if (!dot[x3][y3]) continue;\n            // check no dots on edges (perimeter)\n            // edge p1->p2 (slope1)\n            int dx1 = abs(dx);\n            int xmin1 = min(x,x2), xmax1 = max(x,x2);\n            if (hasDotDiag1(c1, xmin1, xmax1)) continue;\n            // edge p2->p3 (slope -1)\n            int c23 = y2 + x2; // constant for diag2 line through p2? Actually p2->p3 is on diag2 with constant = y2+x2? Let's compute: p2=(x2,y2), p3=(x3,y3). The line between them has y-x? No, it's slope -1, so y+x constant = y2+x2 = y3+x3. So c23 = y2+x2.\n            int xmin23 = min(x2,x3), xmax23 = max(x2,x3);\n            if (hasDotDiag2(c23, xmin23, xmax23)) continue;\n            // edge p3->p4 (slope1)\n            int c34 = y3 - x3 + N-1; // diag1\n            int xmin34 = min(x3,x4), xmax34 = max(x3,x4);\n            if (hasDotDiag1(c34, xmin34, xmax34)) continue;\n            // edge p4->p1 (slope -1)\n            int c41 = y4 + x4; // diag2\n            int xmin41 = min(x4,x), xmax41 = max(x4,x);\n            if (hasDotDiag2(c41, xmin41, xmax41)) continue;\n            // check unit edges\n            if (!checkUnitEdgesDiag1(x,y, x2,y2, x3,y3, x4,y4)) continue;\n            // found\n            rect[0][0]=x; rect[0][1]=y;\n            rect[1][0]=x2; rect[1][1]=y2;\n            rect[2][0]=x3; rect[2][1]=y3;\n            rect[3][0]=x4; rect[3][1]=y4;\n            return true;\n        }\n    }\n    // diagonal type2: p2 on diag2, p4 on diag1\n    for (int x2 : diag2Dots[c2]) {\n        if (x2 == x) continue;\n        int y2 = c2 - x2;\n        int dx = x2 - x;\n        for (int x4 : diag1Dots[c1]) {\n            if (x4 == x) continue;\n            int y4 = x4 + (y-x);\n            int db = x4 - x;\n            // p3 = (x2 + db, y2 + db) (since from p2 go (db, -db)? Actually for type2, vectors: (a,-a) and (b,b). So p2 is (x+a, y-a), p4 is (x+b, y+b). Then p3 = (x+a+b, y-a+b). So here a = dx, b = db.\n            int x3 = x2 + db;\n            int y3 = y2 + db;\n            if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n            if (!dot[x3][y3]) continue;\n            // edges:\n            // p1->p2: slope -1\n            int xmin12 = min(x,x2), xmax12 = max(x,x2);\n            if (hasDotDiag2(c2, xmin12, xmax12)) continue;\n            // p2->p3: slope1\n            int c23 = y2 - x2 + N-1; // diag1 through p2\n            int xmin23 = min(x2,x3), xmax23 = max(x2,x3);\n            if (hasDotDiag1(c23, xmin23, xmax23)) continue;\n            // p3->p4: slope -1\n            int c34 = y3 + x3; // diag2\n            int xmin34 = min(x3,x4), xmax34 = max(x3,x4);\n            if (hasDotDiag2(c34, xmin34, xmax34)) continue;\n            // p4->p1: slope1\n            int c41 = y4 - x4 + N-1; // diag1\n            int xmin41 = min(x4,x), xmax41 = max(x4,x);\n            if (hasDotDiag1(c41, xmin41, xmax41)) continue;\n            // unit edges\n            if (!checkUnitEdgesDiag2(x,y, x2,y2, x3,y3, x4,y4)) continue;\n            rect[0][0]=x; rect[0][1]=y;\n            rect[1][0]=x2; rect[1][1]=y2;\n            rect[2][0]=x3; rect[2][1]=y3;\n            rect[3][0]=x4; rect[3][1]=y4;\n            return true;\n        }\n    }\n    return false;\n}\n\nvoid placeDot(int x, int y) {\n    dot[x][y] = true;\n    // update sorted lists\n    auto ins = [](vector<int>& v, int val) {\n        v.insert(lower_bound(v.begin(), v.end(), val), val);\n    };\n    ins(rowDots[y], x);\n    ins(colDots[x], y);\n    ins(diag1Dots[y - x + N-1], x);\n    ins(diag2Dots[y + x], x);\n}\n\nvoid markUnitEdges(int rect[4][2]) {\n    // axis-aligned: from p1 to p2 (horizontal)\n    auto markH = [&](int x1, int y, int x2) {\n        int step = (x2 > x1) ? 1 : -1;\n        for (int x = x1; x != x2; x += step) {\n            int ux = min(x, x+step);\n            usedH[ux][y] = true;\n        }\n    };\n    auto markV = [&](int x, int y1, int y2) {\n        int step = (y2 > y1) ? 1 : -1;\n        for (int y = y1; y != y2; y += step) {\n            int uy = min(y, y+step);\n            usedV[x][uy] = true;\n        }\n    };\n    auto markD1 = [&](int x1, int y1, int x2, int y2) {\n        int step = (x2 > x1) ? 1 : -1;\n        for (int x = x1; x != x2; x += step) {\n            int y = y1 + (x - x1);\n            usedD1[x][y] = true;\n        }\n    };\n    auto markD2 = [&](int x1, int y1, int x2, int y2) {\n        int step = (x2 > x1) ? 1 : -1;\n        for (int x = x1; x != x2; x += step) {\n            int y = y1 - (x - x1);\n            if (y > 0) usedD2[x][y-1] = true;\n        }\n    };\n    // Determine rectangle type by comparing coordinates\n    // Check if it's axis-aligned (same y for p1 and p2)\n    if (rect[0][1] == rect[1][1]) {\n        markH(rect[0][0], rect[0][1], rect[1][0]);\n        markV(rect[1][0], rect[1][1], rect[2][1]);\n        markH(rect[3][0], rect[3][1], rect[2][0]);\n        markV(rect[0][0], rect[0][1], rect[3][1]);\n    } else {\n        // diagonal: check if p1->p2 has slope 1 (y2 - y1 == x2 - x1)\n        if ( (rect[1][1] - rect[0][1]) == (rect[1][0] - rect[0][0]) ) {\n            // type1\n            markD1(rect[0][0], rect[0][1], rect[1][0], rect[1][1]);\n            markD2(rect[1][0], rect[1][1], rect[2][0], rect[2][1]);\n            markD1(rect[3][0], rect[3][1], rect[2][0], rect[2][1]);\n            markD2(rect[0][0], rect[0][1], rect[3][0], rect[3][1]);\n        } else {\n            // type2\n            markD2(rect[0][0], rect[0][1], rect[1][0], rect[1][1]);\n            markD1(rect[1][0], rect[1][1], rect[2][0], rect[2][1]);\n            markD2(rect[3][0], rect[3][1], rect[2][0], rect[2][1]);\n            markD1(rect[0][0], rect[0][1], rect[3][0], rect[3][1]);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    // read input\n    cin >> N >> M;\n    // initialize\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) dot[i][j] = false;\n    for (int i=0; i<M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        placeDot(x, y);\n    }\n    // precompute weights and sorted points\n    int c = (N-1)/2;\n    for (int y=0; y<N; ++y) {\n        for (int x=0; x<N; ++x) {\n            weight[x][y] = (x-c)*(x-c) + (y-c)*(y-c) + 1;\n            sortedPoints.emplace_back(x, y);\n        }\n    }\n    sort(sortedPoints.begin(), sortedPoints.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n        return weight[a.first][a.second] > weight[b.first][b.second];\n    });\n    // main loop\n    vector<array<int,8>> operations; // store each operation\n    while (true) {\n        bool placed = false;\n        int rect[4][2];\n        for (const auto& p : sortedPoints) {\n            int x = p.first, y = p.second;\n            if (dot[x][y]) continue;\n            if (tryPlace(x, y, rect)) {\n                // perform operation\n                placeDot(rect[0][0], rect[0][1]);\n                markUnitEdges(rect);\n                operations.push_back({rect[0][0], rect[0][1], rect[1][0], rect[1][1], rect[2][0], rect[2][1], rect[3][0], rect[3][1]});\n                placed = true;\n                break;\n            }\n        }\n        if (!placed) break;\n    }\n    // output\n    cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        for (int i=0; i<8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Simulate tilting the box in the given direction.\n// Returns new grid after tilt.\nvector<vector<int>> tilt(const vector<vector<int>>& grid, char dir) {\n    const int N = 10;\n    vector<vector<int>> res(N, vector<int>(N, 0));\n    if (dir == 'F') { // forward -> row 0\n        for (int j = 0; j < N; ++j) {\n            int r = 0;\n            for (int i = 0; i < N; ++i) {\n                if (grid[i][j] != 0) {\n                    res[r][j] = grid[i][j];\n                    ++r;\n                }\n            }\n        }\n    } else if (dir == 'B') { // backward -> row 9\n        for (int j = 0; j < N; ++j) {\n            int r = N - 1;\n            for (int i = N - 1; i >= 0; --i) {\n                if (grid[i][j] != 0) {\n                    res[r][j] = grid[i][j];\n                    --r;\n                }\n            }\n        }\n    } else if (dir == 'L') { // left -> col 0\n        for (int i = 0; i < N; ++i) {\n            int c = 0;\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] != 0) {\n                    res[i][c] = grid[i][j];\n                    ++c;\n                }\n            }\n        }\n    } else { // 'R' -> col 9\n        for (int i = 0; i < N; ++i) {\n            int c = N - 1;\n            for (int j = N - 1; j >= 0; --j) {\n                if (grid[i][j] != 0) {\n                    res[i][c] = grid[i][j];\n                    --c;\n                }\n            }\n        }\n    }\n    return res;\n}\n\n// Compute sum of squares of connected component sizes.\nint compute_score(const vector<vector<int>>& grid) {\n    const int N = 10;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int total = 0;\n    const int dx[4] = {0, 0, 1, -1};\n    const int dy[4] = {1, -1, 0, 0};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != 0 && !visited[i][j]) {\n                int flavor = grid[i][j];\n                int cnt = 0;\n                queue<pair<int,int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    ++cnt;\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = x + dx[d], ny = y + dy[d];\n                        if (nx >= 0 && nx < N && ny >= 0 && ny < N &&\n                            !visited[nx][ny] && grid[nx][ny] == flavor) {\n                            visited[nx][ny] = true;\n                            q.push({nx, ny});\n                        }\n                    }\n                }\n                total += cnt * cnt;\n            }\n        }\n    }\n    return total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read the flavor list for all 100 candies.\n    vector<int> flavors(100);\n    for (int i = 0; i < 100; ++i) {\n        cin >> flavors[i];\n    }\n\n    // Initialize empty grid.\n    const int N = 10;\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n\n    const char dirs[4] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p; // position of new candy among empty cells\n\n        // Locate the p-th empty cell (1-indexed, front-to-back then left-to-right).\n        int idx = 1;\n        int pos_i = -1, pos_j = -1;\n        for (int i = 0; i < N && pos_i == -1; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (grid[i][j] == 0) {\n                    if (idx == p) {\n                        pos_i = i;\n                        pos_j = j;\n                        break;\n                    }\n                    ++idx;\n                }\n            }\n        }\n        // Place the candy of known flavor.\n        grid[pos_i][pos_j] = flavors[t];\n\n        // If this is the 100th candy, we may skip the tilt (output anything).\n        // But we still simulate for consistency.\n        char best_dir = 'F';\n        int best_score = -1;\n\n        // Evaluate all four tilt directions.\n        for (char d : dirs) {\n            auto new_grid = tilt(grid, d);\n            int sc = compute_score(new_grid);\n            if (sc > best_score) {\n                best_score = sc;\n                best_dir = d;\n            }\n        }\n\n        // Output chosen direction and flush.\n        cout << best_dir << '\\n' << flush;\n\n        // Apply the chosen tilt to update the state.\n        grid = tilt(grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <map>\n#include <cassert>\n#include <cmath>\n#include <Eigen/Dense>\n#include <numeric>\n\nusing namespace std;\nusing Eigen::MatrixXd;\nusing Eigen::SelfAdjointEigenSolver;\n\n// ---------- helper for epsilon = 0 : small N ----------\nstring canonical_string(const vector<vector<bool>>& adj, int N) {\n    vector<int> deg(N, 0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (adj[i][j]) ++deg[i];\n    // build signature: (degree, sorted neighbor degrees)\n    vector<pair<int, vector<int>>> sig(N);\n    for (int i = 0; i < N; ++i) {\n        vector<int> nbr;\n        for (int j = 0; j < N; ++j)\n            if (adj[i][j]) nbr.push_back(deg[j]);\n        sort(nbr.begin(), nbr.end());\n        sig[i] = {deg[i], move(nbr)};\n    }\n    // sort vertices by signature\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        const auto& sa = sig[a];\n        const auto& sb = sig[b];\n        if (sa.first != sb.first) return sa.first > sb.first;\n        return sa.second < sb.second;\n    });\n    // build string in this order\n    string s;\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j) {\n            int u = order[i], v = order[j];\n            s.push_back(adj[u][v] ? '1' : '0');\n        }\n    return s;\n}\n\n// ---------- disjoint cliques for epsilon > 0 ----------\nvoid compute_spectrum(int N, const vector<int>& sizes, vector<double>& spec) {\n    spec.clear();\n    for (int s : sizes) {\n        spec.push_back(double(s - 1));\n        for (int i = 1; i < s; ++i) spec.push_back(-1.0);\n    }\n    int isolated = N;\n    for (int s : sizes) isolated -= s;\n    for (int i = 0; i < isolated; ++i) spec.push_back(0.0);\n    sort(spec.rbegin(), spec.rend());\n    assert((int)spec.size() == N);\n}\n\ndouble dist_sq(const vector<double>& a, const vector<double>& b) {\n    double sum = 0.0;\n    for (size_t i = 0; i < a.size(); ++i) {\n        double d = a[i] - b[i];\n        sum += d * d;\n    }\n    return sum;\n}\n\nstring build_graph_string(int N, const vector<int>& sizes) {\n    vector<int> clique_id(N, -1);\n    int cur = 0, cid = 0;\n    for (int s : sizes) {\n        for (int i = 0; i < s; ++i) clique_id[cur++] = cid;\n        ++cid;\n    }\n    string res;\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (clique_id[i] != -1 && clique_id[i] == clique_id[j])\n                res.push_back('1');\n            else\n                res.push_back('0');\n        }\n    }\n    return res;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    if (eps == 0.0) {\n        // use smallest N (4..6) with enough unlabeled graphs\n        const int unlabeled_count[7] = {0,0,0,0,11,34,156};\n        int N = 4;\n        while (N <= 6 && unlabeled_count[N] < M) ++N;\n        // N is guaranteed <=6 because M<=100 <= unlabeled[6]\n        int L = N * (N - 1) / 2;\n        int total = 1 << L;\n        map<string, int> canon_to_id;\n        vector<string> out_strings(M);\n        int found = 0;\n        for (int mask = 0; mask < total && found < M; ++mask) {\n            // build adjacency\n            vector<vector<bool>> adj(N, vector<bool>(N, false));\n            int bit = 0;\n            for (int i = 0; i < N; ++i)\n                for (int j = i + 1; j < N; ++j) {\n                    if (mask >> bit & 1) adj[i][j] = adj[j][i] = true;\n                    ++bit;\n                }\n            string canon = canonical_string(adj, N);\n            if (canon_to_id.find(canon) == canon_to_id.end()) {\n                canon_to_id[canon] = found;\n                out_strings[found] = canon;  // output the canonical form itself\n                ++found;\n            }\n        }\n        cout << N << '\\n';\n        for (int i = 0; i < M; ++i) cout << out_strings[i] << '\\n';\n        cout.flush();\n\n        // answer queries\n        for (int q = 0; q < 100; ++q) {\n            string H;\n            cin >> H;\n            // build adjacency\n            vector<vector<bool>> adj(N, vector<bool>(N, false));\n            int bit = 0;\n            for (int i = 0; i < N; ++i)\n                for (int j = i + 1; j < N; ++j) {\n                    if (H[bit] == '1') adj[i][j] = adj[j][i] = true;\n                    ++bit;\n                }\n            string canon_H = canonical_string(adj, N);\n            int ans = canon_to_id[canon_H];\n            cout << ans << '\\n';\n            cout.flush();\n        }\n        return 0;\n    }\n\n    // epsilon > 0 : use disjoint cliques with N = 100\n    const int N = 100;\n    struct Candidate {\n        vector<int> sizes;\n        vector<double> spectrum;\n        double max_eigen;\n    };\n    vector<Candidate> candidates;\n\n    // generate all partitions into at most 2 cliques of size >= 2\n    for (int s1 = 2; s1 <= N; ++s1) {\n        // one clique\n        {\n            Candidate c;\n            c.sizes = {s1};\n            compute_spectrum(N, c.sizes, c.spectrum);\n            c.max_eigen = s1 - 1;\n            candidates.push_back(move(c));\n        }\n        // two cliques (unordered, s1 <= s2)\n        for (int s2 = s1; s2 <= N - s1; ++s2) {\n            Candidate c;\n            c.sizes = {s1, s2};\n            compute_spectrum(N, c.sizes, c.spectrum);\n            c.max_eigen = max(s1 - 1, s2 - 1);\n            candidates.push_back(move(c));\n        }\n    }\n\n    int K = candidates.size();\n    vector<bool> used(K, false);\n    vector<int> selected;\n\n    // pick the one with largest eigenvalue first\n    int best_init = -1;\n    double best_eigen = -1e9;\n    for (int i = 0; i < K; ++i) {\n        if (candidates[i].max_eigen > best_eigen) {\n            best_eigen = candidates[i].max_eigen;\n            best_init = i;\n        }\n    }\n    used[best_init] = true;\n    selected.push_back(best_init);\n\n    // greedy selection to maximize minimum pairwise distance\n    while ((int)selected.size() < M) {\n        double best_min = -1e9;\n        int best_idx = -1;\n        for (int i = 0; i < K; ++i) if (!used[i]) {\n            double cur_min = 1e100;\n            for (int j : selected) {\n                double d = dist_sq(candidates[i].spectrum, candidates[j].spectrum);\n                if (d < cur_min) cur_min = d;\n            }\n            if (cur_min > best_min) {\n                best_min = cur_min;\n                best_idx = i;\n            }\n        }\n        if (best_idx == -1) break; // should not happen (enough candidates)\n        used[best_idx] = true;\n        selected.push_back(best_idx);\n    }\n\n    // output graphs\n    cout << N << '\\n';\n    for (int idx : selected) {\n        cout << build_graph_string(N, candidates[idx].sizes) << '\\n';\n    }\n    cout.flush();\n\n    // precompute spectra for selected graphs\n    vector<vector<double>> selected_spectra(M);\n    for (int i = 0; i < M; ++i) selected_spectra[i] = candidates[selected[i]].spectrum;\n\n    // process queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n        // build adjacency matrix\n        MatrixXd adj = MatrixXd::Zero(N, N);\n        int bit = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (H[bit] == '1') {\n                    adj(i, j) = 1.0;\n                    adj(j, i) = 1.0;\n                }\n                ++bit;\n            }\n        }\n        // compute eigenvalues\n        SelfAdjointEigenSolver<MatrixXd> solver(adj);\n        vector<double> evals(N);\n        for (int i = 0; i < N; ++i) evals[i] = solver.eigenvalues()[i];\n        sort(evals.rbegin(), evals.rend());\n\n        // find nearest neighbor\n        int best_t = -1;\n        double best_d = 1e100;\n        for (int i = 0; i < M; ++i) {\n            double d = dist_sq(evals, selected_spectra[i]);\n            if (d < best_d) {\n                best_d = d;\n                best_t = i;\n            }\n        }\n        cout << best_t << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nconst ll INF = 1e18;\nconst ll UNREACHABLE = 1000000000LL;\n\n// ------------------------------------------------------------\n// read input and build graph\n// ------------------------------------------------------------\nstruct Edge {\n    int u, v, w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, ll>>> g(N);\n    vector<vector<int>> edge_index(N, vector<int>(N, -1));\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u, v, w};\n        g[u].emplace_back(v, w);\n        g[v].emplace_back(u, w);\n        edge_index[u][v] = edge_index[v][u] = i;\n    }\n\n    // skip vertex coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ------------------------------------------------------------\n    // 1. original all\u2011pairs shortest paths\n    // ------------------------------------------------------------\n    vector<vector<ll>> dist_orig(N, vector<ll>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        dist_orig[s][s] = 0;\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist_orig[s][u]) continue;\n            for (auto [v, w] : g[u]) {\n                ll nd = d + w;\n                if (nd < dist_orig[s][v]) {\n                    dist_orig[s][v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 2. edge betweenness centrality (Brandes)\n    // ------------------------------------------------------------\n    vector<ld> betweenness(M, 0.0);\n\n    for (int s = 0; s < N; ++s) {\n        // shortest distances and number of shortest paths\n        vector<ll> d(N, INF);\n        vector<ld> cnt(N, 0.0);\n        vector<vector<int>> pred(N);\n        d[s] = 0;\n        cnt[s] = 1.0;\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != d[u]) continue;\n            for (auto [v, w] : g[u]) {\n                ll nd = du + w;\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    cnt[v] = cnt[u];\n                    pred[v].clear();\n                    pred[v].push_back(u);\n                    pq.emplace(nd, v);\n                } else if (nd == d[v]) {\n                    cnt[v] += cnt[u];\n                    pred[v].push_back(u);\n                }\n            }\n        }\n\n        // vertices in decreasing distance order\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return d[a] > d[b];\n        });\n\n        vector<ld> dep(N, 0.0);\n        for (int v : order) {\n            if (v == s) continue;\n            if (pred[v].empty()) continue;\n            ld sigma_v = cnt[v];\n            for (int p : pred[v]) {\n                ld contrib = (cnt[p] / sigma_v) * (1.0 + dep[v]);\n                dep[p] += contrib;\n                int eidx = edge_index[p][v];\n                betweenness[eidx] += contrib;\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 3. initial assignment: greedy load balancing of betweenness\n    // ------------------------------------------------------------\n    vector<pair<ld, int>> order_by_bw(M);\n    for (int i = 0; i < M; ++i) {\n        order_by_bw[i] = {betweenness[i], i};\n    }\n    sort(order_by_bw.rbegin(), order_by_bw.rend());   // descending\n\n    vector<int> day_of_edge(M, -1);\n    vector<int> day_cnt(D, 0);\n    vector<ld> day_load(D, 0.0);\n\n    for (auto [bw, eid] : order_by_bw) {\n        int best_day = -1;\n        ld best_load = 1e100;\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_load[d] < best_load) {\n                best_load = day_load[d];\n                best_day = d;\n            }\n        }\n        // capacity is guaranteed by K > ceil(M/D)\n        assert(best_day != -1);\n        day_of_edge[eid] = best_day;\n        day_cnt[best_day]++;\n        day_load[best_day] += bw;\n    }\n\n    // ------------------------------------------------------------\n    // 4. local search to balance betweenness (swap edges)\n    // ------------------------------------------------------------\n    for (int iter = 0; iter < 500; ++iter) {\n        int max_day = max_element(day_load.begin(), day_load.end()) - day_load.begin();\n        int min_day = min_element(day_load.begin(), day_load.end()) - day_load.begin();\n        if (day_load[max_day] - day_load[min_day] < 1e-12) break;\n\n        // find an edge that can be moved to reduce imbalance\n        int move_e = -1;\n        ld best_improve = 0.0;\n        for (int e = 0; e < M; ++e) {\n            if (day_of_edge[e] != max_day) continue;\n            if (day_cnt[min_day] >= K) continue;\n            ld new_max = day_load[max_day] - betweenness[e];\n            ld new_min = day_load[min_day] + betweenness[e];\n            ld new_diff = fabsl(new_max - new_min);\n            ld old_diff = day_load[max_day] - day_load[min_day];\n            ld improve = old_diff - new_diff;\n            if (improve > best_improve) {\n                best_improve = improve;\n                move_e = e;\n            }\n        }\n        if (move_e == -1) break;\n\n        // perform move\n        int e = move_e;\n        int old_day = max_day;\n        int new_day = min_day;\n        day_load[old_day] -= betweenness[e];\n        day_load[new_day] += betweenness[e];\n        day_cnt[old_day]--;\n        day_cnt[new_day]++;\n        day_of_edge[e] = new_day;\n    }\n\n    // ------------------------------------------------------------\n    // 5. compute actual frustration (optional, only for output)\n    // ------------------------------------------------------------\n    // We do not use actual frustration to further improve,\n    // because it would be too time\u2011consuming.\n    // Final output is the day assignment.\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << day_of_edge[i] + 1;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// 3D rotation matrices (proper rotations, 24)\nvector<array<array<int,3>,3>> gen_rotations() {\n    vector<array<array<int,3>,3>> rots;\n    int perm[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n    int parity[6] = {1,-1,-1,1,1,-1};\n    int signs[8][3] = {{1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},\n                       {-1,1,1},{-1,1,-1},{-1,-1,1},{-1,-1,-1}};\n    for (int p=0;p<6;p++) {\n        for (auto s : signs) {\n            int det = s[0]*s[1]*s[2] * parity[p];\n            if (det != 1) continue; // only proper rotations\n            array<array<int,3>,3> mat;\n            for (int i=0;i<3;i++) {\n                for (int j=0;j<3;j++) {\n                    mat[i][j] = (j == perm[p][i]) ? s[i] : 0;\n                }\n            }\n            rots.push_back(mat);\n        }\n    }\n    return rots;\n}\n\n// canonical representation of a set of points (up to translation and rotation)\nstring canonical(const vector<tuple<int,int,int>>& pts, const vector<array<array<int,3>,3>>& rots) {\n    string best;\n    for (const auto& rot : rots) {\n        vector<tuple<int,int,int>> trans;\n        int mnx=1e9, mny=1e9, mnz=1e9;\n        for (auto [x,y,z] : pts) {\n            int nx = rot[0][0]*x + rot[0][1]*y + rot[0][2]*z;\n            int ny = rot[1][0]*x + rot[1][1]*y + rot[1][2]*z;\n            int nz = rot[2][0]*x + rot[2][1]*y + rot[2][2]*z;\n            trans.emplace_back(nx, ny, nz);\n            mnx = min(mnx, nx); mny = min(mny, ny); mnz = min(mnz, nz);\n        }\n        // shift to origin\n        for (auto& [x,y,z] : trans) {\n            x -= mnx; y -= mny; z -= mnz;\n        }\n        sort(trans.begin(), trans.end());\n        string s;\n        for (auto [x,y,z] : trans) {\n            s += to_string(x) + \",\" + to_string(y) + \",\" + to_string(z) + \";\";\n        }\n        if (best.empty() || s < best) best = s;\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int D; cin >> D;\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n    for (int t=0;t<2;t++) {\n        for (int i=0;i<D;i++) cin >> f[t][i];\n        for (int i=0;i<D;i++) cin >> r[t][i];\n    }\n    // 3D bool arrays for valid positions\n    int N = D*D*D;\n    vector<vector<int>> a(2, vector<int>(N, 0));\n    for (int t=0;t<2;t++) {\n        for (int z=0;z<D;z++) {\n            for (int x=0;x<D;x++) {\n                if (f[t][z][x]=='0') continue;\n                for (int y=0;y<D;y++) {\n                    if (r[t][z][y]=='1') {\n                        int idx = x*D*D + y*D + z;\n                        a[t][idx] = 1;\n                    }\n                }\n            }\n        }\n    }\n    // compute components for each object\n    auto rots = gen_rotations();\n    vector<vector<int>> comp_id(2, vector<int>(N, -1));\n    vector<vector<tuple<int,int,int>>> comp_pts[2]; // per component list of points\n    vector<int> comp_vol[2];\n    for (int t=0;t<2;t++) {\n        int cid = 0;\n        for (int idx=0;idx<N;idx++) {\n            if (a[t][idx]==0 || comp_id[t][idx]!=-1) continue;\n            // BFS\n            queue<int> q; q.push(idx);\n            comp_id[t][idx] = cid;\n            vector<tuple<int,int,int>> pts;\n            pts.emplace_back(idx/(D*D), (idx/D)%D, idx%D); // x,y,z\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                int cx = cur/(D*D), cy = (cur/D)%D, cz = cur%D;\n                static int dx[] = {1,-1,0,0,0,0};\n                static int dy[] = {0,0,1,-1,0,0};\n                static int dz[] = {0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx = cx+dx[d], ny = cy+dy[d], nz = cz+dz[d];\n                    if (nx<0 || nx>=D || ny<0 || ny>=D || nz<0 || nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (a[t][nid] && comp_id[t][nid]==-1) {\n                        comp_id[t][nid] = cid;\n                        q.push(nid);\n                        pts.emplace_back(nx,ny,nz);\n                    }\n                }\n            }\n            comp_pts[t].push_back(pts);\n            comp_vol[t].push_back(pts.size());\n            cid++;\n        }\n    }\n    // group components by canonical shape\n    map<string, vector<pair<int,int>>> group[2]; // shape -> (component index, volume)\n    for (int t=0;t<2;t++) {\n        for (size_t i=0;i<comp_pts[t].size();i++) {\n            string can = canonical(comp_pts[t][i], rots);\n            group[t][can].emplace_back(i, comp_vol[t][i]);\n        }\n    }\n    // assign block IDs\n    vector<int> b1(N, 0), b2(N, 0);\n    int block_id = 1;\n    // match shapes\n    for (auto& [key, vec1] : group[0]) {\n        if (group[1].count(key) == 0) continue;\n        auto& vec2 = group[1][key];\n        int m = min(vec1.size(), vec2.size());\n        for (int k=0;k<m;k++) {\n            int idx1 = vec1[k].first, idx2 = vec2[k].first;\n            // fill b1\n            for (auto [x,y,z] : comp_pts[0][idx1]) {\n                b1[x*D*D + y*D + z] = block_id;\n            }\n            // fill b2\n            for (auto [x,y,z] : comp_pts[1][idx2]) {\n                b2[x*D*D + y*D + z] = block_id;\n            }\n            block_id++;\n        }\n        // remove matched from vec2 to avoid reuse\n        for (int k=0;k<m;k++) vec2.erase(vec2.begin()); // erase first m\n        if (vec2.empty()) group[1].erase(key);\n        else group[1][key] = vec2;\n        // also remove from vec1 (we don't need further)\n    }\n    // handle remaining components in both objects\n    for (int t=0;t<2;t++) {\n        for (auto& [key, vec] : group[t]) {\n            for (auto [idx, vol] : vec) {\n                // assign new block id, only used in this object\n                for (auto [x,y,z] : comp_pts[t][idx]) {\n                    if (t==0) b1[x*D*D + y*D + z] = block_id;\n                    else      b2[x*D*D + y*D + z] = block_id;\n                }\n                block_id++;\n            }\n        }\n    }\n    int n = block_id - 1;\n    cout << n << '\\n';\n    for (int i=0;i<N;i++) cout << b1[i] << \" \\n\"[i==N-1];\n    for (int i=0;i<N;i++) cout << b2[i] << \" \\n\"[i==N-1];\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nconst ll INF = 1LL << 60;\n\nstruct UnionFind {\n    vector<int> parent, rank;\n    UnionFind(int n) : parent(n), rank(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) parent[x] = y;\n        else if (rank[x] > rank[y]) parent[y] = x;\n        else { parent[y] = x; rank[x]++; }\n        return true;\n    }\n};\n\nint ceil_sqrt(ll sq) {\n    if (sq <= 0) return 0;\n    double d = sqrt((double)sq);\n    int r = (int)ceil(d);\n    if ((ll)r * r < sq) ++r;\n    return min(r, 5000);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<tuple<int,int,ll>> edges(M);\n    vector<vector<pair<int,ll>>> adj(N);\n    for (int j = 0; j < M; ++j) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].emplace_back(v, w);\n        adj[v].emplace_back(u, w);\n    }\n\n    vector<int> ax(K), ay(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> ax[k] >> ay[k];\n    }\n\n    // Precompute squared distances between residents and nodes\n    vector<vector<ll>> dist2_res(K, vector<ll>(N));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            ll dx = ax[k] - x[i];\n            ll dy = ay[k] - y[i];\n            dist2_res[k][i] = dx*dx + dy*dy;\n        }\n    }\n\n    // For each resident, sort nodes by distance\n    vector<vector<int>> sorted_nodes(K);\n    for (int k = 0; k < K; ++k) {\n        vector<pair<ll,int>> tmp;\n        for (int i = 0; i < N; ++i) {\n            tmp.emplace_back(dist2_res[k][i], i);\n        }\n        sort(tmp.begin(), tmp.end());\n        sorted_nodes[k].reserve(N);\n        for (auto &p : tmp) {\n            sorted_nodes[k].push_back(p.second);\n        }\n    }\n\n    // All-pairs shortest paths\n    vector<vector<ll>> dist_sh(N, vector<ll>(N, INF));\n    vector<vector<int>> prev(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        dist_sh[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist_sh[s][u]) continue;\n            for (auto &[v, w] : adj[u]) {\n                if (dist_sh[s][v] > d + w) {\n                    dist_sh[s][v] = d + w;\n                    prev[s][v] = u;\n                    pq.push({dist_sh[s][v], v});\n                }\n            }\n        }\n    }\n\n    // Cost evaluation function given active set (bool)\n    auto computeCost = [&](const vector<bool>& active) -> ll {\n        vector<ll> maxDistSq(N, 0);\n        for (int k = 0; k < K; ++k) {\n            ll best_d2 = -1;\n            int best_node = -1;\n            for (int i : sorted_nodes[k]) {\n                if (active[i]) {\n                    best_d2 = dist2_res[k][i];\n                    best_node = i;\n                    break;\n                }\n            }\n            if (best_node == -1) return LLONG_MAX; // should not happen\n            if (best_d2 > maxDistSq[best_node])\n                maxDistSq[best_node] = best_d2;\n        }\n        ll sumP2 = 0;\n        for (int i = 0; i < N; ++i) {\n            if (active[i] && maxDistSq[i] > 0) {\n                int r = ceil_sqrt(maxDistSq[i]);\n                sumP2 += (ll)r * r;\n            }\n        }\n\n        vector<int> terms;\n        for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n        ll mst_cost = 0;\n        if (terms.size() > 1) {\n            vector<tuple<ll,int,int>> metric_edges;\n            for (int a = 0; a < (int)terms.size(); ++a) {\n                for (int b = a+1; b < (int)terms.size(); ++b) {\n                    int u = terms[a], v = terms[b];\n                    metric_edges.emplace_back(dist_sh[u][v], u, v);\n                }\n            }\n            sort(metric_edges.begin(), metric_edges.end());\n            UnionFind uf(N);\n            for (auto &[w, u, v] : metric_edges) {\n                if (uf.unite(u, v)) mst_cost += w;\n            }\n        }\n        return sumP2 + mst_cost;\n    };\n\n    // Local search: start from node 1 only\n    vector<bool> active(N, false);\n    active[0] = true; // node 1 is index 0\n    ll best_cost = computeCost(active);\n\n    // Forward selection\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        int best_node = -1;\n        ll best_new = best_cost;\n        for (int i = 0; i < N; ++i) {\n            if (active[i]) continue;\n            active[i] = true;\n            ll new_cost = computeCost(active);\n            if (new_cost < best_new) {\n                best_new = new_cost;\n                best_node = i;\n            }\n            active[i] = false;\n        }\n        if (best_node != -1) {\n            active[best_node] = true;\n            best_cost = best_new;\n            improved = true;\n        }\n    }\n\n    // Backward elimination\n    improved = true;\n    while (improved) {\n        improved = false;\n        int best_node = -1;\n        ll best_new = best_cost;\n        for (int i = 0; i < N; ++i) {\n            if (!active[i] || i == 0) continue;\n            active[i] = false;\n            ll new_cost = computeCost(active);\n            if (new_cost < best_new) {\n                best_new = new_cost;\n                best_node = i;\n            }\n            active[i] = true;\n        }\n        if (best_node != -1) {\n            active[best_node] = false;\n            best_cost = best_new;\n            improved = true;\n        }\n    }\n\n    // Final assignment and powers\n    vector<ll> maxDistSq(N, 0);\n    vector<int> assigned_node(K);\n    for (int k = 0; k < K; ++k) {\n        ll best_d2 = -1;\n        int best_node = -1;\n        for (int i : sorted_nodes[k]) {\n            if (active[i]) {\n                best_d2 = dist2_res[k][i];\n                best_node = i;\n                break;\n            }\n        }\n        assigned_node[k] = best_node;\n        if (best_d2 > maxDistSq[best_node])\n            maxDistSq[best_node] = best_d2;\n    }\n    vector<int> P(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (active[i] && maxDistSq[i] > 0) {\n            P[i] = ceil_sqrt(maxDistSq[i]);\n        }\n    }\n\n    // Build Steiner tree for active set\n    vector<int> terms;\n    for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n    vector<bool> edge_on(M, false);\n\n    // Build edge index map\n    vector<vector<int>> edge_idx(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        auto [u, v, w] = edges[j];\n        edge_idx[u][v] = edge_idx[v][u] = j;\n    }\n\n    if (terms.size() >= 2) {\n        // MST on metric closure\n        vector<tuple<ll,int,int>> metric_edges;\n        for (int a = 0; a < (int)terms.size(); ++a) {\n            for (int b = a+1; b < (int)terms.size(); ++b) {\n                int u = terms[a], v = terms[b];\n                metric_edges.emplace_back(dist_sh[u][v], u, v);\n            }\n        }\n        sort(metric_edges.begin(), metric_edges.end());\n        UnionFind uf1(N);\n        vector<pair<int,int>> mst_pairs;\n        for (auto &[w, u, v] : metric_edges) {\n            if (uf1.unite(u, v)) {\n                mst_pairs.emplace_back(u, v);\n            }\n        }\n\n        // Add all edges from shortest paths of MST pairs\n        for (auto &[u, v] : mst_pairs) {\n            // reconstruct path from u to v using prev[u]\n            int cur = v;\n            while (cur != u) {\n                int par = prev[u][cur];\n                int idx = edge_idx[par][cur];\n                if (idx != -1) {\n                    edge_on[idx] = true;\n                }\n                cur = par;\n            }\n        }\n\n        // Now build spanning tree on the union of these edges\n        vector<int> candidate_edges;\n        for (int j = 0; j < M; ++j) {\n            if (edge_on[j]) candidate_edges.push_back(j);\n        }\n        sort(candidate_edges.begin(), candidate_edges.end(), [&](int a, int b) {\n            return get<2>(edges[a]) < get<2>(edges[b]);\n        });\n        UnionFind uf2(N);\n        fill(edge_on.begin(), edge_on.end(), false);\n        for (int idx : candidate_edges) {\n            auto [u, v, w] = edges[idx];\n            if (uf2.unite(u, v)) {\n                edge_on[idx] = true;\n            }\n        }\n    } // else terms.size()==1 => no edges needed, all edge_on already false.\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (edge_on[j] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    vector<tuple<int, int, int, int>> ops;\n\n    // bottom-up heapify\n    for (int x = N - 2; x >= 0; --x) {\n        for (int y = 0; y <= x; ++y) {\n            int cx = x, cy = y;\n            while (cx < N - 1) {\n                int left_val  = a[cx + 1][cy];\n                int right_val = a[cx + 1][cy + 1];\n                int cur_val   = a[cx][cy];\n\n                if (cur_val > left_val || cur_val > right_val) {\n                    // swap with the smaller child\n                    int child_y = (left_val < right_val) ? cy : cy + 1;\n                    swap(a[cx][cy], a[cx + 1][child_y]);\n                    ops.emplace_back(cx, cy, cx + 1, child_y);\n                    cx = cx + 1;\n                    cy = child_y;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // output\n    cout << ops.size() << \"\\n\";\n    for (const auto& [x1, y1, x2, y2] : ops) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int D = 9;\n    int N;\n    cin >> D >> N; // D is always 9\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // precompute BFS distances from entrance (0,4) ignoring containers\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int, int>> q;\n    dist[0][4] = 0;\n    q.emplace(0, 4);\n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            if (obstacle[nx][ny] || dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            q.emplace(nx, ny);\n        }\n    }\n\n    // list of all usable cells (excluding entrance), sorted by distance\n    vector<tuple<int, int, int>> cells; // (distance, row, col)\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == 0 && j == 4) continue;          // entrance itself\n            if (obstacle[i][j]) continue;\n            cells.emplace_back(dist[i][j], i, j);\n        }\n    }\n    sort(cells.begin(), cells.end());\n    const int total = cells.size();   // = D*D - 1 - N\n\n    // index of each cell in the sorted order (0 .. total-1)\n    vector<vector<int>> order(D, vector<int>(D, -1));\n    for (int idx = 0; idx < total; ++idx) {\n        auto [d, i, j] = cells[idx];\n        order[i][j] = idx;\n    }\n\n    // container number stored at each cell (-1 if empty)\n    vector<vector<int>> container(D, vector<int>(D, -1));\n    vector<vector<bool>> occupied(D, vector<bool>(D, false));\n\n    // BFS from entrance on empty cells (obstacles + occupied cells are walls)\n    auto bfs_reachable = [&]() -> vector<vector<bool>> {\n        vector<vector<bool>> reachable(D, vector<bool>(D, false));\n        queue<pair<int, int>> q;\n        if (!obstacle[0][4] && !occupied[0][4]) {\n            reachable[0][4] = true;\n            q.emplace(0, 4);\n        }\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k], ny = y + dy[k];\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n                if (obstacle[nx][ny] || occupied[nx][ny]) continue;\n                if (reachable[nx][ny]) continue;\n                reachable[nx][ny] = true;\n                q.emplace(nx, ny);\n            }\n        }\n        return reachable;\n    };\n\n    // ---------- placement phase ----------\n    for (int d = 0; d < total; ++d) {\n        int t;\n        cin >> t;\n\n        auto reachable = bfs_reachable();\n\n        // choose the reachable empty cell whose order is closest to t\n        int best_i = -1, best_j = -1;\n        int best_diff = INT_MAX;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || occupied[i][j]) continue;\n                if (i == 0 && j == 4) continue;      // entrance cannot be used\n                if (!reachable[i][j]) continue;\n                int diff = abs(order[i][j] - t);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // place the container\n        occupied[best_i][best_j] = true;\n        container[best_i][best_j] = t;\n        cout << best_i << \" \" << best_j << endl << flush;\n    }\n\n    // ---------- retrieval phase ----------\n    for (int step = 0; step < total; ++step) {\n        auto reachable = bfs_reachable();\n\n        // find the reachable container with the smallest number\n        int best_num = INT_MAX;\n        int best_i = -1, best_j = -1;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || container[i][j] == -1) continue;\n                if (!reachable[i][j]) continue;\n                if (container[i][j] < best_num) {\n                    best_num = container[i][j];\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // remove it\n        occupied[best_i][best_j] = false;\n        container[best_i][best_j] = -1;\n        cout << best_i << \" \" << best_j << \"\\n\";\n    }\n    cout << flush;\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <deque>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int INF = 1e9;\n\n// direction arrays\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\nint n, m;               // grid size, number of colors\nvector<vector<int>> grid; // current output grid\n\n// required adjacency (including color 0)\nvector<vector<bool>> req;\n\n// count of adjacent cell pairs (for colors 1..m, lower triangle)\nvector<vector<int>> adjCnt;\n\n// total cells of each color (1..m)\nvector<int> tot;\n\n// number of cells of each color that are adjacent to 0\nvector<int> zeroCnt;\n\n// check if cell (i,j) of color c can be removed.\nbool can_remove(int i, int j, int c) {\n    // compute net change to zeroCnt for colour c\n    int deltaC = 0;\n    if (i == 0 || i == n-1 || j == 0 || j == n-1) deltaC -= 1; // lose boundary\n    // neighbors\n    int same_neighbors = 0;\n    vector<int> other_neighbors;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        int col = grid[ni][nj];\n        if (col == 0) continue;\n        if (col == c) {\n            same_neighbors++;\n        } else {\n            // adjacency (c,col) might be lost\n            int a = min(c, col);\n            int b = max(c, col);\n            if (adjCnt[a][b] < 2) return false; // would eliminate the only contact\n            other_neighbors.push_back(col);\n        }\n    }\n    deltaC += same_neighbors;\n    // check zero adjacency for c\n    int finalZeroC = zeroCnt[c] + deltaC;\n    if (req[0][c] && finalZeroC <= 0) return false;\n    // check zero adjacency for other neighbor colours\n    for (int col : other_neighbors) {\n        int finalZeroD = zeroCnt[col] + 1; // neighbour gains a zero neighbour\n        if (req[0][col] && finalZeroD <= 0) return false;\n    }\n    // cannot remove the last cell of a colour\n    if (tot[c] <= 1) return false;\n\n    // connectivity check for colour c after removal of (i,j)\n    // BFS on remaining cells of colour c\n    vector<vector<bool>> visited(n, vector<bool>(n, false));\n    queue<pair<int,int>> q;\n    // find a starting cell (any other cell of same colour)\n    int si = -1, sj = -1;\n    // try to use a neighbour of same colour\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        if (grid[ni][nj] == c) {\n            si = ni; sj = nj;\n            break;\n        }\n    }\n    if (si == -1) {\n        // find any other cell of colour c\n        for (int x = 0; x < n; ++x) {\n            for (int y = 0; y < n; ++y) {\n                if ((x != i || y != j) && grid[x][y] == c) {\n                    si = x; sj = y;\n                    break;\n                }\n            }\n            if (si != -1) break;\n        }\n    }\n    if (si == -1) return false; // no other cell (should not happen)\n    q.push({si, sj});\n    visited[si][sj] = true;\n    int cnt = 1;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if ((nx == i && ny == j)) continue; // removed cell is ignored\n            if (!visited[nx][ny] && grid[nx][ny] == c) {\n                visited[nx][ny] = true;\n                cnt++;\n                q.push({nx, ny});\n            }\n        }\n    }\n    if (cnt != tot[c] - 1) return false;\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    const int MAXC = m + 2;\n    req.assign(MAXC, vector<bool>(MAXC, false));\n    adjCnt.assign(MAXC, vector<int>(MAXC, 0));\n    tot.assign(MAXC, 0);\n    zeroCnt.assign(MAXC, 0);\n\n    // initial computations\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = grid[i][j];\n            tot[c]++;\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                zeroCnt[c]++;\n                req[0][c] = req[c][0] = true;\n            }\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int col = grid[ni][nj];\n                if (c != col) {\n                    req[c][col] = req[col][c] = true;\n                    if (c < col) adjCnt[c][col]++;\n                }\n            }\n        }\n    }\n\n    // initial queue: all boundary cells\n    deque<pair<int,int>> que;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                if (grid[i][j] != 0) {\n                    que.push_back({i, j});\n                }\n            }\n        }\n    }\n\n    // greedy removal\n    while (!que.empty()) {\n        auto [i, j] = que.front(); que.pop_front();\n        if (grid[i][j] == 0) continue;\n        int c = grid[i][j];\n        if (can_remove(i, j, c)) {\n            // update structures\n            // neighbours\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int col = grid[ni][nj];\n                if (col == 0) continue;\n                zeroCnt[col]++; // neighbour gains zero adjacency\n                if (col != c) {\n                    int a = min(c, col);\n                    int b = max(c, col);\n                    adjCnt[a][b]--;\n                }\n            }\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                zeroCnt[c]--;\n            }\n            tot[c]--;\n            grid[i][j] = 0;\n            // push neighbours as candidates\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                if (grid[ni][nj] != 0) {\n                    que.push_back({ni, nj});\n                }\n            }\n        }\n    }\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << grid[i][j];\n            if (j < n-1) cout << ' ';\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint queries_left;\nint N, D, Q;\n\n// Perform a comparison and read the result, decrement queries_left\nvoid query(const vector<int>& L, const vector<int>& R, string& res) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    cin >> res;\n    --queries_left;\n}\n\n// Sort comparator: returns true if a is lighter than b (a < b)\nbool lighter(int a, int b) {\n    vector<int> L = {a}, R = {b};\n    string res;\n    query(L, R, res);\n    if (res == \"<\") return true;\n    if (res == \">\") return false;\n    return false; // equal -> not less\n}\n\n// Greedy split of a set into two balanced subsets using the balance\n// Returns pair (left, right)\npair<vector<int>, vector<int>> split_group(const vector<int>& group, const vector<int>& order, const vector<int>& rank) {\n    vector<int> left, right;\n    // Get items in descending weight order\n    vector<int> sorted_group = group;\n    // If we have a rank array (sorted), use it to sort descending\n    if (!rank.empty()) {\n        sort(sorted_group.begin(), sorted_group.end(), [&](int a, int b) {\n            return rank[a] > rank[b];\n        });\n    }\n    // Process items in that order\n    for (int idx = 0; idx < (int)sorted_group.size(); ++idx) {\n        int item = sorted_group[idx];\n        if (left.empty() && right.empty()) {\n            left.push_back(item);\n        } else if (right.empty()) {\n            right.push_back(item);\n        } else {\n            // Both sides non-empty, compare\n            vector<int> left_candidate = left;\n            left_candidate.push_back(item);\n            string res;\n            query(left_candidate, right, res);\n            if (res == \"<\" || res == \"=\") {\n                left.push_back(item);\n            } else {\n                right.push_back(item);\n            }\n        }\n    }\n    return {left, right};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    queries_left = Q;\n\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n\n    // Decide whether we can afford full sorting\n    const int SORT_BUDGET = N * 6; // approximate max needed\n    bool do_sort = (Q >= SORT_BUDGET);\n\n    vector<int> order(N);\n    vector<int> rank(N, -1); // rank[item] = position in sorted order (0 = lightest)\n\n    if (do_sort) {\n        sort(items.begin(), items.end(), lighter);\n        order = items;\n        for (int i = 0; i < N; ++i) rank[order[i]] = i;\n    } else {\n        order = items; // keep original order (no information)\n    }\n\n    // Start with one group containing all items\n    vector<vector<int>> groups;\n    groups.push_back(items);\n\n    // Split groups as long as we have budget and need more groups\n    while ((int)groups.size() < D && queries_left > 0) {\n        // Find the largest group (by number of items)\n        auto it = max_element(groups.begin(), groups.end(),\n                              [](const vector<int>& a, const vector<int>& b) {\n                                  return a.size() < b.size();\n                              });\n        int sz = it->size();\n        if (sz < 2) break; // cannot split further\n\n        int needed = sz - 2; // for greedy split (first two items are free)\n        if (needed > queries_left) break; // not enough queries\n\n        // Perform the split\n        auto [left, right] = split_group(*it, order, rank);\n\n        // Replace the large group with the two new groups\n        int idx = distance(groups.begin(), it);\n        groups.erase(groups.begin() + idx);\n        groups.push_back(move(left));\n        groups.push_back(move(right));\n    }\n\n    // If we still have fewer than D groups, split arbitrary without queries\n    while ((int)groups.size() < D) {\n        auto it = max_element(groups.begin(), groups.end(),\n                              [](const vector<int>& a, const vector<int>& b) {\n                                  return a.size() < b.size();\n                              });\n        int sz = it->size();\n        if (sz < 2) break; // cannot split\n\n        int half = sz / 2;\n        vector<int> left(it->begin(), it->begin() + half);\n        vector<int> right(it->begin() + half, it->end());\n\n        int idx = distance(groups.begin(), it);\n        groups.erase(groups.begin() + idx);\n        groups.push_back(move(left));\n        groups.push_back(move(right));\n    }\n\n    // Ensure exactly D groups (if we still have less, duplicate last groups? but unlikely)\n    // Assign each item to its group\n    vector<int> assign(N);\n    for (int g = 0; g < (int)groups.size(); ++g) {\n        for (int item : groups[g]) assign[item] = g;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        cout << assign[i] << (i == N - 1 ? '\\n' : ' ');\n    }\n\n    // Waste any remaining queries (output dummy comparisons)\n    while (queries_left > 0) {\n        cout << \"1 1 0 1\" << endl;\n        string res;\n        cin >> res;\n        --queries_left;\n    }\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint stack_score(const vector<int>& st) {\n    int sz = st.size();\n    if (sz == 0) return 0;\n    int pref = 1;\n    for (int i = 1; i < sz; ++i) {\n        if (st[i-1] > st[i]) ++pref;\n        else break;\n    }\n    return sz - pref;\n}\n\nint total_score(const vector<vector<int>>& stacks) {\n    int tot = 0;\n    for (const auto& st : stacks) tot += stack_score(st);\n    return tot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int per_stack = n / m;\n    vector<vector<int>> stacks(m);\n    vector<pair<int,int>> pos(n+1); // (stack_index, index_in_stack)\n\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < per_stack; ++j) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            pos[box] = {i, j};\n        }\n    }\n\n    vector<pair<int,int>> operations;\n    int cur_score = total_score(stacks);\n\n    for (int target = 1; target <= n; ++target) {\n        while (true) {\n            int s = pos[target].first;\n            int idx = pos[target].second;\n            auto& src = stacks[s];\n            int top_idx = (int)src.size() - 1;\n            if (idx == top_idx) { // target is on top\n                operations.emplace_back(target, 0);\n                src.pop_back();\n                cur_score = total_score(stacks); // update after removal\n                break;\n            }\n\n            // scores for source and destinations before the move\n            int old_src_score = stack_score(src);\n            vector<int> old_dst_score(m);\n            for (int d = 0; d < m; ++d) if (d != s) old_dst_score[d] = stack_score(stacks[d]);\n\n            vector<tuple<int,int,int,int>> candidates; // (score, block_size, v_idx, dest)\n\n            // consider all possible v (starting point of the block to move)\n            for (int v_idx = idx+1; v_idx <= top_idx; ++v_idx) {\n                int block_size = top_idx - v_idx + 1;\n\n                // source after truncation\n                vector<int> src_new = src;\n                src_new.resize(v_idx);\n                int new_src_score = stack_score(src_new);\n\n                // the block to move\n                vector<int> block(src.begin() + v_idx, src.end());\n\n                // try each destination\n                for (int d = 0; d < m; ++d) {\n                    if (d == s) continue;\n                    // destination after appending the block\n                    vector<int> dst_new = stacks[d];\n                    dst_new.insert(dst_new.end(), block.begin(), block.end());\n                    int new_dst_score = stack_score(dst_new);\n\n                    int new_total = cur_score - old_src_score - old_dst_score[d] + new_src_score + new_dst_score;\n                    candidates.emplace_back(new_total, block_size, v_idx, d);\n                }\n            }\n\n            // choose the best candidate (lower total score, then smaller block size)\n            auto best = *min_element(candidates.begin(), candidates.end(),\n                [](const auto& a, const auto& b) {\n                    if (get<0>(a) != get<0>(b)) return get<0>(a) < get<0>(b);\n                    return get<1>(a) < get<1>(b);\n                });\n\n            int v_idx = get<2>(best);\n            int d = get<3>(best);\n            int v = src[v_idx];\n\n            operations.emplace_back(v, d+1); // output stack number as 1-indexed\n\n            // execute the move on actual stacks\n            auto& dst = stacks[d];\n            int block_start = v_idx;\n            int block_end = src.size() - 1;\n            for (int j = block_start; j <= block_end; ++j) {\n                int box = src[j];\n                dst.push_back(box);\n                pos[box] = {d, (int)dst.size() - 1};\n            }\n            src.resize(block_start);\n\n            // update global score\n            cur_score = get<0>(best);\n        }\n    }\n\n    // output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <cmath>\n#include <queue>\n#include <string>\nusing namespace std;\n\nint N;\nvector<vector<int>> graph; // adjacency list (cell indices)\nvector<double> sqrt_d; // sqrt of d for each cell\n\n// for BFS tree\nvector<int> parent;\nvector<vector<int>> children;\nvector<char> dir_to_parent; // direction to go from parent to this cell (only meaningful for non-root)\nvector<char> dir_to_child; // for each child, we can store direction in children list\n\n// convert (i,j) to index\nint idx(int i, int j) { return i * N + j; }\nint ix(int id) { return id / N; }\nint jy(int id) { return id % N; }\n\n// build graph and BFS tree\nvoid build_tree() {\n    graph.assign(N * N, {});\n    // read walls (already read earlier, we need to store them)\n    // Actually we need h and v arrays. We'll read them in main.\n    // Assume global h and v are available.\n}\n\n// Move characters\nchar dir_char(int di, int dj) {\n    if (di == -1 && dj == 0) return 'U';\n    if (di == 1 && dj == 0) return 'D';\n    if (di == 0 && dj == -1) return 'L';\n    if (di == 0 && dj == 1) return 'R';\n    return '?';\n}\nchar opposite(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return '?';\n}\n\n// post-order compute f values for a given K\nvoid compute_f(double K, vector<int>& f_out, vector<int>& actual_n, int& total_moves) {\n    int M = N * N;\n    vector<int> f(M, 0);\n    vector<int> n_actual(M, 0);\n    // we need post-order traversal. We'll use recursion.\n    function<void(int)> dfs = [&](int v) {\n        int sum_child_f = 0;\n        for (int c : children[v]) {\n            dfs(c);\n            sum_child_f += f[c];\n        }\n        if (v == 0) { // root (0,0)\n            // root's visits = 1 (initial) + sum_child_f\n            n_actual[v] = 1 + sum_child_f;\n            // f_root is not used\n        } else {\n            int target = max(1, (int)round(K * sqrt_d[v]));\n            int desired_f = target - sum_child_f;\n            if (desired_f < 0) {\n                f[v] = 0;\n                n_actual[v] = sum_child_f;\n            } else {\n                f[v] = desired_f;\n                n_actual[v] = target;\n            }\n        }\n    };\n    dfs(0);\n    // total moves = 2 * sum_{v != root} f[v]\n    int sum_f = 0;\n    for (int v = 1; v < M; ++v) sum_f += f[v];\n    total_moves = 2 * sum_f;\n    f_out = f;\n    actual_n = n_actual;\n}\n\n// build route recursively using highest-remaining-first schedule\nstring build_route(int v, const vector<int>& f, const vector<vector<int>>& children) {\n    // children list for this node (from global children)\n    // we need remaining counts for each child\n    vector<int> rem;\n    vector<char> dir;\n    for (int c : children[v]) {\n        int cnt = f[c];\n        if (cnt <= 0) continue;\n        rem.push_back(cnt);\n        // direction from v to c\n        int di = ix(c) - ix(v);\n        int dj = jy(c) - jy(v);\n        dir.push_back(dir_char(di, dj));\n    }\n    // priority queue: (-remaining, index)\n    priority_queue<pair<int,int>> pq;\n    for (int i = 0; i < (int)rem.size(); ++i) {\n        pq.push({-rem[i], i}); // use negative to get max remaining\n    }\n    string moves;\n    while (!pq.empty()) {\n        auto [neg_rem, idx_child] = pq.top(); pq.pop();\n        int& remaining = rem[idx_child];\n        // move to child\n        moves.push_back(dir[idx_child]);\n        // recursively build child's tour\n        string child_tour = build_route(children[v][idx_child], f, children);\n        moves += child_tour;\n        // move back\n        moves.push_back(opposite(dir[idx_child]));\n        // decrement\n        remaining--;\n        if (remaining > 0) {\n            pq.push({-remaining, idx_child});\n        }\n    }\n    return moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    // read N\n    cin >> N;\n    // read walls\n    vector<string> h(N-1), v(N);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    // read dirt values\n    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) \n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    // build graph\n    graph.assign(N*N, {});\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = idx(i,j);\n            // down\n            if (i < N-1 && h[i][j] == '0') {\n                int id2 = idx(i+1, j);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n            // right\n            if (j < N-1 && v[i][j] == '0') {\n                int id2 = idx(i, j+1);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n        }\n    }\n\n    // BFS tree from (0,0)\n    int total_cells = N * N;\n    parent.assign(total_cells, -1);\n    children.assign(total_cells, {});\n    dir_to_parent.assign(total_cells, ' ');\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0; // mark root\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) {\n            if (parent[u] == -1) {\n                parent[u] = v;\n                children[v].push_back(u);\n                int di = ix(u) - ix(v);\n                int dj = jy(u) - jy(v);\n                dir_to_parent[u] = dir_char(di, dj);\n                q.push(u);\n            }\n        }\n    }\n    // compute sqrt_d\n    sqrt_d.assign(total_cells, 0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sqrt_d[idx(i,j)] = sqrt(d[i][j]);\n\n    // binary search for K to get moves near 100000\n    double low = 0, high = 100.0; // initial high\n    vector<int> best_f;\n    int best_moves = 0;\n    for (int iter = 0; iter < 60; ++iter) {\n        double mid = (low + high) / 2;\n        vector<int> f, actual_n;\n        int moves;\n        compute_f(mid, f, actual_n, moves);\n        if (moves <= 100000) {\n            best_f = f;\n            best_moves = moves;\n            low = mid;\n        } else {\n            high = mid;\n        }\n    }\n    // compute final f using low (ensures moves <= 100000)\n    {\n        vector<int> f, actual_n;\n        int moves;\n        compute_f(low, f, actual_n, moves);\n        best_f = f;\n        best_moves = moves;\n    }\n\n    // build route\n    string route = build_route(0, best_f, children);\n    // ensure length matches best_moves\n    // (should match if build_route correct)\n    // output route\n    cout << route << endl;\n\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\nusing LL = long long;\nconst LL INF = 1e18;\nconst int N = 15;\nconst int SZ = N * N; // 225\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int i = 0; i < M; ++i) cin >> patterns[i];\n\n    // positions for each letter (0..25)\n    vector<vector<int>> pos(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            pos[grid[i][j] - 'A'].push_back(idx);\n        }\n    }\n\n    // Manhattan distance matrix\n    array<array<int, SZ>, SZ> dist;\n    for (int i = 0; i < SZ; ++i) {\n        int x1 = i / N, y1 = i % N;\n        for (int j = 0; j < SZ; ++j) {\n            int x2 = j / N, y2 = j % N;\n            dist[i][j] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    int start_idx = si * N + sj;\n    vector<int> best_moves;\n    LL best_total = INF;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    // try several random seeds, deterministic first (trial 0)\n    for (int trial = 0; trial < 6; ++trial) {\n        // time check\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.8) break;\n\n        int cur = start_idx;\n        string S;\n        vector<bool> covered(M, false);\n        int uncovered = M;\n        vector<int> moves;\n\n        auto seed = chrono::steady_clock::now().time_since_epoch().count() + trial * 1000;\n        mt19937 local_rng(seed);\n\n        while (uncovered > 0) {\n            // collect costs for all uncovered patterns\n            vector<pair<LL, int>> candidates;\n            for (int i = 0; i < M; ++i) {\n                if (covered[i]) continue;\n                const string& t = patterns[i];\n                // maximum overlap with suffix of S\n                int ol = 0;\n                for (int l = min(5, (int)S.size()); l >= 1; --l) {\n                    if (S.compare(S.size() - l, l, t, 0, l) == 0) {\n                        ol = l;\n                        break;\n                    }\n                }\n                if (ol == 5) {\n                    covered[i] = true;\n                    uncovered--;\n                    continue;\n                }\n                string rem = t.substr(ol);\n                int len = rem.size();\n                // DP for minimum cost (no backtrack)\n                vector<LL> prev(SZ, INF);\n                for (int p : pos[rem[0] - 'A']) {\n                    prev[p] = dist[cur][p] + 1;\n                }\n                for (int ch = 1; ch < len; ++ch) {\n                    vector<LL> cur_cost(SZ, INF);\n                    int c_idx = rem[ch] - 'A';\n                    int prev_c_idx = rem[ch-1] - 'A';\n                    for (int p : pos[c_idx]) {\n                        LL best = INF;\n                        for (int q : pos[prev_c_idx]) {\n                            if (prev[q] >= INF) continue;\n                            LL cand = prev[q] + dist[q][p] + 1;\n                            if (cand < best) best = cand;\n                        }\n                        cur_cost[p] = best;\n                    }\n                    prev = cur_cost;\n                }\n                LL total = INF;\n                for (int p : pos[rem.back() - 'A']) {\n                    total = min(total, prev[p]);\n                }\n                candidates.emplace_back(total, i);\n            }\n            if (candidates.empty()) break;\n\n            int chosen = -1;\n            // deterministic (trial 0) or random\n            if (trial == 0) {\n                auto it = min_element(candidates.begin(), candidates.end());\n                chosen = it->second;\n            } else {\n                LL minc = INF;\n                for (auto& p : candidates) minc = min(minc, p.first);\n                vector<int> good;\n                for (auto& p : candidates) {\n                    if (p.first <= minc * 1.2) good.push_back(p.second);\n                }\n                if (good.empty()) good.push_back(candidates[0].second);\n                uniform_int_distribution<int> uid(0, (int)good.size() - 1);\n                chosen = good[uid(local_rng)];\n            }\n\n            // get path for chosen pattern\n            const string& t = patterns[chosen];\n            int ol = 0;\n            for (int l = min(5, (int)S.size()); l >= 1; --l) {\n                if (S.compare(S.size() - l, l, t, 0, l) == 0) {\n                    ol = l;\n                    break;\n                }\n            }\n            string rem = t.substr(ol);\n            int len = rem.size();\n            vector<vector<LL>> dp(len, vector<LL>(SZ, INF));\n            vector<vector<int>> prev_step(len, vector<int>(SZ, -1));\n            for (int p : pos[rem[0] - 'A']) {\n                dp[0][p] = dist[cur][p] + 1;\n            }\n            for (int ch = 1; ch < len; ++ch) {\n                int c_idx = rem[ch] - 'A';\n                int p_c_idx = rem[ch-1] - 'A';\n                for (int p : pos[c_idx]) {\n                    LL best = INF;\n                    int best_prev = -1;\n                    for (int q : pos[p_c_idx]) {\n                        if (dp[ch-1][q] >= INF) continue;\n                        LL cand = dp[ch-1][q] + dist[q][p] + 1;\n                        if (cand < best) {\n                            best = cand;\n                            best_prev = q;\n                        }\n                    }\n                    dp[ch][p] = best;\n                    prev_step[ch][p] = best_prev;\n                }\n            }\n            LL bestcost = INF;\n            int final_pos = -1;\n            for (int p : pos[rem.back() - 'A']) {\n                if (dp[len-1][p] < bestcost) {\n                    bestcost = dp[len-1][p];\n                    final_pos = p;\n                }\n            }\n            vector<int> path(len);\n            int p = final_pos;\n            for (int ch = len-1; ch >= 0; --ch) {\n                path[ch] = p;\n                p = prev_step[ch][p];\n            }\n            for (int x : path) moves.push_back(x);\n            cur = final_pos;\n            S += rem;\n            covered[chosen] = true;\n            uncovered--;\n\n            // check other patterns that may have become contained\n            if ((int)S.size() >= 5) {\n                for (int i = 0; i < M; ++i) {\n                    if (covered[i]) continue;\n                    if (S.find(patterns[i]) != string::npos) {\n                        covered[i] = true;\n                        uncovered--;\n                    }\n                }\n            }\n        }\n\n        // compute total cost of this solution\n        LL total = 0;\n        int prev = start_idx;\n        for (int p : moves) {\n            total += dist[prev][p] + 1;\n            prev = p;\n        }\n        if (total < best_total) {\n            best_total = total;\n            best_moves = moves;\n        }\n    }\n\n    // output best solution\n    for (int p : best_moves) {\n        cout << p / N << ' ' << p % N << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int MAX_CELLS = MAX_N * MAX_N; // 400\n\nstruct Placement {\n    int di, dj;\n    bitset<MAX_CELLS> cells_bitset;\n    vector<int> cells_list; // indices of covered cells\n    vector<int> row_counts;\n    vector<int> col_counts;\n};\n\nstruct Field {\n    vector<pair<int,int>> shape; // relative coordinates\n    vector<Placement> placements;\n};\n\nint N, M;\ndouble eps;\nvector<Field> fields;\nvector<int> remaining_placements_per_field[20]; // for each field, indices of still possible placements\nint drilled_v[MAX_CELLS]; // -1 unknown, otherwise exact value\nint ops = 0; // number of operations used\n\nvoid flush_output() {\n    cout.flush();\n}\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        vector<pair<int,int>> shape(d);\n        for (int l = 0; l < d; ++l) {\n            cin >> shape[l].first >> shape[l].second;\n        }\n        fields[k].shape = shape;\n    }\n}\n\nvoid generate_placements() {\n    for (int k = 0; k < M; ++k) {\n        const auto& shape = fields[k].shape;\n        int max_i = 0, max_j = 0;\n        for (const auto& p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1;\n        int w = max_j + 1;\n        for (int di = 0; di <= N - h; ++di) {\n            for (int dj = 0; dj <= N - w; ++dj) {\n                Placement pl;\n                pl.di = di;\n                pl.dj = dj;\n                pl.row_counts.assign(N, 0);\n                pl.col_counts.assign(N, 0);\n                for (const auto& p : shape) {\n                    int i = di + p.first;\n                    int j = dj + p.second;\n                    int cell = i * N + j;\n                    pl.cells_bitset.set(cell);\n                    pl.cells_list.push_back(cell);\n                    pl.row_counts[i]++;\n                    pl.col_counts[j]++;\n                }\n                fields[k].placements.push_back(move(pl));\n            }\n        }\n    }\n}\n\nvoid init() {\n    memset(drilled_v, -1, sizeof(drilled_v));\n    for (int f = 0; f < M; ++f) {\n        int sz = fields[f].placements.size();\n        remaining_placements_per_field[f].resize(sz);\n        iota(remaining_placements_per_field[f].begin(), remaining_placements_per_field[f].end(), 0);\n    }\n}\n\nvoid perform_divine_queries() {\n    // row queries\n    for (int i = 0; i < N; ++i) {\n        cout << \"q \" << N;\n        for (int j = 0; j < N; ++j) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        flush_output();\n        int resp;\n        cin >> resp;\n        ops++;\n        // we ignore the result (could be used for row sum constraints)\n    }\n    // column queries\n    for (int j = 0; j < N; ++j) {\n        cout << \"q \" << N;\n        for (int i = 0; i < N; ++i) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        flush_output();\n        int resp;\n        cin >> resp;\n        ops++;\n    }\n}\n\nint find_best_cell() {\n    int best_cell = -1, best_score = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int cell = i * N + j;\n            if (drilled_v[cell] != -1) continue;\n            int score = 0;\n            for (int f = 0; f < M; ++f) {\n                for (int idx : remaining_placements_per_field[f]) {\n                    if (fields[f].placements[idx].cells_bitset.test(cell)) {\n                        score++;\n                    }\n                }\n            }\n            if (score > best_score) {\n                best_score = score;\n                best_cell = cell;\n            }\n        }\n    }\n    return best_cell;\n}\n\nvoid drill_cell(int cell) {\n    int i = cell / N, j = cell % N;\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    drilled_v[cell] = resp;\n    ops++;\n    if (resp == 0) {\n        // eliminate all placements that cover this cell\n        for (int f = 0; f < M; ++f) {\n            vector<int> new_remaining;\n            for (int idx : remaining_placements_per_field[f]) {\n                if (!fields[f].placements[idx].cells_bitset.test(cell)) {\n                    new_remaining.push_back(idx);\n                }\n            }\n            remaining_placements_per_field[f] = move(new_remaining);\n        }\n    }\n}\n\n// ------------------------------------------------------------\n// Backtracking to find assignments consistent with drilled cells\n// ------------------------------------------------------------\nint found_solutions;\nvector<int> current_assignment; // placement index for each field, -1 if unassigned\nvector<int> best_assignment;\nint current_sum[MAX_CELLS]; // current total v for each cell (from assigned fields)\n\nbool can_place(int f, int pidx) {\n    Placement& pl = fields[f].placements[pidx];\n    for (int cell : pl.cells_list) {\n        if (drilled_v[cell] != -1 && current_sum[cell] + 1 > drilled_v[cell]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid dfs(int step, const vector<int>& order) {\n    if (found_solutions >= 2) return;\n    if (step == (int)order.size()) {\n        // check all drilled cells exactly\n        for (int cell = 0; cell < N*N; ++cell) {\n            if (drilled_v[cell] != -1 && current_sum[cell] != drilled_v[cell]) {\n                return;\n            }\n        }\n        found_solutions++;\n        if (found_solutions == 1) {\n            best_assignment = current_assignment;\n        }\n        return;\n    }\n    int f = order[step];\n    for (int pidx : remaining_placements_per_field[f]) {\n        if (!can_place(f, pidx)) continue;\n        // place this field\n        current_assignment[f] = pidx;\n        Placement& pl = fields[f].placements[pidx];\n        for (int cell : pl.cells_list) {\n            current_sum[cell]++;\n        }\n        dfs(step+1, order);\n        // undo\n        for (int cell : pl.cells_list) {\n            current_sum[cell]--;\n        }\n        current_assignment[f] = -1;\n        if (found_solutions >= 2) return;\n    }\n}\n\n// returns true if exactly one consistent assignment found\nbool find_unique_solution() {\n    found_solutions = 0;\n    // order fields by number of remaining placements (ascending) to reduce branching\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return remaining_placements_per_field[a].size() < remaining_placements_per_field[b].size();\n    });\n    memset(current_sum, 0, sizeof(current_sum));\n    current_assignment.assign(M, -1);\n    best_assignment.assign(M, -1);\n    dfs(0, order);\n    return (found_solutions == 1);\n}\n\nbool estimate_combinations_small() {\n    // return true if product of remaining placements <= 100000\n    long long prod = 1;\n    for (int f = 0; f < M; ++f) {\n        int sz = remaining_placements_per_field[f].size();\n        if (sz == 0) return false;\n        prod *= sz;\n        if (prod > 100000) return false;\n    }\n    return true;\n}\n\nbool guess() {\n    // compute positive cells from best_assignment\n    vector<int> pos_cells;\n    for (int f = 0; f < M; ++f) {\n        int pidx = best_assignment[f];\n        if (pidx == -1) continue; // should not happen\n        Placement& pl = fields[f].placements[pidx];\n        for (int cell : pl.cells_list) {\n            pos_cells.push_back(cell);\n        }\n    }\n    // remove duplicates\n    sort(pos_cells.begin(), pos_cells.end());\n    pos_cells.erase(unique(pos_cells.begin(), pos_cells.end()), pos_cells.end());\n    // output guess\n    cout << \"a \" << pos_cells.size();\n    for (int cell : pos_cells) {\n        int i = cell / N, j = cell % N;\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    ops++;\n    return (resp == 1);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n    generate_placements();\n    init();\n    perform_divine_queries(); // cheap queries, provide extra info (optional)\n\n    int max_ops = 2 * N * N;\n    bool guessed = false;\n    while (ops < max_ops && !guessed) {\n        // try to find unique solution if number of combinations is not too large\n        if (ops >= 10 && estimate_combinations_small()) {\n            if (find_unique_solution()) {\n                if (guess()) {\n                    guessed = true;\n                    break;\n                }\n                // if guess failed, continue drilling (the previous solution was wrong)\n            }\n        }\n        // choose a cell to drill\n        int cell = find_best_cell();\n        if (cell == -1) break; // all cells already drilled\n        drill_cell(cell);\n    }\n\n    // fallback: drill all remaining cells and answer from exact data\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int cell = i * N + j;\n            if (drilled_v[cell] == -1) {\n                drill_cell(cell);\n            }\n        }\n    }\n    // now we have exact v for every cell\n    vector<pair<int,int>> pos;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (drilled_v[i*N+j] > 0) {\n                pos.emplace_back(i, j);\n            }\n        }\n    }\n    cout << \"a \" << pos.size();\n    for (auto [i,j] : pos) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <cassert>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int width() const { return i1 - i0; }\n    int height() const { return j1 - j0; }\n    int area() const { return width() * height(); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // For each day, sort a and store ranked values.\n    vector<vector<int>> a_sorted(D, vector<int>(N));\n    vector<vector<int>> rank_of(D, vector<int>(N)); // original index -> rank after sorting\n    for (int d = 0; d < D; ++d) {\n        vector<pair<int, int>> tmp(N);\n        for (int k = 0; k < N; ++k) tmp[k] = {a[d][k], k};\n        sort(tmp.begin(), tmp.end());\n        for (int k = 0; k < N; ++k) {\n            a_sorted[d][k] = tmp[k].first;\n            rank_of[d][tmp[k].second] = k;\n        }\n    }\n\n    // Collect values for each rank (sorted per day) across days.\n    vector<vector<int>> val_per_rank(N);\n    for (int k = 0; k < N; ++k) {\n        val_per_rank[k].reserve(D);\n        for (int d = 0; d < D; ++d) {\n            val_per_rank[k].push_back(a_sorted[d][k]);\n        }\n        sort(val_per_rank[k].begin(), val_per_rank[k].end());\n    }\n\n    // Greedy allocation of areas to ranks (sorted b).\n    const long long MAX_AREA = W * W;\n    vector<long long> b(N, 0);\n    long long used_area = 0;\n\n    // Each entry: (gain, rank, next_break)\n    priority_queue<pair<long long, int>> pq; // gain = 100 * (D - idx), we store as positive.\n    vector<int> idx(N, 0);\n    vector<long long> next_break(N, 0);\n\n    auto push_rank = [&](int k) {\n        if (idx[k] < D) {\n            long long gain = 100LL * (D - idx[k]);\n            int next_val = val_per_rank[k][idx[k]];\n            pq.push({gain, k});\n            next_break[k] = next_val;\n        }\n    };\n    for (int k = 0; k < N; ++k) push_rank(k);\n\n    while (used_area < MAX_AREA && !pq.empty()) {\n        auto [gain, k] = pq.top(); pq.pop();\n        if (gain <= 0) break;\n        // current b[k] is before next_break\n        long long diff = next_break[k] - b[k];\n        if (diff <= 0) {\n            // already reached this breakpoint, update and push again\n            idx[k]++;\n            push_rank(k);\n            continue;\n        }\n        long long delta = min(diff, MAX_AREA - used_area);\n        b[k] += delta;\n        used_area += delta;\n        if (delta == diff) {\n            // reached breakpoint\n            idx[k]++;\n            push_rank(k);\n        } else {\n            // area exhausted\n            break;\n        }\n    }\n\n    // b now may not be sorted. We must work with sorted b for packing.\n    vector<long long> b_sorted = b;\n    sort(b_sorted.begin(), b_sorted.end());\n\n    // Pack rectangles of areas b_sorted (ascending). We will place largest first.\n    vector<long long> b_desc = b_sorted;\n    reverse(b_desc.begin(), b_desc.end());\n\n    vector<Rect> placed; // in order of b_desc\n    vector<Rect> free_list;\n    free_list.push_back({0, 0, W, W});\n\n    auto place_rect = [&](long long area, int free_idx, int w, int h) {\n        Rect r = free_list[free_idx];\n        // place at top-left corner of free rectangle\n        Rect new_rect = {r.i0, r.j0, r.i0 + w, r.j0 + h};\n        placed.push_back(new_rect);\n        // remove this free rectangle\n        free_list.erase(free_list.begin() + free_idx);\n        // add up to two new free rectangles\n        // right part (same height)\n        if (r.i0 + w < r.i1) {\n            free_list.push_back({r.i0 + w, r.j0, r.i1, r.j0 + h});\n        }\n        // bottom part (full width)\n        if (r.j0 + h < r.j1) {\n            free_list.push_back({r.i0, r.j0 + h, r.i1, r.j1});\n        }\n    };\n\n    for (long long area : b_desc) {\n        bool ok = false;\n        // iterate free rectangles in order (any order)\n        for (int fi = 0; fi < (int)free_list.size(); ++fi) {\n            Rect r = free_list[fi];\n            int w_avail = r.width();\n            int h_avail = r.height();\n            // try to factor area into w*h with integer coordinates\n            bool found = false;\n            int best_w = -1, best_h = -1;\n            // iterate divisors up to sqrt\n            for (int w = 1; w * w <= area; ++w) {\n                if (area % w == 0) {\n                    int h = area / w;\n                    // try w <= w_avail, h <= h_avail\n                    if (w <= w_avail && h <= h_avail) {\n                        best_w = w; best_h = h; found = true; break;\n                    }\n                    // try swapped\n                    int w2 = h, h2 = w;\n                    if (w2 <= w_avail && h2 <= h_avail) {\n                        best_w = w2; best_h = h2; found = true; break;\n                    }\n                }\n            }\n            if (found) {\n                place_rect(area, fi, best_w, best_h);\n                ok = true;\n                break;\n            }\n        }\n        if (!ok) {\n            // fallback: reduce area by 1 and try again (should rarely happen)\n            long long reduced = area - 1;\n            while (reduced > 0) {\n                for (int fi = 0; fi < (int)free_list.size(); ++fi) {\n                    Rect r = free_list[fi];\n                    int w_avail = r.width();\n                    int h_avail = r.height();\n                    for (int w = 1; w * w <= reduced; ++w) {\n                        if (reduced % w == 0) {\n                            int h = reduced / w;\n                            if (w <= w_avail && h <= h_avail) {\n                                place_rect(reduced, fi, w, h);\n                                ok = true;\n                                break;\n                            }\n                            int w2 = h, h2 = w;\n                            if (w2 <= w_avail && h2 <= h_avail) {\n                                place_rect(reduced, fi, w2, h2);\n                                ok = true;\n                                break;\n                            }\n                        }\n                    }\n                    if (ok) break;\n                }\n                if (ok) break;\n                reduced--;\n            }\n            if (!ok) {\n                // Very rare: fallback to 1x1 rectangle (area 1)\n                place_rect(1, 0, 1, 1);\n            }\n        }\n    }\n\n    // placed rectangles are in order of b_desc. Map to rank (ascending area).\n    // placed[i] corresponds to b_desc[i] => rank = N-1-i.\n    vector<Rect> rect_by_rank(N);\n    for (int i = 0; i < N; ++i) {\n        rect_by_rank[N - 1 - i] = placed[i];\n    }\n\n    // Output for each day\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            int r = rank_of[d][k]; // rank of this reservation's desired area\n            const Rect& rr = rect_by_rank[r];\n            cout << rr.i0 << ' ' << rr.j0 << ' ' << rr.i1 << ' ' << rr.j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int K = 81;\nconst int M = 20;\n\nstruct Operation {\n    int m, p, q;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n    // n=9, m=20, k=81 always\n    vector<vector<ll>> board(N, vector<ll>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> board[i][j];\n        }\n    }\n    vector<vector<vector<ll>>> stamps(M, vector<vector<ll>>(3, vector<ll>(3)));\n    for (int id = 0; id < M; ++id) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[id][i][j];\n            }\n        }\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // best solution across trials\n    pair<ll, vector<Operation>> best = {-1, {}};\n\n    const int TRIALS = 6;              // 6 random restarts, enough within 2 sec\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // current state of board during construction\n        vector<vector<ll>> cur = board;\n        ll score = 0;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                score += cur[i][j] % MOD;\n\n        vector<Operation> ops;\n        int used = 0;\n\n        // ---- greedy construction ----\n        while (used < K) {\n            ll best_gain = 0;\n            vector<pair<ll, Operation>> candidates;\n            for (int mid = 0; mid < M; ++mid) {\n                for (int p = 0; p + 2 < N; ++p) {\n                    for (int q = 0; q + 2 < N; ++q) {\n                        ll gain = 0;\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                ll cell = cur[p + i][q + j];\n                                ll old_rem = cell % MOD;\n                                ll new_rem = (cell + stamps[mid][i][j]) % MOD;\n                                gain += new_rem - old_rem;\n                            }\n                        }\n                        if (gain > best_gain) {\n                            best_gain = gain;\n                            candidates.clear();\n                            candidates.emplace_back(gain, Operation{mid, p, q});\n                        } else if (gain == best_gain && gain > 0) {\n                            candidates.emplace_back(gain, Operation{mid, p, q});\n                        }\n                    }\n                }\n            }\n            if (candidates.empty()) break;   // no improving move\n\n            // randomly pick among best\n            uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);\n            auto op = candidates[dist(rng)].second;\n            for (int i = 0; i < 3; ++i)\n                for (int j = 0; j < 3; ++j)\n                    cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n            score += best_gain;\n            ops.push_back(op);\n            ++used;\n        }\n\n        // ---- local search (remove + add) ----\n        auto recompute_score = [&]() -> ll {\n            ll s = 0;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    s += cur[i][j] % MOD;\n            return s;\n        };\n\n        bool improved = true;\n        for (int phase = 0; phase < 15 && improved; ++phase) {\n            improved = false;\n\n            // removal part\n            vector<int> indices(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                auto op = ops[idx];\n                // subtract stamp\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[op.p + i][op.q + j] -= stamps[op.m][i][j];\n                ll new_score = recompute_score();\n                if (new_score > score) {\n                    score = new_score;\n                    ops.erase(ops.begin() + idx);\n                    improved = true;\n                    break; // restart scanning\n                } else {\n                    // restore\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n                }\n            }\n\n            // addition part (fill remaining quota)\n            if (improved) {\n                int remaining = K - (int)ops.size();\n                while (remaining > 0) {\n                    ll best_gain = 0;\n                    vector<pair<ll, Operation>> candidates;\n                    for (int mid = 0; mid < M; ++mid) {\n                        for (int p = 0; p + 2 < N; ++p) {\n                            for (int q = 0; q + 2 < N; ++q) {\n                                ll gain = 0;\n                                for (int i = 0; i < 3; ++i) {\n                                    for (int j = 0; j < 3; ++j) {\n                                        ll cell = cur[p + i][q + j];\n                                        ll old_rem = cell % MOD;\n                                        ll new_rem = (cell + stamps[mid][i][j]) % MOD;\n                                        gain += new_rem - old_rem;\n                                    }\n                                }\n                                if (gain > best_gain) {\n                                    best_gain = gain;\n                                    candidates.clear();\n                                    candidates.emplace_back(gain, Operation{mid, p, q});\n                                } else if (gain == best_gain && gain > 0) {\n                                    candidates.emplace_back(gain, Operation{mid, p, q});\n                                }\n                            }\n                        }\n                    }\n                    if (candidates.empty()) break;\n                    uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);\n                    auto op = candidates[dist(rng)].second;\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n                    score += best_gain;\n                    ops.push_back(op);\n                    --remaining;\n                }\n            }\n        }\n\n        // update best\n        if (score > best.first) {\n            best = {score, ops};\n        }\n    }\n\n    // output best solution\n    const auto &final_ops = best.second;\n    cout << final_ops.size() << \"\\n\";\n    for (const auto &op : final_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nint A[N][N];\nint targetRow[25];   // targetRow[num] = num/5\nint arrivalRow[25];  // row in which the container appears\nint arrivalIdx[25];  // index in A[arrivalRow] (0..4)\n\n// State\nint craneR = 0, craneC = 0;          // large crane position\nbool holding = false;\nint heldContainer = -1;              // only meaningful if holding\nint storageTargetR = -1, storageTargetC = -1; // where to store if not dispatching\nint nextDispatch = 0;                // next container number to dispatch (0..24)\nbool dispatched[25] = {false};\n\n// Grid: -1 = empty, otherwise container number\nint grid[N][N];\n\n// Per row receiving gate state\nint gateCurrent[N];   // current container number at (i,0), -1 if empty\nint nextIdx[N];       // next index in A[i] to appear (0..4)\nbool gateEmpty[N];    // true if gate is empty (no container, no crane holding container there)\n\n// Queue of containers at receiving gates (only used for determining which gate to clear)\n// But we'll just use gateCurrent\n\n// Helper to place a container at a cell (updates grid and pos)\nvoid placeContainer(int num, int r, int c) {\n    grid[r][c] = num;\n}\n\n// Remove container from a cell (used when picking up)\nvoid removeContainer(int r, int c) {\n    grid[r][c] = -1;\n}\n\n// Find a free cell (col1..col3) for temporary storage, prefer near target dispatch cell\npair<int,int> findStorageCell(int targetR) {\n    int bestDist = 100;\n    pair<int,int> best = {-1,-1};\n    for (int r = 0; r < N; ++r) {\n        for (int c = 1; c <= 3; ++c) {\n            if (grid[r][c] == -1 && !(r == craneR && c == craneC)) {\n                int dist = abs(r - targetR) + abs(c - 4);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    best = {r, c};\n                }\n            }\n        }\n    }\n    return best;\n}\n\n// Perform one action for the large crane, return character\nchar getAction() {\n    if (holding) {\n        int targetGateR = targetRow[heldContainer];\n        // If we are already at the dispatch gate, release\n        if (craneR == targetGateR && craneC == 4) {\n            return 'Q';\n        }\n        // Otherwise, if we are holding the next container to dispatch, go to its gate\n        if (heldContainer == nextDispatch) {\n            // move towards (targetGateR, 4)\n            if (craneR < targetGateR) return 'D';\n            if (craneR > targetGateR) return 'U';\n            if (craneC < 4) return 'R';\n            if (craneC > 4) return 'L';\n        } else {\n            // holding a blocking container, go to its storage location\n            if (craneR < storageTargetR) return 'D';\n            if (craneR > storageTargetR) return 'U';\n            if (craneC < storageTargetC) return 'R';\n            if (craneC > storageTargetC) return 'L';\n        }\n        // Should not reach\n        return '.';\n    } else {\n        // Not holding\n        if (nextDispatch >= 25) return '.';\n        // If the next container is already in the grid\n        if (grid[craneR][craneC] == nextDispatch) {\n            return 'P';\n        }\n        // Find the position of nextDispatch if it is in grid\n        bool found = false;\n        int pr = -1, pc = -1;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (grid[r][c] == nextDispatch) {\n                    pr = r; pc = c;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n        if (found) {\n            // Move towards (pr, pc)\n            if (craneR < pr) return 'D';\n            if (craneR > pr) return 'U';\n            if (craneC < pc) return 'R';\n            if (craneC > pc) return 'L';\n        }\n        // Not in grid: try to clear the receiving gate for its arrival row\n        int ar = arrivalRow[nextDispatch];\n        if (gateCurrent[ar] != -1 && gateCurrent[ar] != nextDispatch) {\n            // There is a blocking container at (ar, 0)\n            if (craneR == ar && craneC == 0) {\n                return 'P';\n            } else {\n                // Move towards (ar, 0)\n                if (craneR < ar) return 'D';\n                if (craneR > ar) return 'U';\n                if (craneC < 0) return 'L'; // not needed\n                if (craneC > 0) return 'L';\n                return '.';\n            }\n        }\n        // Gate is empty or already has the needed container (should have been found above)\n        // Otherwise wait\n        return '.';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    cin >> N; // N is always 5, but read anyway\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Precompute targetRow, arrivalRow, arrivalIdx\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int num = A[i][j];\n            targetRow[num] = num / N;\n            arrivalRow[num] = i;\n            arrivalIdx[num] = j;\n        }\n    }\n\n    // Initialize grid: empty\n    memset(grid, -1, sizeof(grid));\n    // Large crane at (0,0) \u2013 occupies the cell but we allow container coexistence? \n    // We'll treat the cell as empty for container, but crane is there.\n    // For simplicity, we don't mark it occupied.\n\n    // Receiving gates initial\n    for (int i = 0; i < N; ++i) {\n        gateCurrent[i] = -1;\n        nextIdx[i] = 0;\n    }\n\n    // Output strings for each crane\n    vector<string> out(N);\n\n    // Turn 1: bomb small cranes, large crane does nothing\n    out[0] += '.';   // large crane\n    for (int i = 1; i < N; ++i) {\n        out[i] += 'B';\n    }\n    // After turn 1, small cranes are removed. No containers appear yet (gates are occupied by cranes, but cranes are bombed, so after bomb the cell becomes empty).\n    // However, the rule: containers appear only when there is no crane and no container. Since we bombed, the cell is empty. So at start of turn2, containers appear.\n\n    // Main loop\n    for (int turn = 2; turn <= 10000; ++turn) {\n        // Step 1: Place new containers at receiving gates\n        for (int i = 0; i < N; ++i) {\n            if (gateCurrent[i] == -1 && nextIdx[i] < N) {\n                int num = A[i][nextIdx[i]++];\n                gateCurrent[i] = num;\n                // Place container at (i,0)\n                placeContainer(num, i, 0);\n            }\n        }\n\n        // Step 2: Determine action for the large crane\n        char action = getAction();\n\n        // Execute action and update state\n        // We will modify the state after the action, but dispatch happens after all actions.\n        if (action == 'P') {\n            // Pick up container at current square\n            int num = grid[craneR][craneC];\n            if (num == -1) {\n                // This shouldn't happen if we plan correctly\n                action = '.';\n            } else {\n                holding = true;\n                heldContainer = num;\n                removeContainer(craneR, craneC);\n                // If we picked from a receiving gate, update gate state\n                if (craneC == 0) {\n                    // It came from a receiving gate\n                    int row = craneR;\n                    if (gateCurrent[row] == num) {\n                        gateCurrent[row] = -1; // gate empty\n                    }\n                }\n                // Decide where to store if it's not the next dispatch\n                if (num != nextDispatch) {\n                    // Find storage cell\n                    auto [sr, sc] = findStorageCell(targetRow[num]);\n                    storageTargetR = sr;\n                    storageTargetC = sc;\n                }\n            }\n        } else if (action == 'Q') {\n            // Release container at current square\n            if (holding) {\n                int num = heldContainer;\n                // Place container\n                grid[craneR][craneC] = num;\n                holding = false;\n                // If released at a dispatch gate, it will be dispatched in step 3 (handled below)\n                // Update pos if needed (we use grid)\n                // If this container is the next dispatch, update later\n            } else {\n                // Should not happen\n                action = '.';\n            }\n        } else if (action == 'U') {\n            if (craneR > 0) craneR--;\n        } else if (action == 'D') {\n            if (craneR < N-1) craneR++;\n        } else if (action == 'L') {\n            if (craneC > 0) craneC--;\n        } else if (action == 'R') {\n            if (craneC < N-1) craneC++;\n        }\n        // '.' does nothing\n\n        // Append action to output for large crane\n        out[0] += action;\n        // Append '.' for other cranes (they are bombed)\n        for (int i = 1; i < N; ++i) {\n            out[i] += '.';\n        }\n\n        // Step 3: Dispatch containers at right edge\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][4] != -1) {\n                int num = grid[i][4];\n                // Check it's the correct row and order (should be, due to our plan)\n                // Dispatch it\n                grid[i][4] = -1;\n                dispatched[num] = true;\n                // If this was the next dispatch, advance\n                if (num == nextDispatch) {\n                    // Increment nextDispatch until we find a not yet dispatched\n                    while (nextDispatch < 25 && dispatched[nextDispatch]) {\n                        nextDispatch++;\n                    }\n                }\n            }\n        }\n\n        // Check if done\n        if (nextDispatch >= 25) {\n            // All dispatched\n            break;\n        }\n    }\n\n    // Output: pad all lines to same length\n    size_t maxLen = 0;\n    for (int i = 0; i < N; ++i) {\n        maxLen = max(maxLen, out[i].size());\n    }\n    for (int i = 0; i < N; ++i) {\n        while (out[i].size() < maxLen) out[i] += '.';\n        cout << out[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\nusing ll = long long;\n\nstruct Node {\n    int x, y, delta;\n};\n\nint N;\nvector<vector<int>> height;\nvector<Node> nodes;\nvector<vector<int>> dist;\nint M; // number of nodes (including dummy start if needed)\nint start_id;\n\n// compute total movement cost for a permutation\nll computeCost(const vector<int>& ord) {\n    ll cost = 0;\n    int cur = ord[0];\n    int load = nodes[cur].delta; // after processing first node\n    for (int i = 1; i < M; ++i) {\n        int nxt = ord[i];\n        int d = dist[cur][nxt];\n        cost += (100LL + load) * d;\n        load += nodes[nxt].delta;\n        cur = nxt;\n    }\n    return cost;\n}\n\n// check feasibility: all prefix sums >= 0\nbool feasible(const vector<int>& ord) {\n    int sum = 0;\n    for (int idx : ord) {\n        sum += nodes[idx].delta;\n        if (sum < 0) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    cin >> N;\n    height.assign(N, vector<int>(N));\n    ll base = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> height[i][j];\n            base += abs(height[i][j]);\n        }\n    }\n\n    // Build node list: all cells with non-zero height\n    vector<int> pos, neg;\n    int start_cell_id = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (height[i][j] != 0) {\n                int id = nodes.size();\n                nodes.push_back({i, j, height[i][j]});\n                if (i == 0 && j == 0) start_cell_id = id;\n                if (height[i][j] > 0) pos.push_back(id);\n                else neg.push_back(id);\n            }\n        }\n    }\n    // Add dummy start node if (0,0) already has height 0\n    if (start_cell_id == -1) {\n        start_id = nodes.size();\n        nodes.push_back({0, 0, 0});\n        start_cell_id = start_id;\n        // (0,0) is zero, no operation needed, but we treat it as first node\n    } else {\n        start_id = start_cell_id;\n    }\n    M = nodes.size();\n\n    // Precompute Manhattan distances\n    dist.assign(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            dist[i][j] = abs(nodes[i].x - nodes[j].x) + abs(nodes[i].y - nodes[j].y);\n        }\n    }\n\n    // Build initial feasible permutation: start -> all positives (nearest neighbor) -> all negatives (nearest neighbor)\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    order.push_back(start_id);\n    used[start_id] = true;\n    int cur = start_id;\n    int load = nodes[cur].delta;\n\n    // Process positives\n    vector<int> remaining_pos;\n    for (int p : pos) if (!used[p]) remaining_pos.push_back(p);\n    while (!remaining_pos.empty()) {\n        int best = -1, bestDist = 1e9;\n        for (int p : remaining_pos) {\n            int d = dist[cur][p];\n            if (d < bestDist) {\n                bestDist = d;\n                best = p;\n            }\n        }\n        order.push_back(best);\n        used[best] = true;\n        load += nodes[best].delta;\n        cur = best;\n        auto it = find(remaining_pos.begin(), remaining_pos.end(), best);\n        remaining_pos.erase(it);\n    }\n\n    // Process negatives\n    vector<int> remaining_neg;\n    for (int n : neg) if (!used[n]) remaining_neg.push_back(n);\n    while (!remaining_neg.empty()) {\n        int best = -1, bestDist = 1e9;\n        for (int n : remaining_neg) {\n            int d = dist[cur][n];\n            if (d < bestDist) {\n                bestDist = d;\n                best = n;\n            }\n        }\n        order.push_back(best);\n        used[best] = true;\n        load += nodes[best].delta;\n        cur = best;\n        auto it = find(remaining_neg.begin(), remaining_neg.end(), best);\n        remaining_neg.erase(it);\n    }\n\n    // Ensure all nodes visited (should be)\n    for (int i = 0; i < M; ++i) assert(used[i]);\n\n    ll best_cost = computeCost(order);\n    vector<int> best_order = order;\n\n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double T_start = 1e6, T_end = 0.1;\n    int iterations = 500000;\n    double T = T_start;\n    vector<int> current_order = order;\n    ll current_cost = best_cost;\n\n    auto start_time = chrono::steady_clock::now();\n    for (int iter = 0; iter < iterations; ++iter) {\n        // Check time left\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() > 1800) break;\n\n        // Propose new order\n        vector<int> new_order = current_order;\n        int type = rng() % 2;\n        if (type == 0) {\n            // swap two random positions (excluding first)\n            int i = uniform_int_distribution<int>(1, M-1)(rng);\n            int j = uniform_int_distribution<int>(1, M-1)(rng);\n            while (j == i) j = uniform_int_distribution<int>(1, M-1)(rng);\n            swap(new_order[i], new_order[j]);\n        } else {\n            // reverse a random segment (excluding first)\n            int l = uniform_int_distribution<int>(1, M-1)(rng);\n            int r = uniform_int_distribution<int>(1, M-1)(rng);\n            if (l > r) swap(l, r);\n            reverse(new_order.begin() + l, new_order.begin() + r + 1);\n        }\n\n        // Feasibility check\n        if (!feasible(new_order)) continue;\n\n        ll new_cost = computeCost(new_order);\n        double delta = new_cost - current_cost;\n        if (delta < 0 || exp(-delta / T) > uniform_real_distribution<double>(0.0, 1.0)(rng)) {\n            current_order = move(new_order);\n            current_cost = new_cost;\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_order = current_order;\n            }\n        }\n\n        // Cool down\n        double progress = (double)iter / iterations;\n        T = T_start * pow(T_end / T_start, progress);\n    }\n\n    // Output sequence\n    vector<string> ops;\n    int cx = 0, cy = 0;\n    // Process first node (start) - it is always visited first\n    int idx0 = best_order[0];\n    if (nodes[idx0].delta != 0) {\n        if (nodes[idx0].delta > 0) {\n            ops.push_back(\"+\" + to_string(nodes[idx0].delta));\n        } else {\n            ops.push_back(\"-\" + to_string(-nodes[idx0].delta));\n        }\n    }\n    // Move to subsequent nodes\n    for (int i = 1; i < M; ++i) {\n        int nid = best_order[i];\n        int nx = nodes[nid].x;\n        int ny = nodes[nid].y;\n        // Move step by step\n        while (cx < nx) { ops.push_back(\"D\"); cx++; }\n        while (cx > nx) { ops.push_back(\"U\"); cx--; }\n        while (cy < ny) { ops.push_back(\"R\"); cy++; }\n        while (cy > ny) { ops.push_back(\"L\"); cy--; }\n        // Perform operation\n        if (nodes[nid].delta != 0) {\n            if (nodes[nid].delta > 0) {\n                ops.push_back(\"+\" + to_string(nodes[nid].delta));\n            } else {\n                ops.push_back(\"-\" + to_string(-nodes[nid].delta));\n            }\n        }\n    }\n\n    // Output\n    for (const string& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <unordered_set>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int SEED_COUNT = 2 * N * (N - 1); // 60\n    const int GRID_SIZE = N * N;           // 36\n\n    vector<vector<int>> X(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> X[i][j];\n        }\n    }\n\n    for (int turn = 0; turn < T; ++turn) {\n        // 1. Evaluate current seeds\n        vector<int> sumX(SEED_COUNT, 0);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            sumX[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // best overall seed (max sum)\n        int bestIdx = max_element(sumX.begin(), sumX.end()) - sumX.begin();\n\n        // per\u2011dimension best seeds\n        vector<int> dimMax(M, -1), dimIdx(M, -1);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int l = 0; l < M; ++l) {\n                if (X[i][l] > dimMax[l]) {\n                    dimMax[l] = X[i][l];\n                    dimIdx[l] = i;\n                }\n            }\n        }\n\n        // 2. Build the set of elite seeds (best overall + per\u2011dimension best)\n        unordered_set<int> eliteSet;\n        eliteSet.insert(bestIdx);\n        for (int l = 0; l < M; ++l) {\n            eliteSet.insert(dimIdx[l]);\n        }\n        vector<int> elite(eliteSet.begin(), eliteSet.end());\n\n        // 3. Select 36 seeds: all elites + top sum among the rest\n        vector<bool> used(SEED_COUNT, false);\n        for (int idx : elite) used[idx] = true;\n        vector<int> additional;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (!used[i]) additional.push_back(i);\n        }\n        sort(additional.begin(), additional.end(), [&](int a, int b) {\n            return sumX[a] > sumX[b];\n        });\n        int needFromAdd = GRID_SIZE - (int)elite.size();\n        // selected = elite + first needFromAdd of additional\n        vector<int> selected = elite;\n        selected.insert(selected.end(), additional.begin(), additional.begin() + needFromAdd);\n\n        // 4. Partition into interior (16) and border (20) seeds\n        int interiorSize = (N - 2) * (N - 2); // 16\n        int eliteSize = (int)elite.size();\n        int takeFromAdd = min(interiorSize - eliteSize, needFromAdd);\n        vector<int> interiorSeeds(elite.begin(), elite.end());\n        interiorSeeds.insert(interiorSeeds.end(), additional.begin(), additional.begin() + takeFromAdd);\n        // borderSeeds: the rest of selected\n        vector<int> borderSeeds(additional.begin() + takeFromAdd, additional.begin() + needFromAdd);\n        // sanity: (int)selected.size() == GRID_SIZE\n        // (int)interiorSeeds.size() == interiorSize\n        // borderSeeds.size() == GRID_SIZE - interiorSize\n\n        // 5. Build the placement grid\n        vector<vector<int>> A(N, vector<int>(N, -1));\n\n        // 5a. Define interior positions (1,\u2026,N-2)\n        vector<pair<int,int>> interiorPos;\n        for (int i = 1; i <= N-2; ++i)\n            for (int j = 1; j <= N-2; ++j)\n                interiorPos.push_back({i, j});\n\n        // 5b. Place the best overall at the centre (2,2)\n        int centre_i = 2, centre_j = 2; // 0\u2011based, inside interior\n        A[centre_i][centre_j] = bestIdx;\n\n        // Remove bestIdx from interiorSeeds (it's the first one)\n        auto it = find(interiorSeeds.begin(), interiorSeeds.end(), bestIdx);\n        if (it != interiorSeeds.end()) interiorSeeds.erase(it);\n        // Now interiorSeeds has size = interiorSize - 1 = 15\n\n        // Compute complement scores with bestIdx\n        vector<pair<int,int>> compScores; // (score, seedIdx)\n        for (int idx : interiorSeeds) {\n            int score = 0;\n            for (int l = 0; l < M; ++l) {\n                score += max(X[bestIdx][l], X[idx][l]);\n            }\n            compScores.push_back({-score, idx}); // negative for descending sort\n        }\n        sort(compScores.begin(), compScores.end());\n        // Top 4 become neighbours\n        vector<pair<int,int>> neighPos = {{centre_i-1, centre_j},\n                                          {centre_i+1, centre_j},\n                                          {centre_i, centre_j-1},\n                                          {centre_i, centre_j+1}};\n        unordered_set<int> usedInterior;\n        usedInterior.insert(bestIdx);\n        for (int k = 0; k < 4; ++k) {\n            int idx = compScores[k].second;\n            int ni = neighPos[k].first, nj = neighPos[k].second;\n            A[ni][nj] = idx;\n            usedInterior.insert(idx);\n        }\n\n        // 5d. Assign remaining interior seeds to remaining interior positions\n        // Remaining interior positions (exclude centre and neighbours)\n        vector<pair<int,int>> restInteriorPos;\n        for (auto [i,j] : interiorPos) {\n            if (i == centre_i && j == centre_j) continue;\n            bool isNeigh = false;\n            for (auto [ni,nj] : neighPos) if (ni==i && nj==j) { isNeigh = true; break; }\n            if (!isNeigh) restInteriorPos.push_back({i,j});\n        }\n        // Get the remaining seeds (not used)\n        vector<int> restSeeds;\n        for (int idx : interiorSeeds) {\n            if (!usedInterior.count(idx)) restSeeds.push_back(idx);\n        }\n        // restSeeds.size() should be 11\n        for (size_t k = 0; k < restInteriorPos.size(); ++k) {\n            A[restInteriorPos[k].first][restInteriorPos[k].second] = restSeeds[k];\n        }\n\n        // 5e. Fill border cells with borderSeeds\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (A[i][j] == -1) {\n                    A[i][j] = borderSeeds.back();\n                    borderSeeds.pop_back();\n                }\n            }\n        }\n\n        // 6. Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << A[i][j];\n                if (j < N-1) cout << ' ';\n            }\n            cout << '\\n';\n        }\n        cout << flush;\n\n        // 7. Read the new generation of seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<string> s_str, t_str;\nvector<vector<bool>> source, target;\n\nint root_x = 0, root_y = 0;\nint V_used;\nvector<int> parent, length;\nvector<int> dir;        // current direction (0:right,1:down,2:left,3:up)\nvector<bool> holding;   // whether fingertip holds a takoyaki\n\nvector<string> commands;\n\n// offsets for each direction: right, down, left, up\nconst vector<pair<int,int>> offset_dir = {{0,1}, {1,0}, {0,-1}, {-1,0}};\n\nvoid rotate_leaf(int i, char c) {\n    if (c == 'R') dir[i] = (dir[i] + 1) % 4;\n    else if (c == 'L') dir[i] = (dir[i] + 3) % 4;\n}\n\n// get four possible positions for a leaf of length L from (rx,ry)\nvector<pair<int,int>> get_positions(int rx, int ry, int L) {\n    vector<pair<int,int>> res;\n    for (int d = 0; d < 4; ++d) {\n        int nx = rx + offset_dir[d].first * L;\n        int ny = ry + offset_dir[d].second * L;\n        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n            res.emplace_back(nx, ny);\n        }\n    }\n    return res;\n}\n\n// Kuhn DFS for bipartite matching\nbool dfs(int u, const vector<vector<int>>& adj, vector<int>& matchR, vector<bool>& visited) {\n    for (int v : adj[u]) {\n        if (!visited[v]) {\n            visited[v] = true;\n            if (matchR[v] == -1 || dfs(matchR[v], adj, matchR, visited)) {\n                matchR[v] = u;\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n    s_str.resize(N);\n    t_str.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n\n    source.assign(N, vector<bool>(N, false));\n    target.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') source[i][j] = true;\n            if (t_str[i][j] == '1') target[i][j] = true;\n        }\n    }\n\n    // ---- design tree (star) ----\n    V_used = V;  // use all vertices\n    parent.resize(V_used, 0);\n    length.resize(V_used, 0);\n    for (int i = 1; i < V_used; ++i) {\n        parent[i] = 0;\n        length[i] = i;   // lengths 1,2,...,V-1\n    }\n\n    // output tree\n    cout << V_used << '\\n';\n    for (int i = 1; i < V_used; ++i) {\n        cout << parent[i] << ' ' << length[i] << '\\n';\n    }\n    // initial root position\n    root_x = 0, root_y = 0;\n    cout << root_x << ' ' << root_y << '\\n';\n\n    // ---- initial state ----\n    dir.assign(V_used, 0);        // all point right\n    holding.assign(V_used, false);\n\n    int total_source = M;\n    int total_target = M;\n\n    // main loop\n    while (total_source > 0 || total_target > 0) {\n        // ----- find best root (greedy counting) -----\n        int best_cnt = -1;\n        int best_rx = -1, best_ry = -1;\n        for (int rx = 0; rx < N; ++rx) {\n            for (int ry = 0; ry < N; ++ry) {\n                int cnt = 0;\n                for (int i = 1; i < V_used; ++i) {\n                    int L = length[i];\n                    auto pos = get_positions(rx, ry, L);\n                    bool ok = false;\n                    for (auto [cx, cy] : pos) {\n                        if (!holding[i] && source[cx][cy]) { ok = true; break; }\n                        if ( holding[i] && target[cx][cy]) { ok = true; break; }\n                    }\n                    if (ok) cnt++;\n                }\n                int dist = abs(rx - root_x) + abs(ry - root_y);\n                if (cnt > best_cnt || (cnt == best_cnt && (best_rx == -1 || dist < abs(best_rx - root_x) + abs(best_ry - root_y)))) {\n                    best_cnt = cnt;\n                    best_rx = rx;\n                    best_ry = ry;\n                }\n            }\n        }\n\n        if (best_cnt == 0) break;   // should not happen\n\n        // ----- move root to best_rx, best_ry (no rotations) -----\n        while (root_x != best_rx || root_y != best_ry) {\n            char move_char = '.';\n            int dx = best_rx - root_x, dy = best_ry - root_y;\n            if (dx > 0) { move_char = 'D'; root_x++; }\n            else if (dx < 0) { move_char = 'U'; root_x--; }\n            else if (dy > 0) { move_char = 'R'; root_y++; }\n            else if (dy < 0) { move_char = 'L'; root_y--; }\n\n            string rot = \"\";\n            for (int i = 1; i < V_used; ++i) rot += '.';\n            string action = \"\";\n            for (int i = 0; i < V_used; ++i) action += '.';\n\n            string cmd = move_char + rot + action;\n            commands.push_back(cmd);\n        }\n\n        // ----- stay at this root and perform actions until no more actions possible -----\n        while (true) {\n            // build bipartite graph for current root (best_rx, best_ry)\n            map<pair<int,int>, int> cell_id;\n            vector<pair<int,int>> id_cell;\n            vector<vector<int>> adj(V_used); // only indices 1..V_used-1 used\n\n            for (int i = 1; i < V_used; ++i) {\n                int L = length[i];\n                auto pos = get_positions(best_rx, best_ry, L);\n                for (auto [cx, cy] : pos) {\n                    bool ok = false;\n                    if (!holding[i] && source[cx][cy]) ok = true;\n                    if ( holding[i] && target[cx][cy]) ok = true;\n                    if (ok) {\n                        auto key = make_pair(cx, cy);\n                        if (cell_id.find(key) == cell_id.end()) {\n                            cell_id[key] = id_cell.size();\n                            id_cell.push_back(key);\n                        }\n                        adj[i].push_back(cell_id[key]);\n                    }\n                }\n            }\n\n            // maximum bipartite matching (Kuhn)\n            int item_cnt = id_cell.size();\n            vector<int> matchR(item_cnt, -1);\n            int matching = 0;\n            for (int i = 1; i < V_used; ++i) {\n                vector<bool> visited(item_cnt, false);\n                if (dfs(i, adj, matchR, visited)) {\n                    matching++;\n                }\n            }\n\n            if (matching == 0) break;\n\n            // obtain assigned cell for each matched leaf\n            vector<pair<int,int>> leaf_target(V_used, {-1, -1});\n            for (int v = 0; v < item_cnt; ++v) {\n                if (matchR[v] != -1) {\n                    leaf_target[matchR[v]] = id_cell[v];\n                }\n            }\n\n            // compute target directions for matched leaves\n            vector<int> target_dir(V_used, -1);\n            for (int i = 1; i < V_used; ++i) {\n                auto [cx, cy] = leaf_target[i];\n                if (cx == -1) continue;\n                int L = length[i];\n                int dx = cx - best_rx, dy = cy - best_ry;\n                if (dx == 0 && dy == L) target_dir[i] = 0;      // right\n                else if (dx == L && dy == 0) target_dir[i] = 1; // down\n                else if (dx == 0 && dy == -L) target_dir[i] = 2; // left\n                else if (dx == -L && dy == 0) target_dir[i] = 3; // up\n            }\n\n            // ---- rotate leaves to target directions (possibly several turns) ----\n            while (true) {\n                bool all_aligned = true;\n                string rot = \"\";\n                for (int i = 1; i < V_used; ++i) {\n                    if (target_dir[i] == -1) { rot += '.'; continue; }\n                    int cur = dir[i];\n                    int tgt = target_dir[i];\n                    int diff = (tgt - cur + 4) % 4;\n                    char c;\n                    if (diff == 0) c = '.';\n                    else if (diff <= 2) c = 'R';\n                    else c = 'L';\n                    rot += c;\n                    if (c != '.') all_aligned = false;\n                    rotate_leaf(i, c);\n                }\n                if (all_aligned) break;\n                string action = \"\";\n                for (int i = 0; i < V_used; ++i) action += '.';\n                commands.push_back('.' + rot + action);\n            }\n\n            // ---- action turn: pick or place ----\n            string rot = \"\";\n            for (int i = 1; i < V_used; ++i) rot += '.';\n            string action = \"\";\n            action += '.'; // root never acts\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) action += 'P';\n                else action += '.';\n            }\n            commands.push_back('.' + rot + action);\n\n            // update state\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) {\n                    auto [cx, cy] = leaf_target[i];\n                    if (!holding[i]) {\n                        // pick\n                        source[cx][cy] = false;\n                        holding[i] = true;\n                        total_source--;\n                    } else {\n                        // place\n                        target[cx][cy] = false;\n                        holding[i] = false;\n                        total_target--;\n                    }\n                }\n            }\n        }\n    }\n\n    // ---- output all commands ----\n    for (const string& cmd : commands) {\n        cout << cmd << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\nusing namespace std;\nusing ll = long long;\n\nconst int COORD_MAX = 100000;\nconst int PERIMETER_LIMIT = 400000;\nconst int TILE_SIZE = 500;          // tune between 250 and 1000\nconst int TILES = (COORD_MAX / TILE_SIZE) + 1; // 201\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<pair<int,int>> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].first >> mackerels[i].second;\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].first >> sardines[i].second;\n    }\n\n    // Build tile grid with weights (+1 for mackerel, -1 for sardine)\n    vector<vector<ll>> score(TILES, vector<ll>(TILES, 0));\n    for (auto [x, y] : mackerels) {\n        int tx = x / TILE_SIZE;\n        int ty = y / TILE_SIZE;\n        score[tx][ty] += 1;\n    }\n    for (auto [x, y] : sardines) {\n        int tx = x / TILE_SIZE;\n        int ty = y / TILE_SIZE;\n        score[tx][ty] -= 1;\n    }\n\n    // Prefix sum for tile grid\n    vector<vector<ll>> pref(TILES+1, vector<ll>(TILES+1, 0));\n    for (int i = 0; i < TILES; ++i) {\n        for (int j = 0; j < TILES; ++j) {\n            pref[i+1][j+1] = pref[i][j+1] + pref[i+1][j] - pref[i][j] + score[i][j];\n        }\n    }\n\n    // Find best rectangle of tiles under perimeter constraint\n    ll best_sum = -1e18;\n    int best_r1 = 0, best_r2 = 0, best_c1 = 0, best_c2 = 0;\n\n    for (int r1 = 0; r1 < TILES; ++r1) {\n        vector<ll> colSum(TILES, 0);\n        for (int r2 = r1; r2 < TILES; ++r2) {\n            // add current row to column sums\n            for (int c = 0; c < TILES; ++c) {\n                colSum[c] += score[r2][c];\n            }\n            int dx = r2 - r1 + 1;               // number of rows\n            int max_dy = (PERIMETER_LIMIT / (2 * TILE_SIZE)) - dx; // max allowed columns\n            if (max_dy <= 0) continue;\n            max_dy = min(max_dy, TILES);\n\n            // Find maximum subarray sum of colSum with length <= max_dy\n            // Using prefix sums and a deque (monotonic queue)\n            vector<ll> prefCol(TILES + 1, 0);\n            for (int i = 0; i < TILES; ++i) prefCol[i+1] = prefCol[i] + colSum[i];\n\n            deque<int> dq;\n            ll local_best = -1e18;\n            int local_c1 = -1, local_c2 = -1;\n\n            for (int i = 0; i <= TILES; ++i) {\n                // remove indices out of window [i-max_dy, i]\n                while (!dq.empty() && dq.front() < i - max_dy)\n                    dq.pop_front();\n\n                if (!dq.empty()) {\n                    ll cur = prefCol[i] - prefCol[dq.front()];\n                    if (cur > local_best) {\n                        local_best = cur;\n                        local_c1 = dq.front();   // leftmost column index (in prefCol)\n                        local_c2 = i - 1;        // rightmost column index\n                    }\n                }\n\n                // maintain increasing prefCol values in deque\n                while (!dq.empty() && prefCol[dq.back()] >= prefCol[i])\n                    dq.pop_back();\n                dq.push_back(i);\n            }\n\n            if (local_best > best_sum) {\n                best_sum = local_best;\n                best_r1 = r1;\n                best_r2 = r2;\n                best_c1 = local_c1;\n                best_c2 = local_c2;\n            }\n        }\n    }\n\n    // If no positive rectangle found (shouldn't happen), fallback to a single tile containing at least one mackerel\n    if (best_sum <= 0) {\n        // find any tile with positive net weight\n        for (int i = 0; i < TILES; ++i) {\n            for (int j = 0; j < TILES; ++j) {\n                if (score[i][j] > 0) {\n                    best_sum = score[i][j];\n                    best_r1 = best_r2 = i;\n                    best_c1 = best_c2 = j;\n                    break;\n                }\n            }\n            if (best_sum > 0) break;\n        }\n    }\n\n    // Convert tile rectangle to actual coordinates (tighten using mackerels)\n    int x_low = best_c1 * TILE_SIZE;\n    int x_high = min(COORD_MAX, (best_c2 + 1) * TILE_SIZE);\n    int y_low = best_r1 * TILE_SIZE;\n    int y_high = min(COORD_MAX, (best_r2 + 1) * TILE_SIZE);\n\n    // Collect mackerels inside the tile rectangle to get tight bounding box\n    int tight_x_min = COORD_MAX + 1, tight_x_max = -1;\n    int tight_y_min = COORD_MAX + 1, tight_y_max = -1;\n    for (auto [x, y] : mackerels) {\n        if (x >= x_low && x <= x_high && y >= y_low && y <= y_high) {\n            tight_x_min = min(tight_x_min, x);\n            tight_x_max = max(tight_x_max, x);\n            tight_y_min = min(tight_y_min, y);\n            tight_y_max = max(tight_y_max, y);\n        }\n    }\n\n    // If there are mackerels inside, use tight box; otherwise use the tile rectangle itself.\n    if (tight_x_min <= COORD_MAX) {\n        x_low = tight_x_min;\n        x_high = tight_x_max;\n        y_low = tight_y_min;\n        y_high = tight_y_max;\n    }\n\n    // Ensure rectangle has positive area (at least 1 unit)\n    if (x_low == x_high) x_high = min(COORD_MAX, x_low + 1);\n    if (y_low == y_high) y_high = min(COORD_MAX, y_low + 1);\n\n    // Output polygon (a simple rectangle)\n    int m = 4;\n    cout << m << '\\n';\n    // Order: counterclockwise (or clockwise) - here we output (x_low, y_low) -> (x_high, y_low) -> (x_high, y_high) -> (x_low, y_high)\n    cout << x_low << \" \" << y_low << '\\n';\n    cout << x_high << \" \" << y_low << '\\n';\n    cout << x_high << \" \" << y_high << '\\n';\n    cout << x_low << \" \" << y_high << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nstruct Rect {\n    int orig;\n    ll x, y, w, h;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<ll> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i) cin >> w_obs[i] >> h_obs[i];\n\n    // initialise estimate sums with the given noisy values\n    vector<ld> sum_w(N), sum_h(N);\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int measure_turns = T - 1;     // last turn is for the final packing\n    int cur_measure = 0;           // index of the next rectangle to measure\n\n    for (int turn = 0; turn < T; ++turn) {\n        if (turn < measure_turns) {\n            // ===== measurement turn: place a single rectangle =====\n            int idx = cur_measure % N;\n            ++cur_measure;\n            cout << \"1\\n\";\n            cout << idx << \" 0 U -1\" << endl;   // flush with endl\n\n            // read noisy bounding box\n            ll Wp, Hp;\n            cin >> Wp >> Hp;\n\n            // update statistics\n            sum_w[idx] += Wp;\n            sum_h[idx] += Hp;\n            cnt[idx]++;\n        } else {\n            // ===== final packing turn =====\n            // compute final estimates (rounded to nearest integer)\n            vector<ll> est_w(N), est_h(N);\n            for (int i = 0; i < N; ++i) {\n                est_w[i] = (ll)llround(sum_w[i] / cnt[i]);\n                est_h[i] = (ll)llround(sum_h[i] / cnt[i]);\n                if (est_w[i] < 1) est_w[i] = 1;\n                if (est_h[i] < 1) est_h[i] = 1;\n            }\n\n            // greedy packing: place rectangles in index order, trying all possibilities\n            vector<Rect> placed;\n            ll curW = 0, curH = 0;\n            vector<tuple<int, int, char, int>> ops;   // (original index, rotation, direction, reference)\n\n            for (int i = 0; i < N; ++i) {\n                struct Option {\n                    int rot;\n                    char dir;\n                    int ref;     // index inside 'placed' vector (-1 for axis)\n                    ll newW, newH;\n                    ll x, y;     // position of the new rectangle\n                };\n                Option best;\n                best.newW = LLONG_MAX;   // large sentinel\n\n                // try both rotations\n                for (int rot = 0; rot <= 1; ++rot) {\n                    ll w = (rot == 0) ? est_w[i] : est_h[i];\n                    ll h = (rot == 0) ? est_h[i] : est_w[i];\n\n                    // try both directions\n                    for (char dir : {'U', 'L'}) {\n                        // all possible references: -1 and every already placed rectangle\n                        vector<int> refs = {-1};\n                        for (int j = 0; j < (int)placed.size(); ++j) refs.push_back(j);\n\n                        for (int ref : refs) {\n                            ll x, y;\n                            if (dir == 'U') {\n                                // horizontal alignment\n                                x = (ref == -1) ? 0 : placed[ref].x + placed[ref].w;\n                                // move upwards (decreasing y) until touching bottom of some rectangle\n                                y = 0;\n                                for (auto &p : placed) {\n                                    if (x < p.x + p.w && x + w > p.x) {\n                                        y = max(y, p.y + p.h);\n                                    }\n                                }\n                            } else { // 'L'\n                                // vertical alignment\n                                y = (ref == -1) ? 0 : placed[ref].y + placed[ref].h;\n                                // move leftwards (decreasing x) until touching right side of some rectangle\n                                x = 0;\n                                for (auto &p : placed) {\n                                    if (y < p.y + p.h && y + h > p.y) {\n                                        x = max(x, p.x + p.w);\n                                    }\n                                }\n                            }\n\n                            ll newW = max(curW, x + w);\n                            ll newH = max(curH, y + h);\n                            ll score = newW + newH;\n                            if (score < best.newW + best.newH) {\n                                best = {rot, dir, ref, newW, newH, x, y};\n                            }\n                        }\n                    }\n                }\n\n                // apply the best option\n                ll w_used = (best.rot == 0) ? est_w[i] : est_h[i];\n                ll h_used = (best.rot == 0) ? est_h[i] : est_w[i];\n                int ref_orig = (best.ref == -1) ? -1 : placed[best.ref].orig;\n\n                placed.push_back({i, best.x, best.y, w_used, h_used});\n                curW = best.newW;\n                curH = best.newH;\n                ops.emplace_back(i, best.rot, best.dir, ref_orig);\n            }\n\n            // output the packing\n            cout << N << \"\\n\";\n            for (auto &[p, r, d, b] : ops) {\n                cout << p << \" \" << r << \" \" << d << \" \" << b << \"\\n\";\n            }\n            cout.flush();\n\n            // consume the measured feedback (irrelevant for our algorithm)\n            ll dummyW, dummyH;\n            cin >> dummyW >> dummyH;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<vector<int>> G(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        G[u].push_back(v);\n        G[v].push_back(u);\n    }\n    // read coordinates, not needed for the algorithm\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. All-pairs shortest distances ----------\n    const int INF = 1e9;\n    vector<vector<int>> dist(N, vector<int>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        vector<int> d(N, -1);\n        queue<int> q;\n        d[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int u : G[v]) if (d[u] == -1) {\n                d[u] = d[v] + 1;\n                q.push(u);\n            }\n        }\n        for (int i = 0; i < N; ++i) dist[s][i] = d[i];\n    }\n\n    // ---------- 2. Sorted order of vertices by distance for each vertex ----------\n    vector<vector<int>> order(N);\n    for (int v = 0; v < N; ++v) {\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int a, int b) {\n            return dist[v][a] < dist[v][b];\n        });\n        order[v] = move(idx);\n    }\n\n    // ---------- 3. Greedy elimination of redundant roots ----------\n    vector<bool> is_root(N, true);\n    vector<int> nearest_root(N), nearest_ptr(N);\n    vector<vector<int>> children(N); // vertices that have this root as nearest\n\n    // Initial state: every vertex is its own root\n    for (int v = 0; v < N; ++v) {\n        nearest_root[v] = v;\n        nearest_ptr[v] = 0;   // index in order[v] of the nearest root (itself)\n        children[v].push_back(v);\n    }\n\n    while (true) {\n        // For each root compute the total gain of removing it\n        vector<ll> score(N, 0);\n        vector<bool> feasible(N, true);\n        for (int v = 0; v < N; ++v) {\n            int r = nearest_root[v];\n            // Find the second-nearest root (the next root in the sorted list)\n            int pos = nearest_ptr[v] + 1;\n            while (pos < N && !is_root[order[v][pos]]) ++pos;\n            if (pos >= N || dist[v][order[v][pos]] > H) {\n                feasible[r] = false;\n            } else {\n                int s = order[v][pos];\n                ll gain = (ll)(dist[v][s] - dist[v][r]) * A[v];\n                score[r] += gain;\n            }\n        }\n\n        // Choose best feasible root with positive gain\n        int best = -1;\n        ll best_score = -1;\n        for (int r = 0; r < N; ++r) {\n            if (is_root[r] && feasible[r] && score[r] > best_score) {\n                best_score = score[r];\n                best = r;\n            }\n        }\n        if (best == -1) break; // no improvement possible\n\n        // Remove best\n        is_root[best] = false;\n        vector<int> cur_children = children[best]; // copy\n        children[best].clear();\n        for (int v : cur_children) {\n            // v was covered by best; find the next root in its sorted list\n            int pos = nearest_ptr[v] + 1;\n            while (pos < N && !is_root[order[v][pos]]) ++pos;\n            // pos is guaranteed to be < N because feasibility checked\n            int new_root = order[v][pos];\n            nearest_root[v] = new_root;\n            nearest_ptr[v] = pos;\n            children[new_root].push_back(v);\n        }\n    }\n\n    // ---------- 4. Build the forest: BFS from the final roots ----------\n    vector<int> parent(N, -1), depth(N, -1);\n    queue<int> q;\n    for (int v = 0; v < N; ++v) if (is_root[v]) {\n        depth[v] = 0;\n        parent[v] = -1;\n        q.push(v);\n    }\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : G[v]) if (depth[u] == -1) {\n            depth[u] = depth[v] + 1;\n            parent[u] = v;\n            q.push(u);\n        }\n    }\n\n    // ---------- 5. Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << parent[i] << (i+1 == N ? \"\\n\" : \" \");\n    }\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    int N = 20;\n    cin >> N;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Collect all Oni positions (initial)\n    vector<pair<int, int>> oni_pos;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'x')\n                oni_pos.emplace_back(i, j);\n\n    // Precompute for each Oni the best safe direction and distance (to edge)\n    struct Info { int dir; int dist; }; // 0:Up, 1:Down, 2:Left, 3:Right\n    vector<Info> oni_info(oni_pos.size());\n\n    for (size_t idx = 0; idx < oni_pos.size(); ++idx) {\n        int r = oni_pos[idx].first;\n        int c = oni_pos[idx].second;\n\n        bool safe[4] = {true, true, true, true};\n\n        // up\n        for (int i = 0; i < r; ++i)\n            if (grid[i][c] == 'o') { safe[0] = false; break; }\n        // down\n        for (int i = r + 1; i < N; ++i)\n            if (grid[i][c] == 'o') { safe[1] = false; break; }\n        // left\n        for (int j = 0; j < c; ++j)\n            if (grid[r][j] == 'o') { safe[2] = false; break; }\n        // right\n        for (int j = c + 1; j < N; ++j)\n            if (grid[r][j] == 'o') { safe[3] = false; break; }\n\n        int best_dir = -1;\n        int best_dist = N + 1;\n        int dists[4] = {r + 1, N - r, c + 1, N - c};\n        for (int d = 0; d < 4; ++d) {\n            if (safe[d] && dists[d] < best_dist) {\n                best_dist = dists[d];\n                best_dir = d;\n            }\n        }\n        // guaranteed to be valid\n        oni_info[idx] = {best_dir, best_dist};\n    }\n\n    vector<pair<char, int>> ops;\n\n    // Shift functions (modify grid in place)\n    auto shift_left = [&](int r) {\n        // remove leftmost piece\n        for (int j = 0; j < N - 1; ++j) grid[r][j] = grid[r][j + 1];\n        grid[r][N - 1] = '.';\n    };\n    auto shift_right = [&](int r) {\n        for (int j = N - 1; j > 0; --j) grid[r][j] = grid[r][j - 1];\n        grid[r][0] = '.';\n    };\n    auto shift_up = [&](int c) {\n        for (int i = 0; i < N - 1; ++i) grid[i][c] = grid[i + 1][c];\n        grid[N - 1][c] = '.';\n    };\n    auto shift_down = [&](int c) {\n        for (int i = N - 1; i > 0; --i) grid[i][c] = grid[i - 1][c];\n        grid[0][c] = '.';\n    };\n\n    // ---------- Phase 1: clear rows that contain no Fukunokami ----------\n    for (int i = 0; i < N; ++i) {\n        bool has_o = false;\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'o') { has_o = true; break; }\n        if (has_o) continue;\n\n        // find Oni in this row\n        int min_x = N, max_x = -1;\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'x') {\n                min_x = min(min_x, j);\n                max_x = max(max_x, j);\n            }\n        if (max_x == -1) continue;   // no Oni\n\n        int left_cost = max_x + 1;     // shifts to remove rightmost Oni\n        int right_cost = N - min_x;    // shifts to remove leftmost Oni\n        if (left_cost <= right_cost) {\n            for (int k = 0; k < left_cost; ++k) {\n                shift_left(i);\n                ops.emplace_back('L', i);\n            }\n        } else {\n            for (int k = 0; k < right_cost; ++k) {\n                shift_right(i);\n                ops.emplace_back('R', i);\n            }\n        }\n    }\n\n    // ---------- Phase 2: clear columns that contain no Fukunokami ----------\n    for (int j = 0; j < N; ++j) {\n        bool has_o = false;\n        for (int i = 0; i < N; ++i)\n            if (grid[i][j] == 'o') { has_o = true; break; }\n        if (has_o) continue;\n\n        int min_x = N, max_x = -1;\n        for (int i = 0; i < N; ++i)\n            if (grid[i][j] == 'x') {\n                min_x = min(min_x, i);\n                max_x = max(max_x, i);\n            }\n        if (max_x == -1) continue;\n\n        int up_cost = max_x + 1;\n        int down_cost = N - min_x;\n        if (up_cost <= down_cost) {\n            for (int k = 0; k < up_cost; ++k) {\n                shift_up(j);\n                ops.emplace_back('U', j);\n            }\n        } else {\n            for (int k = 0; k < down_cost; ++k) {\n                shift_down(j);\n                ops.emplace_back('D', j);\n            }\n        }\n    }\n\n    // ---------- Phase 3: remove remaining Oni individually ----------\n    for (size_t idx = 0; idx < oni_pos.size(); ++idx) {\n        int r = oni_pos[idx].first;\n        int c = oni_pos[idx].second;\n        if (grid[r][c] != 'x') continue;   // already removed\n\n        int dir = oni_info[idx].dir;\n        int dist = oni_info[idx].dist;\n\n        if (dir == 0) {      // up\n            for (int k = 0; k < dist; ++k) { shift_up(c); ops.emplace_back('U', c); }\n            for (int k = 0; k < dist; ++k) { shift_down(c); ops.emplace_back('D', c); }\n        } else if (dir == 1) { // down\n            for (int k = 0; k < dist; ++k) { shift_down(c); ops.emplace_back('D', c); }\n            for (int k = 0; k < dist; ++k) { shift_up(c); ops.emplace_back('U', c); }\n        } else if (dir == 2) { // left\n            for (int k = 0; k < dist; ++k) { shift_left(r); ops.emplace_back('L', r); }\n            for (int k = 0; k < dist; ++k) { shift_right(r); ops.emplace_back('R', r); }\n        } else {               // right\n            for (int k = 0; k < dist; ++k) { shift_right(r); ops.emplace_back('R', r); }\n            for (int k = 0; k < dist; ++k) { shift_left(r); ops.emplace_back('L', r); }\n        }\n    }\n\n    // Output\n    for (const auto &op : ops) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<int> dist_emp(0, N-1);\nuniform_real_distribution<double> dist_prob(0.0, 1.0);\n\nstruct Solution {\n    int a[N], b[N];\n};\n\nint simulate(const Solution& sol, int cnt[]) {\n    fill(cnt, cnt + N, 0);\n    int cur = 0;\n    cnt[0] = 1; // week 1\n    for (int w = 2; w <= L; ++w) {\n        int t = cnt[cur];\n        int nxt = (t & 1) ? sol.a[cur] : sol.b[cur];\n        cnt[nxt]++;\n        cur = nxt;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        err += abs(cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution: uniform cycle\n    Solution sol;\n    for (int i = 0; i < N; ++i) {\n        sol.a[i] = (i + 1) % N;\n        sol.b[i] = (i + 1) % N;\n    }\n\n    int cnt[N];\n    int best_err = simulate(sol, cnt);\n    Solution best_sol = sol;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    double temperature = 1000.0;\n    const double cooling_rate = 0.9995;\n    int iterations = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n\n        // random modification\n        Solution new_sol = sol;\n        int i = dist_emp(rng);\n        if (dist_prob(rng) < 0.5) {\n            new_sol.a[i] = dist_emp(rng);\n        } else {\n            new_sol.b[i] = dist_emp(rng);\n        }\n\n        int new_err = simulate(new_sol, cnt);\n        int delta = new_err - best_err;\n\n        if (delta < 0 || dist_prob(rng) < exp(-delta / temperature)) {\n            sol = new_sol;\n            if (new_err < best_err) {\n                best_err = new_err;\n                best_sol = new_sol;\n            }\n        }\n\n        temperature *= cooling_rate;\n        iterations++;\n    }\n\n    // Output best solution\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.a[i] << \" \" << best_sol.b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\n// ---------- utility ----------\nstruct DSU {\n    vector<int> parent, rank;\n    DSU(int n) : parent(n), rank(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rank[a] < rank[b]) swap(a, b);\n        parent[b] = a;\n        if (rank[a] == rank[b]) rank[a]++;\n        return true;\n    }\n};\n\n// ---------- Morton code (for ordering) ----------\nuint64_t splitBy3(uint32_t a) {\n    uint64_t x = a & 0x1fffff; // lower 21 bits (enough for 0..10000)\n    x = (x | (x << 32)) & 0x00000000ffffffff;\n    x = (x | (x << 16)) & 0x0000ffff0000ffff;\n    x = (x | (x << 8))  & 0x00ff00ff00ff00ff;\n    x = (x | (x << 4))  & 0x0f0f0f0f0f0f0f0f;\n    x = (x | (x << 2))  & 0x3333333333333333;\n    x = (x | (x << 1))  & 0x5555555555555555;\n    return x;\n}\nuint64_t mortonEncode(uint32_t x, uint32_t y) {\n    return (splitBy3(x) | (splitBy3(y) << 1));\n}\n\n// ---------- query helper ----------\nvector<pair<int,int>> do_query(const vector<int>& subset) {\n    int l = subset.size();\n    cout << \"? \" << l;\n    for (int v : subset) cout << ' ' << v;\n    cout << endl;\n    vector<pair<int,int>> res;\n    for (int i = 0; i < l-1; ++i) {\n        int a, b; cin >> a >> b;\n        if (a > b) swap(a, b);\n        res.emplace_back(a, b);\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<ll> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // order cities by Morton code (spatial locality)\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        uint64_t mi = mortonEncode(cx[i], cy[i]);\n        uint64_t mj = mortonEncode(cx[j], cy[j]);\n        return mi < mj;\n    });\n\n    // assign groups by taking consecutive blocks\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        for (int j = 0; j < G[k]; ++j) {\n            groups[k].push_back(order[idx++]);\n        }\n    }\n\n    // answer storage: edges for each group\n    vector<vector<pair<int,int>>> answer_edges(M);\n    int used_queries = 0;\n\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int sz = cities.size();\n        if (sz == 1) continue; // no edges\n\n        if (sz <= L) {\n            // query whole group -> exact MST\n            ++used_queries;\n            auto edges = do_query(cities);\n            for (auto e : edges) answer_edges[k].push_back(e);\n        } else {\n            // sliding windows of size L, overlap 1\n            vector<pair<int,int>> collected;\n            int start = 0;\n            while (start < sz - 1) {\n                int end = min(start + L, sz);\n                if (end - start < 2) break;\n                vector<int> subset(cities.begin() + start, cities.begin() + end);\n                ++used_queries;\n                auto edges = do_query(subset);\n                for (auto e : edges) collected.push_back(e);\n                start = end - 1; // overlap 1\n            }\n\n            // compute MST on collected edges using estimated distances\n            struct Edge { int u, v; ll w; };\n            vector<Edge> cand;\n            for (auto& p : collected) {\n                ll dx = cx[p.first] - cx[p.second];\n                ll dy = cy[p.first] - cy[p.second];\n                ll w = (ll)sqrt(dx*dx + dy*dy);\n                cand.push_back({p.first, p.second, w});\n            }\n            sort(cand.begin(), cand.end(), [](const Edge& a, const Edge& b) { return a.w < b.w; });\n\n            DSU dsu(N);\n            vector<pair<int,int>> selected;\n            for (auto& e : cand) {\n                if (dsu.unite(e.u, e.v)) {\n                    selected.emplace_back(e.u, e.v);\n                }\n            }\n\n            // check connectivity, add edges from estimated complete graph if needed\n            // collect set of components among this group\n            set<int> comps;\n            for (int v : cities) comps.insert(dsu.find(v));\n            while (comps.size() > 1) {\n                ll best_w = 1e18;\n                pair<int,int> best_edge;\n                for (int i = 0; i < sz; ++i) {\n                    int u = cities[i];\n                    for (int j = i+1; j < sz; ++j) {\n                        int v = cities[j];\n                        if (dsu.find(u) == dsu.find(v)) continue;\n                        ll dx = cx[u] - cx[v];\n                        ll dy = cy[u] - cy[v];\n                        ll w = (ll)sqrt(dx*dx + dy*dy);\n                        if (w < best_w) {\n                            best_w = w;\n                            best_edge = {u, v};\n                        }\n                    }\n                }\n                if (best_w == 1e18) break; // shouldn't happen\n                dsu.unite(best_edge.first, best_edge.second);\n                selected.push_back(best_edge);\n                comps.clear();\n                for (int v : cities) comps.insert(dsu.find(v));\n            }\n\n            // store the selected edges (exactly sz-1)\n            for (auto e : selected) answer_edges[k].push_back(e);\n        }\n    }\n\n    // output answer\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        for (int v : groups[k]) cout << v << ' ';\n        cout << endl;\n        for (auto& e : answer_edges[k]) cout << e.first << ' ' << e.second << endl;\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n    vector<pair<int,int>> points(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    // start at first point\n    int cur_i = points[0].first;\n    int cur_j = points[0].second;\n\n    // We will simulate moves without placing any blocks.\n    // For each target in order (including start? start is visited already)\n    // we move step by step using Manhattan distance.\n    for (int t = 1; t < M; ++t) {\n        int target_i = points[t].first;\n        int target_j = points[t].second;\n\n        while (cur_i != target_i || cur_j != target_j) {\n            if (cur_i < target_i) {\n                cout << \"M D\\n\";\n                ++cur_i;\n            } else if (cur_i > target_i) {\n                cout << \"M U\\n\";\n                --cur_i;\n            } else if (cur_j < target_j) {\n                cout << \"M R\\n\";\n                ++cur_j;\n            } else if (cur_j > target_j) {\n                cout << \"M L\\n\";\n                --cur_j;\n            }\n        }\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Rect { int a, b, c, d; }; // [a,c) x [b,d)\nstruct Region { int x0, y0, x1, y1; vector<int> ids; };\nstruct SplitResult { \n    int axis; \n    int s; \n    vector<int> left, right; \n    double metric;\n};\n\nint n;\nvector<int> xi, yi, ri;\n\ndouble calc_p(int idx, long long area) {\n    long long r = ri[idx];\n    long long s = area;\n    long long mn = min(r, s);\n    long long mx = max(r, s);\n    double ratio = (double)mn / mx;\n    return ratio * (2.0 - ratio);\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return max(a.a, b.a) < min(a.c, b.c) && max(a.b, b.b) < min(a.d, b.d);\n}\nbool contains(const Rect& rect, int xi, int yi) {\n    return rect.a <= xi && xi < rect.c && rect.b <= yi && yi < rect.d;\n}\n\ndouble total_score(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; ++i) {\n        long long area = (long long)(rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        sum += calc_p(i, area);\n    }\n    return sum;\n}\n\nSplitResult choose_split(const Region& reg) {\n    int m = reg.ids.size();\n    const auto& ids = reg.ids;\n    int x0 = reg.x0, y0 = reg.y0, x1 = reg.x1, y1 = reg.y1;\n    vector<SplitResult> candidates;\n\n    // ---- vertical split (axis 0) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, xi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, xi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int height = y1 - y0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / height + x0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - x0) * height;\n            long long right_area = (long long)(x1 - s) * height;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({0, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    // ---- horizontal split (axis 1) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return yi[i] < yi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, yi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, yi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int width = x1 - x0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / width + y0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - y0) * width;\n            long long right_area = (long long)(y1 - s) * width;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({1, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    if (candidates.empty()) {\n        // fallback: split vertically at median\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        int mid = m / 2;\n        int split_x = (xi[order[mid-1]] + xi[order[mid]] + 1) / 2;\n        if (split_x <= x0) split_x = x0+1;\n        if (split_x >= x1) split_x = x1-1;\n        vector<int> left(order.begin(), order.begin()+mid);\n        vector<int> right(order.begin()+mid, order.end());\n        double left_sum = accumulate(left.begin(), left.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double right_sum = accumulate(right.begin(), right.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double metric = 0; // unused but set to avoid warning\n        return {0, split_x, move(left), move(right), metric};\n    }\n\n    // stochastic selection with softmax\n    double temperature = 0.02;\n    double max_metric = 1e100;\n    for (auto& c : candidates) if (c.metric < max_metric) max_metric = c.metric;\n    vector<double> weights(candidates.size());\n    double sum_weights = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        weights[i] = exp(- (candidates[i].metric - max_metric) * temperature);\n        sum_weights += weights[i];\n    }\n    uniform_real_distribution<double> dist(0.0, sum_weights);\n    double r = dist(rng);\n    double cum = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        cum += weights[i];\n        if (r <= cum) return move(candidates[i]);\n    }\n    return move(candidates.back());\n}\n\nvoid recursive_split(const Region& reg, vector<Rect>& rects) {\n    if (reg.ids.size() == 1) {\n        int idx = reg.ids[0];\n        rects[idx] = {reg.x0, reg.y0, reg.x1, reg.y1};\n        return;\n    }\n    SplitResult split = choose_split(reg);\n    if (split.axis == 0) {\n        Region left{reg.x0, reg.y0, split.s, reg.y1, move(split.left)};\n        Region right{split.s, reg.y0, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    } else {\n        Region left{reg.x0, reg.y0, reg.x1, split.s, move(split.left)};\n        Region right{reg.x0, split.s, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    }\n}\n\nvoid improve(vector<Rect>& rects) {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < n; ++i) {\n            Rect cur = rects[i];\n            // try expand in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c >= 10000) continue;\n                    newr.c++;\n                } else if (dir == 1) { // left\n                    if (newr.a <= 0) continue;\n                    newr.a--;\n                } else if (dir == 2) { // top\n                    if (newr.d >= 10000) continue;\n                    newr.d++;\n                } else { // bottom\n                    if (newr.b <= 0) continue;\n                    newr.b--;\n                }\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n            // try shrink in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c - 1 <= newr.a) continue;\n                    newr.c--;\n                } else if (dir == 1) { // left\n                    if (newr.a + 1 >= newr.c) continue;\n                    newr.a++;\n                } else if (dir == 2) { // top\n                    if (newr.d - 1 <= newr.b) continue;\n                    newr.d--;\n                } else { // bottom\n                    if (newr.b + 1 >= newr.d) continue;\n                    newr.b++;\n                }\n                // must still contain the point\n                if (!contains(newr, xi[i], yi[i])) continue;\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(15);\n\n    cin >> n;\n    xi.resize(n); yi.resize(n); ri.resize(n);\n    for (int i = 0; i < n; ++i) cin >> xi[i] >> yi[i] >> ri[i];\n\n    vector<Rect> best_rects(n);\n    double best_score = -1.0;\n\n    const int TRIALS = 200; // number of random constructions\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        vector<int> all_ids(n);\n        iota(all_ids.begin(), all_ids.end(), 0);\n        Region full{0, 0, 10000, 10000, move(all_ids)};\n        vector<Rect> rects(n);\n        recursive_split(full, rects);\n        double score = total_score(rects);\n        if (score > best_score) {\n            best_score = score;\n            best_rects = move(rects);\n        }\n    }\n\n    // post-processing on best solution\n    improve(best_rects);\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n             << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_TILES = 2500;\n\n// Direction helpers\nconst char dir_chars[] = {'U', 'D', 'L', 'R'};\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\n// State: current position, visited tiles (bitmask), score, path\nstruct State {\n    int r, c;\n    array<uint64_t, 40> vis; // 2500 bits\n    int sum;\n    string path;\n\n    State() : r(0), c(0), vis{}, sum(0) {}\n};\n\n// Set / test bits for visited tiles\ninline void set_bit(array<uint64_t, 40>& bs, int id) {\n    bs[id / 64] |= (1ULL << (id % 64));\n}\ninline bool test_bit(const array<uint64_t, 40>& bs, int id) {\n    return (bs[id / 64] >> (id % 64)) & 1;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ---- Input ----\n    int si, sj;\n    cin >> si >> sj;\n\n    int tile[N][N];\n    int p[N][N];\n    int max_tile_id = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tile[i][j];\n            if (tile[i][j] > max_tile_id) max_tile_id = tile[i][j];\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> p[i][j];\n        }\n    }\n    const int M = max_tile_id + 1; // number of tiles\n\n    // ---- Precompute per\u2011cell moves (to different tile) ----\n    vector<tuple<int,int,char>> moves[N][N];\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dr[d];\n                int nj = j + dc[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (tile[i][j] != tile[ni][nj]) {\n                    moves[i][j].emplace_back(ni, nj, dir_chars[d]);\n                }\n            }\n        }\n    }\n\n    // ---- Precompute for each tile the maximum cell value ----\n    // (used in heuristic)\n    vector<int> tile_max_value(M, 0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (p[i][j] > tile_max_value[tile[i][j]])\n                tile_max_value[tile[i][j]] = p[i][j];\n\n    // ---- Beam Search Setup ----\n    const int BEAM_WIDTH = 500;\n    const double TIME_LIMIT_MS = 1900.0;\n    auto start = chrono::high_resolution_clock::now();\n\n    // Initial state\n    State start_state;\n    start_state.r = si;\n    start_state.c = sj;\n    fill(start_state.vis.begin(), start_state.vis.end(), 0ULL);\n    set_bit(start_state.vis, tile[si][sj]);\n    start_state.sum = p[si][sj];\n    start_state.path = \"\";\n\n    vector<State> beam;\n    beam.push_back(move(start_state));\n    State best_state = beam[0]; // best by score\n\n    // Helper lambda to evaluate a state: score + heuristic (best immediate neighbor)\n    auto evaluate = [&](const State& s) -> int {\n        int heu = 0;\n        for (auto [nr, nc, dir] : moves[s.r][s.c]) {\n            int nt = tile[nr][nc];\n            if (!test_bit(s.vis, nt)) {\n                heu = max(heu, p[nr][nc]);\n            }\n        }\n        return s.sum + heu; // one\u2011ply lookahead\n    };\n\n    while (true) {\n        // check time\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start).count();\n        if (elapsed > TIME_LIMIT_MS) break;\n\n        vector<pair<int, State>> candidates;\n        candidates.reserve(beam.size() * 3); // average branching\n\n        for (const auto& s : beam) {\n            for (auto [nr, nc, dir] : moves[s.r][s.c]) {\n                int nt = tile[nr][nc];\n                if (test_bit(s.vis, nt)) continue;\n\n                State ns;\n                ns.r = nr;\n                ns.c = nc;\n                ns.vis = s.vis;\n                set_bit(ns.vis, nt);\n                ns.sum = s.sum + p[nr][nc];\n                ns.path = s.path + dir;\n\n                int val = evaluate(ns);\n                candidates.emplace_back(val, move(ns));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        // Keep top BEAM_WIDTH by evaluation value\n        partial_sort(candidates.begin(),\n                     candidates.begin() + min((int)candidates.size(), BEAM_WIDTH),\n                     candidates.end(),\n                     [](const auto& a, const auto& b) { return a.first > b.first; });\n\n        int keep = min((int)candidates.size(), BEAM_WIDTH);\n        beam.clear();\n        for (int i = 0; i < keep; ++i) {\n            beam.push_back(move(candidates[i].second));\n        }\n\n        // Update global best (by actual sum)\n        for (const auto& s : beam) {\n            if (s.sum > best_state.sum) {\n                best_state = s;\n            }\n        }\n    }\n\n    // ---- Optional local extension from best state ----\n    // Greedily extend the path by always moving to the highest\u2011value unvisited neighbour\n    State cur = best_state;\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        int best_val = -1;\n        int best_nr = -1, best_nc = -1;\n        char best_dir = 0;\n        for (auto [nr, nc, dir] : moves[cur.r][cur.c]) {\n            int nt = tile[nr][nc];\n            if (!test_bit(cur.vis, nt) && p[nr][nc] > best_val) {\n                best_val = p[nr][nc];\n                best_nr = nr;\n                best_nc = nc;\n                best_dir = dir;\n            }\n        }\n        if (best_val != -1) {\n            improved = true;\n            cur.r = best_nr;\n            cur.c = best_nc;\n            set_bit(cur.vis, tile[best_nr][best_nc]);\n            cur.sum += best_val;\n            cur.path += best_dir;\n        }\n    }\n    if (cur.sum > best_state.sum) best_state = cur;\n\n    // ---- Output ----\n    cout << best_state.path << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n#include <sstream>\n#include <iomanip>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int H_EDGES = 29; // number of horizontal edges per row\nconst int V_EDGES = 29; // number of vertical edges per column (30 rows -> 29 vertical edges per column)\n\nconst double INIT_EST = 4500.0;\nconst double MIN_EDGE = 1000.0;\nconst double MAX_EDGE = 9000.0;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // estimates, counts, and sum of squared gradients for AdaGrad\n    vector<vector<double>> h_est(GRID_SIZE, vector<double>(H_EDGES, INIT_EST));\n    vector<vector<int>> h_cnt(GRID_SIZE, vector<int>(H_EDGES, 0));\n    vector<vector<double>> h_grad_sq(GRID_SIZE, vector<double>(H_EDGES, 0.0));\n\n    vector<vector<double>> v_est(V_EDGES, vector<double>(GRID_SIZE, INIT_EST));\n    vector<vector<int>> v_cnt(V_EDGES, vector<int>(GRID_SIZE, 0));\n    vector<vector<double>> v_grad_sq(V_EDGES, vector<double>(GRID_SIZE, 0.0));\n\n    // hyperparameters\n    const double lr0 = 0.5;\n    const double C_explore = 500.0;\n    const int explore_until = 400;\n\n    int T = 1000;\n    for (int k = 0; k < T; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        // exploration factor: decays linearly to 0 over first explore_until queries\n        double explore_factor = max(0.0, 1.0 - (double)k / explore_until);\n        double t_weight = sqrt(log(k + 1.0) + 1.0); // UCB time factor\n\n        // ----------------------- Dijkstra with UCB-adjusted weights -----------------------\n        const double INF = 1e18;\n        vector<vector<double>> dist(GRID_SIZE, vector<double>(GRID_SIZE, INF));\n        vector<vector<pair<int,int>>> prev(GRID_SIZE, vector<pair<int,int>>(GRID_SIZE, {-1, -1}));\n        // priority queue: (distance, (i,j))\n        priority_queue<pair<double, pair<int,int>>, vector<pair<double, pair<int,int>>>, greater<>> pq;\n        dist[si][sj] = 0.0;\n        pq.push({0.0, {si, sj}});\n\n        while (!pq.empty()) {\n            auto [d, node] = pq.top(); pq.pop();\n            int i = node.first, j = node.second;\n            if (d > dist[i][j] + 1e-9) continue;\n            if (i == ti && j == tj) break; // reached target\n\n            // neighbor: up (i-1, j) -> vertical edge (i-1, j)\n            if (i > 0) {\n                double w = v_est[i-1][j] - C_explore * t_weight / sqrt(v_cnt[i-1][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i-1][j] - 1e-9) {\n                    dist[i-1][j] = d + w;\n                    prev[i-1][j] = {i, j};\n                    pq.push({dist[i-1][j], {i-1, j}});\n                }\n            }\n            // neighbor: down (i+1, j) -> vertical edge (i, j)\n            if (i < GRID_SIZE - 1) {\n                double w = v_est[i][j] - C_explore * t_weight / sqrt(v_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i+1][j] - 1e-9) {\n                    dist[i+1][j] = d + w;\n                    prev[i+1][j] = {i, j};\n                    pq.push({dist[i+1][j], {i+1, j}});\n                }\n            }\n            // neighbor: left (i, j-1) -> horizontal edge (i, j-1)\n            if (j > 0) {\n                double w = h_est[i][j-1] - C_explore * t_weight / sqrt(h_cnt[i][j-1] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j-1] - 1e-9) {\n                    dist[i][j-1] = d + w;\n                    prev[i][j-1] = {i, j};\n                    pq.push({dist[i][j-1], {i, j-1}});\n                }\n            }\n            // neighbor: right (i, j+1) -> horizontal edge (i, j)\n            if (j < GRID_SIZE - 1) {\n                double w = h_est[i][j] - C_explore * t_weight / sqrt(h_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j+1] - 1e-9) {\n                    dist[i][j+1] = d + w;\n                    prev[i][j+1] = {i, j};\n                    pq.push({dist[i][j+1], {i, j+1}});\n                }\n            }\n        }\n\n        // backtrack to retrieve the path\n        vector<pair<int,int>> path;\n        int ci = ti, cj = tj;\n        while (!(ci == si && cj == sj)) {\n            path.push_back({ci, cj});\n            auto p = prev[ci][cj];\n            ci = p.first;\n            cj = p.second;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n\n        // construct output string (moves)\n        string out;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int di = path[idx].first - path[idx-1].first;\n            int dj = path[idx].second - path[idx-1].second;\n            if (di == -1) out += 'U';\n            else if (di == 1) out += 'D';\n            else if (dj == -1) out += 'L';\n            else if (dj == 1) out += 'R';\n        }\n        cout << out << endl; // flush included\n\n        // read feedback: observed (noisy) path length\n        int feedback;\n        cin >> feedback;\n\n        // ----------------------- Update estimates -----------------------\n        // compute predicted length using current (unadjusted) estimates\n        double L_pred = 0.0;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                L_pred += h_est[i1][jmin];\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                L_pred += v_est[imin][j1];\n            }\n        }\n\n        double error = feedback - L_pred;\n        double rel_error = error / max(L_pred, 1.0);\n        // clamp to avoid extreme updates from large mispredictions\n        rel_error = clamp(rel_error, -3.0, 3.0);\n\n        // update each edge on the path\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                // accumulate squared gradient\n                h_grad_sq[i1][jmin] += rel_error * rel_error;\n                double lr = lr0 / sqrt(h_grad_sq[i1][jmin] + 1e-8);\n                double new_val = h_est[i1][jmin] + lr * rel_error;\n                h_est[i1][jmin] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                h_cnt[i1][jmin]++;\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                v_grad_sq[imin][j1] += rel_error * rel_error;\n                double lr = lr0 / sqrt(v_grad_sq[imin][j1] + 1e-8);\n                double new_val = v_est[imin][j1] + lr * rel_error;\n                v_est[imin][j1] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                v_cnt[imin][j1]++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPH = 8;\n\nint M;\nvector<string> strs;\nvector<uint64_t> hashes;\nunordered_map<uint64_t, vector<int>> hash_to_ids;\n\nvector<string> mat; // current matrix\nvector<int> occ;    // occurrences per input string\nint matched = 0;    // number of input strings with occ>0\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// encode a string to a 64-bit integer (3 bits per character)\nuint64_t encode(const string &s) {\n    uint64_t h = 0;\n    for (char c : s) {\n        h = (h << 3) | (c - 'A');\n    }\n    return h;\n}\n\n// generate all substrings that include cell (r,c) under the assumption that\n// mat[r][c] has the given character (used for delta computation)\nvoid collect_hashes(int r, int c, char cell_char, vector<uint64_t> &out_hashes) {\n    out_hashes.clear();\n    auto get_char = [&](int i, int j) -> char {\n        if (i == r && j == c) return cell_char;\n        return mat[i][j];\n    };\n    // horizontal substrings\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_col = (c - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int col = (start_col + t) % N;\n                char ch = get_char(r, col);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out_hashes.push_back(h);\n        }\n    }\n    // vertical substrings\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_row = (r - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int row = (start_row + t) % N;\n                char ch = get_char(row, c);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out_hashes.push_back(h);\n        }\n    }\n}\n\n// compute the change in 'matched' if we set (r,c) from old_char to new_char\nint compute_delta(int r, int c, char old_char, char new_char) {\n    static vector<uint64_t> old_hashes, new_hashes;\n    static vector<int> delta_occ(M, 0);\n    static vector<int> affected_ids;\n    affected_ids.clear();\n\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]--;\n            }\n        }\n    }\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]++;\n            }\n        }\n    }\n\n    int delta_matched = 0;\n    for (int id : affected_ids) {\n        int new_occ = occ[id] + delta_occ[id];\n        if (occ[id] == 0 && new_occ > 0) delta_matched++;\n        if (occ[id] > 0 && new_occ == 0) delta_matched--;\n    }\n    // clean up\n    for (int id : affected_ids) delta_occ[id] = 0;\n    return delta_matched;\n}\n\n// apply the change: update matrix and global occ/matched\nvoid apply_change(int r, int c, char new_char) {\n    char old_char = mat[r][c];\n    if (old_char == new_char) return;\n    static vector<uint64_t> old_hashes, new_hashes;\n    // remove old substrings\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                occ[id]--;\n                if (occ[id] == 0) matched--;\n            }\n        }\n    }\n    // set new character\n    mat[r][c] = new_char;\n    // add new substrings\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (occ[id] == 0) matched++;\n                occ[id]++;\n            }\n        }\n    }\n}\n\n// compute initial occ and matched by scanning the whole matrix\nvoid compute_initial_state() {\n    fill(occ.begin(), occ.end(), 0);\n    matched = 0;\n    // scan all substrings\n    for (int r = 0; r < N; ++r) {\n        for (int len = 2; len <= 12; ++len) {\n            // horizontal\n            for (int start_col = 0; start_col < N; ++start_col) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int col = (start_col + t) % N;\n                    char ch = mat[r][col];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n            // vertical\n            for (int start_row = 0; start_row < N; ++start_row) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int row = (start_row + t) % N;\n                    char ch = mat[row][start_row]; // column is start_row? Actually vertical: column fixed = start_row? No, column should be start_row? Wait, we need a fixed column. The original code used start_row as column, which is wrong. We need to iterate over all columns. So we need a separate loop for columns.\n                    // Correct: we need to iterate over columns as well.\n                    // For each column c, we take vertical substrings starting at (start_row, c)\n                }\n                // Fix: We'll rewrite this part later.\n            }\n        }\n    }\n    // Actually we must fix the vertical scanning: \n    // For each column c, and each starting row, take vertical substrings.\n    for (int c = 0; c < N; ++c) {\n        for (int len = 2; len <= 12; ++len) {\n            for (int start_row = 0; start_row < N; ++start_row) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int row = (start_row + t) % N;\n                    char ch = mat[row][c];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// structure for a placement (for greedy)\nstruct Placement {\n    vector<int> cells;   // linear indices (r*20 + c)\n    vector<char> letters;\n};\n\n// greedy initialisation: fill matrix with as many strings as possible\nvoid greedy_initialization(vector<vector<Placement>> &placements) {\n    mat.assign(N, string(N, '.'));\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int idx : order) {\n        int best_score = -1;\n        int best_p = -1;\n        for (int p = 0; p < (int)placements[idx].size(); ++p) {\n            auto &pl = placements[idx][p];\n            int score = 0;\n            bool ok = true;\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                char cur = mat[r][c];\n                if (cur == '.') {\n                    // fine\n                } else if (cur != pl.letters[t]) {\n                    ok = false;\n                    break;\n                } else {\n                    score++;\n                }\n            }\n            if (ok && score > best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        if (best_p != -1) {\n            auto &pl = placements[idx][best_p];\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                mat[r][c] = pl.letters[t];\n            }\n        }\n    }\n    compute_initial_state();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummy;\n    cin >> dummy; // read N (always 20) and ignore\n    cin >> M;\n\n    strs.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n    }\n\n    // compute hashes and mapping\n    hashes.resize(M);\n    for (int i = 0; i < M; ++i) {\n        hashes[i] = encode(strs[i]);\n        hash_to_ids[hashes[i]].push_back(i);\n    }\n\n    // Precompute all placements for each string\n    vector<vector<Placement>> placements(M);\n    for (int i = 0; i < M; ++i) {\n        const string &s = strs[i];\n        int len = s.size();\n        placements[i].reserve(800);\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // horizontal\n                Placement ph;\n                ph.cells.reserve(len);\n                ph.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int col = (c + t) % N;\n                    ph.cells.push_back(r * N + col);\n                    ph.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(ph));\n                // vertical\n                Placement pv;\n                pv.cells.reserve(len);\n                pv.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int row = (r + t) % N;\n                    pv.cells.push_back(row * N + c);\n                    pv.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(pv));\n            }\n        }\n    }\n\n    // Resize global occ\n    occ.resize(M, 0);\n\n    // Try several greedy initializations and keep the best one\n    const int TRIES = 5;\n    int best_matched = -1;\n    vector<string> best_mat;\n    for (int t = 0; t < TRIES; ++t) {\n        greedy_initialization(placements);\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n        if (best_matched == M) break;\n    }\n    // set state to best found\n    mat = best_mat;\n    // recompute state after loading best mat (occ etc.)\n    compute_initial_state();\n\n    // Simulated Annealing\n    const int MAX_ITER = 100000;\n    double T = 1.0;\n    const double COOLING = 0.99999;\n    const double MIN_T = 1e-4;\n    int iter = 0;\n    while (matched < M && iter < MAX_ITER && T > MIN_T) {\n        int r = uniform_int_distribution<int>(0, N-1)(rng);\n        int c = uniform_int_distribution<int>(0, N-1)(rng);\n        char oldc = mat[r][c];\n        char newc;\n        do {\n            newc = 'A' + uniform_int_distribution<int>(0, ALPH-1)(rng);\n        } while (newc == oldc);\n\n        int delta = compute_delta(r, c, oldc, newc);\n        if (delta > 0) {\n            apply_change(r, c, newc);\n        } else if (delta == 0) {\n            if (uniform_real_distribution<double>(0,1)(rng) < 0.1) {\n                apply_change(r, c, newc);\n            }\n        } else {\n            double prob = exp(delta / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                apply_change(r, c, newc);\n            }\n        }\n        T *= COOLING;\n        iter++;\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n    }\n\n    // If we have all strings, try to remove cells to increase score\n    if (best_matched == M) {\n        mat = best_mat;\n        compute_initial_state(); // this already sets matched = M\n        // greedy removal: try to set each cell to '.' and keep if still all matched\n        vector<int> cell_order(N*N);\n        iota(cell_order.begin(), cell_order.end(), 0);\n        shuffle(cell_order.begin(), cell_order.end(), rng);\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int cell : cell_order) {\n                int r = cell / N, c = cell % N;\n                if (mat[r][c] == '.') continue;\n                int delta = compute_delta(r, c, mat[r][c], '.');\n                if (delta == 0) { // still all strings present\n                    apply_change(r, c, '.');\n                    changed = true;\n                }\n            }\n        }\n        best_mat = mat;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << best_mat[i] << \"\\n\";\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint16 = unsigned short;\nconst uint16 INF16 = UINT16_MAX;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int,int>> pos;       // coordinates of each road square\nvector<int> weight;              // time cost of each road square\nvector<vector<int>> adj;         // adjacency list (neighbor indices)\nint R;                           // number of road squares\n\n// map (i,j) -> id\nint id[70][70];\n\nvoid read_input() {\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    // assign ids to road squares\n    R = 0;\n    memset(id, -1, sizeof(id));\n    pos.clear();\n    weight.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R;\n                pos.emplace_back(i, j);\n                weight.push_back(grid[i][j] - '0');\n                ++R;\n            }\n        }\n    }\n    // build adjacency\n    adj.assign(R, vector<int>());\n    int di[] = {-1,1,0,0};\n    int dj[] = {0,0,-1,1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == '#') continue;\n            int u = id[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && grid[ni][nj] != '#') {\n                    int v = id[ni][nj];\n                    adj[u].push_back(v);\n                }\n            }\n        }\n    }\n}\n\n// Precompute all-pair shortest paths (distance matrix)\nvector<vector<uint16>> precompute_all_pairs() {\n    vector<vector<uint16>> dist(R, vector<uint16>(R, INF16));\n    for (int src = 0; src < R; ++src) {\n        vector<uint16> d(R, INF16);\n        d[src] = 0;\n        priority_queue<pair<uint16,int>, vector<pair<uint16,int>>, greater<pair<uint16,int>>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top(); pq.pop();\n            if (cd != d[u]) continue;\n            for (int v : adj[u]) {\n                uint16 nd = cd + weight[v];\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n        dist[src] = d;\n    }\n    return dist;\n}\n\n// Get horizontal segments\npair<vector<vector<int>>, vector<int>> get_h_segments() {\n    vector<int> h_id(R, -1);\n    vector<vector<int>> h_nodes;\n    int hcnt = 0;\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') { ++j; continue; }\n            int start = j;\n            while (j < N && grid[i][j] != '#') ++j;\n            vector<int> seg;\n            for (int k = start; k < j; ++k) {\n                int uid = id[i][k];\n                h_id[uid] = hcnt;\n                seg.push_back(uid);\n            }\n            h_nodes.push_back(seg);\n            ++hcnt;\n        }\n    }\n    return {move(h_nodes), move(h_id)};\n}\n\n// Build groups (start group + all H-segments except start's)\nvector<vector<int>> build_groups(const vector<vector<int>> &h_nodes, const vector<int> &h_id, int start_id) {\n    vector<vector<int>> groups;\n    // group 0 = start\n    groups.push_back({start_id});\n    int start_h = h_id[start_id];\n    for (size_t g = 0; g < h_nodes.size(); ++g) {\n        if ((int)g == start_h) continue;\n        groups.push_back(h_nodes[g]);\n    }\n    return groups;\n}\n\n// Compute segment distance matrix\nvector<vector<uint16>> segment_dist_matrix(const vector<vector<int>> &groups, const vector<vector<uint16>> &dist) {\n    int G = groups.size();\n    vector<vector<uint16>> D(G, vector<uint16>(G, INF16));\n    for (int i = 0; i < G; ++i) {\n        D[i][i] = 0;\n        for (int j = i+1; j < G; ++j) {\n            uint16 best = INF16;\n            for (int u : groups[i]) {\n                for (int v : groups[j]) {\n                    best = min(best, dist[u][v]);\n                }\n            }\n            D[i][j] = D[j][i] = best;\n        }\n    }\n    return D;\n}\n\n// TSP on groups with 2-opt (fix start group 0)\nvector<int> solve_tsp(const vector<vector<uint16>> &D) {\n    int G = D.size();\n    if (G <= 1) return {0};\n    vector<int> tour(G);\n    // nearest neighbour\n    vector<bool> visited(G, false);\n    tour[0] = 0;\n    visited[0] = true;\n    for (int k = 1; k < G; ++k) {\n        int cur = tour[k-1];\n        int best = -1;\n        uint16 bestDist = INF16;\n        for (int i = 0; i < G; ++i) {\n            if (!visited[i] && D[cur][i] < bestDist) {\n                bestDist = D[cur][i];\n                best = i;\n            }\n        }\n        tour[k] = best;\n        visited[best] = true;\n    }\n    // 2-opt improvement (cycle)\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i < G-1; ++i) {\n            for (int j = i+1; j < G; ++j) {\n                int a = tour[i-1];\n                int b = tour[i];\n                int c = tour[j];\n                int d = (j+1 < G) ? tour[j+1] : tour[0];\n                uint16 old = D[a][b] + D[c][d];\n                uint16 nw = D[a][c] + D[b][d];\n                if (nw < old) {\n                    reverse(tour.begin() + i, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    return tour;\n}\n\n// DP to select one node per group given a fixed order\nvector<int> select_nodes(const vector<int> &order, const vector<vector<int>> &groups, const vector<vector<uint16>> &dist) {\n    int G = order.size();\n    if (G == 1) return {groups[0][0]}; // only start\n    vector<unordered_map<int,uint16>> dp_cost(G);\n    vector<unordered_map<int,int>> dp_prev(G);\n    // initialize start group (order[0] should be 0)\n    int start_id = groups[0][0];\n    dp_cost[0][start_id] = 0;\n    for (int pos = 1; pos < G; ++pos) {\n        int g = order[pos];\n        int prev_g = order[pos-1];\n        for (int v : groups[g]) {\n            uint16 best = INF16;\n            int best_u = -1;\n            for (int u : groups[prev_g]) {\n                auto it = dp_cost[pos-1].find(u);\n                if (it != dp_cost[pos-1].end()) {\n                    uint16 cand = it->second + dist[u][v];\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n            }\n            if (best != INF16) {\n                dp_cost[pos][v] = best;\n                dp_prev[pos][v] = best_u;\n            }\n        }\n    }\n    // final step: return to start\n    uint16 total_best = INF16;\n    int last_node = -1;\n    for (int u : groups[order[G-1]]) {\n        auto it = dp_cost[G-1].find(u);\n        if (it != dp_cost[G-1].end()) {\n            uint16 cand = it->second + dist[u][start_id];\n            if (cand < total_best) {\n                total_best = cand;\n                last_node = u;\n            }\n        }\n    }\n    // backtrace\n    vector<int> selected(G);\n    selected[G-1] = last_node;\n    for (int pos = G-1; pos >= 1; --pos) {\n        int v = selected[pos];\n        int u = dp_prev[pos][v];\n        selected[pos-1] = u;\n    }\n    return selected;\n}\n\n// Reconstruct path string between two nodes\nstring get_path(int from, int to, const vector<vector<uint16>> &dist) {\n    if (from == to) return \"\";\n    // Dijkstra from 'from' to 'to'\n    vector<uint16> d(R, INF16);\n    vector<int> parent(R, -1);\n    vector<char> move_char(R, 0);\n    d[from] = 0;\n    priority_queue<pair<uint16,int>, vector<pair<uint16,int>>, greater<pair<uint16,int>>> pq;\n    pq.emplace(0, from);\n    while (!pq.empty()) {\n        auto [cd, u] = pq.top(); pq.pop();\n        if (cd != d[u]) continue;\n        if (u == to) break;\n        for (int v : adj[u]) {\n            uint16 nd = cd + weight[v];\n            if (nd < d[v]) {\n                d[v] = nd;\n                parent[v] = u;\n                // direction\n                int dx = pos[v].first - pos[u].first;\n                int dy = pos[v].second - pos[u].second;\n                if (dx == -1) move_char[v] = 'U';\n                else if (dx == 1) move_char[v] = 'D';\n                else if (dy == -1) move_char[v] = 'L';\n                else if (dy == 1) move_char[v] = 'R';\n                pq.emplace(nd, v);\n            }\n        }\n    }\n    // backtrack\n    string path;\n    int cur = to;\n    while (cur != from) {\n        path.push_back(move_char[cur]);\n        cur = parent[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n\n    // precompute all-pair distances\n    auto dist = precompute_all_pairs();\n\n    // get horizontal segments\n    auto [h_nodes, h_id] = get_h_segments();\n    int start_id = id[si][sj];\n\n    // build groups (start + all H-segments except start's)\n    auto groups = build_groups(h_nodes, h_id, start_id);\n    int G = groups.size();\n\n    // segment distance matrix\n    auto D = segment_dist_matrix(groups, dist);\n\n    // TSP on groups\n    auto order = solve_tsp(D);\n    // for each group index in order, the actual group id is order[i]\n    // Now select nodes with DP\n    vector<int> selected = select_nodes(order, groups, dist);\n\n    // build final path\n    string ans;\n    for (int i = 0; i < G-1; ++i) {\n        ans += get_path(selected[i], selected[i+1], dist);\n    }\n    ans += get_path(selected[G-1], selected[0], dist);\n\n    cout << ans << endl;\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ========== constants ==========\nconst int MAX_DAY = 2000;\nconst double INIT_SKILL_MEAN = -1.0; // placeholder\nconst double LR_GAMMA = 0.5;\nconst double EXPLORE_BETA = 0.2;\n\nint N, M, K, R;\nvector<vector<int>> d; // N x K\nvector<vector<int>> preds, succs;\nvector<int> rem_preds; // remaining predecessors\n\n// task state\nvector<int> status;   // -1: not started, 0: in progress, 1: completed\nvector<int> start_day;\nvector<int> worker_of_task;\nvector<int> actual_dur;\nvector<int> pred_dur_at_start; // predicted duration at assignment time\n\n// worker state\nvector<int> cur_task; // -1 if idle\nvector<vector<double>> skill_est; // M x K\nvector<vector<int>> skill_count;  // number of updates per skill per worker\nvector<int> assign_count; // total assignments per worker\n\n// ========== helper functions ==========\ndouble predicted_duration(int task, int worker) {\n    double w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) w += diff;\n    }\n    return (w == 0.0) ? 1.0 : (1.0 + w);\n}\n\ndouble adjusted_duration(int task, int worker, int day) {\n    double base = predicted_duration(task, worker);\n    double bonus = EXPLORE_BETA * sqrt(log(day + 1) / (1.0 + assign_count[worker]));\n    return base - bonus;   // lower is better for UCB\n}\n\nvoid update_skills(int worker, int task, int actual_t, int day) {\n    int observed_w = max(0, actual_t - 1);\n    // compute predicted w\n    double pred_w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) pred_w += diff;\n    }\n    double error = pred_w - observed_w;\n    // adaptive learning rate per skill\n    auto lr = [&](int k) -> double {\n        return LR_GAMMA / sqrt(1.0 + skill_count[worker][k]);\n    };\n    if (observed_w == 0) {\n        // worker was sufficient for all skills\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                // increase skill towards requirement\n                double delta = lr(k) * (d[task][k] - skill_est[worker][k]);\n                skill_est[worker][k] += delta;\n                skill_count[worker][k]++;\n            }\n        }\n    } else {\n        // observed_w > 0\n        // update deficient skills using gradient\n        double grad_scale = error / max(1.0, pred_w);  // normalize by total deficiency\n        for (int k = 0; k < K; ++k) {\n            double diff = d[task][k] - skill_est[worker][k];\n            if (diff > 0) {\n                double delta = lr(k) * grad_scale;\n                skill_est[worker][k] += delta;\n                skill_count[worker][k]++;\n            }\n        }\n        // special case: predicted no deficiency but actual deficiency existed\n        if (pred_w == 0.0 && observed_w > 0) {\n            // decrease skills that are above requirement\n            for (int k = 0; k < K; ++k) {\n                if (skill_est[worker][k] > d[task][k]) {\n                    skill_est[worker][k] = max(0.0, skill_est[worker][k] - lr(k) * 0.5);\n                    skill_count[worker][k]++;\n                }\n            }\n        }\n        // clamp to [0, 200]\n        for (int k = 0; k < K; ++k) {\n            if (skill_est[worker][k] < 0) skill_est[worker][k] = 0;\n            if (skill_est[worker][k] > 200) skill_est[worker][k] = 200;\n        }\n    }\n}\n\n// ========== main ==========\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- read -----\n    cin >> N >> M >> K >> R;\n    d.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < K; ++j)\n            cin >> d[i][j];\n\n    preds.assign(N, vector<int>());\n    succs.assign(N, vector<int>());\n    rem_preds.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        preds[v].push_back(u);\n        succs[u].push_back(v);\n        rem_preds[v]++;\n    }\n\n    // ----- initialize state -----\n    status.assign(N, -1);\n    start_day.assign(N, 0);\n    worker_of_task.assign(N, -1);\n    actual_dur.assign(N, 0);\n    pred_dur_at_start.assign(N, 0.0);\n    cur_task.assign(M, -1);\n    assign_count.assign(M, 0);\n    skill_est.assign(M, vector<double>(K, 0.0));\n    skill_count.assign(M, vector<int>(K, 0));\n\n    // set initial skill estimates to average task difficulty per dimension\n    vector<double> avg(K, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            avg[k] += d[i][k];\n    for (int k = 0; k < K; ++k) avg[k] /= N;\n    for (int j = 0; j < M; ++j)\n        for (int k = 0; k < K; ++k)\n            skill_est[j][k] = avg[k];\n\n    // ----- main loop -----\n    int day = 1;\n    while (true) {\n        // ==== compute finish times for tasks (actual/estimated) ====\n        vector<double> finish_time(N, -1e9);\n        // forward pass: topological order (0..N-1 because u<v)\n        for (int i = 0; i < N; ++i) {\n            if (status[i] == 1) {\n                finish_time[i] = start_day[i] + actual_dur[i] - 1.0;\n            } else if (status[i] == 0) {\n                double orig = pred_dur_at_start[i];\n                double remain = max(0.0, orig - (day - start_day[i]));\n                finish_time[i] = day + remain - 1.0;\n            } else {\n                // unstarted: compute earliest start from predecessors\n                double latest_pred_finish = 0.0;\n                for (int p : preds[i]) {\n                    if (finish_time[p] > latest_pred_finish) latest_pred_finish = finish_time[p];\n                }\n                double est_start = max(1.0, latest_pred_finish + 1.0);\n                // optimistic duration = min over workers\n                double best_dur = 1e9;\n                for (int j = 0; j < M; ++j) {\n                    double dur = predicted_duration(i, j);\n                    if (dur < best_dur) best_dur = dur;\n                }\n                finish_time[i] = est_start + best_dur - 1.0;\n            }\n        }\n        double D_est = 0.0;\n        for (int i = 0; i < N; ++i) if (finish_time[i] > D_est) D_est = finish_time[i];\n        if (D_est < day) D_est = day; // at least today\n\n        // backward pass: compute LST for unstarted tasks only\n        vector<double> LST(N, D_est);\n        for (int i = N - 1; i >= 0; --i) {\n            if (status[i] == 1 || status[i] == 0) {\n                // already fixed; ignore in scoping\n                // for slack calculation of predecessors, we need finish_time of successors\n                continue;\n            }\n            // unstarted\n            double min_succ_lst = D_est;\n            for (int s : succs[i]) {\n                double lst_s;\n                if (status[s] == 1 || status[s] == 0) {\n                    // use finish_time[s] as deadline for i\n                    lst_s = finish_time[s] + 1.0; // must finish day before s starts? Actually s cannot start before i finishes. So i must finish at or before start of s. The start of s is max( pred finish +1). For schedule, i's finish must be \u2264 start_s-1? The dependency: i must be completed by end of day before s starts. So if s' finish_time (which is end of day) is known, then i must finish \u2264 finish_time(s) - actual_dur(s) - 1? This is messy. For simplicity, we treat the backward pass using the same estimated start: i must finish \u2264 LST[s] - 1 (since s can start at LST[s] if i finishes by day LST[s]-1).\n                    lst_s = finish_time[s];\n                } else {\n                    lst_s = LST[s];\n                }\n                // i must finish by lst_s - 1 (since s starts at lst_s)\n                double lft_i = lst_s - 1.0;\n                // estimated duration of i (optimistic)\n                double dur_i = 1e9;\n                for (int j = 0; j < M; ++j) {\n                    double dur = predicted_duration(i, j);\n                    if (dur < dur_i) dur_i = dur;\n                }\n                double lst_i = lft_i - dur_i + 1.0;\n                if (lst_i < min_succ_lst) min_succ_lst = lst_i;\n            }\n            if (min_succ_lst < finish_time[i] - (predicted_duration(i,0) - 1.0)) // not needed\n                LST[i] = min_succ_lst;\n        }\n\n        // ==== collect ready tasks ====\n        vector<int> ready;\n        for (int i = 0; i < N; ++i) {\n            if (status[i] == -1 && rem_preds[i] == 0) ready.push_back(i);\n        }\n\n        // ==== compute slack for each ready task ====\n        // slack = LST - EST (EST is finish_time - dur + 1)\n        vector<pair<double, int>> slack_ready;\n        for (int i : ready) {\n            double est_start = max(1.0, finish_time[i] - (1.0) + 1.0); // finish_time = est_start + dur -1 => est_start = finish_time - dur +1\n            double dur_i = 1e9;\n            for (int j = 0; j < M; ++j) {\n                double dur = predicted_duration(i, j);\n                if (dur < dur_i) dur_i = dur;\n            }\n            double est = finish_time[i] - dur_i + 1.0;\n            double slack = LST[i] - est;\n            slack_ready.emplace_back(slack, i);\n        }\n        sort(slack_ready.begin(), slack_ready.end()); // most critical first\n\n        // ==== idle workers ====\n        vector<int> idle;\n        for (int j = 0; j < M; ++j) if (cur_task[j] == -1) idle.push_back(j);\n\n        // ==== assignment using UCB ====\n        vector<int> assign_out; // flattened: worker, task pairs (0-indexed)\n        for (auto &p : slack_ready) {\n            if (idle.empty()) break;\n            int task = p.second;\n            // choose best idle worker using adjusted duration (UCB)\n            int best_worker = -1;\n            double best_adj = 1e9;\n            for (int j : idle) {\n                double adj = adjusted_duration(task, j, day);\n                if (adj < best_adj) {\n                    best_adj = adj;\n                    best_worker = j;\n                }\n            }\n            // assign\n            assign_out.push_back(best_worker);\n            assign_out.push_back(task);\n            cur_task[best_worker] = task;\n            start_day[task] = day;\n            worker_of_task[task] = best_worker;\n            pred_dur_at_start[task] = predicted_duration(task, best_worker);\n            status[task] = 0;\n            assign_count[best_worker]++;\n            // remove worker from idle\n            auto it = find(idle.begin(), idle.end(), best_worker);\n            if (it != idle.end()) {\n                *it = idle.back();\n                idle.pop_back();\n            }\n        }\n\n        // ==== output ====\n        int m = assign_out.size() / 2;\n        cout << m;\n        for (int idx = 0; idx < (int)assign_out.size(); ++idx) {\n            cout << ' ' << (assign_out[idx] + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        // ==== read input ====\n        int dummy;\n        cin >> dummy;\n        if (dummy == -1) break; // all tasks done or day 2000\n\n        // process completed workers\n        for (int i = 0; i < dummy; ++i) {\n            int worker;\n            cin >> worker;\n            --worker;\n            int task = cur_task[worker];\n            int duration = day - start_day[task] + 1;\n            // mark completed\n            status[task] = 1;\n            actual_dur[task] = duration;\n            cur_task[worker] = -1;\n            // update skill estimates\n            update_skills(worker, task, duration, day);\n            // update remaining predecessors of successors\n            for (int s : succs[task]) {\n                rem_preds[s]--;\n            }\n        }\n        ++day;\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nconst int DEPOT_ID = 2000;\nconst int NUM_ORDERS = 1000;\nconst int NUM_SELECT = 50;\nconst int COORD_MAX = 800;\nconst int CENTER = 400;\n\n// Manhattan distance\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    srand(time(0));\n\n    // Read input\n    vector<pair<int,int>> pickup(NUM_ORDERS), delivery(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int a,b,c,d;\n        cin >> a >> b >> c >> d;\n        pickup[i] = {a,b};\n        delivery[i] = {c,d};\n    }\n\n    // Node coordinates: for order i: pickup node = 2*i, delivery node = 2*i+1, depot = DEPOT_ID\n    vector<int> node_x(2001), node_y(2001);\n    node_x[DEPOT_ID] = node_y[DEPOT_ID] = CENTER;\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        node_x[2*i] = pickup[i].first;\n        node_y[2*i] = pickup[i].second;\n        node_x[2*i+1] = delivery[i].first;\n        node_y[2*i+1] = delivery[i].second;\n    }\n\n    // Precompute distance matrix (2001 x 2001)\n    vector<vector<int>> dist(2001, vector<int>(2001));\n    for (int i = 0; i < 2001; ++i) {\n        for (int j = 0; j < 2001; ++j) {\n            dist[i][j] = manhattan(node_x[i], node_y[i], node_x[j], node_y[j]);\n        }\n    }\n\n    // ----- Construction: cheapest insertion (pickup+delivery as a block) -----\n    vector<int> route = {DEPOT_ID, DEPOT_ID}; // start and end\n    int total_dist = 0; // sum of distances along the route\n    vector<bool> selected(NUM_ORDERS, false);\n    int selected_cnt = 0;\n\n    while (selected_cnt < NUM_SELECT) {\n        int best_order = -1;\n        int best_pos = -1;\n        int best_inc = INT_MAX;\n        for (int i = 0; i < NUM_ORDERS; ++i) {\n            if (selected[i]) continue;\n            int p = 2*i;   // pickup node id\n            int d = 2*i+1; // delivery node id\n            int L = route.size();\n            for (int pos = 0; pos < L-1; ++pos) {\n                int left = route[pos];\n                int right = route[pos+1];\n                // increase if we insert [p, d] between left and right\n                int inc = -dist[left][right] + dist[left][p] + dist[p][d] + dist[d][right];\n                if (inc < best_inc) {\n                    best_inc = inc;\n                    best_order = i;\n                    best_pos = pos;\n                }\n            }\n        }\n        // Insert the best order\n        selected[best_order] = true;\n        int p = 2*best_order;\n        int d = 2*best_order+1;\n        int pos = best_pos;\n        route.insert(route.begin() + pos + 1, {p, d}); // insert after pos\n        total_dist += best_inc;\n        ++selected_cnt;\n    }\n\n    // Now route has 2 depots and 100 customer nodes -> size = 102\n    // total_dist is sum of edge lengths\n\n    // ----- Local Search: Simulated Annealing -----\n    vector<int> best_route = route;\n    int best_total = total_dist;\n\n    auto start_time = chrono::steady_clock::now();\n    double elapsed_time = 0.0;\n    double temperature = 1000.0;\n    const double cooling_rate = 0.999;\n    const int max_iter = 300000; // safety limit\n\n    // Helper function to compute total distance of a route (O(n))\n    auto compute_total = [&](const vector<int>& r) {\n        int n = r.size();\n        int tot = 0;\n        for (int i = 0; i < n-1; ++i) {\n            tot += dist[r[i]][r[i+1]];\n        }\n        return tot;\n    };\n\n    // Helper function to check precedence constraints for all orders\n    auto is_feasible = [&](const vector<int>& r) {\n        // For each order, find positions of pickup and delivery\n        vector<int> first_occur(2*NUM_ORDERS, -1);\n        vector<int> second_occur(2*NUM_ORDERS, -1);\n        int n = r.size();\n        for (int i = 0; i < n; ++i) {\n            int node = r[i];\n            if (node == DEPOT_ID) continue;\n            int order = node / 2;\n            int type = node % 2; // 0=pickup, 1=delivery\n            if (type == 0) {\n                // pickup\n                if (first_occur[node] == -1) first_occur[node] = i;\n                else return false; // duplicate pickup? not possible\n            } else {\n                // delivery\n                if (second_occur[node] == -1) second_occur[node] = i;\n                else return false;\n            }\n        }\n        // Check each order\n        for (int i = 0; i < NUM_ORDERS; ++i) {\n            int p = 2*i;\n            int d = 2*i+1;\n            if (first_occur[p] == -1 || second_occur[d] == -1) continue; // not selected? but all selected in our route\n            if (first_occur[p] > second_occur[d]) return false;\n        }\n        return true;\n    };\n\n    // SA loop\n    for (int iter = 0; iter < max_iter; ++iter) {\n        auto now = chrono::steady_clock::now();\n        elapsed_time = chrono::duration_cast<chrono::duration<double>>(now - start_time).count();\n        if (elapsed_time > 1.9) break;\n\n        // Generate random move type: 0=relocate, 1=swap\n        int move_type = rand() % 2;\n        vector<int> new_route = route;\n        int delta = 0;\n        bool feasible = false;\n\n        if (move_type == 0) {\n            // Relocate: pick a random non-depot node and move it to another position\n            int n = new_route.size();\n            int idx = rand() % (n-2) + 1; // 1..n-2\n            int new_pos = rand() % (n-1); // insert before new_pos (0..n-2)\n            // ensure new_pos != idx (difficult after removal, so we generate and later adjust)\n            int node = new_route[idx];\n            new_route.erase(new_route.begin() + idx);\n            // now size = n-1\n            // new_pos must be in 0..new_size\n            if (new_pos > new_route.size()) new_pos = new_route.size();\n            // avoid inserting at same position? if new_pos == idx after removal, it's okay but trivial\n            new_route.insert(new_route.begin() + new_pos, node);\n            // compute total distance quickly? We'll just compute full\n            int new_total = compute_total(new_route);\n            delta = new_total - total_dist;\n            feasible = is_feasible(new_route);\n        } else {\n            // Swap two non-depot nodes\n            int n = new_route.size();\n            int i = rand() % (n-2) + 1;\n            int j = rand() % (n-2) + 1;\n            if (i == j) continue;\n            swap(new_route[i], new_route[j]);\n            int new_total = compute_total(new_route);\n            delta = new_total - total_dist;\n            feasible = is_feasible(new_route);\n        }\n\n        if (feasible) {\n            double accept_prob = 1.0;\n            if (delta > 0) {\n                accept_prob = exp(-delta / temperature);\n            }\n            if ((double)rand() / RAND_MAX < accept_prob) {\n                route = new_route;\n                total_dist = compute_total(route); // update\n                if (total_dist < best_total) {\n                    best_total = total_dist;\n                    best_route = route;\n                }\n            }\n        }\n        temperature *= cooling_rate;\n    }\n\n    // Build output: list of selected orders (in some order; we can output in the order they appear in route)\n    // Find selected orders from the best route\n    vector<int> selected_orders;\n    for (int node : best_route) {\n        if (node == DEPOT_ID) continue;\n        int order = node / 2;\n        if (selected_orders.empty() || selected_orders.back() != order) {\n            selected_orders.push_back(order);\n        }\n    }\n    // double-check size\n    if (selected_orders.size() != NUM_SELECT) {\n        // should not happen, but fallback: use construction order\n        for (int i = 0; i < NUM_ORDERS; ++i) if (selected[i]) selected_orders.push_back(i);\n    }\n\n    // Output final result\n    cout << NUM_SELECT;\n    for (int o : selected_orders) cout << \" \" << o+1; // 1-indexed output\n    cout << '\\n';\n\n    int n = best_route.size();\n    cout << n;\n    for (int node : best_route) {\n        cout << \" \" << node_x[node] << \" \" << node_y[node];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, rank;\n    DSU(int n) {\n        parent.resize(n);\n        rank.resize(n, 0);\n        for (int i = 0; i < n; ++i) parent[i] = i;\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) swap(x, y);\n        parent[y] = x;\n        if (rank[x] == rank[y]) ++rank[x];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    // read vertex coordinates\n    vector<pair<int, int>> coord(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coord[i].first >> coord[i].second;\n    }\n\n    // read edges (only endpoints)\n    struct Edge { int u, v, d; };\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = coord[u].first - coord[v].first;\n        int dy = coord[u].second - coord[v].second;\n        double dist = sqrt(dx * dx + dy * dy);\n        int d = round(dist);\n        edges[i] = {u, v, d};\n    }\n\n    // build MST based on the rounded Euclidean distance d\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return edges[a].d < edges[b].d;\n    });\n\n    DSU dsu(N);\n    vector<bool> in_mst(M, false);\n    int accepted = 0;\n    for (int idx : order) {\n        auto &e = edges[idx];\n        if (dsu.unite(e.u, e.v)) {\n            in_mst[idx] = true;\n            ++accepted;\n            if (accepted == N - 1) break;\n        }\n    }\n\n    // online phase \u2013 adopt exactly the edges of the precomputed MST\n    for (int i = 0; i < M; ++i) {\n        long long l;\n        cin >> l;                // read true length\n        if (in_mst[i]) {\n            cout << \"1\\n\";\n        } else {\n            cout << \"0\\n\";\n        }\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int MAXT = 300;\nconst int MAXN = 20;\nconst int MAXM = 10;\n\nint N, M;\nint pet_x[MAXN], pet_y[MAXN], pet_type[MAXN];\nint human_x[MAXM], human_y[MAXM];\n\nbool impassable[GRID+2][GRID+2]; // 1-indexed\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char move_ch[4] = {'U','D','L','R'};\nconst char block_ch[4] = {'u','d','l','r'};\n\ninline bool inside(int x, int y) {\n    return 1 <= x && x <= GRID && 1 <= y && y <= GRID;\n}\n\n// BFS structure\nstruct BFSResult {\n    int area;\n    int pet_cnt;\n    vector<pair<int,int>> boundary; // cells in region with at least one neighbor outside region\n};\n\n// BFS from (sx,sy) on the given impassable grid. Returns area, pet count, and boundary.\nBFSResult bfs(int sx, int sy, const bool tmp_impassable[GRID+2][GRID+2],\n              const int start_pet_x[], const int start_pet_y[]) {\n    static bool visited[GRID+2][GRID+2];\n    static int visited_turn = 0; // timestamp to avoid memset\n    ++visited_turn;\n\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    visited[sx][sy] = true;\n    int area = 1;\n    BFSResult res;\n    res.boundary.clear();\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        // check if this cell is a boundary (any neighbor outside region)\n        bool is_boundary = false;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_impassable[nx][ny]) continue;\n            if (visited[nx][ny] == true) continue; // already visited\n            // neighbor not yet visited: it is inside the region, will be visited later\n        }\n        // Actually, we need to detect boundary: a cell is boundary if at least one adjacent cell is either impassable or outside grid (impassable) or not visited (but will be visited). The boundary definition: cells that have at least one neighbor that is not passable (i.e., impassable or outside). Since we haven't visited all neighbors yet, we can check after BFS.\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny) || tmp_impassable[nx][ny]) {\n                is_boundary = true;\n                break;\n            }\n        }\n        if (is_boundary) res.boundary.push_back({x, y});\n\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_impassable[nx][ny]) continue;\n            if (visited[nx][ny]) continue;\n            visited[nx][ny] = true;\n            q.push({nx, ny});\n            ++area;\n        }\n    }\n\n    // Count pets inside region\n    int pet_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        if (visited[start_pet_x[i]][start_pet_y[i]]) ++pet_cnt;\n    }\n    res.area = area;\n    res.pet_cnt = pet_cnt;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N;\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_x[i] >> pet_y[i] >> pet_type[i];\n    }\n    cin >> M;\n    for (int i = 0; i < M; ++i) {\n        cin >> human_x[i] >> human_y[i];\n    }\n\n    // Initialize impassable (all passable)\n    memset(impassable, 0, sizeof(impassable));\n\n    for (int turn = 0; turn < MAXT; ++turn) {\n        // Record start positions\n        int start_hx[MAXM], start_hy[MAXM];\n        int start_px[MAXN], start_py[MAXN];\n        for (int i = 0; i < M; ++i) {\n            start_hx[i] = human_x[i];\n            start_hy[i] = human_y[i];\n        }\n        for (int i = 0; i < N; ++i) {\n            start_px[i] = pet_x[i];\n            start_py[i] = pet_y[i];\n        }\n\n        // copy current impassable\n        bool cur_impassable[GRID+2][GRID+2];\n        memcpy(cur_impassable, impassable, sizeof(impassable));\n\n        int cur_hx[MAXM], cur_hy[MAXM];\n        memcpy(cur_hx, start_hx, sizeof(int)*M);\n        memcpy(cur_hy, start_hy, sizeof(int)*M);\n\n        char actions[MAXM];\n\n        // Process each human sequentially\n        for (int i = 0; i < M; ++i) {\n            int sx = cur_hx[i], sy = cur_hy[i];\n            BFSResult br = bfs(sx, sy, cur_impassable, start_px, start_py);\n\n            char best_action = '.';\n            // Decide action\n            if (br.pet_cnt > 0) {\n                // Try to block a boundary cell that is adjacent to a pet (outside)\n                // Also try to move away from pets? For now, just try to block.\n                bool found = false;\n                for (auto [bx, by] : br.boundary) {\n                    // Check if this boundary cell is adjacent to any pet (outside region)\n                    bool adj_pet = false;\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = bx + dx[d], ay = by + dy[d];\n                        if (!inside(ax, ay)) continue;\n                        // Check if a pet is at (ax,ay) (start positions)\n                        for (int p = 0; p < N; ++p) {\n                            if (start_px[p] == ax && start_py[p] == ay) {\n                                adj_pet = true;\n                                break;\n                            }\n                        }\n                        if (adj_pet) break;\n                    }\n                    if (adj_pet) {\n                        // We want to block this boundary cell to prevent pet from entering\n                        // Verify block conditions: cell must be passable, not contain human/pet at start, not adjacent to any pet\n                        if (cur_impassable[bx][by]) continue;\n                        // must not contain any start human or pet\n                        bool occupied = false;\n                        for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                        if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                        if (occupied) continue;\n                        // must not be adjacent to any pet (the block rule)\n                        bool adj_pet2 = false;\n                        for (int d = 0; d < 4; ++d) {\n                            int ax = bx + dx[d], ay = by + dy[d];\n                            if (!inside(ax, ay)) continue;\n                            for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet2 = true; break; }\n                            if (adj_pet2) break;\n                        }\n                        if (adj_pet2) continue;\n                        // Found a valid block\n                        // Determine direction relative to human (sx,sy)\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = block_ch[d];\n                                found = true;\n                                break;\n                            }\n                        }\n                        if (found) break;\n                    }\n                }\n                if (!found) {\n                    // If no good block, try to move to a boundary cell that is not adjacent to any pet inside? Just stay.\n                    // Maybe move to a boundary cell to expand region? But region already has pets, moving won't help.\n                    best_action = '.';\n                }\n            } else {\n                // No pet inside region. We want to expand or seal.\n                // First, try to block any boundary cell that is adjacent to an outside pet to prevent entry.\n                bool blocked = false;\n                for (auto [bx, by] : br.boundary) {\n                    // Check adjacent pets (outside region)\n                    bool adj_pet = false;\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = bx + dx[d], ay = by + dy[d];\n                        if (!inside(ax, ay)) continue;\n                        for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet = true; break; }\n                        if (adj_pet) break;\n                    }\n                    if (adj_pet) {\n                        // Try to block this boundary cell\n                        // Check conditions\n                        if (cur_impassable[bx][by]) continue;\n                        bool occupied = false;\n                        for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                        if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                        if (occupied) continue;\n                        bool adj_pet2 = false;\n                        for (int d = 0; d < 4; ++d) {\n                            int ax = bx + dx[d], ay = by + dy[d];\n                            if (!inside(ax, ay)) continue;\n                            for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet2 = true; break; }\n                            if (adj_pet2) break;\n                        }\n                        if (adj_pet2) continue;\n                        // valid block\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = block_ch[d];\n                                blocked = true;\n                                break;\n                            }\n                        }\n                        if (blocked) break;\n                    }\n                }\n                if (!blocked) {\n                    // No pet adjacent to boundary. Try to move to a boundary cell to expand.\n                    // Choose a boundary cell that is not occupied at start, and not adjacent to any pet (to avoid bringing one in).\n                    pair<int,int> best_move = {-1, -1};\n                    for (auto [bx, by] : br.boundary) {\n                        // check if this cell is passable and reachable by move (adjacent to human)\n                        if (abs(bx - sx) + abs(by - sy) == 1 && !cur_impassable[bx][by]) {\n                            // Check not occupied at start\n                            bool occupied = false;\n                            for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                            if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                            if (occupied) continue;\n                            // Check if this boundary cell is adjacent to any pet (outside)\n                            bool adj_pet = false;\n                            for (int d = 0; d < 4; ++d) {\n                                int ax = bx + dx[d], ay = by + dy[d];\n                                if (!inside(ax, ay)) continue;\n                                for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet = true; break; }\n                                if (adj_pet) break;\n                            }\n                            if (adj_pet) continue; // don't move to a cell adjacent to a pet (might bring it in)\n                            // Accept this move\n                            best_move = {bx, by};\n                            break;\n                        }\n                    }\n                    if (best_move.first != -1) {\n                        int bx = best_move.first, by = best_move.second;\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = move_ch[d];\n                                break;\n                            }\n                        }\n                    } else {\n                        // Can't move; try to block a random boundary cell? Or stay.\n                        best_action = '.';\n                    }\n                }\n            }\n\n            // Execute action\n            if (best_action == '.') {\n                // do nothing\n            } else {\n                bool is_move = false;\n                int d = -1;\n                for (int k = 0; k < 4; ++k) {\n                    if (best_action == move_ch[k]) { is_move = true; d = k; break; }\n                    if (best_action == block_ch[k]) { d = k; break; }\n                }\n                int nx = sx + dx[d], ny = sy + dy[d];\n                if (is_move) {\n                    cur_hx[i] = nx;\n                    cur_hy[i] = ny;\n                } else {\n                    cur_impassable[nx][ny] = true;\n                }\n            }\n            actions[i] = best_action;\n        }\n\n        // Output actions\n        for (int i = 0; i < M; ++i) cout << actions[i];\n        cout << endl;\n        cout.flush();\n\n        // Read pet moves\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            if (s == \".\") continue;\n            int x = pet_x[i], y = pet_y[i];\n            for (char c : s) {\n                if (c == 'U') { x -= 1; }\n                else if (c == 'D') { x += 1; }\n                else if (c == 'L') { y -= 1; }\n                else if (c == 'R') { y += 1; }\n            }\n            pet_x[i] = x;\n            pet_y[i] = y;\n        }\n\n        // Update global impassable\n        memcpy(impassable, cur_impassable, sizeof(impassable));\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(20);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    vector<string> v(19);\n    for (int i = 0; i < 19; ++i) cin >> v[i];\n\n    // BFS to find the shortest path from start to goal\n    const int INF = 1e9;\n    vector<vector<int>> dist(20, vector<int>(20, INF));\n    vector<vector<pair<int, int>>> parent(20, vector<pair<int, int>>(20, {-1, -1}));\n    queue<pair<int, int>> q;\n    dist[si][sj] = 0;\n    q.emplace(si, sj);\n\n    // directions: D, R, U, L\n    const int dr[] = {1, 0, -1, 0};\n    const int dc[] = {0, 1, 0, -1};\n    const char dirs[] = {'D', 'R', 'U', 'L'};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        if (i == ti && j == tj) break;\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + dr[d], nj = j + dc[d];\n            if (ni < 0 || ni >= 20 || nj < 0 || nj >= 20) continue;\n            bool ok = false;\n            if (d == 0) { // down\n                if (i < 19 && v[i][j] == '0') ok = true;\n            } else if (d == 1) { // right\n                if (j < 19 && h[i][j] == '0') ok = true;\n            } else if (d == 2) { // up\n                if (i > 0 && v[i-1][j] == '0') ok = true;\n            } else { // left\n                if (j > 0 && h[i][j-1] == '0') ok = true;\n            }\n            if (ok && dist[ni][nj] > dist[i][j] + 1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                parent[ni][nj] = {i, j};\n                q.emplace(ni, nj);\n            }\n        }\n    }\n\n    // Reconstruct the path as a string of moves\n    string path;\n    int ci = ti, cj = tj;\n    while (!(ci == si && cj == sj)) {\n        auto [pi, pj] = parent[ci][cj];\n        if (pi == -1) break; // should not happen\n        int d = -1;\n        if (pi + 1 == ci && pj == cj) d = 0;       // down\n        else if (pi - 1 == ci && pj == cj) d = 2; // up\n        else if (pi == ci && pj + 1 == cj) d = 1; // right\n        else if (pi == ci && pj - 1 == cj) d = 3; // left\n        path.push_back(dirs[d]);\n        ci = pi; cj = pj;\n    }\n    reverse(path.begin(), path.end());\n\n    // Build the final string of length exactly 200 by repeating the path\n    string ans;\n    int L = (int)path.size();\n    if (L > 0) {\n        int repeat = 200 / L;\n        int rem = 200 % L;\n        for (int i = 0; i < repeat; ++i) ans += path;\n        ans += path.substr(0, rem);\n    }\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstring>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst int N = 30;\nconst int M = N * N; // 900\n\n// direction arrays: 0:left, 1:up, 2:right, 3:down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to[t][d] = exit direction when entering tile t from direction d, -1 if invalid\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0\n    {3, -1, -1, 0},  // 1\n    {-1, -1, 3, 2},  // 2\n    {-1, 2, 1, -1},  // 3\n    {1, 0, 3, 2},    // 4\n    {3, 2, 1, 0},    // 5\n    {2, -1, 0, -1},  // 6\n    {-1, 3, -1, 1}   // 7\n};\n\n// rotate function: given original type t and rotation r (0..3), return the effective state\ninline int rotate(int t, int r) {\n    if (t < 4) return (t + r) % 4;                     // single curve\n    if (t < 6) return 4 + ((t - 4 + r) % 2);          // double curve (4<->5)\n    return 6 + ((t - 6 + r) % 2);                     // straight (6<->7)\n}\n\n// evaluate the board state and return L1 * L2\nint evaluate(const int* state) {\n    // visited flags for each half-edge (tile, direction)\n    char visited[M * 4] = {0};\n\n    int best = 0, second = 0;\n\n    for (int idx = 0; idx < M; ++idx) {\n        int i = idx / N;\n        int j = idx % N;\n        int s = state[idx];\n\n        for (int d = 0; d < 4; ++d) {\n            if (to[s][d] == -1) continue;\n            int vidx = idx * 4 + d;\n            if (visited[vidx]) continue;\n\n            // start tracing\n            int ci = i, cj = j, cd = d;\n            int len = 0;\n            bool is_cycle = false;\n\n            while (true) {\n                visited[(ci * N + cj) * 4 + cd] = 1;\n                int d2 = to[state[ci * N + cj]][cd];\n                if (d2 == -1) break;                     // broken track (should not happen)\n                int ni = ci + di[d2];\n                int nj = cj + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) break; // out of board\n                cd = (d2 + 2) & 3;                      // opposite direction at neighbour\n                ci = ni;\n                cj = nj;\n                len++;\n                if (ci == i && cj == j && cd == d) {\n                    is_cycle = true;\n                    break;\n                }\n            }\n\n            if (is_cycle) {\n                if (len > best) {\n                    second = best;\n                    best = len;\n                } else if (len > second) {\n                    second = len;\n                }\n            }\n            // non\u2011cycle paths are also marked visited (they cannot be part of a cycle)\n        }\n    }\n\n    return best * second;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read original tile types\n    vector<int> orig(M);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            orig[i * N + j] = s[j] - '0';\n        }\n    }\n\n    // random number generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist4(0, 3);\n    uniform_int_distribution<int> dist900(0, M - 1);\n\n    // current state and rotation\n    vector<int> state(M), rot(M);\n    // best found\n    vector<int> best_rot(M);\n    int best_score = 0;\n\n    auto start_time = chrono::steady_clock::now();\n    long long step = 0;\n\n    // initial random state\n    for (int i = 0; i < M; ++i) {\n        rot[i] = dist4(rng);\n        state[i] = rotate(orig[i], rot[i]);\n    }\n    int cur_score = evaluate(state.data());\n    if (cur_score > best_score) {\n        best_score = cur_score;\n        best_rot = rot;\n    }\n\n    // hill\u2011climbing loop\n    while (true) {\n        // time check every 1000 steps\n        if (step % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n            if (elapsed >= 1900) break;\n        }\n\n        // choose a random tile and a new rotation\n        int idx = dist900(rng);\n        int r_old = rot[idx];\n        int r_new = (r_old + 1 + (rng() % 3)) % 4; // guarantee different\n        int old_state = state[idx];\n        int new_state = rotate(orig[idx], r_new);\n\n        // apply candidate\n        state[idx] = new_state;\n        rot[idx] = r_new;\n        int new_score = evaluate(state.data());\n\n        if (new_score > cur_score) {\n            cur_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                best_rot = rot;\n            }\n        } else {\n            // revert\n            state[idx] = old_state;\n            rot[idx] = r_old;\n        }\n\n        ++step;\n\n        // periodic restart to escape local optima\n        if (step % 200000 == 0) {\n            for (int i = 0; i < M; ++i) {\n                rot[i] = dist4(rng);\n                state[i] = rotate(orig[i], rot[i]);\n            }\n            cur_score = evaluate(state.data());\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_rot = rot;\n            }\n        }\n    }\n\n    // output the best rotation string\n    for (int i = 0; i < M; ++i) {\n        cout << best_rot[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- union-find (identical to before) ----------\nstruct DSU {\n    vector<int> parent, sz, edges;\n    DSU(int n) : parent(n), sz(n, 1), edges(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (x != parent[x]) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) {\n            edges[a]++;\n            return;\n        }\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        edges[a] += edges[b] + 1;\n    }\n};\n\nint largest_tree(const vector<int>& board, int N) {\n    DSU dsu(N * N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            int tile = board[id];\n            if (tile == 0) continue;\n            // right\n            if (j + 1 < N && board[id + 1] != 0 &&\n                (tile & 4) && (board[id + 1] & 1)) {\n                dsu.unite(id, id + 1);\n            }\n            // down\n            if (i + 1 < N && board[id + N] != 0 &&\n                (tile & 8) && (board[id + N] & 2)) {\n                dsu.unite(id, id + N);\n            }\n        }\n    }\n    int best = 0;\n    for (int i = 0; i < N * N; ++i) {\n        if (board[i] == 0) continue;\n        if (dsu.find(i) == i) {\n            if (dsu.edges[i] == dsu.sz[i] - 1) {\n                best = max(best, dsu.sz[i]);\n            }\n        }\n    }\n    return best;\n}\n\n// ---------- beam search ----------\nstruct State {\n    vector<int> board;\n    int ei, ej;\n    string moves;\n    int score; // largest tree size\n\n    bool operator<(const State& o) const {\n        if (score != o.score) return score > o.score;\n        return moves.size() < o.moves.size();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    int total_cells = N * N;\n    int full = total_cells - 1;\n\n    vector<string> raw(N);\n    vector<int> init_board(total_cells);\n    int ei = -1, ej = -1;\n    for (int i = 0; i < N; ++i) {\n        cin >> raw[i];\n        for (int j = 0; j < N; ++j) {\n            char c = raw[i][j];\n            int val;\n            if (isdigit(c)) val = c - '0';\n            else val = 10 + (c - 'a');\n            init_board[i * N + j] = val;\n            if (val == 0) { ei = i; ej = j; }\n        }\n    }\n\n    int init_score = largest_tree(init_board, N);\n    if (init_score == full) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    const char dir_ch[] = {'U', 'D', 'L', 'R'};\n\n    // beam width\n    const int BEAM_WIDTH = 30;\n\n    vector<State> cur;\n    cur.push_back({init_board, ei, ej, \"\", init_score});\n\n    int best_score = init_score;\n    string best_moves = \"\";\n\n    unordered_set<size_t> seen_this_step;\n\n    for (int step = 0; step < T; ++step) {\n        if (best_score == full) break;\n\n        vector<State> candidates;\n        seen_this_step.clear();\n\n        for (auto& s : cur) {\n            for (int d = 0; d < 4; ++d) {\n                int ni = s.ei + di[d];\n                int nj = s.ej + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n\n                // apply move\n                vector<int> nb = s.board;\n                int src_id = s.ei * N + s.ej;\n                int dst_id = ni * N + nj;\n                swap(nb[src_id], nb[dst_id]);\n\n                // hash to avoid duplicates in this step\n                size_t h = 0;\n                for (int v : nb) h = h * 1000000007 + v; // simple hash\n                if (seen_this_step.count(h)) continue;\n                seen_this_step.insert(h);\n\n                int new_score = largest_tree(nb, N);\n                string new_moves = s.moves + dir_ch[d];\n                if ((int)new_moves.size() > T) continue;\n\n                candidates.push_back({move(nb), ni, nj, move(new_moves), new_score});\n\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    best_moves = s.moves + dir_ch[d];\n                    if (best_score == full) break; // found perfect solution\n                }\n            }\n            if (best_score == full) break;\n        }\n\n        if (best_score == full) break;\n\n        if (candidates.empty()) break;\n\n        // sort and keep best\n        sort(candidates.begin(), candidates.end());\n        if ((int)candidates.size() > BEAM_WIDTH)\n            candidates.resize(BEAM_WIDTH);\n        cur.swap(candidates);\n    }\n\n    if (best_score == full) {\n        cout << best_moves << endl;\n    } else {\n        // if not full, output the best found\n        cout << best_moves << endl;\n    }\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nusing ll = long long;\nusing i128 = __int128_t;\nconst ll R = 10000;\nconst ll R_SQ = (ll)R * R;\n\nstruct Line {\n    ll px, py, qx, qy;\n};\n\n// Check if line cuts the circle (distance from origin < R)\nbool lineCutsCircle(const Line& l) {\n    ll dx = l.qx - l.px;\n    ll dy = l.qy - l.py;\n    if (dx == 0 && dy == 0) return false;\n    i128 cross = (i128)dx * l.py - (i128)dy * l.px;\n    i128 dsq = (i128)dx * dx + (i128)dy * dy;\n    i128 left = cross * cross;\n    i128 right = R_SQ * dsq;\n    return left < right;\n}\n\n// Generate a random line that cuts the circle\nLine genRandomLine(mt19937& rng) {\n    static uniform_int_distribution<ll> dist(-20000, 20000);\n    while (true) {\n        ll px = dist(rng), py = dist(rng);\n        ll qx = dist(rng), qy = dist(rng);\n        if (px == qx && py == qy) continue;\n        Line l{px, py, qx, qy};\n        if (lineCutsCircle(l)) return l;\n    }\n}\n\n// Evaluate score from a set of lines and point masks (final)\nint evaluateFromMasks(const vector<pair<uint64_t,uint64_t>>& masks, const int a[11]) {\n    int n = masks.size();\n    vector<pair<uint64_t,uint64_t>> sorted(masks.begin(), masks.end());\n    sort(sorted.begin(), sorted.end());\n    int b[11] = {0};\n    for (int i = 0; i < n; ) {\n        int j = i;\n        while (j < n && sorted[j] == sorted[i]) ++j;\n        int cnt = j - i;\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n        i = j;\n    }\n    int tot = 0;\n    for (int d = 1; d <= 10; ++d) tot += min(a[d], b[d]);\n    return tot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<pair<int,int>> pts(N);\n    for (int i = 0; i < N; ++i) cin >> pts[i].first >> pts[i].second;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Current masks for each point (low and high parts)\n    vector<uint64_t> mask_low(N, 0), mask_high(N, 0);\n    // Current lines\n    vector<Line> lines;\n    // Temporary array for new masks (reused)\n    vector<pair<uint64_t,uint64_t>> new_masks(N);\n\n    const int TRIALS = 60;          // number of candidate lines per step\n    const int MAX_LINES = min(K, 100); // K is 100, but we may stop early\n\n    for (int step = 0; step < MAX_LINES; ++step) {\n        int best_score = -1;\n        Line best_line;\n        bool found = false;\n\n        // Try candidate lines\n        for (int t = 0; t < TRIALS; ++t) {\n            Line cand = genRandomLine(rng);\n            ll dx = cand.qx - cand.px;\n            ll dy = cand.qy - cand.py;\n            bool valid = true;\n\n            // Compute new masks\n            for (int i = 0; i < N; ++i) {\n                ll cross = dx * (pts[i].second - cand.py) - dy * (pts[i].first - cand.px);\n                if (cross == 0) { valid = false; break; }\n                int side = (cross > 0) ? 1 : 0;\n                uint64_t new_low = mask_low[i];\n                uint64_t new_high = mask_high[i];\n                if (step < 64) {\n                    new_low |= (uint64_t)side << step;\n                } else {\n                    new_high |= (uint64_t)side << (step - 64);\n                }\n                new_masks[i] = {new_low, new_high};\n            }\n            if (!valid) continue;\n\n            // Sort and compute b_d\n            sort(new_masks.begin(), new_masks.end());\n            int b[11] = {0};\n            for (int i = 0; i < N; ) {\n                int j = i;\n                while (j < N && new_masks[j] == new_masks[i]) ++j;\n                int cnt = j - i;\n                if (cnt >= 1 && cnt <= 10) b[cnt]++;\n                i = j;\n            }\n            int score = 0;\n            for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n\n            if (score > best_score) {\n                best_score = score;\n                best_line = cand;\n                found = true;\n            }\n        }\n\n        // If no improvement, stop\n        if (!found || best_score <= evaluateFromMasks(new_masks, a)) {\n            // Here we need current score; but we can break if no improvement\n            // However, we don't have current score easily. Since we didn't update masks yet,\n            // we need to compute current score. We'll compute it once.\n            // Since this is only for stopping condition, we can compute after each step.\n            // For simplicity, we break if no line was found.\n            break;\n        }\n\n        // Add the best line\n        lines.push_back(best_line);\n        // Update masks globally\n        ll dx = best_line.qx - best_line.px;\n        ll dy = best_line.qy - best_line.py;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (pts[i].second - best_line.py) - dy * (pts[i].first - best_line.px);\n            int side = (cross > 0) ? 1 : 0;\n            if (step < 64) {\n                mask_low[i] |= (uint64_t)side << step;\n            } else {\n                mask_high[i] |= (uint64_t)side << (step - 64);\n            }\n        }\n    }\n\n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const auto& l : lines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 61;\nint N, M;\nbool dot[MAXN][MAXN]; // true if dot present\nvector<int> rowDots[MAXN]; // for each y, sorted x\nvector<int> colDots[MAXN]; // for each x, sorted y\nvector<int> diag1Dots[2*MAXN]; // (y-x) + (N-1) -> sorted x\nvector<int> diag2Dots[2*MAXN]; // (y+x) -> sorted x\n\n// used unit edges\nbool usedH[MAXN-1][MAXN]; // horizontal (x,y) -> (x+1,y)\nbool usedV[MAXN][MAXN-1]; // vertical (x,y) -> (x,y+1)\nbool usedD1[MAXN-1][MAXN-1]; // diagonal (1,1): (x,y)->(x+1,y+1), x in [0,N-2], y in [0,N-2]\nbool usedD2[MAXN-1][MAXN-1]; // diagonal (1,-1): (x,y)->(x+1,y-1), store as (x, y-1) for y>=1\n\nint64_t weight[MAXN][MAXN]; // w(x,y)\nvector<pair<int,int>> sortedPoints; // by weight descending\n\n// Interval helpers: check if any dot in open interval (l+1 .. r-1)\ninline bool hasDotRow(int y, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = rowDots[y];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotCol(int x, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = colDots[x];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotDiag1(int c, int lx, int rx) { // c = y-x + (N-1)\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag1Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\ninline bool hasDotDiag2(int c, int lx, int rx) { // c = y+x\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag2Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\n\n// Check unit edges on axis-aligned rectangle\nbool checkUnitEdgesAxis(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {\n    // (x1,y1) -> (x2,y2) horizontal\n    int stepx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += stepx) {\n        int ux = min(x, x+stepx);\n        if (usedH[ux][y1]) return false;\n    }\n    // (x2,y2) -> (x3,y3) vertical\n    int stepy = (y3 > y2) ? 1 : -1;\n    for (int y = y2; y != y3; y += stepy) {\n        int uy = min(y, y+stepy);\n        if (usedV[x2][uy]) return false;\n    }\n    // (x3,y3) -> (x4,y4) horizontal (same y as y3)\n    stepx = (x4 > x3) ? 1 : -1;\n    for (int x = x3; x != x4; x += stepx) {\n        int ux = min(x, x+stepx);\n        if (usedH[ux][y3]) return false;\n    }\n    // (x4,y4) -> (x1,y1) vertical\n    stepy = (y1 > y4) ? 1 : -1;\n    for (int y = y4; y != y1; y += stepy) {\n        int uy = min(y, y+stepy);\n        if (usedV[x4][uy]) return false;\n    }\n    return true;\n}\n\n// Check unit edges on diagonal rectangle (type1: (a,a) and (b,-b))\nbool checkUnitEdgesDiag1(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {\n    // edge p1->p2: slope1 (dx positive assumed, but we handle direction\n    int stepx = (x2 > x1) ? 1 : -1;\n    int dx = x2 - x1;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x1 + t * stepx;\n        int y = y1 + t * stepx; // since dy=dx for slope1\n        if (usedD1[x][y]) return false; // x in [0,N-2], y in [0,N-2] should hold\n    }\n    // edge p2->p3: slope -1\n    stepx = (x3 > x2) ? 1 : -1;\n    dx = x3 - x2;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x2 + t * stepx;\n        int y = y2 - t * stepx; // dy = -dx\n        // usedD2[x][y-1] if y>0\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    // edge p3->p4: slope1 (reverse direction: p4->p3 is slope1, but going p3->p4 is opposite direction, same line)\n    int stepx2 = (x4 > x3) ? 1 : -1;\n    dx = x4 - x3;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x3 + t * stepx2;\n        int y = y3 + t * stepx2;\n        if (usedD1[x][y]) return false;\n    }\n    // edge p4->p1: slope -1\n    stepx = (x1 > x4) ? 1 : -1;\n    dx = x1 - x4;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x4 + t * stepx;\n        int y = y4 - t * stepx;\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    return true;\n}\n// similar for type2: (a,-a) and (b,b)\nbool checkUnitEdgesDiag2(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {\n    // edge p1->p2: slope -1\n    int stepx = (x2 > x1) ? 1 : -1;\n    int dx = x2 - x1;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x1 + t * stepx;\n        int y = y1 - t * stepx;\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    // edge p2->p3: slope1\n    stepx = (x3 > x2) ? 1 : -1;\n    dx = x3 - x2;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x2 + t * stepx;\n        int y = y2 + t * stepx;\n        if (usedD1[x][y]) return false;\n    }\n    // edge p3->p4: slope -1\n    stepx = (x4 > x3) ? 1 : -1;\n    dx = x4 - x3;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x3 + t * stepx;\n        int y = y3 - t * stepx;\n        if (y <= 0) continue;\n        if (usedD2[x][y-1]) return false;\n    }\n    // edge p4->p1: slope1\n    stepx = (x1 > x4) ? 1 : -1;\n    dx = x1 - x4;\n    for (int t = 0; t < abs(dx); ++t) {\n        int x = x4 + t * stepx;\n        int y = y4 + t * stepx;\n        if (usedD1[x][y]) return false;\n    }\n    return true;\n}\n\n// try to place a dot at (x,y) by finding a valid rectangle\nbool tryPlace(int x, int y, int rect[4][2]) {\n    // axis-aligned\n    const auto& row = rowDots[y];\n    const auto& col = colDots[x];\n    for (int x2 : row) {\n        if (x2 == x) continue;\n        int xmin = min(x,x2), xmax = max(x,x2);\n        for (int y4 : col) {\n            if (y4 == y) continue;\n            if (!dot[x2][y4]) continue;\n            int ymin = min(y,y4), ymax = max(y,y4);\n            // check dots on edges\n            if (hasDotRow(y, xmin, xmax)) continue;\n            if (hasDotRow(y4, xmin, xmax)) continue;\n            if (hasDotCol(x, ymin, ymax)) continue;\n            if (hasDotCol(x2, ymin, ymax)) continue;\n            // check unit edges\n            if (!checkUnitEdgesAxis(x,y, x2,y, x2,y4, x,y4)) continue;\n            // found\n            rect[0][0]=x; rect[0][1]=y;\n            rect[1][0]=x2; rect[1][1]=y;\n            rect[2][0]=x2; rect[2][1]=y4;\n            rect[3][0]=x; rect[3][1]=y4;\n            return true;\n        }\n    }\n    // diagonal type1: p2 on diag1 (y-x constant), p4 on diag2 (y+x constant)\n    int c1 = y - x + N-1; // index for diag1\n    int c2 = y + x; // index for diag2\n    for (int x2 : diag1Dots[c1]) {\n        if (x2 == x) continue;\n        int y2 = x2 + (y-x); // because y2-x2 = y-x\n        int dx = x2 - x; // a = dx = dy\n        for (int x4 : diag2Dots[c2]) {\n            if (x4 == x) continue;\n            int y4 = c2 - x4; // y4 = (y+x) - x4\n            int db = x4 - x;\n            // check if p3 exists: (x2 + db, y2 - db)\n            int x3 = x2 + db;\n            int y3 = y2 - db;\n            if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n            if (!dot[x3][y3]) continue;\n            // check no dots on edges (perimeter)\n            // edge p1->p2 (slope1)\n            int dx1 = abs(dx);\n            int xmin1 = min(x,x2), xmax1 = max(x,x2);\n            if (hasDotDiag1(c1, xmin1, xmax1)) continue;\n            // edge p2->p3 (slope -1)\n            int c23 = y2 + x2; // constant for diag2 line through p2? Actually p2->p3 is on diag2 with constant = y2+x2? Let's compute: p2=(x2,y2), p3=(x3,y3). The line between them has y-x? No, it's slope -1, so y+x constant = y2+x2 = y3+x3. So c23 = y2+x2.\n            int xmin23 = min(x2,x3), xmax23 = max(x2,x3);\n            if (hasDotDiag2(c23, xmin23, xmax23)) continue;\n            // edge p3->p4 (slope1)\n            int c34 = y3 - x3 + N-1; // diag1\n            int xmin34 = min(x3,x4), xmax34 = max(x3,x4);\n            if (hasDotDiag1(c34, xmin34, xmax34)) continue;\n            // edge p4->p1 (slope -1)\n            int c41 = y4 + x4; // diag2\n            int xmin41 = min(x4,x), xmax41 = max(x4,x);\n            if (hasDotDiag2(c41, xmin41, xmax41)) continue;\n            // check unit edges\n            if (!checkUnitEdgesDiag1(x,y, x2,y2, x3,y3, x4,y4)) continue;\n            // found\n            rect[0][0]=x; rect[0][1]=y;\n            rect[1][0]=x2; rect[1][1]=y2;\n            rect[2][0]=x3; rect[2][1]=y3;\n            rect[3][0]=x4; rect[3][1]=y4;\n            return true;\n        }\n    }\n    // diagonal type2: p2 on diag2, p4 on diag1\n    for (int x2 : diag2Dots[c2]) {\n        if (x2 == x) continue;\n        int y2 = c2 - x2;\n        int dx = x2 - x;\n        for (int x4 : diag1Dots[c1]) {\n            if (x4 == x) continue;\n            int y4 = x4 + (y-x);\n            int db = x4 - x;\n            // p3 = (x2 + db, y2 + db) (since from p2 go (db, -db)? Actually for type2, vectors: (a,-a) and (b,b). So p2 is (x+a, y-a), p4 is (x+b, y+b). Then p3 = (x+a+b, y-a+b). So here a = dx, b = db.\n            int x3 = x2 + db;\n            int y3 = y2 + db;\n            if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n            if (!dot[x3][y3]) continue;\n            // edges:\n            // p1->p2: slope -1\n            int xmin12 = min(x,x2), xmax12 = max(x,x2);\n            if (hasDotDiag2(c2, xmin12, xmax12)) continue;\n            // p2->p3: slope1\n            int c23 = y2 - x2 + N-1; // diag1 through p2\n            int xmin23 = min(x2,x3), xmax23 = max(x2,x3);\n            if (hasDotDiag1(c23, xmin23, xmax23)) continue;\n            // p3->p4: slope -1\n            int c34 = y3 + x3; // diag2\n            int xmin34 = min(x3,x4), xmax34 = max(x3,x4);\n            if (hasDotDiag2(c34, xmin34, xmax34)) continue;\n            // p4->p1: slope1\n            int c41 = y4 - x4 + N-1; // diag1\n            int xmin41 = min(x4,x), xmax41 = max(x4,x);\n            if (hasDotDiag1(c41, xmin41, xmax41)) continue;\n            // unit edges\n            if (!checkUnitEdgesDiag2(x,y, x2,y2, x3,y3, x4,y4)) continue;\n            rect[0][0]=x; rect[0][1]=y;\n            rect[1][0]=x2; rect[1][1]=y2;\n            rect[2][0]=x3; rect[2][1]=y3;\n            rect[3][0]=x4; rect[3][1]=y4;\n            return true;\n        }\n    }\n    return false;\n}\n\nvoid placeDot(int x, int y) {\n    dot[x][y] = true;\n    // update sorted lists\n    auto ins = [](vector<int>& v, int val) {\n        v.insert(lower_bound(v.begin(), v.end(), val), val);\n    };\n    ins(rowDots[y], x);\n    ins(colDots[x], y);\n    ins(diag1Dots[y - x + N-1], x);\n    ins(diag2Dots[y + x], x);\n}\n\nvoid markUnitEdges(int rect[4][2]) {\n    // axis-aligned: from p1 to p2 (horizontal)\n    auto markH = [&](int x1, int y, int x2) {\n        int step = (x2 > x1) ? 1 : -1;\n        for (int x = x1; x != x2; x += step) {\n            int ux = min(x, x+step);\n            usedH[ux][y] = true;\n        }\n    };\n    auto markV = [&](int x, int y1, int y2) {\n        int step = (y2 > y1) ? 1 : -1;\n        for (int y = y1; y != y2; y += step) {\n            int uy = min(y, y+step);\n            usedV[x][uy] = true;\n        }\n    };\n    auto markD1 = [&](int x1, int y1, int x2, int y2) {\n        int step = (x2 > x1) ? 1 : -1;\n        for (int x = x1; x != x2; x += step) {\n            int y = y1 + (x - x1);\n            usedD1[x][y] = true;\n        }\n    };\n    auto markD2 = [&](int x1, int y1, int x2, int y2) {\n        int step = (x2 > x1) ? 1 : -1;\n        for (int x = x1; x != x2; x += step) {\n            int y = y1 - (x - x1);\n            if (y > 0) usedD2[x][y-1] = true;\n        }\n    };\n    // Determine rectangle type by comparing coordinates\n    // Check if it's axis-aligned (same y for p1 and p2)\n    if (rect[0][1] == rect[1][1]) {\n        markH(rect[0][0], rect[0][1], rect[1][0]);\n        markV(rect[1][0], rect[1][1], rect[2][1]);\n        markH(rect[3][0], rect[3][1], rect[2][0]);\n        markV(rect[0][0], rect[0][1], rect[3][1]);\n    } else {\n        // diagonal: check if p1->p2 has slope 1 (y2 - y1 == x2 - x1)\n        if ( (rect[1][1] - rect[0][1]) == (rect[1][0] - rect[0][0]) ) {\n            // type1\n            markD1(rect[0][0], rect[0][1], rect[1][0], rect[1][1]);\n            markD2(rect[1][0], rect[1][1], rect[2][0], rect[2][1]);\n            markD1(rect[3][0], rect[3][1], rect[2][0], rect[2][1]);\n            markD2(rect[0][0], rect[0][1], rect[3][0], rect[3][1]);\n        } else {\n            // type2\n            markD2(rect[0][0], rect[0][1], rect[1][0], rect[1][1]);\n            markD1(rect[1][0], rect[1][1], rect[2][0], rect[2][1]);\n            markD2(rect[3][0], rect[3][1], rect[2][0], rect[2][1]);\n            markD1(rect[0][0], rect[0][1], rect[3][0], rect[3][1]);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    // read input\n    cin >> N >> M;\n    // initialize\n    for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) dot[i][j] = false;\n    for (int i=0; i<M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        placeDot(x, y);\n    }\n    // precompute weights and sorted points\n    int c = (N-1)/2;\n    for (int y=0; y<N; ++y) {\n        for (int x=0; x<N; ++x) {\n            weight[x][y] = (x-c)*(x-c) + (y-c)*(y-c) + 1;\n            sortedPoints.emplace_back(x, y);\n        }\n    }\n    sort(sortedPoints.begin(), sortedPoints.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n        return weight[a.first][a.second] > weight[b.first][b.second];\n    });\n    // main loop\n    vector<array<int,8>> operations; // store each operation\n    while (true) {\n        bool placed = false;\n        int rect[4][2];\n        for (const auto& p : sortedPoints) {\n            int x = p.first, y = p.second;\n            if (dot[x][y]) continue;\n            if (tryPlace(x, y, rect)) {\n                // perform operation\n                placeDot(rect[0][0], rect[0][1]);\n                markUnitEdges(rect);\n                operations.push_back({rect[0][0], rect[0][1], rect[1][0], rect[1][1], rect[2][0], rect[2][1], rect[3][0], rect[3][1]});\n                placed = true;\n                break;\n            }\n        }\n        if (!placed) break;\n    }\n    // output\n    cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        for (int i=0; i<8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\n\n// Simulate tilt\nvector<vector<int>> tilt(const vector<vector<int>>& grid, char dir) {\n    vector<vector<int>> res(N, vector<int>(N, 0));\n    if (dir == 'F') {\n        for (int j = 0; j < N; ++j) {\n            int r = 0;\n            for (int i = 0; i < N; ++i) if (grid[i][j]) res[r++][j] = grid[i][j];\n        }\n    } else if (dir == 'B') {\n        for (int j = 0; j < N; ++j) {\n            int r = N - 1;\n            for (int i = N - 1; i >= 0; --i) if (grid[i][j]) res[r--][j] = grid[i][j];\n        }\n    } else if (dir == 'L') {\n        for (int i = 0; i < N; ++i) {\n            int c = 0;\n            for (int j = 0; j < N; ++j) if (grid[i][j]) res[i][c++] = grid[i][j];\n        }\n    } else { // 'R'\n        for (int i = 0; i < N; ++i) {\n            int c = N - 1;\n            for (int j = N - 1; j >= 0; --j) if (grid[i][j]) res[i][c--] = grid[i][j];\n        }\n    }\n    return res;\n}\n\n// Compute sum of squares of connected component sizes\nint compute_score(const vector<vector<int>>& grid) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    int total = 0;\n    const int dx[4] = {0,0,1,-1}, dy[4] = {1,-1,0,0};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] && !vis[i][j]) {\n                int flavor = grid[i][j];\n                int cnt = 0;\n                queue<pair<int,int>> q;\n                q.push({i,j});\n                vis[i][j] = true;\n                while (!q.empty()) {\n                    auto [x,y] = q.front(); q.pop();\n                    ++cnt;\n                    for (int d=0; d<4; ++d) {\n                        int nx = x+dx[d], ny = y+dy[d];\n                        if (nx>=0 && nx<N && ny>=0 && ny<N && !vis[nx][ny] && grid[nx][ny]==flavor) {\n                            vis[nx][ny] = true;\n                            q.push({nx,ny});\n                        }\n                    }\n                }\n                total += cnt * cnt;\n            }\n        }\n    }\n    return total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(100);\n    for (int i=0; i<100; ++i) cin >> f[i];\n\n    vector<vector<int>> grid(N, vector<int>(N, 0));\n    const char dirs[4] = {'F','B','L','R'};\n\n    for (int t=0; t<100; ++t) {\n        int p;\n        cin >> p;\n        // Place the new candy (flavor f[t]) at the p-th empty cell\n        int idx = 1;\n        bool placed = false;\n        for (int i=0; i<N && !placed; ++i) {\n            for (int j=0; j<N; ++j) {\n                if (grid[i][j]==0) {\n                    if (idx == p) {\n                        grid[i][j] = f[t];\n                        placed = true;\n                        break;\n                    }\n                    ++idx;\n                }\n            }\n        }\n\n        // Evaluate each tilt direction\n        int best_score = -1;\n        char best_dir = 'F';\n        for (char d : dirs) {\n            auto g = tilt(grid, d);\n            int cur_score = compute_score(g); // immediate score after this tilt\n\n            // If not the last candy, compute expected best score after next step\n            if (t < 99) {\n                // Collect empty cells in g\n                vector<pair<int,int>> empties;\n                for (int i=0; i<N; ++i)\n                    for (int j=0; j<N; ++j)\n                        if (g[i][j]==0) empties.push_back({i,j});\n                int M = empties.size();\n                double exp_next = 0.0;\n                int next_flavor = f[t+1];\n                for (auto [ei, ej] : empties) {\n                    // Place next candy\n                    auto g2 = g;\n                    g2[ei][ej] = next_flavor;\n                    // Evaluate all tilts for the next step\n                    int best_next = 0;\n                    for (char d2 : dirs) {\n                        auto g3 = tilt(g2, d2);\n                        best_next = max(best_next, compute_score(g3));\n                    }\n                    exp_next += best_next;\n                }\n                exp_next /= M;\n                // Combine: weight immediate score and lookahead\n                // We can use exp_next directly because it includes the current tilt effect.\n                // But to be safe, use a weighted sum.\n                // Here we simply use exp_next as the evaluation (since it's future score after optimal next action)\n                // For the last step, we use cur_score.\n                cur_score = (int)exp_next; // use lookahead score (may be larger)\n            }\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_dir = d;\n            }\n        }\n\n        // Apply the chosen tilt\n        grid = tilt(grid, best_dir);\n        cout << best_dir << '\\n' << flush;\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n#include <cstdint>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    // Choose smallest N such that number of unlabeled graphs >= M\n    int N;\n    if (M <= 11) N = 4;\n    else if (M <= 34) N = 5;\n    else N = 6;   // 156 graphs, enough for M <= 100\n\n    int L = N * (N - 1) / 2;\n    const int total_masks = 1 << L;\n\n    // Precompute all permutations once\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    vector<vector<uint8_t>> perms_bit;  // each permutation-> mapping original bit -> new bit\n    vector<vector<int>> perms_order;    // actual permutation array for later use (not needed)\n    {\n        vector<int> p(N);\n        iota(p.begin(), p.end(), 0);\n        do {\n            // Precompute bit_perm[orig_index] = new_index\n            vector<uint8_t> bit_perm(L);\n            int ptr = 0;\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    int u = p[i], v = p[j];\n                    if (u > v) swap(u, v);\n                    // (u,v) is the edge in original labeling\n                    // Its index in the original bit order is: u*(2*N-u-1)/2 + (v-u-1)\n                    int idx = u * (2*N - u - 1) / 2 + (v - u - 1);\n                    bit_perm[ptr] = (uint8_t)idx;\n                    ++ptr;\n                }\n            }\n            perms_bit.push_back(bit_perm);\n        } while (next_permutation(p.begin(), p.end()));\n    }\n\n    // Compute canonical mask for every possible mask (graph)\n    vector<uint16_t> can_mask(total_masks);\n    {\n        for (int mask = 0; mask < total_masks; ++mask) {\n            uint16_t best = UINT16_MAX;\n            for (const auto& bit_perm : perms_bit) {\n                uint16_t new_mask = 0;\n                // iterate over each original bit\n                for (int k = 0; k < L; ++k) {\n                    if ((mask >> k) & 1) {\n                        new_mask |= (1 << bit_perm[k]);\n                    }\n                }\n                if (new_mask < best) best = new_mask;\n            }\n            can_mask[mask] = best;\n        }\n    }\n\n    // Collect all distinct canonical masks\n    unordered_map<uint16_t, int> canon_to_idx;\n    vector<uint16_t> canonical_masks;\n    for (int m = 0; m < total_masks; ++m) {\n        uint16_t cm = can_mask[m];\n        if (canon_to_idx.find(cm) == canon_to_idx.end()) {\n            int id = (int)canonical_masks.size();\n            canon_to_idx[cm] = id;\n            canonical_masks.push_back(cm);\n        }\n    }\n    int K = (int)canonical_masks.size(); // number of unlabeled graphs\n\n    // Greedy selection of M graphs maximizing minimum Hamming distance\n    // Precompute distances between canonical masks\n    vector<vector<int>> dist(K, vector<int>(K, 0));\n    for (int i = 0; i < K; ++i) {\n        for (int j = i + 1; j < K; ++j) {\n            int d = __builtin_popcount(canonical_masks[i] ^ canonical_masks[j]);\n            dist[i][j] = dist[j][i] = d;\n        }\n    }\n\n    vector<int> selected;\n    vector<bool> used(K, false);\n    // start with the mask having largest total distance? simple: start with index 0\n    selected.push_back(0);\n    used[0] = true;\n    while ((int)selected.size() < M) {\n        int best_idx = -1;\n        int best_min = -1;\n        for (int i = 0; i < K; ++i) {\n            if (used[i]) continue;\n            int cur_min = L + 1;\n            for (int j : selected) {\n                if (dist[i][j] < cur_min) cur_min = dist[i][j];\n            }\n            if (cur_min > best_min) {\n                best_min = cur_min;\n                best_idx = i;\n            }\n        }\n        selected.push_back(best_idx);\n        used[best_idx] = true;\n    }\n\n    // Build lookup table: for each canonical mask, the index of nearest selected mask\n    vector<int> lookup(total_masks, 0); // total_masks <= 2^15 = 32768\n    for (int cm = 0; cm < total_masks; ++cm) {\n        int best_d = L + 1;\n        int best_idx = 0;\n        for (int i = 0; i < M; ++i) {\n            int d = __builtin_popcount(cm ^ canonical_masks[selected[i]]);\n            if (d < best_d) {\n                best_d = d;\n                best_idx = i;\n            }\n        }\n        lookup[cm] = best_idx;\n    }\n\n    // Output\n    cout << N << '\\n';\n    for (int idx : selected) {\n        uint16_t mask = canonical_masks[idx];\n        string s;\n        for (int b = 0; b < L; ++b) {\n            s.push_back(((mask >> b) & 1) ? '1' : '0');\n        }\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // Process queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n        int mask = 0;\n        for (int b = 0; b < L; ++b) {\n            if (H[b] == '1') mask |= (1 << b);\n        }\n        int canonical = can_mask[mask];\n        int ans = lookup[canonical];\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nconst ll INF = 1e18;\nconst ll UNREACHABLE = 1000000000LL;\n\n// ------------------------------------------------------------\n// read input and build graph\n// ------------------------------------------------------------\nstruct Edge {\n    int u, v, w;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, ll>>> g(N);\n    vector<vector<int>> edge_index(N, vector<int>(N, -1));\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u, v, w};\n        g[u].emplace_back(v, w);\n        g[v].emplace_back(u, w);\n        edge_index[u][v] = edge_index[v][u] = i;\n    }\n\n    // skip vertex coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ------------------------------------------------------------\n    // 1. original all\u2011pairs shortest paths\n    // ------------------------------------------------------------\n    vector<vector<ll>> dist_orig(N, vector<ll>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        dist_orig[s][s] = 0;\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist_orig[s][u]) continue;\n            for (auto [v, w] : g[u]) {\n                ll nd = d + w;\n                if (nd < dist_orig[s][v]) {\n                    dist_orig[s][v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 2. edge betweenness centrality (Brandes)\n    // ------------------------------------------------------------\n    vector<ld> betweenness(M, 0.0);\n\n    for (int s = 0; s < N; ++s) {\n        // shortest distances and number of shortest paths\n        vector<ll> d(N, INF);\n        vector<ld> cnt(N, 0.0);\n        vector<vector<int>> pred(N);\n        d[s] = 0;\n        cnt[s] = 1.0;\n        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != d[u]) continue;\n            for (auto [v, w] : g[u]) {\n                ll nd = du + w;\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    cnt[v] = cnt[u];\n                    pred[v].clear();\n                    pred[v].push_back(u);\n                    pq.emplace(nd, v);\n                } else if (nd == d[v]) {\n                    cnt[v] += cnt[u];\n                    pred[v].push_back(u);\n                }\n            }\n        }\n\n        // vertices in decreasing distance order\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return d[a] > d[b];\n        });\n\n        vector<ld> dep(N, 0.0);\n        for (int v : order) {\n            if (v == s) continue;\n            if (pred[v].empty()) continue;\n            ld sigma_v = cnt[v];\n            for (int p : pred[v]) {\n                ld contrib = (cnt[p] / sigma_v) * (1.0 + dep[v]);\n                dep[p] += contrib;\n                int eidx = edge_index[p][v];\n                betweenness[eidx] += contrib;\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // 3. initial assignment: greedy load balancing of betweenness\n    // ------------------------------------------------------------\n    vector<pair<ld, int>> order_by_bw(M);\n    for (int i = 0; i < M; ++i) {\n        order_by_bw[i] = {betweenness[i], i};\n    }\n    sort(order_by_bw.rbegin(), order_by_bw.rend());   // descending\n\n    vector<int> day_of_edge(M, -1);\n    vector<int> day_cnt(D, 0);\n    vector<ld> day_load(D, 0.0);\n\n    for (auto [bw, eid] : order_by_bw) {\n        int best_day = -1;\n        ld best_load = 1e100;\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_load[d] < best_load) {\n                best_load = day_load[d];\n                best_day = d;\n            }\n        }\n        // capacity is guaranteed by K > ceil(M/D)\n        assert(best_day != -1);\n        day_of_edge[eid] = best_day;\n        day_cnt[best_day]++;\n        day_load[best_day] += bw;\n    }\n\n    // ------------------------------------------------------------\n    // 4. local search to balance betweenness (swap edges)\n    // ------------------------------------------------------------\n    for (int iter = 0; iter < 500; ++iter) {\n        int max_day = max_element(day_load.begin(), day_load.end()) - day_load.begin();\n        int min_day = min_element(day_load.begin(), day_load.end()) - day_load.begin();\n        if (day_load[max_day] - day_load[min_day] < 1e-12) break;\n\n        // find an edge that can be moved to reduce imbalance\n        int move_e = -1;\n        ld best_improve = 0.0;\n        for (int e = 0; e < M; ++e) {\n            if (day_of_edge[e] != max_day) continue;\n            if (day_cnt[min_day] >= K) continue;\n            ld new_max = day_load[max_day] - betweenness[e];\n            ld new_min = day_load[min_day] + betweenness[e];\n            ld new_diff = fabsl(new_max - new_min);\n            ld old_diff = day_load[max_day] - day_load[min_day];\n            ld improve = old_diff - new_diff;\n            if (improve > best_improve) {\n                best_improve = improve;\n                move_e = e;\n            }\n        }\n        if (move_e == -1) break;\n\n        // perform move\n        int e = move_e;\n        int old_day = max_day;\n        int new_day = min_day;\n        day_load[old_day] -= betweenness[e];\n        day_load[new_day] += betweenness[e];\n        day_cnt[old_day]--;\n        day_cnt[new_day]++;\n        day_of_edge[e] = new_day;\n    }\n\n    // ------------------------------------------------------------\n    // 5. compute actual frustration (optional, only for output)\n    // ------------------------------------------------------------\n    // We do not use actual frustration to further improve,\n    // because it would be too time\u2011consuming.\n    // Final output is the day assignment.\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << day_of_edge[i] + 1;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// 24 proper rotations (det=1)\nvector<array<array<int,3>,3>> rotations;\n\nvoid init_rotations() {\n    int perm[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n    int parity[6] = {1,-1,-1,1,1,-1};\n    int signs[8][3] = {{1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},\n                       {-1,1,1},{-1,1,-1},{-1,-1,1},{-1,-1,-1}};\n    for (int p=0;p<6;p++) {\n        for (auto s : signs) {\n            int det = s[0]*s[1]*s[2] * parity[p];\n            if (det != 1) continue;\n            array<array<int,3>,3> mat;\n            for (int i=0;i<3;i++) {\n                for (int j=0;j<3;j++) {\n                    mat[i][j] = (j == perm[p][i]) ? s[i] : 0;\n                }\n            }\n            rotations.push_back(mat);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    init_rotations();\n\n    int D; cin >> D;\n    int N = D*D*D;               // total voxels per object\n    vector<string> f[2], r[2];\n    for (int t=0;t<2;t++) {\n        f[t].resize(D);\n        for (int i=0;i<D;i++) cin >> f[t][i];\n        r[t].resize(D);\n        for (int i=0;i<D;i++) cin >> r[t][i];\n    }\n\n    // occupancy per object (flattened)\n    vector<char> occ[2];\n    for (int t=0;t<2;t++) occ[t].resize(N, 0);\n\n    for (int t=0;t<2;t++) {\n        for (int z=0;z<D;z++) {\n            for (int x=0;x<D;x++) {\n                if (f[t][z][x] == '0') continue;\n                for (int y=0;y<D;y++) {\n                    if (r[t][z][y] == '1') {\n                        int idx = x*D*D + y*D + z;\n                        occ[t][idx] = 1;\n                    }\n                }\n            }\n        }\n    }\n\n    // connected components for each object\n    vector<vector<tuple<int,int,int>>> comps[2]; // list of points per component\n    vector<int> compSize[2];                     // volume per component\n    vector<char> vis[2];\n    for (int t=0;t<2;t++) vis[t].resize(N, 0);\n\n    for (int t=0;t<2;t++) {\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || vis[t][start]) continue;\n            queue<int> q; q.push(start);\n            vis[t][start] = 1;\n            vector<tuple<int,int,int>> pts;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                pts.emplace_back(x,y,z);\n                static int dx[] = {1,-1,0,0,0,0};\n                static int dy[] = {0,0,1,-1,0,0};\n                static int dz[] = {0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n                    if (nx<0 || nx>=D || ny<0 || ny>=D || nz<0 || nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !vis[t][nid]) {\n                        vis[t][nid] = 1;\n                        q.push(nid);\n                    }\n                }\n            }\n            comps[t].push_back(pts);\n            compSize[t].push_back((int)pts.size());\n        }\n    }\n\n    // used cells for both objects\n    vector<char> used[2];\n    for (int t=0;t<2;t++) used[t].resize(N, 0);\n\n    // final block assignments\n    vector<int> b1(N,0), b2(N,0);\n    int blockId = 1;\n\n    // candidate components: (volume, object, component index)\n    vector<tuple<int,int,int>> candidates;\n    for (int t=0;t<2;t++) {\n        for (size_t i=0;i<comps[t].size();i++) {\n            candidates.emplace_back(compSize[t][i], t, (int)i);\n        }\n    }\n    sort(candidates.rbegin(), candidates.rend()); // largest first\n\n    // lambda to find a placement of a component from source object into the other object\n    auto findPlacement = [&](const vector<tuple<int,int,int>>& srcPts, int otherObj,\n                             vector<tuple<int,int,int>>& outPts) -> bool {\n        // srcPts are absolute coordinates in the source object\n        for (const auto& rot : rotations) {\n            // apply rotation to srcPts\n            vector<tuple<int,int,int>> rotated;\n            int mnx=1e9, mny=1e9, mnz=1e9;\n            int mxx=-1e9, mxy=-1e9, mxz=-1e9;\n            for (auto [x,y,z] : srcPts) {\n                int nx = rot[0][0]*x + rot[0][1]*y + rot[0][2]*z;\n                int ny = rot[1][0]*x + rot[1][1]*y + rot[1][2]*z;\n                int nz = rot[2][0]*x + rot[2][1]*y + rot[2][2]*z;\n                rotated.emplace_back(nx,ny,nz);\n                mnx = min(mnx, nx); mxx = max(mxx, nx);\n                mny = min(mny, ny); mxy = max(mxy, ny);\n                mnz = min(mnz, nz); mxz = max(mxz, nz);\n            }\n            int sx = mxx - mnx, sy = mxy - mny, sz = mxz - mnz;\n            // bounding box must fit in [0,D-1]\n            for (int tx=0; tx+sx < D; tx++) {\n                for (int ty=0; ty+sy < D; ty++) {\n                    for (int tz=0; tz+sz < D; tz++) {\n                        bool ok = true;\n                        for (auto [nx,ny,nz] : rotated) {\n                            int gx = nx - mnx + tx;\n                            int gy = ny - mny + ty;\n                            int gz = nz - mnz + tz;\n                            int idx = gx*D*D + gy*D + gz;\n                            if (!occ[otherObj][idx] || used[otherObj][idx]) {\n                                ok = false;\n                                break;\n                            }\n                        }\n                        if (ok) {\n                            outPts.clear();\n                            for (auto [nx,ny,nz] : rotated) {\n                                int gx = nx - mnx + tx;\n                                int gy = ny - mny + ty;\n                                int gz = nz - mnz + tz;\n                                outPts.emplace_back(gx,gy,gz);\n                            }\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n        return false;\n    };\n\n    for (auto [vol, obj, compIdx] : candidates) {\n        const auto& pts = comps[obj][compIdx];\n        // check if any cell already used in its own object\n        bool anyUsed = false;\n        for (auto [x,y,z] : pts) {\n            int idx = x*D*D + y*D + z;\n            if (used[obj][idx]) { anyUsed = true; break; }\n        }\n        if (anyUsed) continue;\n\n        int other = 1 - obj;\n        vector<tuple<int,int,int>> placement;\n        if (!findPlacement(pts, other, placement)) continue;\n\n        // assign a new common block\n        // mark used in source object\n        for (auto [x,y,z] : pts) {\n            int idx = x*D*D + y*D + z;\n            used[obj][idx] = 1;\n            if (obj == 0) b1[idx] = blockId;\n            else          b2[idx] = blockId;\n        }\n        // mark used in other object\n        for (auto [x,y,z] : placement) {\n            int idx = x*D*D + y*D + z;\n            used[other][idx] = 1;\n            if (other == 0) b1[idx] = blockId;\n            else            b2[idx] = blockId;\n        }\n        blockId++;\n    }\n\n    // handle residual cells (single-use blocks)\n    for (int t=0;t<2;t++) {\n        vector<char> seen(N, 0);\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || used[t][start] || seen[start]) continue;\n            // BFS to collect component\n            queue<int> q; q.push(start);\n            seen[start] = 1;\n            vector<int> compIndices;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                compIndices.push_back(cur);\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                static int dx[] = {1,-1,0,0,0,0};\n                static int dy[] = {0,0,1,-1,0,0};\n                static int dz[] = {0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx = x+dx[d], ny = y+dy[d], nz = z+dz[d];\n                    if (nx<0 || nx>=D || ny<0 || ny>=D || nz<0 || nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !used[t][nid] && !seen[nid]) {\n                        seen[nid] = 1;\n                        q.push(nid);\n                    }\n                }\n            }\n            // assign new block id\n            for (int idx : compIndices) {\n                if (t == 0) b1[idx] = blockId;\n                else        b2[idx] = blockId;\n            }\n            blockId++;\n        }\n    }\n\n    int n = blockId - 1;\n    cout << n << '\\n';\n    for (int i=0;i<N;i++) cout << b1[i] << \" \\n\"[i==N-1];\n    for (int i=0;i<N;i++) cout << b2[i] << \" \\n\"[i==N-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing ll = long long;\nconst ll INF = 1LL << 60;\n\nstruct UnionFind {\n    vector<int> parent, rank;\n    UnionFind(int n) : parent(n), rank(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) parent[x] = y;\n        else if (rank[x] > rank[y]) parent[y] = x;\n        else { parent[y] = x; rank[x]++; }\n        return true;\n    }\n};\n\nint ceil_sqrt(ll sq) {\n    if (sq <= 0) return 0;\n    double d = sqrt((double)sq);\n    int r = (int)ceil(d);\n    if ((ll)r * r < sq) ++r;\n    return min(r, 5000);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::steady_clock::now();\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<tuple<int,int,ll>> edges(M);\n    vector<vector<pair<int,ll>>> adj(N);\n    for (int j = 0; j < M; ++j) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].emplace_back(v, w);\n        adj[v].emplace_back(u, w);\n    }\n\n    vector<int> ax(K), ay(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> ax[k] >> ay[k];\n    }\n\n    // Precompute squared distances between residents and nodes\n    vector<vector<ll>> dist2_res(K, vector<ll>(N));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            ll dx = ax[k] - x[i];\n            ll dy = ay[k] - y[i];\n            dist2_res[k][i] = dx*dx + dy*dy;\n        }\n    }\n\n    // For each resident, sort nodes by distance\n    vector<vector<int>> sorted_nodes(K);\n    for (int k = 0; k < K; ++k) {\n        vector<pair<ll,int>> tmp;\n        for (int i = 0; i < N; ++i) {\n            tmp.emplace_back(dist2_res[k][i], i);\n        }\n        sort(tmp.begin(), tmp.end());\n        sorted_nodes[k].reserve(N);\n        for (auto &p : tmp) {\n            sorted_nodes[k].push_back(p.second);\n        }\n    }\n\n    // All-pairs shortest paths\n    vector<vector<ll>> dist_sh(N, vector<ll>(N, INF));\n    vector<vector<int>> prev(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        dist_sh[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist_sh[s][u]) continue;\n            for (auto &[v, w] : adj[u]) {\n                if (dist_sh[s][v] > d + w) {\n                    dist_sh[s][v] = d + w;\n                    prev[s][v] = u;\n                    pq.push({dist_sh[s][v], v});\n                }\n            }\n        }\n    }\n\n    // Edge index map\n    vector<vector<int>> edge_idx(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        auto [u, v, w] = edges[j];\n        edge_idx[u][v] = edge_idx[v][u] = j;\n    }\n\n    // Quick coverage test\n    auto can_cover = [&](const vector<bool>& active) -> bool {\n        for (int k = 0; k < K; ++k) {\n            bool found = false;\n            for (int i : sorted_nodes[k]) {\n                if (active[i] && dist2_res[k][i] <= 5000LL*5000LL) {\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                // If no station within 5000, but input guarantees at least one station overall,\n                // we must have incorrectly removed the covering station.\n                return false;\n            }\n        }\n        return true;\n    };\n\n    // Cost evaluation function given active set (bool)\n    auto computeCost = [&](const vector<bool>& active) -> ll {\n        // Check coverage\n        for (int k = 0; k < K; ++k) {\n            bool found = false;\n            for (int i : sorted_nodes[k]) {\n                if (active[i] && dist2_res[k][i] <= 5000LL*5000LL) {\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) return LLONG_MAX;\n        }\n\n        vector<ll> maxDistSq(N, 0);\n        for (int k = 0; k < K; ++k) {\n            ll best_d2 = LLONG_MAX;\n            int best_node = -1;\n            for (int i : sorted_nodes[k]) {\n                if (active[i]) {\n                    best_d2 = dist2_res[k][i];\n                    best_node = i;\n                    break;\n                }\n            }\n            if (best_node == -1) return LLONG_MAX; // should not happen\n            if (best_d2 > maxDistSq[best_node])\n                maxDistSq[best_node] = best_d2;\n        }\n        ll sumP2 = 0;\n        for (int i = 0; i < N; ++i) {\n            if (active[i] && maxDistSq[i] > 0) {\n                int r = ceil_sqrt(maxDistSq[i]);\n                sumP2 += (ll)r * r;\n            }\n        }\n\n        vector<int> terms;\n        for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n        ll mst_cost = 0;\n        if (terms.size() > 1) {\n            vector<tuple<ll,int,int>> metric_edges;\n            for (int a = 0; a < (int)terms.size(); ++a) {\n                for (int b = a+1; b < (int)terms.size(); ++b) {\n                    int u = terms[a], v = terms[b];\n                    metric_edges.emplace_back(dist_sh[u][v], u, v);\n                }\n            }\n            sort(metric_edges.begin(), metric_edges.end());\n            UnionFind uf(N);\n            for (auto &[w, u, v] : metric_edges) {\n                if (uf.unite(u, v)) mst_cost += w;\n            }\n        }\n        return sumP2 + mst_cost;\n    };\n\n    // Build initial set: for each resident, add its closest station that is within 5000\n    vector<bool> active(N, false);\n    for (int k = 0; k < K; ++k) {\n        for (int i : sorted_nodes[k]) {\n            if (dist2_res[k][i] <= 5000LL*5000LL) {\n                active[i] = true;\n                break;\n            }\n        }\n    }\n    // Ensure station 1 is active\n    active[0] = true;\n    // Remove redundant stations: try to remove each station while coverage maintained\n    // This is a simple greedy\n    for (int i = 1; i < N; ++i) {\n        if (!active[i]) continue;\n        active[i] = false;\n        if (can_cover(active)) {\n            // keep it off\n        } else {\n            active[i] = true;\n        }\n    }\n\n    ll best_cost = computeCost(active);\n    vector<bool> best_active = active;\n\n    // Simulated Annealing\n    double temp = 5e6;\n    double cooling = 0.9999;\n    int max_iters = 30000;\n    int iters = 0;\n    while (iters < max_iters) {\n        // Check time\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1800) {\n            break;\n        }\n\n        // Pick a random station to flip (excluding 0)\n        int flip = uniform_int_distribution<int>(1, N-1)(rng);\n        vector<bool> new_active = active;\n        new_active[flip] = !new_active[flip];\n        // Keep 0 always active\n        new_active[0] = true;\n\n        // Compute cost\n        ll new_cost = computeCost(new_active);\n        if (new_cost == LLONG_MAX) {\n            // Invalid, reject\n            temp *= cooling;\n            iters++;\n            continue;\n        }\n\n        if (new_cost < best_cost) {\n            best_cost = new_cost;\n            best_active = new_active;\n        }\n\n        double delta = (double)(new_cost - best_cost);\n        if (delta < 0 || exp(-delta / temp) > uniform_real_distribution<double>(0,1)(rng)) {\n            active = new_active;\n            best_cost = new_cost; // update current best for acceptance\n        }\n\n        temp *= cooling;\n        iters++;\n    }\n\n    // Assign powers based on best_active\n    vector<ll> maxDistSq(N, 0);\n    vector<int> P(N, 0);\n    for (int k = 0; k < K; ++k) {\n        for (int i : sorted_nodes[k]) {\n            if (best_active[i] && dist2_res[k][i] <= 5000LL*5000LL) {\n                if (dist2_res[k][i] > maxDistSq[i])\n                    maxDistSq[i] = dist2_res[k][i];\n                break;\n            }\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        if (best_active[i] && maxDistSq[i] > 0) {\n            P[i] = ceil_sqrt(maxDistSq[i]);\n        }\n    }\n\n    // Build Steiner tree for best_active\n    vector<int> terms;\n    for (int i = 0; i < N; ++i) if (best_active[i]) terms.push_back(i);\n    vector<bool> edge_on(M, false);\n\n    if (terms.size() >= 2) {\n        vector<tuple<ll,int,int>> metric_edges;\n        for (int a = 0; a < (int)terms.size(); ++a) {\n            for (int b = a+1; b < (int)terms.size(); ++b) {\n                int u = terms[a], v = terms[b];\n                metric_edges.emplace_back(dist_sh[u][v], u, v);\n            }\n        }\n        sort(metric_edges.begin(), metric_edges.end());\n        UnionFind uf1(N);\n        vector<pair<int,int>> mst_pairs;\n        for (auto &[w, u, v] : metric_edges) {\n            if (uf1.unite(u, v)) {\n                mst_pairs.emplace_back(u, v);\n            }\n        }\n\n        // Add edges along shortest paths of MST pairs\n        for (auto &[u, v] : mst_pairs) {\n            int cur = v;\n            while (cur != u) {\n                int par = prev[u][cur];\n                int idx = edge_idx[par][cur];\n                if (idx != -1) {\n                    edge_on[idx] = true;\n                }\n                cur = par;\n            }\n        }\n\n        // Build spanning tree on these candidate edges\n        vector<int> candidate_edges;\n        for (int j = 0; j < M; ++j) {\n            if (edge_on[j]) candidate_edges.push_back(j);\n        }\n        sort(candidate_edges.begin(), candidate_edges.end(), [&](int a, int b) {\n            return get<2>(edges[a]) < get<2>(edges[b]);\n        });\n        UnionFind uf2(N);\n        fill(edge_on.begin(), edge_on.end(), false);\n        for (int idx : candidate_edges) {\n            auto [u, v, w] = edges[idx];\n            if (uf2.unite(u, v)) {\n                edge_on[idx] = true;\n            }\n        }\n    } else if (terms.size() == 1) {\n        // No edges needed\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (edge_on[j] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    vector<tuple<int, int, int, int>> ops;\n\n    // bottom-up heapify\n    for (int x = N - 2; x >= 0; --x) {\n        for (int y = 0; y <= x; ++y) {\n            int cx = x, cy = y;\n            while (cx < N - 1) {\n                int left_val  = a[cx + 1][cy];\n                int right_val = a[cx + 1][cy + 1];\n                int cur_val   = a[cx][cy];\n\n                if (cur_val > left_val || cur_val > right_val) {\n                    // swap with the smaller child\n                    int child_y = (left_val < right_val) ? cy : cy + 1;\n                    swap(a[cx][cy], a[cx + 1][child_y]);\n                    ops.emplace_back(cx, cy, cx + 1, child_y);\n                    cx = cx + 1;\n                    cy = child_y;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // output\n    cout << ops.size() << \"\\n\";\n    for (const auto& [x1, y1, x2, y2] : ops) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int D = 9;\n    int N;\n    cin >> D >> N; // D is always 9\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // precompute BFS distances from entrance (0,4) ignoring containers\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int, int>> q;\n    dist[0][4] = 0;\n    q.emplace(0, 4);\n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            if (obstacle[nx][ny] || dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            q.emplace(nx, ny);\n        }\n    }\n\n    // list of all usable cells (excluding entrance), sorted by distance\n    vector<tuple<int, int, int>> cells; // (distance, row, col)\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == 0 && j == 4) continue;          // entrance itself\n            if (obstacle[i][j]) continue;\n            cells.emplace_back(dist[i][j], i, j);\n        }\n    }\n    sort(cells.begin(), cells.end());\n    const int total = cells.size();   // = D*D - 1 - N\n\n    // index of each cell in the sorted order (0 .. total-1)\n    vector<vector<int>> order(D, vector<int>(D, -1));\n    for (int idx = 0; idx < total; ++idx) {\n        auto [d, i, j] = cells[idx];\n        order[i][j] = idx;\n    }\n\n    // container number stored at each cell (-1 if empty)\n    vector<vector<int>> container(D, vector<int>(D, -1));\n    vector<vector<bool>> occupied(D, vector<bool>(D, false));\n\n    // BFS from entrance on empty cells (obstacles + occupied cells are walls)\n    auto bfs_reachable = [&]() -> vector<vector<bool>> {\n        vector<vector<bool>> reachable(D, vector<bool>(D, false));\n        queue<pair<int, int>> q;\n        if (!obstacle[0][4] && !occupied[0][4]) {\n            reachable[0][4] = true;\n            q.emplace(0, 4);\n        }\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k], ny = y + dy[k];\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n                if (obstacle[nx][ny] || occupied[nx][ny]) continue;\n                if (reachable[nx][ny]) continue;\n                reachable[nx][ny] = true;\n                q.emplace(nx, ny);\n            }\n        }\n        return reachable;\n    };\n\n    // ---------- placement phase ----------\n    for (int d = 0; d < total; ++d) {\n        int t;\n        cin >> t;\n\n        auto reachable = bfs_reachable();\n\n        // choose the reachable empty cell whose order is closest to t\n        int best_i = -1, best_j = -1;\n        int best_diff = INT_MAX;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || occupied[i][j]) continue;\n                if (i == 0 && j == 4) continue;      // entrance cannot be used\n                if (!reachable[i][j]) continue;\n                int diff = abs(order[i][j] - t);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // place the container\n        occupied[best_i][best_j] = true;\n        container[best_i][best_j] = t;\n        cout << best_i << \" \" << best_j << endl << flush;\n    }\n\n    // ---------- retrieval phase ----------\n    for (int step = 0; step < total; ++step) {\n        auto reachable = bfs_reachable();\n\n        // find the reachable container with the smallest number\n        int best_num = INT_MAX;\n        int best_i = -1, best_j = -1;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || container[i][j] == -1) continue;\n                if (!reachable[i][j]) continue;\n                if (container[i][j] < best_num) {\n                    best_num = container[i][j];\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // remove it\n        occupied[best_i][best_j] = false;\n        container[best_i][best_j] = -1;\n        cout << best_i << \" \" << best_j << \"\\n\";\n    }\n    cout << flush;\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\nint n, m;\nvector<vector<int>> grid;\n\n// original adjacency relations (including 0)\nvector<vector<bool>> orig;\n\n// adjacency count between colors (lower triangle, 1..m)\nvector<vector<int>> adjCnt;\n\n// total cells of each color\nvector<int> tot;\n\n// number of boundary cells of each color (adjacent to outside)\nvector<int> zeroCnt;\n\n// whether a color originally touches the boundary\nvector<bool> touchesBoundary;\n\nbool can_remove(int i, int j, int c) {\n    if (c == 0) return false;\n\n    // color must originally touch boundary\n    if (!touchesBoundary[c]) return false;\n\n    // check boundary cell count for c\n    int onBoundary = (i == 0 || i == n-1 || j == 0 || j == n-1) ? 1 : 0;\n    if (onBoundary && zeroCnt[c] <= 1) return false; // would lose all boundary cells\n\n    // neighbours\n    vector<int> neighColors;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        int col = grid[ni][nj];\n        if (col == 0) continue; // neighbour is already zero, no new adjacency\n        // all neighbour colors must originally touch boundary\n        if (!touchesBoundary[col]) return false;\n        // adjacency between c and col must remain\n        int a = min(c, col);\n        int b = max(c, col);\n        if (adjCnt[a][b] < 2) return false; // this cell contributes to the only adjacency\n        neighColors.push_back(col);\n    }\n\n    // connectivity check for color c after removal\n    vector<vector<bool>> visited(n, vector<bool>(n, false));\n    queue<pair<int,int>> q;\n    // find a starting cell (any other cell of same colour)\n    bool found = false;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        if (grid[ni][nj] == c) {\n            q.push({ni, nj});\n            visited[ni][nj] = true;\n            found = true;\n            break;\n        }\n    }\n    if (!found) {\n        // find any other cell of colour c\n        for (int x = 0; x < n; ++x) {\n            for (int y = 0; y < n; ++y) {\n                if ((x != i || y != j) && grid[x][y] == c) {\n                    q.push({x, y});\n                    visited[x][y] = true;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n    }\n    if (!found) return false; // only one cell of colour c (should not happen because tot[c]>1)\n    int cnt = 1;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (nx == i && ny == j) continue;\n            if (!visited[nx][ny] && grid[nx][ny] == c) {\n                visited[nx][ny] = true;\n                cnt++;\n                q.push({nx, ny});\n            }\n        }\n    }\n    if (cnt != tot[c] - 1) return false;\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    const int MAXC = m + 2;\n    orig.assign(MAXC, vector<bool>(MAXC, false));\n    adjCnt.assign(MAXC, vector<int>(MAXC, 0));\n    tot.assign(MAXC, 0);\n    zeroCnt.assign(MAXC, 0);\n    touchesBoundary.assign(MAXC, false);\n\n    // initial data from original map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = grid[i][j];\n            tot[c]++;\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                zeroCnt[c]++;\n                touchesBoundary[c] = true;\n                orig[0][c] = orig[c][0] = true;\n            }\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int col = grid[ni][nj];\n                if (c != col) {\n                    orig[c][col] = orig[col][c] = true;\n                    if (c < col) adjCnt[c][col]++;\n                }\n            }\n        }\n    }\n\n    // BFS from boundary (all cells on grid boundary)\n    deque<pair<int,int>> que;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                if (grid[i][j] != 0) {\n                    que.push_back({i, j});\n                }\n            }\n        }\n    }\n\n    // iterative removal\n    while (!que.empty()) {\n        auto [i, j] = que.front(); que.pop_front();\n        int c = grid[i][j];\n        if (c == 0) continue;\n        if (can_remove(i, j, c)) {\n            // update structures\n            // neighbours\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int col = grid[ni][nj];\n                if (col == 0) continue;\n                // zero adjacency to neighbour increases\n                zeroCnt[col]++;\n                // adjacency between c and col decreases\n                if (col != c) {\n                    int a = min(c, col);\n                    int b = max(c, col);\n                    adjCnt[a][b]--;\n                }\n                // push neighbour for further consideration\n                if (grid[ni][nj] != 0) { // already zero? no\n                    que.push_back({ni, nj});\n                }\n            }\n            // boundary status of c\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                zeroCnt[c]--;\n            }\n            tot[c]--;\n            grid[i][j] = 0;\n            // also push neighbours of removed cell\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                if (grid[ni][nj] != 0) {\n                    que.push_back({ni, nj});\n                }\n            }\n        }\n    }\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << grid[i][j];\n            if (j < n-1) cout << ' ';\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint queries_left;\nint N, D, Q;\n\n// Perform a comparison and read the result, decrement queries_left\nvoid query(const vector<int>& L, const vector<int>& R, string& res) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    cin >> res;\n    --queries_left;\n}\n\n// Sort comparator: returns true if a is lighter than b (a < b)\nbool lighter(int a, int b) {\n    vector<int> L = {a}, R = {b};\n    string res;\n    query(L, R, res);\n    if (res == \"<\") return true;\n    if (res == \">\") return false;\n    return false; // equal -> not less\n}\n\n// Greedy split of a set into two balanced subsets using the balance\n// Returns pair (left, right)\npair<vector<int>, vector<int>> split_group(const vector<int>& group, const vector<int>& order, const vector<int>& rank) {\n    vector<int> left, right;\n    // Get items in descending weight order\n    vector<int> sorted_group = group;\n    // If we have a rank array (sorted), use it to sort descending\n    if (!rank.empty()) {\n        sort(sorted_group.begin(), sorted_group.end(), [&](int a, int b) {\n            return rank[a] > rank[b];\n        });\n    }\n    // Process items in that order\n    for (int idx = 0; idx < (int)sorted_group.size(); ++idx) {\n        int item = sorted_group[idx];\n        if (left.empty() && right.empty()) {\n            left.push_back(item);\n        } else if (right.empty()) {\n            right.push_back(item);\n        } else {\n            // Both sides non-empty, compare\n            vector<int> left_candidate = left;\n            left_candidate.push_back(item);\n            string res;\n            query(left_candidate, right, res);\n            if (res == \"<\" || res == \"=\") {\n                left.push_back(item);\n            } else {\n                right.push_back(item);\n            }\n        }\n    }\n    return {left, right};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    queries_left = Q;\n\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n\n    // Decide whether we can afford full sorting\n    const int SORT_BUDGET = N * 6; // approximate max needed\n    bool do_sort = (Q >= SORT_BUDGET);\n\n    vector<int> order(N);\n    vector<int> rank(N, -1); // rank[item] = position in sorted order (0 = lightest)\n\n    if (do_sort) {\n        sort(items.begin(), items.end(), lighter);\n        order = items;\n        for (int i = 0; i < N; ++i) rank[order[i]] = i;\n    } else {\n        order = items; // keep original order (no information)\n    }\n\n    // Start with one group containing all items\n    vector<vector<int>> groups;\n    groups.push_back(items);\n\n    // Split groups as long as we have budget and need more groups\n    while ((int)groups.size() < D && queries_left > 0) {\n        // Find the largest group (by number of items)\n        auto it = max_element(groups.begin(), groups.end(),\n                              [](const vector<int>& a, const vector<int>& b) {\n                                  return a.size() < b.size();\n                              });\n        int sz = it->size();\n        if (sz < 2) break; // cannot split further\n\n        int needed = sz - 2; // for greedy split (first two items are free)\n        if (needed > queries_left) break; // not enough queries\n\n        // Perform the split\n        auto [left, right] = split_group(*it, order, rank);\n\n        // Replace the large group with the two new groups\n        int idx = distance(groups.begin(), it);\n        groups.erase(groups.begin() + idx);\n        groups.push_back(move(left));\n        groups.push_back(move(right));\n    }\n\n    // If we still have fewer than D groups, split arbitrary without queries\n    while ((int)groups.size() < D) {\n        auto it = max_element(groups.begin(), groups.end(),\n                              [](const vector<int>& a, const vector<int>& b) {\n                                  return a.size() < b.size();\n                              });\n        int sz = it->size();\n        if (sz < 2) break; // cannot split\n\n        int half = sz / 2;\n        vector<int> left(it->begin(), it->begin() + half);\n        vector<int> right(it->begin() + half, it->end());\n\n        int idx = distance(groups.begin(), it);\n        groups.erase(groups.begin() + idx);\n        groups.push_back(move(left));\n        groups.push_back(move(right));\n    }\n\n    // Ensure exactly D groups (if we still have less, duplicate last groups? but unlikely)\n    // Assign each item to its group\n    vector<int> assign(N);\n    for (int g = 0; g < (int)groups.size(); ++g) {\n        for (int item : groups[g]) assign[item] = g;\n    }\n\n    // Output final division\n    for (int i = 0; i < N; ++i) {\n        cout << assign[i] << (i == N - 1 ? '\\n' : ' ');\n    }\n\n    // Waste any remaining queries (output dummy comparisons)\n    while (queries_left > 0) {\n        cout << \"1 1 0 1\" << endl;\n        string res;\n        cin >> res;\n        --queries_left;\n    }\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// length of longest strictly decreasing prefix (from bottom)\nint decreasing_prefix_len(const vector<int>& st) {\n    int sz = st.size();\n    if (sz == 0) return 0;\n    int len = 1;\n    for (int i = 1; i < sz; ++i) {\n        if (st[i-1] > st[i]) ++len;\n        else break;\n    }\n    return len;\n}\n\n// score of a single stack = number of boxes not in the decreasing prefix\nint stack_score(const vector<int>& st) {\n    return (int)st.size() - decreasing_prefix_len(st);\n}\n\n// total score over all stacks\nint total_score(const vector<vector<int>>& stacks) {\n    int s = 0;\n    for (const auto& st : stacks) s += stack_score(st);\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int per_stack = n / m;\n    vector<vector<int>> stacks(m);\n    vector<pair<int,int>> pos(n+1); // (stack, index)\n\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < per_stack; ++j) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            pos[box] = {i, j};\n        }\n    }\n\n    vector<pair<int,int>> operations;\n    int cur_score = total_score(stacks);\n    const int LAMBDA = 2; // weight for (block_size + 1) in the objective\n\n    for (int target = 1; target <= n; ++target) {\n        while (true) {\n            int s = pos[target].first;\n            int idx = pos[target].second;\n            auto& src = stacks[s];\n            int top_idx = (int)src.size() - 1;\n\n            // target already on top -> carry out\n            if (idx == top_idx) {\n                operations.emplace_back(target, 0);\n                src.pop_back();\n                cur_score = total_score(stacks);\n                break;\n            }\n\n            // current scores\n            int old_src_score = stack_score(src);\n            vector<int> old_dst_score(m);\n            for (int d = 0; d < m; ++d) if (d != s) old_dst_score[d] = stack_score(stacks[d]);\n\n            // evaluate all possible moves\n            struct Candidate {\n                int new_total_score;  // total score after move\n                int block_size;       // number of boxes moved\n                int v_idx;            // start index of the block in src\n                int dest;             // destination stack\n            };\n            vector<Candidate> cand;\n\n            for (int v_idx = idx + 1; v_idx <= top_idx; ++v_idx) {\n                int block_size = top_idx - v_idx + 1;\n                // source after removal\n                vector<int> src_new = src;\n                src_new.resize(v_idx);\n                int new_src_score = stack_score(src_new);\n\n                // the block\n                vector<int> block(src.begin() + v_idx, src.end());\n\n                for (int d = 0; d < m; ++d) {\n                    if (d == s) continue;\n                    vector<int> dst_new = stacks[d];\n                    dst_new.insert(dst_new.end(), block.begin(), block.end());\n                    int new_dst_score = stack_score(dst_new);\n                    int new_total = cur_score - old_src_score - old_dst_score[d]\n                                    + new_src_score + new_dst_score;\n                    cand.push_back({new_total, block_size, v_idx, d});\n                }\n            }\n\n            // choose best candidate using objective: new_total_score + LAMBDA * (block_size+1)\n            auto best = *min_element(cand.begin(), cand.end(),\n                [](const Candidate& a, const Candidate& b) {\n                    int obj_a = a.new_total_score + LAMBDA * (a.block_size + 1);\n                    int obj_b = b.new_total_score + LAMBDA * (b.block_size + 1);\n                    if (obj_a != obj_b) return obj_a < obj_b;\n                    if (a.block_size != b.block_size) return a.block_size < b.block_size;\n                    return a.v_idx < b.v_idx; // arbitrary tie\u2011break\n                });\n\n            // output the move\n            operations.emplace_back(src[best.v_idx], best.dest + 1);\n\n            // execute the move on actual stacks\n            auto& dst = stacks[best.dest];\n            for (int j = best.v_idx; j < (int)src.size(); ++j) {\n                int box = src[j];\n                dst.push_back(box);\n                pos[box] = {best.dest, (int)dst.size() - 1};\n            }\n            src.resize(best.v_idx);\n            cur_score = best.new_total_score;\n        }\n    }\n\n    // output the whole sequence\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <cmath>\n#include <queue>\n#include <string>\nusing namespace std;\n\nint N;\nvector<vector<int>> graph; // adjacency list (cell indices)\nvector<double> sqrt_d; // sqrt of d for each cell\n\n// for BFS tree\nvector<int> parent;\nvector<vector<int>> children;\nvector<char> dir_to_parent; // direction to go from parent to this cell (only meaningful for non-root)\nvector<char> dir_to_child; // for each child, we can store direction in children list\n\n// convert (i,j) to index\nint idx(int i, int j) { return i * N + j; }\nint ix(int id) { return id / N; }\nint jy(int id) { return id % N; }\n\n// build graph and BFS tree\nvoid build_tree() {\n    graph.assign(N * N, {});\n    // read walls (already read earlier, we need to store them)\n    // Actually we need h and v arrays. We'll read them in main.\n    // Assume global h and v are available.\n}\n\n// Move characters\nchar dir_char(int di, int dj) {\n    if (di == -1 && dj == 0) return 'U';\n    if (di == 1 && dj == 0) return 'D';\n    if (di == 0 && dj == -1) return 'L';\n    if (di == 0 && dj == 1) return 'R';\n    return '?';\n}\nchar opposite(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return '?';\n}\n\n// post-order compute f values for a given K\nvoid compute_f(double K, vector<int>& f_out, vector<int>& actual_n, int& total_moves) {\n    int M = N * N;\n    vector<int> f(M, 0);\n    vector<int> n_actual(M, 0);\n    // we need post-order traversal. We'll use recursion.\n    function<void(int)> dfs = [&](int v) {\n        int sum_child_f = 0;\n        for (int c : children[v]) {\n            dfs(c);\n            sum_child_f += f[c];\n        }\n        if (v == 0) { // root (0,0)\n            // root's visits = 1 (initial) + sum_child_f\n            n_actual[v] = 1 + sum_child_f;\n            // f_root is not used\n        } else {\n            int target = max(1, (int)round(K * sqrt_d[v]));\n            int desired_f = target - sum_child_f;\n            if (desired_f < 0) {\n                f[v] = 0;\n                n_actual[v] = sum_child_f;\n            } else {\n                f[v] = desired_f;\n                n_actual[v] = target;\n            }\n        }\n    };\n    dfs(0);\n    // total moves = 2 * sum_{v != root} f[v]\n    int sum_f = 0;\n    for (int v = 1; v < M; ++v) sum_f += f[v];\n    total_moves = 2 * sum_f;\n    f_out = f;\n    actual_n = n_actual;\n}\n\n// build route recursively using highest-remaining-first schedule\nstring build_route(int v, const vector<int>& f, const vector<vector<int>>& children) {\n    // children list for this node (from global children)\n    // we need remaining counts for each child\n    vector<int> rem;\n    vector<char> dir;\n    for (int c : children[v]) {\n        int cnt = f[c];\n        if (cnt <= 0) continue;\n        rem.push_back(cnt);\n        // direction from v to c\n        int di = ix(c) - ix(v);\n        int dj = jy(c) - jy(v);\n        dir.push_back(dir_char(di, dj));\n    }\n    // priority queue: (-remaining, index)\n    priority_queue<pair<int,int>> pq;\n    for (int i = 0; i < (int)rem.size(); ++i) {\n        pq.push({-rem[i], i}); // use negative to get max remaining\n    }\n    string moves;\n    while (!pq.empty()) {\n        auto [neg_rem, idx_child] = pq.top(); pq.pop();\n        int& remaining = rem[idx_child];\n        // move to child\n        moves.push_back(dir[idx_child]);\n        // recursively build child's tour\n        string child_tour = build_route(children[v][idx_child], f, children);\n        moves += child_tour;\n        // move back\n        moves.push_back(opposite(dir[idx_child]));\n        // decrement\n        remaining--;\n        if (remaining > 0) {\n            pq.push({-remaining, idx_child});\n        }\n    }\n    return moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    // read N\n    cin >> N;\n    // read walls\n    vector<string> h(N-1), v(N);\n    for (int i = 0; i < N-1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    // read dirt values\n    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) \n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    // build graph\n    graph.assign(N*N, {});\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = idx(i,j);\n            // down\n            if (i < N-1 && h[i][j] == '0') {\n                int id2 = idx(i+1, j);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n            // right\n            if (j < N-1 && v[i][j] == '0') {\n                int id2 = idx(i, j+1);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n        }\n    }\n\n    // BFS tree from (0,0)\n    int total_cells = N * N;\n    parent.assign(total_cells, -1);\n    children.assign(total_cells, {});\n    dir_to_parent.assign(total_cells, ' ');\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0; // mark root\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) {\n            if (parent[u] == -1) {\n                parent[u] = v;\n                children[v].push_back(u);\n                int di = ix(u) - ix(v);\n                int dj = jy(u) - jy(v);\n                dir_to_parent[u] = dir_char(di, dj);\n                q.push(u);\n            }\n        }\n    }\n    // compute sqrt_d\n    sqrt_d.assign(total_cells, 0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sqrt_d[idx(i,j)] = sqrt(d[i][j]);\n\n    // binary search for K to get moves near 100000\n    double low = 0, high = 100.0; // initial high\n    vector<int> best_f;\n    int best_moves = 0;\n    for (int iter = 0; iter < 60; ++iter) {\n        double mid = (low + high) / 2;\n        vector<int> f, actual_n;\n        int moves;\n        compute_f(mid, f, actual_n, moves);\n        if (moves <= 100000) {\n            best_f = f;\n            best_moves = moves;\n            low = mid;\n        } else {\n            high = mid;\n        }\n    }\n    // compute final f using low (ensures moves <= 100000)\n    {\n        vector<int> f, actual_n;\n        int moves;\n        compute_f(low, f, actual_n, moves);\n        best_f = f;\n        best_moves = moves;\n    }\n\n    // build route\n    string route = build_route(0, best_f, children);\n    // ensure length matches best_moves\n    // (should match if build_route correct)\n    // output route\n    cout << route << endl;\n\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\nusing LL = long long;\nconst LL INF = 1e18;\nconst int N = 15;\nconst int SZ = N * N; // 225\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int input_N, M;\n    cin >> input_N >> M; // input_N is guaranteed to be 15\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int i = 0; i < M; ++i) cin >> patterns[i];\n\n    // Precompute positions for each letter\n    vector<vector<int>> pos(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            pos[grid[i][j] - 'A'].push_back(idx);\n        }\n    }\n\n    // Manhattan distance matrix\n    array<array<int, SZ>, SZ> dist;\n    for (int i = 0; i < SZ; ++i) {\n        int x1 = i / N, y1 = i % N;\n        for (int j = 0; j < SZ; ++j) {\n            int x2 = j / N, y2 = j % N;\n            dist[i][j] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    int start_idx = si * N + sj;\n    vector<int> best_moves;\n    LL best_total = INF;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    // Try several random seeds (trial 0 is deterministic, others random)\n    for (int trial = 0; trial < 6; ++trial) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.8) break; // time guard\n\n        int cur = start_idx;\n        string S;\n        vector<bool> covered(M, false);\n        int uncovered = M;\n        vector<int> moves;\n\n        auto seed = chrono::steady_clock::now().time_since_epoch().count() + trial * 1000;\n        mt19937 local_rng(seed);\n\n        while (uncovered > 0) {\n            vector<pair<LL, int>> candidates;\n            for (int i = 0; i < M; ++i) {\n                if (covered[i]) continue;\n                const string& t = patterns[i];\n                int ol = 0;\n                for (int l = min(5, (int)S.size()); l >= 1; --l) {\n                    if (S.compare(S.size() - l, l, t, 0, l) == 0) {\n                        ol = l;\n                        break;\n                    }\n                }\n                if (ol == 5) {\n                    covered[i] = true;\n                    uncovered--;\n                    continue;\n                }\n                string rem = t.substr(ol);\n                int len = rem.size();\n                vector<LL> prev(SZ, INF);\n                for (int p : pos[rem[0] - 'A']) {\n                    prev[p] = dist[cur][p] + 1;\n                }\n                for (int ch = 1; ch < len; ++ch) {\n                    vector<LL> cur_cost(SZ, INF);\n                    int c_idx = rem[ch] - 'A';\n                    int p_c_idx = rem[ch-1] - 'A';\n                    for (int p : pos[c_idx]) {\n                        LL best = INF;\n                        for (int q : pos[p_c_idx]) {\n                            if (prev[q] >= INF) continue;\n                            LL cand = prev[q] + dist[q][p] + 1;\n                            if (cand < best) best = cand;\n                        }\n                        cur_cost[p] = best;\n                    }\n                    prev = cur_cost;\n                }\n                LL total = INF;\n                for (int p : pos[rem.back() - 'A']) {\n                    total = min(total, prev[p]);\n                }\n                candidates.emplace_back(total, i);\n            }\n            if (candidates.empty()) break;\n\n            int chosen = -1;\n            if (trial == 0) {\n                auto it = min_element(candidates.begin(), candidates.end());\n                chosen = it->second;\n            } else {\n                LL minc = INF;\n                for (auto& p : candidates) minc = min(minc, p.first);\n                vector<int> good;\n                for (auto& p : candidates) {\n                    if (p.first <= minc * 1.2) good.push_back(p.second);\n                }\n                if (good.empty()) good.push_back(candidates[0].second);\n                uniform_int_distribution<int> uid(0, (int)good.size() - 1);\n                chosen = good[uid(local_rng)];\n            }\n\n            const string& t = patterns[chosen];\n            int ol = 0;\n            for (int l = min(5, (int)S.size()); l >= 1; --l) {\n                if (S.compare(S.size() - l, l, t, 0, l) == 0) {\n                    ol = l;\n                    break;\n                }\n            }\n            string rem = t.substr(ol);\n            int len = rem.size();\n            vector<vector<LL>> dp(len, vector<LL>(SZ, INF));\n            vector<vector<int>> prev_step(len, vector<int>(SZ, -1));\n            for (int p : pos[rem[0] - 'A']) {\n                dp[0][p] = dist[cur][p] + 1;\n            }\n            for (int ch = 1; ch < len; ++ch) {\n                int c_idx = rem[ch] - 'A';\n                int p_c_idx = rem[ch-1] - 'A';\n                for (int p : pos[c_idx]) {\n                    LL best = INF;\n                    int best_prev = -1;\n                    for (int q : pos[p_c_idx]) {\n                        if (dp[ch-1][q] >= INF) continue;\n                        LL cand = dp[ch-1][q] + dist[q][p] + 1;\n                        if (cand < best) {\n                            best = cand;\n                            best_prev = q;\n                        }\n                    }\n                    dp[ch][p] = best;\n                    prev_step[ch][p] = best_prev;\n                }\n            }\n            LL bestcost = INF;\n            int final_pos = -1;\n            for (int p : pos[rem.back() - 'A']) {\n                if (dp[len-1][p] < bestcost) {\n                    bestcost = dp[len-1][p];\n                    final_pos = p;\n                }\n            }\n            vector<int> path(len);\n            int p = final_pos;\n            for (int ch = len-1; ch >= 0; --ch) {\n                path[ch] = p;\n                p = prev_step[ch][p];\n            }\n            for (int x : path) moves.push_back(x);\n            cur = final_pos;\n            S += rem;\n            covered[chosen] = true;\n            uncovered--;\n\n            // Check other patterns that may have become contained\n            if ((int)S.size() >= 5) {\n                for (int i = 0; i < M; ++i) {\n                    if (covered[i]) continue;\n                    if (S.find(patterns[i]) != string::npos) {\n                        covered[i] = true;\n                        uncovered--;\n                    }\n                }\n            }\n        }\n\n        // Compute total cost of this solution\n        LL total = 0;\n        int prev = start_idx;\n        for (int p : moves) {\n            total += dist[prev][p] + 1;\n            prev = p;\n        }\n        if (total < best_total) {\n            best_total = total;\n            best_moves = moves;\n        }\n    }\n\n    // Output best solution\n    for (int p : best_moves) {\n        cout << p / N << ' ' << p % N << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int MAX_CELLS = MAX_N * MAX_N; // 400\n\nstruct Placement {\n    int di, dj;\n    bitset<MAX_CELLS> cells_bitset;\n    vector<int> cells_list; // indices of covered cells\n    vector<int> row_counts;\n    vector<int> col_counts;\n};\n\nstruct Field {\n    vector<pair<int,int>> shape; // relative coordinates\n    vector<Placement> placements;\n};\n\nint N, M;\ndouble eps;\nvector<Field> fields;\nvector<int> remaining_placements_per_field[20]; // for each field, indices of still possible placements\nint drilled_v[MAX_CELLS]; // -1 unknown, otherwise exact value\nint ops = 0; // number of operations used\n\nvoid flush_output() {\n    cout.flush();\n}\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        vector<pair<int,int>> shape(d);\n        for (int l = 0; l < d; ++l) {\n            cin >> shape[l].first >> shape[l].second;\n        }\n        fields[k].shape = shape;\n    }\n}\n\nvoid generate_placements() {\n    for (int k = 0; k < M; ++k) {\n        const auto& shape = fields[k].shape;\n        int max_i = 0, max_j = 0;\n        for (const auto& p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1;\n        int w = max_j + 1;\n        for (int di = 0; di <= N - h; ++di) {\n            for (int dj = 0; dj <= N - w; ++dj) {\n                Placement pl;\n                pl.di = di;\n                pl.dj = dj;\n                pl.row_counts.assign(N, 0);\n                pl.col_counts.assign(N, 0);\n                for (const auto& p : shape) {\n                    int i = di + p.first;\n                    int j = dj + p.second;\n                    int cell = i * N + j;\n                    pl.cells_bitset.set(cell);\n                    pl.cells_list.push_back(cell);\n                    pl.row_counts[i]++;\n                    pl.col_counts[j]++;\n                }\n                fields[k].placements.push_back(move(pl));\n            }\n        }\n    }\n}\n\nvoid init() {\n    memset(drilled_v, -1, sizeof(drilled_v));\n    for (int f = 0; f < M; ++f) {\n        int sz = fields[f].placements.size();\n        remaining_placements_per_field[f].resize(sz);\n        iota(remaining_placements_per_field[f].begin(), remaining_placements_per_field[f].end(), 0);\n    }\n}\n\nvoid perform_divine_queries() {\n    // row queries\n    for (int i = 0; i < N; ++i) {\n        cout << \"q \" << N;\n        for (int j = 0; j < N; ++j) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        flush_output();\n        int resp;\n        cin >> resp;\n        ops++;\n        // we ignore the result (could be used for row sum constraints)\n    }\n    // column queries\n    for (int j = 0; j < N; ++j) {\n        cout << \"q \" << N;\n        for (int i = 0; i < N; ++i) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        flush_output();\n        int resp;\n        cin >> resp;\n        ops++;\n    }\n}\n\nint find_best_cell() {\n    int best_cell = -1, best_score = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int cell = i * N + j;\n            if (drilled_v[cell] != -1) continue;\n            int score = 0;\n            for (int f = 0; f < M; ++f) {\n                for (int idx : remaining_placements_per_field[f]) {\n                    if (fields[f].placements[idx].cells_bitset.test(cell)) {\n                        score++;\n                    }\n                }\n            }\n            if (score > best_score) {\n                best_score = score;\n                best_cell = cell;\n            }\n        }\n    }\n    return best_cell;\n}\n\nvoid drill_cell(int cell) {\n    int i = cell / N, j = cell % N;\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    drilled_v[cell] = resp;\n    ops++;\n    if (resp == 0) {\n        // eliminate all placements that cover this cell\n        for (int f = 0; f < M; ++f) {\n            vector<int> new_remaining;\n            for (int idx : remaining_placements_per_field[f]) {\n                if (!fields[f].placements[idx].cells_bitset.test(cell)) {\n                    new_remaining.push_back(idx);\n                }\n            }\n            remaining_placements_per_field[f] = move(new_remaining);\n        }\n    }\n}\n\n// ------------------------------------------------------------\n// Backtracking to find assignments consistent with drilled cells\n// ------------------------------------------------------------\nint found_solutions;\nvector<int> current_assignment; // placement index for each field, -1 if unassigned\nvector<int> best_assignment;\nint current_sum[MAX_CELLS]; // current total v for each cell (from assigned fields)\n\nbool can_place(int f, int pidx) {\n    Placement& pl = fields[f].placements[pidx];\n    for (int cell : pl.cells_list) {\n        if (drilled_v[cell] != -1 && current_sum[cell] + 1 > drilled_v[cell]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid dfs(int step, const vector<int>& order) {\n    if (found_solutions >= 2) return;\n    if (step == (int)order.size()) {\n        // check all drilled cells exactly\n        for (int cell = 0; cell < N*N; ++cell) {\n            if (drilled_v[cell] != -1 && current_sum[cell] != drilled_v[cell]) {\n                return;\n            }\n        }\n        found_solutions++;\n        if (found_solutions == 1) {\n            best_assignment = current_assignment;\n        }\n        return;\n    }\n    int f = order[step];\n    for (int pidx : remaining_placements_per_field[f]) {\n        if (!can_place(f, pidx)) continue;\n        // place this field\n        current_assignment[f] = pidx;\n        Placement& pl = fields[f].placements[pidx];\n        for (int cell : pl.cells_list) {\n            current_sum[cell]++;\n        }\n        dfs(step+1, order);\n        // undo\n        for (int cell : pl.cells_list) {\n            current_sum[cell]--;\n        }\n        current_assignment[f] = -1;\n        if (found_solutions >= 2) return;\n    }\n}\n\n// returns true if exactly one consistent assignment found\nbool find_unique_solution() {\n    found_solutions = 0;\n    // order fields by number of remaining placements (ascending) to reduce branching\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return remaining_placements_per_field[a].size() < remaining_placements_per_field[b].size();\n    });\n    memset(current_sum, 0, sizeof(current_sum));\n    current_assignment.assign(M, -1);\n    best_assignment.assign(M, -1);\n    dfs(0, order);\n    return (found_solutions == 1);\n}\n\nbool estimate_combinations_small() {\n    // return true if product of remaining placements <= 100000\n    long long prod = 1;\n    for (int f = 0; f < M; ++f) {\n        int sz = remaining_placements_per_field[f].size();\n        if (sz == 0) return false;\n        prod *= sz;\n        if (prod > 100000) return false;\n    }\n    return true;\n}\n\nbool guess() {\n    // compute positive cells from best_assignment\n    vector<int> pos_cells;\n    for (int f = 0; f < M; ++f) {\n        int pidx = best_assignment[f];\n        if (pidx == -1) continue; // should not happen\n        Placement& pl = fields[f].placements[pidx];\n        for (int cell : pl.cells_list) {\n            pos_cells.push_back(cell);\n        }\n    }\n    // remove duplicates\n    sort(pos_cells.begin(), pos_cells.end());\n    pos_cells.erase(unique(pos_cells.begin(), pos_cells.end()), pos_cells.end());\n    // output guess\n    cout << \"a \" << pos_cells.size();\n    for (int cell : pos_cells) {\n        int i = cell / N, j = cell % N;\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    ops++;\n    return (resp == 1);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n    generate_placements();\n    init();\n    perform_divine_queries(); // cheap queries, provide extra info (optional)\n\n    int max_ops = 2 * N * N;\n    bool guessed = false;\n    while (ops < max_ops && !guessed) {\n        // try to find unique solution if number of combinations is not too large\n        if (ops >= 10 && estimate_combinations_small()) {\n            if (find_unique_solution()) {\n                if (guess()) {\n                    guessed = true;\n                    break;\n                }\n                // if guess failed, continue drilling (the previous solution was wrong)\n            }\n        }\n        // choose a cell to drill\n        int cell = find_best_cell();\n        if (cell == -1) break; // all cells already drilled\n        drill_cell(cell);\n    }\n\n    // fallback: drill all remaining cells and answer from exact data\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int cell = i * N + j;\n            if (drilled_v[cell] == -1) {\n                drill_cell(cell);\n            }\n        }\n    }\n    // now we have exact v for every cell\n    vector<pair<int,int>> pos;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (drilled_v[i*N+j] > 0) {\n                pos.emplace_back(i, j);\n            }\n        }\n    }\n    cout << \"a \" << pos.size();\n    for (auto [i,j] : pos) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <cassert>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int width() const { return i1 - i0; }\n    int height() const { return j1 - j0; }\n    int area() const { return width() * height(); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // For each day, sort a and store ranked values.\n    vector<vector<int>> a_sorted(D, vector<int>(N));\n    vector<vector<int>> rank_of(D, vector<int>(N)); // original index -> rank after sorting\n    for (int d = 0; d < D; ++d) {\n        vector<pair<int, int>> tmp(N);\n        for (int k = 0; k < N; ++k) tmp[k] = {a[d][k], k};\n        sort(tmp.begin(), tmp.end());\n        for (int k = 0; k < N; ++k) {\n            a_sorted[d][k] = tmp[k].first;\n            rank_of[d][tmp[k].second] = k;\n        }\n    }\n\n    // Collect values for each rank (sorted per day) across days.\n    vector<vector<int>> val_per_rank(N);\n    for (int k = 0; k < N; ++k) {\n        val_per_rank[k].reserve(D);\n        for (int d = 0; d < D; ++d) {\n            val_per_rank[k].push_back(a_sorted[d][k]);\n        }\n        sort(val_per_rank[k].begin(), val_per_rank[k].end());\n    }\n\n    // Greedy allocation of areas to ranks (sorted b).\n    const long long MAX_AREA = W * W;\n    vector<long long> b(N, 0);\n    long long used_area = 0;\n\n    // Each entry: (gain, rank, next_break)\n    priority_queue<pair<long long, int>> pq; // gain = 100 * (D - idx), we store as positive.\n    vector<int> idx(N, 0);\n    vector<long long> next_break(N, 0);\n\n    auto push_rank = [&](int k) {\n        if (idx[k] < D) {\n            long long gain = 100LL * (D - idx[k]);\n            int next_val = val_per_rank[k][idx[k]];\n            pq.push({gain, k});\n            next_break[k] = next_val;\n        }\n    };\n    for (int k = 0; k < N; ++k) push_rank(k);\n\n    while (used_area < MAX_AREA && !pq.empty()) {\n        auto [gain, k] = pq.top(); pq.pop();\n        if (gain <= 0) break;\n        // current b[k] is before next_break\n        long long diff = next_break[k] - b[k];\n        if (diff <= 0) {\n            // already reached this breakpoint, update and push again\n            idx[k]++;\n            push_rank(k);\n            continue;\n        }\n        long long delta = min(diff, MAX_AREA - used_area);\n        b[k] += delta;\n        used_area += delta;\n        if (delta == diff) {\n            // reached breakpoint\n            idx[k]++;\n            push_rank(k);\n        } else {\n            // area exhausted\n            break;\n        }\n    }\n\n    // b now may not be sorted. We must work with sorted b for packing.\n    vector<long long> b_sorted = b;\n    sort(b_sorted.begin(), b_sorted.end());\n\n    // Pack rectangles of areas b_sorted (ascending). We will place largest first.\n    vector<long long> b_desc = b_sorted;\n    reverse(b_desc.begin(), b_desc.end());\n\n    vector<Rect> placed; // in order of b_desc\n    vector<Rect> free_list;\n    free_list.push_back({0, 0, W, W});\n\n    auto place_rect = [&](long long area, int free_idx, int w, int h) {\n        Rect r = free_list[free_idx];\n        // place at top-left corner of free rectangle\n        Rect new_rect = {r.i0, r.j0, r.i0 + w, r.j0 + h};\n        placed.push_back(new_rect);\n        // remove this free rectangle\n        free_list.erase(free_list.begin() + free_idx);\n        // add up to two new free rectangles\n        // right part (same height)\n        if (r.i0 + w < r.i1) {\n            free_list.push_back({r.i0 + w, r.j0, r.i1, r.j0 + h});\n        }\n        // bottom part (full width)\n        if (r.j0 + h < r.j1) {\n            free_list.push_back({r.i0, r.j0 + h, r.i1, r.j1});\n        }\n    };\n\n    for (long long area : b_desc) {\n        bool ok = false;\n        // iterate free rectangles in order (any order)\n        for (int fi = 0; fi < (int)free_list.size(); ++fi) {\n            Rect r = free_list[fi];\n            int w_avail = r.width();\n            int h_avail = r.height();\n            // try to factor area into w*h with integer coordinates\n            bool found = false;\n            int best_w = -1, best_h = -1;\n            // iterate divisors up to sqrt\n            for (int w = 1; w * w <= area; ++w) {\n                if (area % w == 0) {\n                    int h = area / w;\n                    // try w <= w_avail, h <= h_avail\n                    if (w <= w_avail && h <= h_avail) {\n                        best_w = w; best_h = h; found = true; break;\n                    }\n                    // try swapped\n                    int w2 = h, h2 = w;\n                    if (w2 <= w_avail && h2 <= h_avail) {\n                        best_w = w2; best_h = h2; found = true; break;\n                    }\n                }\n            }\n            if (found) {\n                place_rect(area, fi, best_w, best_h);\n                ok = true;\n                break;\n            }\n        }\n        if (!ok) {\n            // fallback: reduce area by 1 and try again (should rarely happen)\n            long long reduced = area - 1;\n            while (reduced > 0) {\n                for (int fi = 0; fi < (int)free_list.size(); ++fi) {\n                    Rect r = free_list[fi];\n                    int w_avail = r.width();\n                    int h_avail = r.height();\n                    for (int w = 1; w * w <= reduced; ++w) {\n                        if (reduced % w == 0) {\n                            int h = reduced / w;\n                            if (w <= w_avail && h <= h_avail) {\n                                place_rect(reduced, fi, w, h);\n                                ok = true;\n                                break;\n                            }\n                            int w2 = h, h2 = w;\n                            if (w2 <= w_avail && h2 <= h_avail) {\n                                place_rect(reduced, fi, w2, h2);\n                                ok = true;\n                                break;\n                            }\n                        }\n                    }\n                    if (ok) break;\n                }\n                if (ok) break;\n                reduced--;\n            }\n            if (!ok) {\n                // Very rare: fallback to 1x1 rectangle (area 1)\n                place_rect(1, 0, 1, 1);\n            }\n        }\n    }\n\n    // placed rectangles are in order of b_desc. Map to rank (ascending area).\n    // placed[i] corresponds to b_desc[i] => rank = N-1-i.\n    vector<Rect> rect_by_rank(N);\n    for (int i = 0; i < N; ++i) {\n        rect_by_rank[N - 1 - i] = placed[i];\n    }\n\n    // Output for each day\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            int r = rank_of[d][k]; // rank of this reservation's desired area\n            const Rect& rr = rect_by_rank[r];\n            cout << rr.i0 << ' ' << rr.j0 << ' ' << rr.i1 << ' ' << rr.j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int K = 81;\nconst int M = 20;\n\nstruct Operation {\n    int m, p, q;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n    // n=9, m=20, k=81 always\n    vector<vector<ll>> board(N, vector<ll>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> board[i][j];\n        }\n    }\n    vector<vector<vector<ll>>> stamps(M, vector<vector<ll>>(3, vector<ll>(3)));\n    for (int id = 0; id < M; ++id) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[id][i][j];\n            }\n        }\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // best solution across trials\n    pair<ll, vector<Operation>> best = {-1, {}};\n\n    const int TRIALS = 6;              // 6 random restarts, enough within 2 sec\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // current state of board during construction\n        vector<vector<ll>> cur = board;\n        ll score = 0;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                score += cur[i][j] % MOD;\n\n        vector<Operation> ops;\n        int used = 0;\n\n        // ---- greedy construction ----\n        while (used < K) {\n            ll best_gain = 0;\n            vector<pair<ll, Operation>> candidates;\n            for (int mid = 0; mid < M; ++mid) {\n                for (int p = 0; p + 2 < N; ++p) {\n                    for (int q = 0; q + 2 < N; ++q) {\n                        ll gain = 0;\n                        for (int i = 0; i < 3; ++i) {\n                            for (int j = 0; j < 3; ++j) {\n                                ll cell = cur[p + i][q + j];\n                                ll old_rem = cell % MOD;\n                                ll new_rem = (cell + stamps[mid][i][j]) % MOD;\n                                gain += new_rem - old_rem;\n                            }\n                        }\n                        if (gain > best_gain) {\n                            best_gain = gain;\n                            candidates.clear();\n                            candidates.emplace_back(gain, Operation{mid, p, q});\n                        } else if (gain == best_gain && gain > 0) {\n                            candidates.emplace_back(gain, Operation{mid, p, q});\n                        }\n                    }\n                }\n            }\n            if (candidates.empty()) break;   // no improving move\n\n            // randomly pick among best\n            uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);\n            auto op = candidates[dist(rng)].second;\n            for (int i = 0; i < 3; ++i)\n                for (int j = 0; j < 3; ++j)\n                    cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n            score += best_gain;\n            ops.push_back(op);\n            ++used;\n        }\n\n        // ---- local search (remove + add) ----\n        auto recompute_score = [&]() -> ll {\n            ll s = 0;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    s += cur[i][j] % MOD;\n            return s;\n        };\n\n        bool improved = true;\n        for (int phase = 0; phase < 15 && improved; ++phase) {\n            improved = false;\n\n            // removal part\n            vector<int> indices(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                auto op = ops[idx];\n                // subtract stamp\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[op.p + i][op.q + j] -= stamps[op.m][i][j];\n                ll new_score = recompute_score();\n                if (new_score > score) {\n                    score = new_score;\n                    ops.erase(ops.begin() + idx);\n                    improved = true;\n                    break; // restart scanning\n                } else {\n                    // restore\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n                }\n            }\n\n            // addition part (fill remaining quota)\n            if (improved) {\n                int remaining = K - (int)ops.size();\n                while (remaining > 0) {\n                    ll best_gain = 0;\n                    vector<pair<ll, Operation>> candidates;\n                    for (int mid = 0; mid < M; ++mid) {\n                        for (int p = 0; p + 2 < N; ++p) {\n                            for (int q = 0; q + 2 < N; ++q) {\n                                ll gain = 0;\n                                for (int i = 0; i < 3; ++i) {\n                                    for (int j = 0; j < 3; ++j) {\n                                        ll cell = cur[p + i][q + j];\n                                        ll old_rem = cell % MOD;\n                                        ll new_rem = (cell + stamps[mid][i][j]) % MOD;\n                                        gain += new_rem - old_rem;\n                                    }\n                                }\n                                if (gain > best_gain) {\n                                    best_gain = gain;\n                                    candidates.clear();\n                                    candidates.emplace_back(gain, Operation{mid, p, q});\n                                } else if (gain == best_gain && gain > 0) {\n                                    candidates.emplace_back(gain, Operation{mid, p, q});\n                                }\n                            }\n                        }\n                    }\n                    if (candidates.empty()) break;\n                    uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);\n                    auto op = candidates[dist(rng)].second;\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n                    score += best_gain;\n                    ops.push_back(op);\n                    --remaining;\n                }\n            }\n        }\n\n        // update best\n        if (score > best.first) {\n            best = {score, ops};\n        }\n    }\n\n    // output best solution\n    const auto &final_ops = best.second;\n    cout << final_ops.size() << \"\\n\";\n    for (const auto &op : final_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;                     // N is always 5\nint A[N][N];\nint targetRow[25];                   // targetRow[num] = num/5\nint arrivalRow[25];\nint arrivalIdx[25];\n\n// State\nint craneR = 0, craneC = 0;\nbool holding = false;\nint heldContainer = -1;\nint storageTargetR = -1, storageTargetC = -1;\nint nextDispatch = 0;\nbool dispatched[25] = {false};\n\nint grid[N][N];                      // -1 = empty, else container number\n\nint gateCurrent[N];\nint nextIdx[N];\n\n// Helper functions\nvoid placeContainer(int num, int r, int c) {\n    grid[r][c] = num;\n}\n\nvoid removeContainer(int r, int c) {\n    grid[r][c] = -1;\n}\n\npair<int,int> findStorageCell(int targetR) {\n    int bestDist = 100;\n    pair<int,int> best = {-1,-1};\n    for (int r = 0; r < N; ++r) {\n        for (int c = 1; c <= 3; ++c) {\n            if (grid[r][c] == -1 && !(r == craneR && c == craneC)) {\n                int dist = abs(r - targetR) + abs(c - 4);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    best = {r, c};\n                }\n            }\n        }\n    }\n    return best;\n}\n\nchar getAction() {\n    if (holding) {\n        int targetGateR = targetRow[heldContainer];\n        if (craneR == targetGateR && craneC == 4) {\n            return 'Q';\n        }\n        if (heldContainer == nextDispatch) {\n            if (craneR < targetGateR) return 'D';\n            if (craneR > targetGateR) return 'U';\n            if (craneC < 4) return 'R';\n            if (craneC > 4) return 'L';\n        } else {\n            if (craneR < storageTargetR) return 'D';\n            if (craneR > storageTargetR) return 'U';\n            if (craneC < storageTargetC) return 'R';\n            if (craneC > storageTargetC) return 'L';\n        }\n        return '.';\n    } else {\n        if (nextDispatch >= 25) return '.';\n        if (grid[craneR][craneC] == nextDispatch) {\n            return 'P';\n        }\n        bool found = false;\n        int pr = -1, pc = -1;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (grid[r][c] == nextDispatch) {\n                    pr = r; pc = c;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n        if (found) {\n            if (craneR < pr) return 'D';\n            if (craneR > pr) return 'U';\n            if (craneC < pc) return 'R';\n            if (craneC > pc) return 'L';\n        }\n        int ar = arrivalRow[nextDispatch];\n        if (gateCurrent[ar] != -1 && gateCurrent[ar] != nextDispatch) {\n            if (craneR == ar && craneC == 0) {\n                return 'P';\n            } else {\n                if (craneR < ar) return 'D';\n                if (craneR > ar) return 'U';\n                if (craneC > 0) return 'L';\n                return '.';\n            }\n        }\n        return '.';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read N (always 5, ignore)\n    int dummyN;\n    cin >> dummyN;\n    // Read the N x N container numbers\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Precompute targetRow, arrivalRow, arrivalIdx\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int num = A[i][j];\n            targetRow[num] = num / N;\n            arrivalRow[num] = i;\n            arrivalIdx[num] = j;\n        }\n    }\n\n    memset(grid, -1, sizeof(grid));\n    memset(gateCurrent, -1, sizeof(gateCurrent));\n    memset(nextIdx, 0, sizeof(nextIdx));\n\n    vector<string> out(N);\n\n    // Turn 1: bomb small cranes\n    out[0] += '.';\n    for (int i = 1; i < N; ++i) {\n        out[i] += 'B';\n    }\n\n    // Main loop\n    for (int turn = 2; turn <= 10000; ++turn) {\n        // Step 1: place new containers at receiving gates\n        for (int i = 0; i < N; ++i) {\n            if (gateCurrent[i] == -1 && nextIdx[i] < N) {\n                int num = A[i][nextIdx[i]++];\n                gateCurrent[i] = num;\n                placeContainer(num, i, 0);\n            }\n        }\n\n        // Step 2: decide action for the large crane\n        char action = getAction();\n\n        // Execute action\n        if (action == 'P') {\n            int num = grid[craneR][craneC];\n            if (num != -1) {\n                holding = true;\n                heldContainer = num;\n                removeContainer(craneR, craneC);\n                if (craneC == 0) {\n                    int row = craneR;\n                    if (gateCurrent[row] == num) {\n                        gateCurrent[row] = -1;\n                    }\n                }\n                if (num != nextDispatch) {\n                    auto [sr, sc] = findStorageCell(targetRow[num]);\n                    storageTargetR = sr;\n                    storageTargetC = sc;\n                }\n            } else {\n                action = '.';\n            }\n        } else if (action == 'Q') {\n            if (holding) {\n                int num = heldContainer;\n                grid[craneR][craneC] = num;\n                holding = false;\n            } else {\n                action = '.';\n            }\n        } else if (action == 'U') {\n            if (craneR > 0) craneR--;\n        } else if (action == 'D') {\n            if (craneR < N-1) craneR++;\n        } else if (action == 'L') {\n            if (craneC > 0) craneC--;\n        } else if (action == 'R') {\n            if (craneC < N-1) craneC++;\n        }\n\n        out[0] += action;\n        for (int i = 1; i < N; ++i) {\n            out[i] += '.';\n        }\n\n        // Step 3: dispatch containers at right edge\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][4] != -1) {\n                int num = grid[i][4];\n                grid[i][4] = -1;\n                dispatched[num] = true;\n                if (num == nextDispatch) {\n                    while (nextDispatch < 25 && dispatched[nextDispatch]) {\n                        nextDispatch++;\n                    }\n                }\n            }\n        }\n\n        if (nextDispatch >= 25) break;\n    }\n\n    // Pad all output strings to the same length and print\n    size_t maxLen = 0;\n    for (int i = 0; i < N; ++i) {\n        maxLen = max(maxLen, out[i].size());\n    }\n    for (int i = 0; i < N; ++i) {\n        while (out[i].size() < maxLen) out[i] += '.';\n        cout << out[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\nusing ll = long long;\n\nstruct Node {\n    int x, y, delta;\n};\n\nint N;\nvector<vector<int>> height;\nvector<Node> nodes;\nvector<vector<int>> dist;\nint M; // number of nodes (including dummy start if needed)\nint start_id;\n\n// compute total movement cost for a permutation\nll computeCost(const vector<int>& ord) {\n    ll cost = 0;\n    int cur = ord[0];\n    int load = nodes[cur].delta; // after processing first node\n    for (int i = 1; i < M; ++i) {\n        int nxt = ord[i];\n        int d = dist[cur][nxt];\n        cost += (100LL + load) * d;\n        load += nodes[nxt].delta;\n        cur = nxt;\n    }\n    return cost;\n}\n\n// check feasibility: all prefix sums >= 0\nbool feasible(const vector<int>& ord) {\n    int sum = 0;\n    for (int idx : ord) {\n        sum += nodes[idx].delta;\n        if (sum < 0) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    cin >> N;\n    height.assign(N, vector<int>(N));\n    ll base = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> height[i][j];\n            base += abs(height[i][j]);\n        }\n    }\n\n    // Build node list: all cells with non-zero height\n    vector<int> pos, neg;\n    int start_cell_id = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (height[i][j] != 0) {\n                int id = nodes.size();\n                nodes.push_back({i, j, height[i][j]});\n                if (i == 0 && j == 0) start_cell_id = id;\n                if (height[i][j] > 0) pos.push_back(id);\n                else neg.push_back(id);\n            }\n        }\n    }\n    // Add dummy start node if (0,0) already has height 0\n    if (start_cell_id == -1) {\n        start_id = nodes.size();\n        nodes.push_back({0, 0, 0});\n        start_cell_id = start_id;\n        // (0,0) is zero, no operation needed, but we treat it as first node\n    } else {\n        start_id = start_cell_id;\n    }\n    M = nodes.size();\n\n    // Precompute Manhattan distances\n    dist.assign(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            dist[i][j] = abs(nodes[i].x - nodes[j].x) + abs(nodes[i].y - nodes[j].y);\n        }\n    }\n\n    // Build initial feasible permutation: start -> all positives (nearest neighbor) -> all negatives (nearest neighbor)\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    order.push_back(start_id);\n    used[start_id] = true;\n    int cur = start_id;\n    int load = nodes[cur].delta;\n\n    // Process positives\n    vector<int> remaining_pos;\n    for (int p : pos) if (!used[p]) remaining_pos.push_back(p);\n    while (!remaining_pos.empty()) {\n        int best = -1, bestDist = 1e9;\n        for (int p : remaining_pos) {\n            int d = dist[cur][p];\n            if (d < bestDist) {\n                bestDist = d;\n                best = p;\n            }\n        }\n        order.push_back(best);\n        used[best] = true;\n        load += nodes[best].delta;\n        cur = best;\n        auto it = find(remaining_pos.begin(), remaining_pos.end(), best);\n        remaining_pos.erase(it);\n    }\n\n    // Process negatives\n    vector<int> remaining_neg;\n    for (int n : neg) if (!used[n]) remaining_neg.push_back(n);\n    while (!remaining_neg.empty()) {\n        int best = -1, bestDist = 1e9;\n        for (int n : remaining_neg) {\n            int d = dist[cur][n];\n            if (d < bestDist) {\n                bestDist = d;\n                best = n;\n            }\n        }\n        order.push_back(best);\n        used[best] = true;\n        load += nodes[best].delta;\n        cur = best;\n        auto it = find(remaining_neg.begin(), remaining_neg.end(), best);\n        remaining_neg.erase(it);\n    }\n\n    // Ensure all nodes visited (should be)\n    for (int i = 0; i < M; ++i) assert(used[i]);\n\n    ll best_cost = computeCost(order);\n    vector<int> best_order = order;\n\n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double T_start = 1e6, T_end = 0.1;\n    int iterations = 500000;\n    double T = T_start;\n    vector<int> current_order = order;\n    ll current_cost = best_cost;\n\n    auto start_time = chrono::steady_clock::now();\n    for (int iter = 0; iter < iterations; ++iter) {\n        // Check time left\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() > 1800) break;\n\n        // Propose new order\n        vector<int> new_order = current_order;\n        int type = rng() % 2;\n        if (type == 0) {\n            // swap two random positions (excluding first)\n            int i = uniform_int_distribution<int>(1, M-1)(rng);\n            int j = uniform_int_distribution<int>(1, M-1)(rng);\n            while (j == i) j = uniform_int_distribution<int>(1, M-1)(rng);\n            swap(new_order[i], new_order[j]);\n        } else {\n            // reverse a random segment (excluding first)\n            int l = uniform_int_distribution<int>(1, M-1)(rng);\n            int r = uniform_int_distribution<int>(1, M-1)(rng);\n            if (l > r) swap(l, r);\n            reverse(new_order.begin() + l, new_order.begin() + r + 1);\n        }\n\n        // Feasibility check\n        if (!feasible(new_order)) continue;\n\n        ll new_cost = computeCost(new_order);\n        double delta = new_cost - current_cost;\n        if (delta < 0 || exp(-delta / T) > uniform_real_distribution<double>(0.0, 1.0)(rng)) {\n            current_order = move(new_order);\n            current_cost = new_cost;\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_order = current_order;\n            }\n        }\n\n        // Cool down\n        double progress = (double)iter / iterations;\n        T = T_start * pow(T_end / T_start, progress);\n    }\n\n    // Output sequence\n    vector<string> ops;\n    int cx = 0, cy = 0;\n    // Process first node (start) - it is always visited first\n    int idx0 = best_order[0];\n    if (nodes[idx0].delta != 0) {\n        if (nodes[idx0].delta > 0) {\n            ops.push_back(\"+\" + to_string(nodes[idx0].delta));\n        } else {\n            ops.push_back(\"-\" + to_string(-nodes[idx0].delta));\n        }\n    }\n    // Move to subsequent nodes\n    for (int i = 1; i < M; ++i) {\n        int nid = best_order[i];\n        int nx = nodes[nid].x;\n        int ny = nodes[nid].y;\n        // Move step by step\n        while (cx < nx) { ops.push_back(\"D\"); cx++; }\n        while (cx > nx) { ops.push_back(\"U\"); cx--; }\n        while (cy < ny) { ops.push_back(\"R\"); cy++; }\n        while (cy > ny) { ops.push_back(\"L\"); cy--; }\n        // Perform operation\n        if (nodes[nid].delta != 0) {\n            if (nodes[nid].delta > 0) {\n                ops.push_back(\"+\" + to_string(nodes[nid].delta));\n            } else {\n                ops.push_back(\"-\" + to_string(-nodes[nid].delta));\n            }\n        }\n    }\n\n    // Output\n    for (const string& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <unordered_set>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int SEED_COUNT = 2 * N * (N - 1); // 60\n    const int GRID_SIZE = N * N;           // 36\n\n    vector<vector<int>> X(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> X[i][j];\n        }\n    }\n\n    for (int turn = 0; turn < T; ++turn) {\n        // 1. Evaluate current seeds\n        vector<int> sumX(SEED_COUNT, 0);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            sumX[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // best overall seed (max sum)\n        int bestIdx = max_element(sumX.begin(), sumX.end()) - sumX.begin();\n\n        // per\u2011dimension best seeds\n        vector<int> dimMax(M, -1), dimIdx(M, -1);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int l = 0; l < M; ++l) {\n                if (X[i][l] > dimMax[l]) {\n                    dimMax[l] = X[i][l];\n                    dimIdx[l] = i;\n                }\n            }\n        }\n\n        // 2. Build the set of elite seeds (best overall + per\u2011dimension best)\n        unordered_set<int> eliteSet;\n        eliteSet.insert(bestIdx);\n        for (int l = 0; l < M; ++l) {\n            eliteSet.insert(dimIdx[l]);\n        }\n        vector<int> elite(eliteSet.begin(), eliteSet.end());\n\n        // 3. Select 36 seeds: all elites + top sum among the rest\n        vector<bool> used(SEED_COUNT, false);\n        for (int idx : elite) used[idx] = true;\n        vector<int> additional;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (!used[i]) additional.push_back(i);\n        }\n        sort(additional.begin(), additional.end(), [&](int a, int b) {\n            return sumX[a] > sumX[b];\n        });\n        int needFromAdd = GRID_SIZE - (int)elite.size();\n        // selected = elite + first needFromAdd of additional\n        vector<int> selected = elite;\n        selected.insert(selected.end(), additional.begin(), additional.begin() + needFromAdd);\n\n        // 4. Partition into interior (16) and border (20) seeds\n        int interiorSize = (N - 2) * (N - 2); // 16\n        int eliteSize = (int)elite.size();\n        int takeFromAdd = min(interiorSize - eliteSize, needFromAdd);\n        vector<int> interiorSeeds(elite.begin(), elite.end());\n        interiorSeeds.insert(interiorSeeds.end(), additional.begin(), additional.begin() + takeFromAdd);\n        // borderSeeds: the rest of selected\n        vector<int> borderSeeds(additional.begin() + takeFromAdd, additional.begin() + needFromAdd);\n        // sanity: (int)selected.size() == GRID_SIZE\n        // (int)interiorSeeds.size() == interiorSize\n        // borderSeeds.size() == GRID_SIZE - interiorSize\n\n        // 5. Build the placement grid\n        vector<vector<int>> A(N, vector<int>(N, -1));\n\n        // 5a. Define interior positions (1,\u2026,N-2)\n        vector<pair<int,int>> interiorPos;\n        for (int i = 1; i <= N-2; ++i)\n            for (int j = 1; j <= N-2; ++j)\n                interiorPos.push_back({i, j});\n\n        // 5b. Place the best overall at the centre (2,2)\n        int centre_i = 2, centre_j = 2; // 0\u2011based, inside interior\n        A[centre_i][centre_j] = bestIdx;\n\n        // Remove bestIdx from interiorSeeds (it's the first one)\n        auto it = find(interiorSeeds.begin(), interiorSeeds.end(), bestIdx);\n        if (it != interiorSeeds.end()) interiorSeeds.erase(it);\n        // Now interiorSeeds has size = interiorSize - 1 = 15\n\n        // Compute complement scores with bestIdx\n        vector<pair<int,int>> compScores; // (score, seedIdx)\n        for (int idx : interiorSeeds) {\n            int score = 0;\n            for (int l = 0; l < M; ++l) {\n                score += max(X[bestIdx][l], X[idx][l]);\n            }\n            compScores.push_back({-score, idx}); // negative for descending sort\n        }\n        sort(compScores.begin(), compScores.end());\n        // Top 4 become neighbours\n        vector<pair<int,int>> neighPos = {{centre_i-1, centre_j},\n                                          {centre_i+1, centre_j},\n                                          {centre_i, centre_j-1},\n                                          {centre_i, centre_j+1}};\n        unordered_set<int> usedInterior;\n        usedInterior.insert(bestIdx);\n        for (int k = 0; k < 4; ++k) {\n            int idx = compScores[k].second;\n            int ni = neighPos[k].first, nj = neighPos[k].second;\n            A[ni][nj] = idx;\n            usedInterior.insert(idx);\n        }\n\n        // 5d. Assign remaining interior seeds to remaining interior positions\n        // Remaining interior positions (exclude centre and neighbours)\n        vector<pair<int,int>> restInteriorPos;\n        for (auto [i,j] : interiorPos) {\n            if (i == centre_i && j == centre_j) continue;\n            bool isNeigh = false;\n            for (auto [ni,nj] : neighPos) if (ni==i && nj==j) { isNeigh = true; break; }\n            if (!isNeigh) restInteriorPos.push_back({i,j});\n        }\n        // Get the remaining seeds (not used)\n        vector<int> restSeeds;\n        for (int idx : interiorSeeds) {\n            if (!usedInterior.count(idx)) restSeeds.push_back(idx);\n        }\n        // restSeeds.size() should be 11\n        for (size_t k = 0; k < restInteriorPos.size(); ++k) {\n            A[restInteriorPos[k].first][restInteriorPos[k].second] = restSeeds[k];\n        }\n\n        // 5e. Fill border cells with borderSeeds\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (A[i][j] == -1) {\n                    A[i][j] = borderSeeds.back();\n                    borderSeeds.pop_back();\n                }\n            }\n        }\n\n        // 6. Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << A[i][j];\n                if (j < N-1) cout << ' ';\n            }\n            cout << '\\n';\n        }\n        cout << flush;\n\n        // 7. Read the new generation of seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<string> s_str, t_str;\nvector<vector<bool>> source, target;\n\nint root_x = 0, root_y = 0;\nint V_used;\nvector<int> parent, length;\nvector<int> dir;        // current direction (0:right,1:down,2:left,3:up)\nvector<bool> holding;   // whether fingertip holds a takoyaki\n\nvector<string> commands;\n\n// offsets for each direction: right, down, left, up\nconst vector<pair<int,int>> offset_dir = {{0,1}, {1,0}, {0,-1}, {-1,0}};\n\nvoid rotate_leaf(int i, char c) {\n    if (c == 'R') dir[i] = (dir[i] + 1) % 4;\n    else if (c == 'L') dir[i] = (dir[i] + 3) % 4;\n}\n\n// return all four possible positions for a leaf of length L from (rx,ry)\nvector<pair<int,int>> get_positions(int rx, int ry, int L) {\n    vector<pair<int,int>> res;\n    for (int d = 0; d < 4; ++d) {\n        int nx = rx + offset_dir[d].first * L;\n        int ny = ry + offset_dir[d].second * L;\n        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n            res.emplace_back(nx, ny);\n        }\n    }\n    return res;\n}\n\n// Kuhn DFS for bipartite matching\nbool dfs(int u, const vector<vector<int>>& adj, vector<int>& matchR, vector<bool>& visited) {\n    for (int v : adj[u]) {\n        if (!visited[v]) {\n            visited[v] = true;\n            if (matchR[v] == -1 || dfs(matchR[v], adj, matchR, visited)) {\n                matchR[v] = u;\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n    s_str.resize(N);\n    t_str.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n\n    source.assign(N, vector<bool>(N, false));\n    target.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') source[i][j] = true;\n            if (t_str[i][j] == '1') target[i][j] = true;\n        }\n    }\n\n    // ---- design tree (star) ----\n    V_used = V;  // use all vertices\n    parent.resize(V_used, 0);\n    length.resize(V_used, 0);\n    for (int i = 1; i < V_used; ++i) {\n        parent[i] = 0;\n        length[i] = i;   // lengths 1,2,...,V-1\n    }\n\n    // output tree\n    cout << V_used << '\\n';\n    for (int i = 1; i < V_used; ++i) {\n        cout << parent[i] << ' ' << length[i] << '\\n';\n    }\n    // initial root position\n    root_x = 0, root_y = 0;\n    cout << root_x << ' ' << root_y << '\\n';\n\n    // ---- initial state ----\n    dir.assign(V_used, 0);        // all point right\n    holding.assign(V_used, false);\n\n    int total_source = M;\n    int total_target = M;\n    int turn_count = 0;\n\n    // safety cap on total turns\n    const int MAX_TURNS = 100000;\n\n    // main loop\n    while ((total_source > 0 || total_target > 0) && turn_count < MAX_TURNS) {\n        // ----- find best root (greedy counting) -----\n        int best_cnt = -1;\n        int best_rx = -1, best_ry = -1;\n        for (int rx = 0; rx < N; ++rx) {\n            for (int ry = 0; ry < N; ++ry) {\n                int cnt = 0;\n                for (int i = 1; i < V_used; ++i) {\n                    int L = length[i];\n                    auto pos = get_positions(rx, ry, L);\n                    bool ok = false;\n                    for (auto [cx, cy] : pos) {\n                        if (!holding[i] && source[cx][cy]) { ok = true; break; }\n                        if ( holding[i] && target[cx][cy] && !source[cx][cy]) { ok = true; break; }\n                    }\n                    if (ok) cnt++;\n                }\n                int dist = abs(rx - root_x) + abs(ry - root_y);\n                if (cnt > best_cnt || (cnt == best_cnt && (best_rx == -1 || dist < abs(best_rx - root_x) + abs(best_ry - root_y)))) {\n                    best_cnt = cnt;\n                    best_rx = rx;\n                    best_ry = ry;\n                }\n            }\n        }\n\n        if (best_cnt == 0) break;\n\n        // ----- move root to best_rx, best_ry (no rotations) -----\n        while (root_x != best_rx || root_y != best_ry) {\n            if (turn_count >= MAX_TURNS) break;\n            char move_char = '.';\n            int dx = best_rx - root_x, dy = best_ry - root_y;\n            if (dx > 0) { move_char = 'D'; root_x++; }\n            else if (dx < 0) { move_char = 'U'; root_x--; }\n            else if (dy > 0) { move_char = 'R'; root_y++; }\n            else if (dy < 0) { move_char = 'L'; root_y--; }\n\n            string rot(V_used - 1, '.');\n            string action(V_used, '.');\n            commands.push_back(move_char + rot + action);\n            turn_count++;\n        }\n        if (turn_count >= MAX_TURNS) break;\n\n        // ----- stay at this root and perform actions until no more actions possible -----\n        while (turn_count < MAX_TURNS) {\n            // build bipartite graph for current root (best_rx, best_ry)\n            map<pair<int,int>, int> cell_id;\n            vector<pair<int,int>> id_cell;\n            vector<vector<int>> adj(V_used); // only indices 1..V_used-1 used\n\n            for (int i = 1; i < V_used; ++i) {\n                int L = length[i];\n                auto pos = get_positions(best_rx, best_ry, L);\n                for (auto [cx, cy] : pos) {\n                    bool ok = false;\n                    if (!holding[i] && source[cx][cy]) ok = true;\n                    if ( holding[i] && target[cx][cy] && !source[cx][cy]) ok = true;  // <-- FIX: avoid placing on source square\n                    if (ok) {\n                        auto key = make_pair(cx, cy);\n                        if (cell_id.find(key) == cell_id.end()) {\n                            cell_id[key] = id_cell.size();\n                            id_cell.push_back(key);\n                        }\n                        adj[i].push_back(cell_id[key]);\n                    }\n                }\n            }\n\n            // maximum bipartite matching (Kuhn)\n            int item_cnt = id_cell.size();\n            vector<int> matchR(item_cnt, -1);\n            int matching = 0;\n            for (int i = 1; i < V_used; ++i) {\n                vector<bool> visited(item_cnt, false);\n                if (dfs(i, adj, matchR, visited)) {\n                    matching++;\n                }\n            }\n\n            if (matching == 0) break;\n\n            // obtain assigned cell for each matched leaf\n            vector<pair<int,int>> leaf_target(V_used, {-1, -1});\n            for (int v = 0; v < item_cnt; ++v) {\n                if (matchR[v] != -1) {\n                    leaf_target[matchR[v]] = id_cell[v];\n                }\n            }\n\n            // compute target directions for matched leaves\n            vector<int> target_dir(V_used, -1);\n            for (int i = 1; i < V_used; ++i) {\n                auto [cx, cy] = leaf_target[i];\n                if (cx == -1) continue;\n                int L = length[i];\n                int dx = cx - best_rx, dy = cy - best_ry;\n                if (dx == 0 && dy == L) target_dir[i] = 0;      // right\n                else if (dx == L && dy == 0) target_dir[i] = 1; // down\n                else if (dx == 0 && dy == -L) target_dir[i] = 2; // left\n                else if (dx == -L && dy == 0) target_dir[i] = 3; // up\n            }\n\n            // ---- rotate leaves to target directions (possibly several turns) ----\n            while (true) {\n                if (turn_count >= MAX_TURNS) break;\n                bool all_aligned = true;\n                string rot = \"\";\n                for (int i = 1; i < V_used; ++i) {\n                    if (target_dir[i] == -1) { rot += '.'; continue; }\n                    int cur = dir[i];\n                    int tgt = target_dir[i];\n                    int diff = (tgt - cur + 4) % 4;\n                    char c;\n                    if (diff == 0) c = '.';\n                    else if (diff <= 2) c = 'R';\n                    else c = 'L';\n                    rot += c;\n                    if (c != '.') all_aligned = false;\n                    rotate_leaf(i, c);\n                }\n                if (all_aligned) break;\n                string action(V_used, '.');\n                commands.push_back('.' + rot + action);\n                turn_count++;\n            }\n            if (turn_count >= MAX_TURNS) break;\n\n            // ---- action turn: pick or place ----\n            string rot(V_used - 1, '.');\n            string action = \".\";\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) action += 'P';\n                else action += '.';\n            }\n            commands.push_back('.' + rot + action);\n            turn_count++;\n\n            // update state\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) {\n                    auto [cx, cy] = leaf_target[i];\n                    if (!holding[i]) {\n                        // pick\n                        source[cx][cy] = false;\n                        holding[i] = true;\n                        total_source--;\n                    } else {\n                        // place\n                        target[cx][cy] = false;\n                        holding[i] = false;\n                        total_target--;\n                    }\n                }\n            }\n            // if no source or target left, break\n            if (total_source == 0 && total_target == 0) break;\n        }\n    }\n\n    // ---- output all commands ----\n    for (const string& cmd : commands) {\n        cout << cmd << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\nusing namespace std;\nusing ll = long long;\n\nconst int COORD_MAX = 100000;\nconst int PERIMETER_LIMIT = 400000;\nconst int TILE_SIZE = 500;          // tune between 250 and 1000\nconst int TILES = (COORD_MAX / TILE_SIZE) + 1; // 201\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<pair<int,int>> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].first >> mackerels[i].second;\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].first >> sardines[i].second;\n    }\n\n    // Build tile grid with weights (+1 for mackerel, -1 for sardine)\n    vector<vector<ll>> score(TILES, vector<ll>(TILES, 0));\n    for (auto [x, y] : mackerels) {\n        int tx = x / TILE_SIZE;\n        int ty = y / TILE_SIZE;\n        score[tx][ty] += 1;\n    }\n    for (auto [x, y] : sardines) {\n        int tx = x / TILE_SIZE;\n        int ty = y / TILE_SIZE;\n        score[tx][ty] -= 1;\n    }\n\n    // Prefix sum for tile grid\n    vector<vector<ll>> pref(TILES+1, vector<ll>(TILES+1, 0));\n    for (int i = 0; i < TILES; ++i) {\n        for (int j = 0; j < TILES; ++j) {\n            pref[i+1][j+1] = pref[i][j+1] + pref[i+1][j] - pref[i][j] + score[i][j];\n        }\n    }\n\n    // Find best rectangle of tiles under perimeter constraint\n    ll best_sum = -1e18;\n    int best_r1 = 0, best_r2 = 0, best_c1 = 0, best_c2 = 0;\n\n    for (int r1 = 0; r1 < TILES; ++r1) {\n        vector<ll> colSum(TILES, 0);\n        for (int r2 = r1; r2 < TILES; ++r2) {\n            // add current row to column sums\n            for (int c = 0; c < TILES; ++c) {\n                colSum[c] += score[r2][c];\n            }\n            int dx = r2 - r1 + 1;               // number of rows\n            int max_dy = (PERIMETER_LIMIT / (2 * TILE_SIZE)) - dx; // max allowed columns\n            if (max_dy <= 0) continue;\n            max_dy = min(max_dy, TILES);\n\n            // Find maximum subarray sum of colSum with length <= max_dy\n            // Using prefix sums and a deque (monotonic queue)\n            vector<ll> prefCol(TILES + 1, 0);\n            for (int i = 0; i < TILES; ++i) prefCol[i+1] = prefCol[i] + colSum[i];\n\n            deque<int> dq;\n            ll local_best = -1e18;\n            int local_c1 = -1, local_c2 = -1;\n\n            for (int i = 0; i <= TILES; ++i) {\n                // remove indices out of window [i-max_dy, i]\n                while (!dq.empty() && dq.front() < i - max_dy)\n                    dq.pop_front();\n\n                if (!dq.empty()) {\n                    ll cur = prefCol[i] - prefCol[dq.front()];\n                    if (cur > local_best) {\n                        local_best = cur;\n                        local_c1 = dq.front();   // leftmost column index (in prefCol)\n                        local_c2 = i - 1;        // rightmost column index\n                    }\n                }\n\n                // maintain increasing prefCol values in deque\n                while (!dq.empty() && prefCol[dq.back()] >= prefCol[i])\n                    dq.pop_back();\n                dq.push_back(i);\n            }\n\n            if (local_best > best_sum) {\n                best_sum = local_best;\n                best_r1 = r1;\n                best_r2 = r2;\n                best_c1 = local_c1;\n                best_c2 = local_c2;\n            }\n        }\n    }\n\n    // If no positive rectangle found (shouldn't happen), fallback to a single tile containing at least one mackerel\n    if (best_sum <= 0) {\n        // find any tile with positive net weight\n        for (int i = 0; i < TILES; ++i) {\n            for (int j = 0; j < TILES; ++j) {\n                if (score[i][j] > 0) {\n                    best_sum = score[i][j];\n                    best_r1 = best_r2 = i;\n                    best_c1 = best_c2 = j;\n                    break;\n                }\n            }\n            if (best_sum > 0) break;\n        }\n    }\n\n    // Convert tile rectangle to actual coordinates (tighten using mackerels)\n    int x_low = best_c1 * TILE_SIZE;\n    int x_high = min(COORD_MAX, (best_c2 + 1) * TILE_SIZE);\n    int y_low = best_r1 * TILE_SIZE;\n    int y_high = min(COORD_MAX, (best_r2 + 1) * TILE_SIZE);\n\n    // Collect mackerels inside the tile rectangle to get tight bounding box\n    int tight_x_min = COORD_MAX + 1, tight_x_max = -1;\n    int tight_y_min = COORD_MAX + 1, tight_y_max = -1;\n    for (auto [x, y] : mackerels) {\n        if (x >= x_low && x <= x_high && y >= y_low && y <= y_high) {\n            tight_x_min = min(tight_x_min, x);\n            tight_x_max = max(tight_x_max, x);\n            tight_y_min = min(tight_y_min, y);\n            tight_y_max = max(tight_y_max, y);\n        }\n    }\n\n    // If there are mackerels inside, use tight box; otherwise use the tile rectangle itself.\n    if (tight_x_min <= COORD_MAX) {\n        x_low = tight_x_min;\n        x_high = tight_x_max;\n        y_low = tight_y_min;\n        y_high = tight_y_max;\n    }\n\n    // Ensure rectangle has positive area (at least 1 unit)\n    if (x_low == x_high) x_high = min(COORD_MAX, x_low + 1);\n    if (y_low == y_high) y_high = min(COORD_MAX, y_low + 1);\n\n    // Output polygon (a simple rectangle)\n    int m = 4;\n    cout << m << '\\n';\n    // Order: counterclockwise (or clockwise) - here we output (x_low, y_low) -> (x_high, y_low) -> (x_high, y_high) -> (x_low, y_high)\n    cout << x_low << \" \" << y_low << '\\n';\n    cout << x_high << \" \" << y_low << '\\n';\n    cout << x_high << \" \" << y_high << '\\n';\n    cout << x_low << \" \" << y_high << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nstruct Rect {\n    int orig;\n    ll x, y, w, h;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<ll> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i) cin >> w_obs[i] >> h_obs[i];\n\n    // initialise estimate sums with the given noisy values\n    vector<ld> sum_w(N), sum_h(N);\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int measure_turns = T - 1;     // last turn is for the final packing\n    int cur_measure = 0;           // index of the next rectangle to measure\n\n    for (int turn = 0; turn < T; ++turn) {\n        if (turn < measure_turns) {\n            // ===== measurement turn: place a single rectangle =====\n            int idx = cur_measure % N;\n            ++cur_measure;\n            cout << \"1\\n\";\n            cout << idx << \" 0 U -1\" << endl;   // flush with endl\n\n            // read noisy bounding box\n            ll Wp, Hp;\n            cin >> Wp >> Hp;\n\n            // update statistics\n            sum_w[idx] += Wp;\n            sum_h[idx] += Hp;\n            cnt[idx]++;\n        } else {\n            // ===== final packing turn =====\n            // compute final estimates (rounded to nearest integer)\n            vector<ll> est_w(N), est_h(N);\n            for (int i = 0; i < N; ++i) {\n                est_w[i] = (ll)llround(sum_w[i] / cnt[i]);\n                est_h[i] = (ll)llround(sum_h[i] / cnt[i]);\n                if (est_w[i] < 1) est_w[i] = 1;\n                if (est_h[i] < 1) est_h[i] = 1;\n            }\n\n            // greedy packing: place rectangles in index order, trying all possibilities\n            vector<Rect> placed;\n            ll curW = 0, curH = 0;\n            vector<tuple<int, int, char, int>> ops;   // (original index, rotation, direction, reference)\n\n            for (int i = 0; i < N; ++i) {\n                struct Option {\n                    int rot;\n                    char dir;\n                    int ref;     // index inside 'placed' vector (-1 for axis)\n                    ll newW, newH;\n                    ll x, y;     // position of the new rectangle\n                };\n                Option best;\n                best.newW = LLONG_MAX;   // large sentinel\n\n                // try both rotations\n                for (int rot = 0; rot <= 1; ++rot) {\n                    ll w = (rot == 0) ? est_w[i] : est_h[i];\n                    ll h = (rot == 0) ? est_h[i] : est_w[i];\n\n                    // try both directions\n                    for (char dir : {'U', 'L'}) {\n                        // all possible references: -1 and every already placed rectangle\n                        vector<int> refs = {-1};\n                        for (int j = 0; j < (int)placed.size(); ++j) refs.push_back(j);\n\n                        for (int ref : refs) {\n                            ll x, y;\n                            if (dir == 'U') {\n                                // horizontal alignment\n                                x = (ref == -1) ? 0 : placed[ref].x + placed[ref].w;\n                                // move upwards (decreasing y) until touching bottom of some rectangle\n                                y = 0;\n                                for (auto &p : placed) {\n                                    if (x < p.x + p.w && x + w > p.x) {\n                                        y = max(y, p.y + p.h);\n                                    }\n                                }\n                            } else { // 'L'\n                                // vertical alignment\n                                y = (ref == -1) ? 0 : placed[ref].y + placed[ref].h;\n                                // move leftwards (decreasing x) until touching right side of some rectangle\n                                x = 0;\n                                for (auto &p : placed) {\n                                    if (y < p.y + p.h && y + h > p.y) {\n                                        x = max(x, p.x + p.w);\n                                    }\n                                }\n                            }\n\n                            ll newW = max(curW, x + w);\n                            ll newH = max(curH, y + h);\n                            ll score = newW + newH;\n                            if (score < best.newW + best.newH) {\n                                best = {rot, dir, ref, newW, newH, x, y};\n                            }\n                        }\n                    }\n                }\n\n                // apply the best option\n                ll w_used = (best.rot == 0) ? est_w[i] : est_h[i];\n                ll h_used = (best.rot == 0) ? est_h[i] : est_w[i];\n                int ref_orig = (best.ref == -1) ? -1 : placed[best.ref].orig;\n\n                placed.push_back({i, best.x, best.y, w_used, h_used});\n                curW = best.newW;\n                curH = best.newH;\n                ops.emplace_back(i, best.rot, best.dir, ref_orig);\n            }\n\n            // output the packing\n            cout << N << \"\\n\";\n            for (auto &[p, r, d, b] : ops) {\n                cout << p << \" \" << r << \" \" << d << \" \" << b << \"\\n\";\n            }\n            cout.flush();\n\n            // consume the measured feedback (irrelevant for our algorithm)\n            ll dummyW, dummyH;\n            cin >> dummyW >> dummyH;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<vector<int>> G(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        G[u].push_back(v);\n        G[v].push_back(u);\n    }\n    // read coordinates, not needed for the algorithm\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. All-pairs shortest distances ----------\n    const int INF = 1e9;\n    vector<vector<int>> dist(N, vector<int>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        vector<int> d(N, -1);\n        queue<int> q;\n        d[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int u : G[v]) if (d[u] == -1) {\n                d[u] = d[v] + 1;\n                q.push(u);\n            }\n        }\n        for (int i = 0; i < N; ++i) dist[s][i] = d[i];\n    }\n\n    // ---------- 2. Sorted order of vertices by distance for each vertex ----------\n    vector<vector<int>> order(N);\n    for (int v = 0; v < N; ++v) {\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int a, int b) {\n            return dist[v][a] < dist[v][b];\n        });\n        order[v] = move(idx);\n    }\n\n    // ---------- 3. Greedy elimination of redundant roots ----------\n    vector<bool> is_root(N, true);\n    vector<int> nearest_root(N), nearest_ptr(N);\n    vector<vector<int>> children(N); // vertices that have this root as nearest\n\n    // Initial state: every vertex is its own root\n    for (int v = 0; v < N; ++v) {\n        nearest_root[v] = v;\n        nearest_ptr[v] = 0;   // index in order[v] of the nearest root (itself)\n        children[v].push_back(v);\n    }\n\n    while (true) {\n        // For each root compute the total gain of removing it\n        vector<ll> score(N, 0);\n        vector<bool> feasible(N, true);\n        for (int v = 0; v < N; ++v) {\n            int r = nearest_root[v];\n            // Find the second-nearest root (the next root in the sorted list)\n            int pos = nearest_ptr[v] + 1;\n            while (pos < N && !is_root[order[v][pos]]) ++pos;\n            if (pos >= N || dist[v][order[v][pos]] > H) {\n                feasible[r] = false;\n            } else {\n                int s = order[v][pos];\n                ll gain = (ll)(dist[v][s] - dist[v][r]) * A[v];\n                score[r] += gain;\n            }\n        }\n\n        // Choose best feasible root with positive gain\n        int best = -1;\n        ll best_score = -1;\n        for (int r = 0; r < N; ++r) {\n            if (is_root[r] && feasible[r] && score[r] > best_score) {\n                best_score = score[r];\n                best = r;\n            }\n        }\n        if (best == -1) break; // no improvement possible\n\n        // Remove best\n        is_root[best] = false;\n        vector<int> cur_children = children[best]; // copy\n        children[best].clear();\n        for (int v : cur_children) {\n            // v was covered by best; find the next root in its sorted list\n            int pos = nearest_ptr[v] + 1;\n            while (pos < N && !is_root[order[v][pos]]) ++pos;\n            // pos is guaranteed to be < N because feasibility checked\n            int new_root = order[v][pos];\n            nearest_root[v] = new_root;\n            nearest_ptr[v] = pos;\n            children[new_root].push_back(v);\n        }\n    }\n\n    // ---------- 4. Build the forest: BFS from the final roots ----------\n    vector<int> parent(N, -1), depth(N, -1);\n    queue<int> q;\n    for (int v = 0; v < N; ++v) if (is_root[v]) {\n        depth[v] = 0;\n        parent[v] = -1;\n        q.push(v);\n    }\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : G[v]) if (depth[u] == -1) {\n            depth[u] = depth[v] + 1;\n            parent[u] = v;\n            q.push(u);\n        }\n    }\n\n    // ---------- 5. Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << parent[i] << (i+1 == N ? \"\\n\" : \" \");\n    }\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    int N = 20;\n    cin >> N;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Collect all Oni positions (initial)\n    vector<pair<int, int>> oni_pos;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'x')\n                oni_pos.emplace_back(i, j);\n\n    // Precompute for each Oni the best safe direction and distance (to edge)\n    struct Info { int dir; int dist; }; // 0:Up, 1:Down, 2:Left, 3:Right\n    vector<Info> oni_info(oni_pos.size());\n\n    for (size_t idx = 0; idx < oni_pos.size(); ++idx) {\n        int r = oni_pos[idx].first;\n        int c = oni_pos[idx].second;\n\n        bool safe[4] = {true, true, true, true};\n\n        // up\n        for (int i = 0; i < r; ++i)\n            if (grid[i][c] == 'o') { safe[0] = false; break; }\n        // down\n        for (int i = r + 1; i < N; ++i)\n            if (grid[i][c] == 'o') { safe[1] = false; break; }\n        // left\n        for (int j = 0; j < c; ++j)\n            if (grid[r][j] == 'o') { safe[2] = false; break; }\n        // right\n        for (int j = c + 1; j < N; ++j)\n            if (grid[r][j] == 'o') { safe[3] = false; break; }\n\n        int best_dir = -1;\n        int best_dist = N + 1;\n        int dists[4] = {r + 1, N - r, c + 1, N - c};\n        for (int d = 0; d < 4; ++d) {\n            if (safe[d] && dists[d] < best_dist) {\n                best_dist = dists[d];\n                best_dir = d;\n            }\n        }\n        // guaranteed to be valid\n        oni_info[idx] = {best_dir, best_dist};\n    }\n\n    vector<pair<char, int>> ops;\n\n    // Shift functions (modify grid in place)\n    auto shift_left = [&](int r) {\n        // remove leftmost piece\n        for (int j = 0; j < N - 1; ++j) grid[r][j] = grid[r][j + 1];\n        grid[r][N - 1] = '.';\n    };\n    auto shift_right = [&](int r) {\n        for (int j = N - 1; j > 0; --j) grid[r][j] = grid[r][j - 1];\n        grid[r][0] = '.';\n    };\n    auto shift_up = [&](int c) {\n        for (int i = 0; i < N - 1; ++i) grid[i][c] = grid[i + 1][c];\n        grid[N - 1][c] = '.';\n    };\n    auto shift_down = [&](int c) {\n        for (int i = N - 1; i > 0; --i) grid[i][c] = grid[i - 1][c];\n        grid[0][c] = '.';\n    };\n\n    // ---------- Phase 1: clear rows that contain no Fukunokami ----------\n    for (int i = 0; i < N; ++i) {\n        bool has_o = false;\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'o') { has_o = true; break; }\n        if (has_o) continue;\n\n        // find Oni in this row\n        int min_x = N, max_x = -1;\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'x') {\n                min_x = min(min_x, j);\n                max_x = max(max_x, j);\n            }\n        if (max_x == -1) continue;   // no Oni\n\n        int left_cost = max_x + 1;     // shifts to remove rightmost Oni\n        int right_cost = N - min_x;    // shifts to remove leftmost Oni\n        if (left_cost <= right_cost) {\n            for (int k = 0; k < left_cost; ++k) {\n                shift_left(i);\n                ops.emplace_back('L', i);\n            }\n        } else {\n            for (int k = 0; k < right_cost; ++k) {\n                shift_right(i);\n                ops.emplace_back('R', i);\n            }\n        }\n    }\n\n    // ---------- Phase 2: clear columns that contain no Fukunokami ----------\n    for (int j = 0; j < N; ++j) {\n        bool has_o = false;\n        for (int i = 0; i < N; ++i)\n            if (grid[i][j] == 'o') { has_o = true; break; }\n        if (has_o) continue;\n\n        int min_x = N, max_x = -1;\n        for (int i = 0; i < N; ++i)\n            if (grid[i][j] == 'x') {\n                min_x = min(min_x, i);\n                max_x = max(max_x, i);\n            }\n        if (max_x == -1) continue;\n\n        int up_cost = max_x + 1;\n        int down_cost = N - min_x;\n        if (up_cost <= down_cost) {\n            for (int k = 0; k < up_cost; ++k) {\n                shift_up(j);\n                ops.emplace_back('U', j);\n            }\n        } else {\n            for (int k = 0; k < down_cost; ++k) {\n                shift_down(j);\n                ops.emplace_back('D', j);\n            }\n        }\n    }\n\n    // ---------- Phase 3: remove remaining Oni individually ----------\n    for (size_t idx = 0; idx < oni_pos.size(); ++idx) {\n        int r = oni_pos[idx].first;\n        int c = oni_pos[idx].second;\n        if (grid[r][c] != 'x') continue;   // already removed\n\n        int dir = oni_info[idx].dir;\n        int dist = oni_info[idx].dist;\n\n        if (dir == 0) {      // up\n            for (int k = 0; k < dist; ++k) { shift_up(c); ops.emplace_back('U', c); }\n            for (int k = 0; k < dist; ++k) { shift_down(c); ops.emplace_back('D', c); }\n        } else if (dir == 1) { // down\n            for (int k = 0; k < dist; ++k) { shift_down(c); ops.emplace_back('D', c); }\n            for (int k = 0; k < dist; ++k) { shift_up(c); ops.emplace_back('U', c); }\n        } else if (dir == 2) { // left\n            for (int k = 0; k < dist; ++k) { shift_left(r); ops.emplace_back('L', r); }\n            for (int k = 0; k < dist; ++k) { shift_right(r); ops.emplace_back('R', r); }\n        } else {               // right\n            for (int k = 0; k < dist; ++k) { shift_right(r); ops.emplace_back('R', r); }\n            for (int k = 0; k < dist; ++k) { shift_left(r); ops.emplace_back('L', r); }\n        }\n    }\n\n    // Output\n    for (const auto &op : ops) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<int> dist_emp(0, N-1);\nuniform_real_distribution<double> dist_prob(0.0, 1.0);\n\nstruct Solution {\n    int a[N], b[N];\n};\n\nint simulate(const Solution& sol, int cnt[]) {\n    fill(cnt, cnt + N, 0);\n    int cur = 0;\n    cnt[0] = 1; // week 1\n    for (int w = 2; w <= L; ++w) {\n        int t = cnt[cur];\n        int nxt = (t & 1) ? sol.a[cur] : sol.b[cur];\n        cnt[nxt]++;\n        cur = nxt;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        err += abs(cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution: uniform cycle\n    Solution sol;\n    for (int i = 0; i < N; ++i) {\n        sol.a[i] = (i + 1) % N;\n        sol.b[i] = (i + 1) % N;\n    }\n\n    int cnt[N];\n    int best_err = simulate(sol, cnt);\n    Solution best_sol = sol;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    double temperature = 1000.0;\n    const double cooling_rate = 0.9995;\n    int iterations = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n\n        // random modification\n        Solution new_sol = sol;\n        int i = dist_emp(rng);\n        if (dist_prob(rng) < 0.5) {\n            new_sol.a[i] = dist_emp(rng);\n        } else {\n            new_sol.b[i] = dist_emp(rng);\n        }\n\n        int new_err = simulate(new_sol, cnt);\n        int delta = new_err - best_err;\n\n        if (delta < 0 || dist_prob(rng) < exp(-delta / temperature)) {\n            sol = new_sol;\n            if (new_err < best_err) {\n                best_err = new_err;\n                best_sol = new_sol;\n            }\n        }\n\n        temperature *= cooling_rate;\n        iterations++;\n    }\n\n    // Output best solution\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.a[i] << \" \" << best_sol.b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\n// ---------- DSU ----------\nstruct DSU {\n    vector<int> parent, rank;\n    DSU(int n) : parent(n), rank(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rank[a] < rank[b]) swap(a, b);\n        parent[b] = a;\n        if (rank[a] == rank[b]) rank[a]++;\n        return true;\n    }\n};\n\n// ---------- Hilbert index (14 bits per coordinate, total 28 bits) ----------\nuint64_t hilbertIndex(uint32_t x, uint32_t y, int bits = 14) {\n    const uint32_t n = 1u << bits;\n    uint64_t d = 0;\n    uint32_t rx, ry, s;\n    for (s = n >> 1; s; s >>= 1) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d = (d << 2) | ((rx * 3) ^ ry);\n        // rotate/reflect\n        if (ry == 0) {\n            if (rx == 1) {\n                x = (uint32_t)(n - 1) - x;\n                y = (uint32_t)(n - 1) - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// ---------- query helper ----------\nvector<pair<int,int>> do_query(const vector<int>& subset) {\n    int l = subset.size();\n    cout << \"? \" << l;\n    for (int v : subset) cout << ' ' << v;\n    cout << endl;\n    vector<pair<int,int>> res;\n    for (int i = 0; i < l-1; ++i) {\n        int a, b; cin >> a >> b;\n        if (a > b) swap(a, b);\n        res.emplace_back(a, b);\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<ll> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // ---------- order cities by Hilbert index (based on center) ----------\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    // scale coordinates to 14-bit (0..16383) - 10000 fits well\n    auto scale = [&](ll v) -> uint32_t {\n        return (uint32_t)clamp(v, 0LL, 16383LL);\n    };\n    vector<uint64_t> hi(N);\n    for (int i = 0; i < N; ++i) {\n        hi[i] = hilbertIndex(scale(cx[i]), scale(cy[i]));\n    }\n    sort(order.begin(), order.end(), [&](int a, int b) { return hi[a] < hi[b]; });\n\n    // ---------- assign groups by consecutive blocks ----------\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        for (int j = 0; j < G[k]; ++j) {\n            groups[k].push_back(order[idx++]);\n        }\n    }\n\n    // ---------- plan how many queries to spend on each group ----------\n    // count small groups that need exactly 1 query\n    int small_cnt = 0;\n    vector<int> full_needed(M, 0);\n    for (int k = 0; k < M; ++k) {\n        int sz = (int)groups[k].size();\n        if (sz <= L) {\n            full_needed[k] = 1;   // one query for the whole group\n            ++small_cnt;\n        } else {\n            // sliding window with step 1 would need (sz - L + 1) queries\n            full_needed[k] = sz - L + 1;\n        }\n    }\n    int total_full = accumulate(full_needed.begin(), full_needed.end(), 0);\n    int remaining = Q; // we will subtract small groups first\n    // allocate queries to large groups proportionally if necessary\n    vector<int> queries_per_group(M, 0);\n    int assigned_small = 0;\n    // first assign 1 query to every small group\n    for (int k = 0; k < M; ++k) {\n        if ((int)groups[k].size() <= L) {\n            if (assigned_small < Q) {\n                queries_per_group[k] = 1;\n                ++assigned_small;\n            } else {\n                // not enough queries, can't query this small group\n                queries_per_group[k] = 0; // will handle later\n            }\n        }\n    }\n    int remaining_queries = Q - assigned_small; // queries left for large groups\n\n    if (remaining_queries > 0) {\n        // collect large groups indices\n        vector<int> large_idx;\n        for (int k = 0; k < M; ++k) {\n            if ((int)groups[k].size() > L) {\n                large_idx.push_back(k);\n            }\n        }\n        if (!large_idx.empty()) {\n            // sum of full_needed for large groups\n            ll sum_large = 0;\n            for (int k : large_idx) sum_large += full_needed[k];\n            // allocate proportionally\n            for (int k : large_idx) {\n                ll alloc = (ll)remaining_queries * full_needed[k] / sum_large;\n                if (alloc == 0) alloc = 1;\n                queries_per_group[k] = (int)alloc;\n            }\n            // ensure total does not exceed remaining (adjust the last)\n            int used = 0;\n            for (int k : large_idx) used += queries_per_group[k];\n            if (used > remaining_queries) {\n                for (int k : large_idx) {\n                    if (used <= remaining_queries) break;\n                    if (queries_per_group[k] > 1) {\n                        --queries_per_group[k];\n                        --used;\n                    }\n                }\n            }\n        }\n    }\n\n    // ---------- perform queries ----------\n    vector<vector<pair<int,int>>> answer_edges(M);\n    int used_queries = 0;\n\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int sz = cities.size();\n        if (sz == 1) continue;\n        int nq = queries_per_group[k];\n        if (nq <= 0) {\n            // no query for this group -> we must build MST from estimated distances\n            // using all pairs? We'll do a simple MST using estimated distances.\n            // This is a fallback.\n            vector<tuple<ll,int,int>> edges;\n            for (int i = 0; i < sz; ++i) {\n                for (int j = i+1; j < sz; ++j) {\n                    ll dx = cx[cities[i]] - cx[cities[j]];\n                    ll dy = cy[cities[i]] - cy[cities[j]];\n                    ll w = (ll)sqrt(dx*dx + dy*dy);\n                    edges.emplace_back(w, cities[i], cities[j]);\n                }\n            }\n            sort(edges.begin(), edges.end());\n            DSU dsu(N);\n            vector<pair<int,int>> mst;\n            for (auto& e : edges) {\n                int u = get<1>(e), v = get<2>(e);\n                if (dsu.unite(u, v)) mst.emplace_back(u, v);\n            }\n            for (auto& p : mst) answer_edges[k].push_back(p);\n            continue;\n        }\n\n        if (sz <= L) {\n            // query whole group\n            ++used_queries;\n            auto res = do_query(cities);\n            for (auto e : res) answer_edges[k].push_back(e);\n        } else {\n            // sliding window with step size to achieve nq queries\n            int step = max(1, (sz - L + 1 + nq - 1) / nq); // ceil division\n            vector<pair<int,int>> collected;\n            for (int start = 0; start + L <= sz; start += step) {\n                ++used_queries;\n                vector<int> subset(cities.begin() + start, cities.begin() + start + L);\n                auto res = do_query(subset);\n                for (auto e : res) collected.push_back(e);\n            }\n            // also need to handle the tail? The last window may not be covered if step >1.\n            // But the sliding windows may not cover all edges. We'll cover the rest by adding estimated edges.\n            // To ensure connectivity, we will now build MST from collected edges + additional estimated edges.\n            // Use estimated distances for all pairs.\n            vector<tuple<ll,int,int>> cand;\n            for (auto& p : collected) {\n                ll dx = cx[p.first] - cx[p.second];\n                ll dy = cy[p.first] - cy[p.second];\n                ll w = (ll)sqrt(dx*dx + dy*dy);\n                cand.emplace_back(w, p.first, p.second);\n            }\n            // add all other pairs with estimated weight\n            for (int i = 0; i < sz; ++i) {\n                int u = cities[i];\n                for (int j = i+1; j < sz; ++j) {\n                    int v = cities[j];\n                    // check if already in collected (optional)\n                    bool already = false;\n                    for (auto& p : collected) {\n                        if ((p.first == u && p.second == v) || (p.first == v && p.second == u)) {\n                            already = true;\n                            break;\n                        }\n                    }\n                    if (already) continue;\n                    ll dx = cx[u] - cx[v];\n                    ll dy = cy[u] - cy[v];\n                    ll w = (ll)sqrt(dx*dx + dy*dy);\n                    cand.emplace_back(w, u, v);\n                }\n            }\n            sort(cand.begin(), cand.end());\n            DSU dsu(N);\n            vector<pair<int,int>> mst;\n            for (auto& e : cand) {\n                int u = get<1>(e), v = get<2>(e);\n                if (dsu.unite(u, v)) mst.emplace_back(u, v);\n            }\n            for (auto& p : mst) answer_edges[k].push_back(p);\n        }\n    }\n\n    // ---------- output answer ----------\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        for (int v : groups[k]) cout << v << ' ';\n        cout << endl;\n        for (auto& e : answer_edges[k]) cout << e.first << ' ' << e.second << endl;\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nconst int dy[4] = {-1, 1, 0, 0}; // U, D, L, R\nconst int dx[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\n// BFS to find shortest path from (si,sj) to (ti,tj) using only Move and Slide.\n// Returns vector of (action, direction) pairs.\nvector<pair<char, char>> get_path(int si, int sj, int ti, int tj) {\n    int start = si * N + sj, goal = ti * N + tj;\n    vector<int> dist(N * N, -1), prev(N * N, -1), act(N * N, -1), dir(N * N, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        if (u == goal) break;\n        int i = u / N, j = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move one step\n            int ni = i + dy[d], nj = j + dx[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int v = ni * N + nj;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 0; // Move\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n\n            // Slide to the edge in direction d\n            // Only valid if the first square in that direction is inside (otherwise slide does nothing)\n            if (d == 0 && i > 0) { // up\n                int v = 0 * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1; // Slide\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 1 && i < N - 1) { // down\n                int v = (N - 1) * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 2 && j > 0) { // left\n                int v = i * N + 0;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 3 && j < N - 1) { // right\n                int v = i * N + (N - 1);\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n        }\n    }\n\n    // Reconstruct path from goal to start\n    vector<pair<char, char>> rev;\n    int cur = goal;\n    while (cur != start) {\n        int a = act[cur];\n        int d = dir[cur];\n        rev.push_back({(a == 0 ? 'M' : 'S'), dir_char[d]});\n        cur = prev[cur];\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int, int>> points(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    int cur_i = points[0].first, cur_j = points[0].second;\n\n    for (int t = 1; t < M; ++t) {\n        int ti = points[t].first, tj = points[t].second;\n        auto path = get_path(cur_i, cur_j, ti, tj);\n        for (auto [act, dir] : path) {\n            cout << act << \" \" << dir << \"\\n\";\n        }\n        cur_i = ti;\n        cur_j = tj;\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Rect { int a, b, c, d; }; // [a,c) x [b,d)\nstruct Region { int x0, y0, x1, y1; vector<int> ids; };\nstruct SplitResult { \n    int axis; \n    int s; \n    vector<int> left, right; \n    double metric;\n};\n\nint n;\nvector<int> xi, yi, ri;\n\ndouble calc_p(int idx, long long area) {\n    long long r = ri[idx];\n    long long s = area;\n    long long mn = min(r, s);\n    long long mx = max(r, s);\n    double ratio = (double)mn / mx;\n    return ratio * (2.0 - ratio);\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return max(a.a, b.a) < min(a.c, b.c) && max(a.b, b.b) < min(a.d, b.d);\n}\nbool contains(const Rect& rect, int xi, int yi) {\n    return rect.a <= xi && xi < rect.c && rect.b <= yi && yi < rect.d;\n}\n\ndouble total_score(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; ++i) {\n        long long area = (long long)(rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        sum += calc_p(i, area);\n    }\n    return sum;\n}\n\nSplitResult choose_split(const Region& reg) {\n    int m = reg.ids.size();\n    const auto& ids = reg.ids;\n    int x0 = reg.x0, y0 = reg.y0, x1 = reg.x1, y1 = reg.y1;\n    vector<SplitResult> candidates;\n\n    // ---- vertical split (axis 0) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, xi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, xi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int height = y1 - y0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / height + x0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - x0) * height;\n            long long right_area = (long long)(x1 - s) * height;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({0, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    // ---- horizontal split (axis 1) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return yi[i] < yi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, yi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, yi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int width = x1 - x0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / width + y0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - y0) * width;\n            long long right_area = (long long)(y1 - s) * width;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({1, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    if (candidates.empty()) {\n        // fallback: split vertically at median\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        int mid = m / 2;\n        int split_x = (xi[order[mid-1]] + xi[order[mid]] + 1) / 2;\n        if (split_x <= x0) split_x = x0+1;\n        if (split_x >= x1) split_x = x1-1;\n        vector<int> left(order.begin(), order.begin()+mid);\n        vector<int> right(order.begin()+mid, order.end());\n        double left_sum = accumulate(left.begin(), left.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double right_sum = accumulate(right.begin(), right.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double metric = 0; // unused but set to avoid warning\n        return {0, split_x, move(left), move(right), metric};\n    }\n\n    // stochastic selection with softmax\n    double temperature = 0.02;\n    double max_metric = 1e100;\n    for (auto& c : candidates) if (c.metric < max_metric) max_metric = c.metric;\n    vector<double> weights(candidates.size());\n    double sum_weights = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        weights[i] = exp(- (candidates[i].metric - max_metric) * temperature);\n        sum_weights += weights[i];\n    }\n    uniform_real_distribution<double> dist(0.0, sum_weights);\n    double r = dist(rng);\n    double cum = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        cum += weights[i];\n        if (r <= cum) return move(candidates[i]);\n    }\n    return move(candidates.back());\n}\n\nvoid recursive_split(const Region& reg, vector<Rect>& rects) {\n    if (reg.ids.size() == 1) {\n        int idx = reg.ids[0];\n        rects[idx] = {reg.x0, reg.y0, reg.x1, reg.y1};\n        return;\n    }\n    SplitResult split = choose_split(reg);\n    if (split.axis == 0) {\n        Region left{reg.x0, reg.y0, split.s, reg.y1, move(split.left)};\n        Region right{split.s, reg.y0, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    } else {\n        Region left{reg.x0, reg.y0, reg.x1, split.s, move(split.left)};\n        Region right{reg.x0, split.s, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    }\n}\n\nvoid improve(vector<Rect>& rects) {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < n; ++i) {\n            Rect cur = rects[i];\n            // try expand in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c >= 10000) continue;\n                    newr.c++;\n                } else if (dir == 1) { // left\n                    if (newr.a <= 0) continue;\n                    newr.a--;\n                } else if (dir == 2) { // top\n                    if (newr.d >= 10000) continue;\n                    newr.d++;\n                } else { // bottom\n                    if (newr.b <= 0) continue;\n                    newr.b--;\n                }\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n            // try shrink in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c - 1 <= newr.a) continue;\n                    newr.c--;\n                } else if (dir == 1) { // left\n                    if (newr.a + 1 >= newr.c) continue;\n                    newr.a++;\n                } else if (dir == 2) { // top\n                    if (newr.d - 1 <= newr.b) continue;\n                    newr.d--;\n                } else { // bottom\n                    if (newr.b + 1 >= newr.d) continue;\n                    newr.b++;\n                }\n                // must still contain the point\n                if (!contains(newr, xi[i], yi[i])) continue;\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(15);\n\n    cin >> n;\n    xi.resize(n); yi.resize(n); ri.resize(n);\n    for (int i = 0; i < n; ++i) cin >> xi[i] >> yi[i] >> ri[i];\n\n    vector<Rect> best_rects(n);\n    double best_score = -1.0;\n\n    const int TRIALS = 200; // number of random constructions\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        vector<int> all_ids(n);\n        iota(all_ids.begin(), all_ids.end(), 0);\n        Region full{0, 0, 10000, 10000, move(all_ids)};\n        vector<Rect> rects(n);\n        recursive_split(full, rects);\n        double score = total_score(rects);\n        if (score > best_score) {\n            best_score = score;\n            best_rects = move(rects);\n        }\n    }\n\n    // post-processing on best solution\n    improve(best_rects);\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n             << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <chrono>\n#include <bitset>\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_CELLS = N * N;\nconst int MAX_TILES = 2500;\n\nusing Bitset = bitset<MAX_TILES>;\n\n// Global arrays\nint tile_id[MAX_CELLS];          // tile id for each cell\nint p_val[MAX_CELLS];            // value\nvector<int> neighbors[MAX_CELLS]; // neighbor cell indices (different tile)\nchar dir_char[MAX_CELLS][4];     // direction character for each neighbor (max 4)\nint neighbor_cnt[MAX_CELLS];     // number of neighbors\n\n// Precomputed max neighbor value for each cell? We'll compute on the fly.\n\nstruct State {\n    int pos;          // current cell index (0..2499)\n    Bitset vis;       // visited tiles\n    int sum;          // total score so far\n    vector<char> path; // path as characters (for efficiency)\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- Input -----\n    int si, sj;\n    cin >> si >> sj;\n    int start_pos = si * N + sj;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i * N + j];\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p_val[i * N + j];\n\n    // Determine number of tiles M\n    int M = 0;\n    for (int i = 0; i < MAX_CELLS; ++i)\n        if (tile_id[i] + 1 > M) M = tile_id[i] + 1;\n    // safety: M <= 2500\n\n    // ----- Build adjacency -----\n    const int dr[] = {-1, 1, 0, 0};\n    const int dc[] = {0, 0, -1, 1};\n    const char dirs[] = {'U', 'D', 'L', 'R'};\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int me = i * N + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dr[d];\n                int nj = j + dc[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int other = ni * N + nj;\n                if (tile_id[me] != tile_id[other]) {\n                    neighbors[me].push_back(other);\n                    dir_char[me][neighbor_cnt[me]] = dirs[d];\n                    neighbor_cnt[me]++;\n                }\n            }\n        }\n    }\n\n    // ----- Beam Search -----\n    const int BEAM_WIDTH = 1500;\n    const double TIME_LIMIT_MS = 1900.0;\n    auto start_time = chrono::high_resolution_clock::now();\n\n    // Initial state\n    State init;\n    init.pos = start_pos;\n    init.vis.reset();\n    init.vis.set(tile_id[start_pos]);\n    init.sum = p_val[start_pos];\n    init.path.clear();\n\n    vector<State> beam;\n    beam.push_back(move(init));\n    State best = beam[0];\n\n    // Heuristic: sum + max value among unvisited neighbor cells\n    auto heuristic = [&](const State& s) -> int {\n        int add = 0;\n        for (int nb : neighbors[s.pos]) {\n            if (!s.vis.test(tile_id[nb])) {\n                add = max(add, p_val[nb]);\n            }\n        }\n        return s.sum + add;\n    };\n\n    while (!beam.empty()) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > TIME_LIMIT_MS) break;\n\n        vector<pair<int, State>> candidates;\n        candidates.reserve(beam.size() * 3); // typical branching\n\n        for (const auto& s : beam) {\n            for (int k = 0; k < neighbor_cnt[s.pos]; ++k) {\n                int nb = neighbors[s.pos][k];\n                int nt = tile_id[nb];\n                if (s.vis.test(nt)) continue; // tile already visited\n\n                State ns;\n                ns.pos = nb;\n                ns.vis = s.vis;\n                ns.vis.set(nt);\n                ns.sum = s.sum + p_val[nb];\n                // copy path and append char\n                ns.path = s.path;\n                ns.path.push_back(dir_char[s.pos][k]);\n\n                int val = heuristic(ns);\n                candidates.emplace_back(val, move(ns));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        // Keep top BEAM_WIDTH by heuristic score\n        int keep = min((int)candidates.size(), BEAM_WIDTH);\n        partial_sort(candidates.begin(), candidates.begin() + keep, candidates.end(),\n                     [](const auto& a, const auto& b) { return a.first > b.first; });\n\n        beam.clear();\n        for (int i = 0; i < keep; ++i) {\n            beam.push_back(move(candidates[i].second));\n            // Update global best by actual sum\n            if (beam.back().sum > best.sum) best = beam.back();\n        }\n    }\n\n    // ---- Greedy extension from best state (1-ply) ----\n    auto extend_greedy = [&](State cur) -> State {\n        while (true) {\n            int best_val = -1;\n            int best_nb = -1;\n            char best_dir = 0;\n            for (int k = 0; k < neighbor_cnt[cur.pos]; ++k) {\n                int nb = neighbors[cur.pos][k];\n                int nt = tile_id[nb];\n                if (cur.vis.test(nt)) continue;\n                if (p_val[nb] > best_val) {\n                    best_val = p_val[nb];\n                    best_nb = nb;\n                    best_dir = dir_char[cur.pos][k];\n                }\n            }\n            if (best_val == -1) break;\n            cur.pos = best_nb;\n            cur.vis.set(tile_id[best_nb]);\n            cur.sum += best_val;\n            cur.path.push_back(best_dir);\n        }\n        return cur;\n    };\n\n    // ---- Greedy extension from best state (2-ply) ----\n    auto extend_greedy2 = [&](State cur) -> State {\n        while (true) {\n            int best_total = -1;\n            int best_nb = -1;\n            char best_dir = 0;\n            for (int k = 0; k < neighbor_cnt[cur.pos]; ++k) {\n                int nb = neighbors[cur.pos][k];\n                int nt = tile_id[nb];\n                if (cur.vis.test(nt)) continue;\n                int val1 = p_val[nb];\n                int best_next = 0;\n                // look one step ahead from nb\n                for (int k2 = 0; k2 < neighbor_cnt[nb]; ++k2) {\n                    int nb2 = neighbors[nb][k2];\n                    int nt2 = tile_id[nb2];\n                    if (cur.vis.test(nt2) || nt2 == nt) continue;\n                    best_next = max(best_next, p_val[nb2]);\n                }\n                int total = val1 + best_next;\n                if (total > best_total) {\n                    best_total = total;\n                    best_nb = nb;\n                    best_dir = dir_char[cur.pos][k];\n                }\n            }\n            if (best_total == -1) break;\n            cur.pos = best_nb;\n            cur.vis.set(tile_id[best_nb]);\n            cur.sum += p_val[best_nb];\n            cur.path.push_back(best_dir);\n        }\n        return cur;\n    };\n\n    // ---- Try greedy extensions from the top few states ----\n    State best_ext = best;\n    // also consider other states in beam that might be better after extension\n    if (!beam.empty()) {\n        // sort beam by sum descending\n        sort(beam.begin(), beam.end(),\n             [](const State& a, const State& b) { return a.sum > b.sum; });\n        int limit = min(10, (int)beam.size());\n        for (int i = 0; i < limit; ++i) {\n            State ext1 = extend_greedy(beam[i]);\n            if (ext1.sum > best_ext.sum) best_ext = ext1;\n            State ext2 = extend_greedy2(beam[i]);\n            if (ext2.sum > best_ext.sum) best_ext = ext2;\n        }\n    }\n    // also extend the already best state\n    State best1 = extend_greedy(best);\n    if (best1.sum > best_ext.sum) best_ext = best1;\n    State best2 = extend_greedy2(best);\n    if (best2.sum > best_ext.sum) best_ext = best2;\n\n    // ---- Output ----\n    string out(best_ext.path.begin(), best_ext.path.end());\n    cout << out << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n#include <sstream>\n#include <iomanip>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int H_EDGES = 29; // number of horizontal edges per row\nconst int V_EDGES = 29; // number of vertical edges per column (30 rows -> 29 vertical edges per column)\n\nconst double INIT_EST = 4500.0;\nconst double MIN_EDGE = 1000.0;\nconst double MAX_EDGE = 9000.0;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // estimates, counts, and sum of squared gradients for AdaGrad\n    vector<vector<double>> h_est(GRID_SIZE, vector<double>(H_EDGES, INIT_EST));\n    vector<vector<int>> h_cnt(GRID_SIZE, vector<int>(H_EDGES, 0));\n    vector<vector<double>> h_grad_sq(GRID_SIZE, vector<double>(H_EDGES, 0.0));\n\n    vector<vector<double>> v_est(V_EDGES, vector<double>(GRID_SIZE, INIT_EST));\n    vector<vector<int>> v_cnt(V_EDGES, vector<int>(GRID_SIZE, 0));\n    vector<vector<double>> v_grad_sq(V_EDGES, vector<double>(GRID_SIZE, 0.0));\n\n    // hyperparameters\n    const double lr0 = 0.5;\n    const double C_explore = 500.0;\n    const int explore_until = 400;\n\n    int T = 1000;\n    for (int k = 0; k < T; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        // exploration factor: decays linearly to 0 over first explore_until queries\n        double explore_factor = max(0.0, 1.0 - (double)k / explore_until);\n        double t_weight = sqrt(log(k + 1.0) + 1.0); // UCB time factor\n\n        // ----------------------- Dijkstra with UCB-adjusted weights -----------------------\n        const double INF = 1e18;\n        vector<vector<double>> dist(GRID_SIZE, vector<double>(GRID_SIZE, INF));\n        vector<vector<pair<int,int>>> prev(GRID_SIZE, vector<pair<int,int>>(GRID_SIZE, {-1, -1}));\n        // priority queue: (distance, (i,j))\n        priority_queue<pair<double, pair<int,int>>, vector<pair<double, pair<int,int>>>, greater<>> pq;\n        dist[si][sj] = 0.0;\n        pq.push({0.0, {si, sj}});\n\n        while (!pq.empty()) {\n            auto [d, node] = pq.top(); pq.pop();\n            int i = node.first, j = node.second;\n            if (d > dist[i][j] + 1e-9) continue;\n            if (i == ti && j == tj) break; // reached target\n\n            // neighbor: up (i-1, j) -> vertical edge (i-1, j)\n            if (i > 0) {\n                double w = v_est[i-1][j] - C_explore * t_weight / sqrt(v_cnt[i-1][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i-1][j] - 1e-9) {\n                    dist[i-1][j] = d + w;\n                    prev[i-1][j] = {i, j};\n                    pq.push({dist[i-1][j], {i-1, j}});\n                }\n            }\n            // neighbor: down (i+1, j) -> vertical edge (i, j)\n            if (i < GRID_SIZE - 1) {\n                double w = v_est[i][j] - C_explore * t_weight / sqrt(v_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i+1][j] - 1e-9) {\n                    dist[i+1][j] = d + w;\n                    prev[i+1][j] = {i, j};\n                    pq.push({dist[i+1][j], {i+1, j}});\n                }\n            }\n            // neighbor: left (i, j-1) -> horizontal edge (i, j-1)\n            if (j > 0) {\n                double w = h_est[i][j-1] - C_explore * t_weight / sqrt(h_cnt[i][j-1] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j-1] - 1e-9) {\n                    dist[i][j-1] = d + w;\n                    prev[i][j-1] = {i, j};\n                    pq.push({dist[i][j-1], {i, j-1}});\n                }\n            }\n            // neighbor: right (i, j+1) -> horizontal edge (i, j)\n            if (j < GRID_SIZE - 1) {\n                double w = h_est[i][j] - C_explore * t_weight / sqrt(h_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j+1] - 1e-9) {\n                    dist[i][j+1] = d + w;\n                    prev[i][j+1] = {i, j};\n                    pq.push({dist[i][j+1], {i, j+1}});\n                }\n            }\n        }\n\n        // backtrack to retrieve the path\n        vector<pair<int,int>> path;\n        int ci = ti, cj = tj;\n        while (!(ci == si && cj == sj)) {\n            path.push_back({ci, cj});\n            auto p = prev[ci][cj];\n            ci = p.first;\n            cj = p.second;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n\n        // construct output string (moves)\n        string out;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int di = path[idx].first - path[idx-1].first;\n            int dj = path[idx].second - path[idx-1].second;\n            if (di == -1) out += 'U';\n            else if (di == 1) out += 'D';\n            else if (dj == -1) out += 'L';\n            else if (dj == 1) out += 'R';\n        }\n        cout << out << endl; // flush included\n\n        // read feedback: observed (noisy) path length\n        int feedback;\n        cin >> feedback;\n\n        // ----------------------- Update estimates -----------------------\n        // compute predicted length using current (unadjusted) estimates\n        double L_pred = 0.0;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                L_pred += h_est[i1][jmin];\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                L_pred += v_est[imin][j1];\n            }\n        }\n\n        double error = feedback - L_pred;\n        double rel_error = error / max(L_pred, 1.0);\n        // clamp to avoid extreme updates from large mispredictions\n        rel_error = clamp(rel_error, -3.0, 3.0);\n\n        // update each edge on the path\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                // accumulate squared gradient\n                h_grad_sq[i1][jmin] += rel_error * rel_error;\n                double lr = lr0 / sqrt(h_grad_sq[i1][jmin] + 1e-8);\n                double new_val = h_est[i1][jmin] + lr * rel_error;\n                h_est[i1][jmin] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                h_cnt[i1][jmin]++;\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                v_grad_sq[imin][j1] += rel_error * rel_error;\n                double lr = lr0 / sqrt(v_grad_sq[imin][j1] + 1e-8);\n                double new_val = v_est[imin][j1] + lr * rel_error;\n                v_est[imin][j1] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                v_cnt[imin][j1]++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPH = 8;\n\nint M;\nvector<string> strs;\nvector<uint64_t> hashes;\nunordered_map<uint64_t, vector<int>> hash_to_ids;\n\nvector<string> mat; // current matrix\nvector<int> occ;    // occurrences per input string\nint matched = 0;    // number of input strings with occ>0\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// encode a string to a 64-bit integer (3 bits per character)\nuint64_t encode(const string &s) {\n    uint64_t h = 0;\n    for (char c : s) {\n        h = (h << 3) | (c - 'A');\n    }\n    return h;\n}\n\n// generate all substrings that include cell (r,c) under the assumption that\n// mat[r][c] has the given character (used for delta computation)\nvoid collect_hashes(int r, int c, char cell_char, vector<uint64_t> &out_hashes) {\n    out_hashes.clear();\n    auto get_char = [&](int i, int j) -> char {\n        if (i == r && j == c) return cell_char;\n        return mat[i][j];\n    };\n    // horizontal substrings\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_col = (c - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int col = (start_col + t) % N;\n                char ch = get_char(r, col);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out_hashes.push_back(h);\n        }\n    }\n    // vertical substrings\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_row = (r - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int row = (start_row + t) % N;\n                char ch = get_char(row, c);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out_hashes.push_back(h);\n        }\n    }\n}\n\n// compute the change in 'matched' if we set (r,c) from old_char to new_char\nint compute_delta(int r, int c, char old_char, char new_char) {\n    static vector<uint64_t> old_hashes, new_hashes;\n    static vector<int> delta_occ(M, 0);\n    static vector<int> affected_ids;\n    affected_ids.clear();\n\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]--;\n            }\n        }\n    }\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]++;\n            }\n        }\n    }\n\n    int delta_matched = 0;\n    for (int id : affected_ids) {\n        int new_occ = occ[id] + delta_occ[id];\n        if (occ[id] == 0 && new_occ > 0) delta_matched++;\n        if (occ[id] > 0 && new_occ == 0) delta_matched--;\n    }\n    // clean up\n    for (int id : affected_ids) delta_occ[id] = 0;\n    return delta_matched;\n}\n\n// apply the change: update matrix and global occ/matched\nvoid apply_change(int r, int c, char new_char) {\n    char old_char = mat[r][c];\n    if (old_char == new_char) return;\n    static vector<uint64_t> old_hashes, new_hashes;\n    // remove old substrings\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                occ[id]--;\n                if (occ[id] == 0) matched--;\n            }\n        }\n    }\n    // set new character\n    mat[r][c] = new_char;\n    // add new substrings\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (occ[id] == 0) matched++;\n                occ[id]++;\n            }\n        }\n    }\n}\n\n// compute initial occ and matched by scanning the whole matrix\nvoid compute_initial_state() {\n    fill(occ.begin(), occ.end(), 0);\n    matched = 0;\n    // horizontal substrings\n    for (int r = 0; r < N; ++r) {\n        for (int len = 2; len <= 12; ++len) {\n            for (int start_col = 0; start_col < N; ++start_col) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int col = (start_col + t) % N;\n                    char ch = mat[r][col];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    // vertical substrings\n    for (int c = 0; c < N; ++c) {\n        for (int len = 2; len <= 12; ++len) {\n            for (int start_row = 0; start_row < N; ++start_row) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int row = (start_row + t) % N;\n                    char ch = mat[row][c];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// structure for a placement (for greedy)\nstruct Placement {\n    vector<int> cells;   // linear indices (r*20 + c)\n    vector<char> letters;\n};\n\n// greedy initialisation: fill matrix with as many strings as possible\nvoid greedy_initialization(vector<vector<Placement>> &placements) {\n    mat.assign(N, string(N, '.'));\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int idx : order) {\n        int best_score = -1;\n        int best_p = -1;\n        for (int p = 0; p < (int)placements[idx].size(); ++p) {\n            auto &pl = placements[idx][p];\n            int score = 0;\n            bool ok = true;\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                char cur = mat[r][c];\n                if (cur == '.') {\n                    // fine\n                } else if (cur != pl.letters[t]) {\n                    ok = false;\n                    break;\n                } else {\n                    score++;\n                }\n            }\n            if (ok && score > best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        if (best_p != -1) {\n            auto &pl = placements[idx][best_p];\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                mat[r][c] = pl.letters[t];\n            }\n        }\n    }\n    compute_initial_state();\n}\n\n// remove cells that are not essential for any string (safe removal)\nvoid remove_redundant_cells() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int cell = 0; cell < N * N; ++cell) {\n            int r = cell / N, c = cell % N;\n            if (mat[r][c] == '.') continue;\n            // check if this cell is essential for any string (occ==1)\n            bool essential = false;\n            static vector<uint64_t> hashes_cell;\n            collect_hashes(r, c, mat[r][c], hashes_cell);\n            for (uint64_t h : hashes_cell) {\n                auto it = hash_to_ids.find(h);\n                if (it == hash_to_ids.end()) continue;\n                for (int id : it->second) {\n                    if (occ[id] == 1) {\n                        essential = true;\n                        break;\n                    }\n                }\n                if (essential) break;\n            }\n            if (!essential) {\n                apply_change(r, c, '.');\n                changed = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummy;\n    cin >> dummy; // read N (always 20) and ignore\n    cin >> M;\n\n    strs.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n    }\n\n    // compute hashes and mapping\n    hashes.resize(M);\n    for (int i = 0; i < M; ++i) {\n        hashes[i] = encode(strs[i]);\n        hash_to_ids[hashes[i]].push_back(i);\n    }\n\n    // Precompute all placements for each string\n    vector<vector<Placement>> placements(M);\n    for (int i = 0; i < M; ++i) {\n        const string &s = strs[i];\n        int len = s.size();\n        placements[i].reserve(800);\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // horizontal\n                Placement ph;\n                ph.cells.reserve(len);\n                ph.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int col = (c + t) % N;\n                    ph.cells.push_back(r * N + col);\n                    ph.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(ph));\n                // vertical\n                Placement pv;\n                pv.cells.reserve(len);\n                pv.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int row = (r + t) % N;\n                    pv.cells.push_back(row * N + c);\n                    pv.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(pv));\n            }\n        }\n    }\n\n    // Resize global occ\n    occ.resize(M, 0);\n\n    // Try several greedy initializations and keep the best one\n    const int TRIES = 8;\n    int best_matched = -1;\n    vector<string> best_mat;\n    for (int t = 0; t < TRIES; ++t) {\n        greedy_initialization(placements);\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n        if (best_matched == M) break;\n    }\n    // set state to best found\n    mat = best_mat;\n    compute_initial_state();\n\n    // Simulated Annealing\n    const double TIME_LIMIT = 2.85; // seconds\n    auto start_time = chrono::steady_clock::now();\n    int iter = 0;\n    double T = 1.0;\n    const double COOLING = 0.99999;\n    const double MIN_T = 1e-4;\n    while (matched < M) {\n        double elapsed = chrono::duration_cast<chrono::duration<double>>(\n                             chrono::steady_clock::now() - start_time)\n                             .count();\n        if (elapsed >= TIME_LIMIT) break;\n        if (T < MIN_T) break;\n\n        int r = uniform_int_distribution<int>(0, N-1)(rng);\n        int c = uniform_int_distribution<int>(0, N-1)(rng);\n        char oldc = mat[r][c];\n        char newc;\n        do {\n            newc = 'A' + uniform_int_distribution<int>(0, ALPH-1)(rng);\n        } while (newc == oldc);\n\n        int delta = compute_delta(r, c, oldc, newc);\n        if (delta > 0) {\n            apply_change(r, c, newc);\n        } else if (delta == 0) {\n            if (uniform_real_distribution<double>(0,1)(rng) < 0.1) {\n                apply_change(r, c, newc);\n            }\n        } else {\n            double prob = exp(delta / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                apply_change(r, c, newc);\n            }\n        }\n        T *= COOLING;\n        iter++;\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n    }\n\n    // If we have all strings, try to remove cells to increase score\n    if (best_matched == M) {\n        mat = best_mat;\n        compute_initial_state();\n        remove_redundant_cells();\n        best_mat = mat;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << best_mat[i] << \"\\n\";\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\nusing uint16 = unsigned short;\nconst uint16 INF16 = UINT16_MAX;\n\nint N, si, sj;\nvector<string> grid;\nvector<pair<int,int>> pos;       // coordinates of each road square\nvector<int> weight;              // time cost of each road square\nvector<vector<int>> adj;         // adjacency list (neighbor indices)\nint R;                           // number of road squares\n\n// map (i,j) -> id\nint id[70][70];\n\nvoid read_input() {\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    // assign ids to road squares\n    R = 0;\n    memset(id, -1, sizeof(id));\n    pos.clear();\n    weight.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R;\n                pos.emplace_back(i, j);\n                weight.push_back(grid[i][j] - '0');\n                ++R;\n            }\n        }\n    }\n    // build adjacency\n    adj.assign(R, vector<int>());\n    int di[] = {-1,1,0,0};\n    int dj[] = {0,0,-1,1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == '#') continue;\n            int u = id[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && grid[ni][nj] != '#') {\n                    int v = id[ni][nj];\n                    adj[u].push_back(v);\n                }\n            }\n        }\n    }\n}\n\n// Precompute all-pair shortest paths (distance matrix)\nvector<vector<uint16>> precompute_all_pairs() {\n    vector<vector<uint16>> dist(R, vector<uint16>(R, INF16));\n    for (int src = 0; src < R; ++src) {\n        vector<uint16> d(R, INF16);\n        d[src] = 0;\n        priority_queue<pair<uint16,int>, vector<pair<uint16,int>>, greater<pair<uint16,int>>> pq;\n        pq.emplace(0, src);\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top(); pq.pop();\n            if (cd != d[u]) continue;\n            for (int v : adj[u]) {\n                uint16 nd = cd + weight[v];\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n        dist[src] = d;\n    }\n    return dist;\n}\n\n// Get horizontal segments\npair<vector<vector<int>>, vector<int>> get_h_segments() {\n    vector<int> h_id(R, -1);\n    vector<vector<int>> h_nodes;\n    int hcnt = 0;\n    for (int i = 0; i < N; ++i) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') { ++j; continue; }\n            int start = j;\n            while (j < N && grid[i][j] != '#') ++j;\n            vector<int> seg;\n            for (int k = start; k < j; ++k) {\n                int uid = id[i][k];\n                h_id[uid] = hcnt;\n                seg.push_back(uid);\n            }\n            h_nodes.push_back(seg);\n            ++hcnt;\n        }\n    }\n    return {move(h_nodes), move(h_id)};\n}\n\n// Build groups (start group + all H-segments except start's)\nvector<vector<int>> build_groups(const vector<vector<int>> &h_nodes, const vector<int> &h_id, int start_id) {\n    vector<vector<int>> groups;\n    // group 0 = start\n    groups.push_back({start_id});\n    int start_h = h_id[start_id];\n    for (size_t g = 0; g < h_nodes.size(); ++g) {\n        if ((int)g == start_h) continue;\n        groups.push_back(h_nodes[g]);\n    }\n    return groups;\n}\n\n// Compute segment distance matrix\nvector<vector<uint16>> segment_dist_matrix(const vector<vector<int>> &groups, const vector<vector<uint16>> &dist) {\n    int G = groups.size();\n    vector<vector<uint16>> D(G, vector<uint16>(G, INF16));\n    for (int i = 0; i < G; ++i) {\n        D[i][i] = 0;\n        for (int j = i+1; j < G; ++j) {\n            uint16 best = INF16;\n            for (int u : groups[i]) {\n                for (int v : groups[j]) {\n                    best = min(best, dist[u][v]);\n                }\n            }\n            D[i][j] = D[j][i] = best;\n        }\n    }\n    return D;\n}\n\n// TSP on groups with 2-opt (fix start group 0)\nvector<int> solve_tsp(const vector<vector<uint16>> &D) {\n    int G = D.size();\n    if (G <= 1) return {0};\n    vector<int> tour(G);\n    // nearest neighbour\n    vector<bool> visited(G, false);\n    tour[0] = 0;\n    visited[0] = true;\n    for (int k = 1; k < G; ++k) {\n        int cur = tour[k-1];\n        int best = -1;\n        uint16 bestDist = INF16;\n        for (int i = 0; i < G; ++i) {\n            if (!visited[i] && D[cur][i] < bestDist) {\n                bestDist = D[cur][i];\n                best = i;\n            }\n        }\n        tour[k] = best;\n        visited[best] = true;\n    }\n    // 2-opt improvement (cycle)\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 1; i < G-1; ++i) {\n            for (int j = i+1; j < G; ++j) {\n                int a = tour[i-1];\n                int b = tour[i];\n                int c = tour[j];\n                int d = (j+1 < G) ? tour[j+1] : tour[0];\n                uint16 old = D[a][b] + D[c][d];\n                uint16 nw = D[a][c] + D[b][d];\n                if (nw < old) {\n                    reverse(tour.begin() + i, tour.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    return tour;\n}\n\n// DP to select one node per group given a fixed order\nvector<int> select_nodes(const vector<int> &order, const vector<vector<int>> &groups, const vector<vector<uint16>> &dist) {\n    int G = order.size();\n    if (G == 1) return {groups[0][0]}; // only start\n    vector<unordered_map<int,uint16>> dp_cost(G);\n    vector<unordered_map<int,int>> dp_prev(G);\n    // initialize start group (order[0] should be 0)\n    int start_id = groups[0][0];\n    dp_cost[0][start_id] = 0;\n    for (int pos = 1; pos < G; ++pos) {\n        int g = order[pos];\n        int prev_g = order[pos-1];\n        for (int v : groups[g]) {\n            uint16 best = INF16;\n            int best_u = -1;\n            for (int u : groups[prev_g]) {\n                auto it = dp_cost[pos-1].find(u);\n                if (it != dp_cost[pos-1].end()) {\n                    uint16 cand = it->second + dist[u][v];\n                    if (cand < best) {\n                        best = cand;\n                        best_u = u;\n                    }\n                }\n            }\n            if (best != INF16) {\n                dp_cost[pos][v] = best;\n                dp_prev[pos][v] = best_u;\n            }\n        }\n    }\n    // final step: return to start\n    uint16 total_best = INF16;\n    int last_node = -1;\n    for (int u : groups[order[G-1]]) {\n        auto it = dp_cost[G-1].find(u);\n        if (it != dp_cost[G-1].end()) {\n            uint16 cand = it->second + dist[u][start_id];\n            if (cand < total_best) {\n                total_best = cand;\n                last_node = u;\n            }\n        }\n    }\n    // backtrace\n    vector<int> selected(G);\n    selected[G-1] = last_node;\n    for (int pos = G-1; pos >= 1; --pos) {\n        int v = selected[pos];\n        int u = dp_prev[pos][v];\n        selected[pos-1] = u;\n    }\n    return selected;\n}\n\n// Reconstruct path string between two nodes\nstring get_path(int from, int to, const vector<vector<uint16>> &dist) {\n    if (from == to) return \"\";\n    // Dijkstra from 'from' to 'to'\n    vector<uint16> d(R, INF16);\n    vector<int> parent(R, -1);\n    vector<char> move_char(R, 0);\n    d[from] = 0;\n    priority_queue<pair<uint16,int>, vector<pair<uint16,int>>, greater<pair<uint16,int>>> pq;\n    pq.emplace(0, from);\n    while (!pq.empty()) {\n        auto [cd, u] = pq.top(); pq.pop();\n        if (cd != d[u]) continue;\n        if (u == to) break;\n        for (int v : adj[u]) {\n            uint16 nd = cd + weight[v];\n            if (nd < d[v]) {\n                d[v] = nd;\n                parent[v] = u;\n                // direction\n                int dx = pos[v].first - pos[u].first;\n                int dy = pos[v].second - pos[u].second;\n                if (dx == -1) move_char[v] = 'U';\n                else if (dx == 1) move_char[v] = 'D';\n                else if (dy == -1) move_char[v] = 'L';\n                else if (dy == 1) move_char[v] = 'R';\n                pq.emplace(nd, v);\n            }\n        }\n    }\n    // backtrack\n    string path;\n    int cur = to;\n    while (cur != from) {\n        path.push_back(move_char[cur]);\n        cur = parent[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n\n    // precompute all-pair distances\n    auto dist = precompute_all_pairs();\n\n    // get horizontal segments\n    auto [h_nodes, h_id] = get_h_segments();\n    int start_id = id[si][sj];\n\n    // build groups (start + all H-segments except start's)\n    auto groups = build_groups(h_nodes, h_id, start_id);\n    int G = groups.size();\n\n    // segment distance matrix\n    auto D = segment_dist_matrix(groups, dist);\n\n    // TSP on groups\n    auto order = solve_tsp(D);\n    // for each group index in order, the actual group id is order[i]\n    // Now select nodes with DP\n    vector<int> selected = select_nodes(order, groups, dist);\n\n    // build final path\n    string ans;\n    for (int i = 0; i < G-1; ++i) {\n        ans += get_path(selected[i], selected[i+1], dist);\n    }\n    ans += get_path(selected[G-1], selected[0], dist);\n\n    cout << ans << endl;\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ========== constants ==========\nconst double INF = 1e9;\nconst double LR0 = 0.5;           // base learning rate\nconst double EXPLORE = 1.0;       // exploration coefficient for UCB\n\nint N, M, K, R;\nvector<vector<int>> d;           // N x K difficulty\nvector<vector<int>> preds, succs;\nvector<int> rem_pred;\n\n// state\nvector<int> status;              // -1: not started, 0: in progress, 1: done\nvector<int> start_day;\nvector<int> worker_of_task;\nvector<int> actual_dur;\nvector<double> pred_dur_at_start;\nvector<int> cur_task;            // -1 if idle\nvector<vector<double>> skill_est; // M x K\nvector<vector<int>> skill_cnt;   // how many times each skill was updated (per worker)\n\n// estimates\nvector<double> est_dur;          // current estimated duration of each task (for scheduling)\n\n// ========== helpers ==========\ninline double predict_dur(int task, int worker) {\n    double w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) w += diff;\n    }\n    return (w == 0.0) ? 1.0 : (1.0 + w);\n}\n\ninline double ucb_score(int task, int worker, int day) {\n    double base = predict_dur(task, worker);\n    double exploration = EXPLORE * sqrt(log(day + 1.0) / (1.0 + skill_cnt[worker][0])); // count total assignments roughly\n    return base - exploration;   // lower is better\n}\n\n// update skill estimates after observing actual duration\nvoid update_skills(int worker, int task, int actual_t) {\n    int obs_w = max(0, actual_t - 1);\n    // predicted w before task\n    double pred_w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) pred_w += diff;\n    }\n    double error = pred_w - obs_w;   // positive -> overestimate\n    // per-skill learning rate\n    auto lr = [&](int k) -> double {\n        return LR0 / sqrt(1.0 + skill_cnt[worker][k]);\n    };\n    if (obs_w == 0) {\n        // no deficiency -> increase skills that were lacking\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                skill_est[worker][k] += lr(k) * (d[task][k] - skill_est[worker][k]);\n                skill_cnt[worker][k]++;\n            }\n        }\n    } else {\n        // deficiency existed\n        double scale = (pred_w > 0) ? error / pred_w : 0.0;\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                skill_est[worker][k] += lr(k) * scale;\n                skill_cnt[worker][k]++;\n            }\n        }\n        // case: predicted no deficiency but actually deficiency existed\n        if (pred_w == 0.0 && obs_w > 0) {\n            for (int k = 0; k < K; ++k) {\n                if (skill_est[worker][k] > d[task][k]) {\n                    skill_est[worker][k] = max(0.0, skill_est[worker][k] - lr(k) * 0.5);\n                    skill_cnt[worker][k]++;\n                }\n            }\n        }\n    }\n    // clamp\n    for (int k = 0; k < K; ++k) {\n        if (skill_est[worker][k] < 0) skill_est[worker][k] = 0;\n        if (skill_est[worker][k] > 200) skill_est[worker][k] = 200;\n    }\n}\n\n// ========== main ==========\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    cin >> N >> M >> K >> R;\n    d.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < K; ++j)\n            cin >> d[i][j];\n\n    preds.assign(N, vector<int>());\n    succs.assign(N, vector<int>());\n    rem_pred.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        preds[v].push_back(u);\n        succs[u].push_back(v);\n        rem_pred[v]++;\n    }\n\n    // initialize state\n    status.assign(N, -1);\n    start_day.assign(N, 0);\n    worker_of_task.assign(N, -1);\n    actual_dur.assign(N, 0);\n    pred_dur_at_start.assign(N, 0.0);\n    cur_task.assign(M, -1);\n    skill_est.assign(M, vector<double>(K, 0.0));\n    skill_cnt.assign(M, vector<int>(K, 0));\n\n    // better initial skill: use average task difficulty per dimension\n    vector<double> avg_skill(K, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            avg_skill[k] += d[i][k];\n    for (int k = 0; k < K; ++k) avg_skill[k] /= N;\n    for (int j = 0; j < M; ++j)\n        for (int k = 0; k < K; ++k)\n            skill_est[j][k] = avg_skill[k] * (0.8 + 0.4 * (double)rand() / RAND_MAX); // perturb\n\n    // main loop\n    int day = 1;\n    while (true) {\n        // ---- compute estimated duration and critical path weights ----\n        est_dur.assign(N, 0.0);\n        vector<double> finish_time(N, 0.0);\n        // forward pass (topological order)\n        for (int i = 0; i < N; ++i) {\n            double max_pred_finish = 0.0;\n            for (int p : preds[i]) {\n                if (finish_time[p] > max_pred_finish)\n                    max_pred_finish = finish_time[p];\n            }\n            double est_start_i = max_pred_finish + 1.0;\n            if (status[i] == 1) {\n                est_dur[i] = actual_dur[i];\n                finish_time[i] = start_day[i] + actual_dur[i] - 1.0;\n            } else if (status[i] == 0) {\n                double remain = max(0.0, pred_dur_at_start[i] - (day - start_day[i]));\n                est_dur[i] = remain;\n                // finish_time remains same? We'll keep it consistent: started tasks are already scheduled.\n                finish_time[i] = day + remain - 1.0;\n            } else {\n                // unstarted: find the best worker (optimistic)\n                double best = INF;\n                for (int j = 0; j < M; ++j) {\n                    double ddd = predict_dur(i, j);\n                    if (ddd < best) best = ddd;\n                }\n                est_dur[i] = best;\n                finish_time[i] = est_start_i + best - 1.0;\n            }\n        }\n\n        // ---- compute criticality (longest path to leaf) ----\n        vector<double> criticality(N, 0.0);\n        for (int i = N - 1; i >= 0; --i) {\n            double max_succ = 0.0;\n            for (int s : succs[i]) {\n                if (criticality[s] > max_succ) max_succ = criticality[s];\n            }\n            criticality[i] = est_dur[i] + max_succ;\n        }\n\n        // ---- ready tasks ----\n        vector<int> ready;\n        for (int i = 0; i < N; ++i)\n            if (status[i] == -1 && rem_pred[i] == 0) ready.push_back(i);\n\n        // ---- sort by criticality (descending) ----\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (criticality[a] != criticality[b])\n                return criticality[a] > criticality[b];\n            return a < b;\n        });\n\n        // ---- idle workers ----\n        vector<int> idle;\n        for (int j = 0; j < M; ++j) if (cur_task[j] == -1) idle.push_back(j);\n\n        // ---- assignment ----\n        vector<int> assign_out; // flattened: worker, task (0-index)\n        for (int task : ready) {\n            if (idle.empty()) break;\n            // pick best idle worker via UCB\n            int best_w = -1;\n            double best_val = INF;\n            for (int j : idle) {\n                double u = ucb_score(task, j, day);\n                if (u < best_val) {\n                    best_val = u;\n                    best_w = j;\n                }\n            }\n            // assign\n            assign_out.push_back(best_w);\n            assign_out.push_back(task);\n            cur_task[best_w] = task;\n            start_day[task] = day;\n            worker_of_task[task] = best_w;\n            pred_dur_at_start[task] = predict_dur(task, best_w);\n            status[task] = 0;\n            // update counts (roughly)\n            for (int k = 0; k < K; ++k) skill_cnt[best_w][k]++; // increment all\n            // remove worker from idle\n            auto it = find(idle.begin(), idle.end(), best_w);\n            if (it != idle.end()) {\n                *it = idle.back();\n                idle.pop_back();\n            }\n        }\n\n        // ---- output ----\n        int m = assign_out.size() / 2;\n        cout << m;\n        for (int x : assign_out) cout << ' ' << (x + 1);\n        cout << '\\n';\n        cout.flush();\n\n        // ---- read response ----\n        int dummy;\n        cin >> dummy;\n        if (dummy == -1) break;\n\n        // ---- process completions ----\n        for (int i = 0; i < dummy; ++i) {\n            int worker;\n            cin >> worker;\n            --worker;\n            int task = cur_task[worker];\n            int duration = day - start_day[task] + 1;\n\n            status[task] = 1;\n            actual_dur[task] = duration;\n            cur_task[worker] = -1;\n\n            // update skill estimates\n            update_skills(worker, task, duration);\n\n            // update remaining predecessors of successors\n            for (int s : succs[task]) {\n                rem_pred[s]--;\n            }\n        }\n        ++day;\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst int DEPOT_ID = 2000;\nconst int NUM_ORDERS = 1000;\nconst int NUM_SELECT = 50;\nconst int CENTER = 400;\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// Compute total distance of a route (array of node ids)\nint total_distance(const vector<int>& route, const vector<vector<int>>& dist) {\n    int sum = 0;\n    for (size_t i = 0; i + 1 < route.size(); ++i)\n        sum += dist[route[i]][route[i + 1]];\n    return sum;\n}\n\n// Check that for each order, pickup appears before delivery in the route\nbool is_feasible(const vector<int>& route) {\n    vector<int> first(2000, -1), second(2000, -1);\n    for (size_t i = 0; i < route.size(); ++i) {\n        int node = route[i];\n        if (node == DEPOT_ID) continue;\n        int idx = node;\n        if (node % 2 == 0) { // pickup\n            if (first[idx] != -1) return false;\n            first[idx] = (int)i;\n        } else { // delivery\n            if (second[idx] != -1) return false;\n            second[idx] = (int)i;\n        }\n    }\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int p = 2 * i, d = 2 * i + 1;\n        if (first[p] == -1 && second[d] == -1) continue; // order not selected\n        if (first[p] == -1 || second[d] == -1) return false; // incomplete order\n        if (first[p] > second[d]) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    vector<pair<int,int>> pickup(NUM_ORDERS), delivery(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int a, b, c, d;\n        cin >> a >> b >> c >> d;\n        pickup[i] = {a, b};\n        delivery[i] = {c, d};\n    }\n\n    // Node coordinates: order i -> pickup 2*i, delivery 2*i+1, depot = 2000\n    vector<int> node_x(2001), node_y(2001);\n    node_x[DEPOT_ID] = node_y[DEPOT_ID] = CENTER;\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        node_x[2 * i] = pickup[i].first;\n        node_y[2 * i] = pickup[i].second;\n        node_x[2 * i + 1] = delivery[i].first;\n        node_y[2 * i + 1] = delivery[i].second;\n    }\n\n    // Precompute distance matrix (2001 x 2001)\n    vector<vector<int>> dist(2001, vector<int>(2001));\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist[i][j] = manhattan(node_x[i], node_y[i], node_x[j], node_y[j]);\n\n    // ---------- Phase 1: Select 50 orders ----------\n    // Score used: distance(pickup, depot) + distance(delivery, depot)\n    vector<pair<int,int>> order_score(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int s = dist[2 * i][DEPOT_ID] + dist[2 * i + 1][DEPOT_ID];\n        order_score[i] = {s, i};\n    }\n    sort(order_score.begin(), order_score.end());\n    vector<bool> selected(NUM_ORDERS, false);\n    for (int k = 0; k < NUM_SELECT; ++k)\n        selected[order_score[k].second] = true;\n\n    // ---------- Phase 2: Greedy Cheapest Insertion ----------\n    vector<int> route = {DEPOT_ID, DEPOT_ID};\n    int total = 0;\n    for (int iter = 0; iter < NUM_SELECT; ++iter) {\n        // find the order (among unselected) that minimizes insertion cost\n        int best_o = -1, best_pos = -1, best_inc = INT_MAX;\n        for (int i = 0; i < NUM_ORDERS; ++i) {\n            if (!selected[i]) continue; // already in route? need to track used\n        }\n        // Actually we need to process only the selected orders\n        // Build a list of selected order indices\n    }\n    // Better: use list of selected orders\n    vector<int> order_list;\n    for (auto& p : order_score)\n        if (selected[p.second]) order_list.push_back(p.second);\n\n    for (int o : order_list) {\n        int p = 2 * o;\n        int d = 2 * o + 1;\n        int L = route.size();\n        int best_pos = -1, best_inc = INT_MAX;\n        for (int pos = 0; pos < L - 1; ++pos) {\n            int left = route[pos];\n            int right = route[pos + 1];\n            int inc = -dist[left][right] + dist[left][p] + dist[p][d] + dist[d][right];\n            if (inc < best_inc) {\n                best_inc = inc;\n                best_pos = pos;\n            }\n        }\n        route.insert(route.begin() + best_pos + 1, {p, d});\n        total += best_inc;\n        selected[o] = false; // mark as used (but we iterate each once)\n    }\n    // After insertion, route size = 102 (2 depots + 100 nodes)\n    // Verify feasibility\n    if (!is_feasible(route)) {\n        cerr << \"ERROR: Infeasible initial route\" << endl;\n        return 1;\n    }\n\n    // ---------- Phase 3: Local Search (Simulated Annealing) ----------\n    vector<int> best_route = route;\n    int best_total = total;\n    double temperature = 500.0;\n    double cooling = 0.9999;\n    auto start_time = chrono::steady_clock::now();\n    double elapsed = 0.0;\n    int iteration = 0;\n\n    while (elapsed < 1.9 && iteration < 100000) {\n        ++iteration;\n        // pick random move: 0 = relocate node, 1 = swap two nodes\n        int move_type = rng() % 2;\n        vector<int> new_route = route;\n        int n = (int)new_route.size();\n        // only consider positions 1..n-2 (non-depot)\n        int i = rng() % (n - 2) + 1;\n        int j = rng() % (n - 2) + 1;\n        if (i == j) continue;\n\n        if (move_type == 0) {\n            // relocate node at i to position j\n            int node = new_route[i];\n            new_route.erase(new_route.begin() + i);\n            // adjust j if necessary (since size decreased by 1)\n            if (j > (int)new_route.size()) j = new_route.size();\n            new_route.insert(new_route.begin() + j, node);\n        } else {\n            // swap nodes at i and j\n            swap(new_route[i], new_route[j]);\n        }\n\n        // feasibility check\n        if (!is_feasible(new_route)) continue;\n\n        int new_total = total_distance(new_route, dist);\n        int delta = new_total - total;\n\n        // acceptance criterion\n        if (delta < 0 || (exp(-delta / temperature) > (double)rng() / rng.max())) {\n            route = new_route;\n            total = new_total;\n            if (total < best_total) {\n                best_total = total;\n                best_route = route;\n            }\n        }\n\n        temperature *= cooling;\n        elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    }\n\n    // ---------- Phase 4: Output ----------\n    // Extract order indices in appearance order from best_route\n    vector<int> out_orders;\n    for (int node : best_route) {\n        if (node == DEPOT_ID) continue;\n        int o = node / 2;\n        if (out_orders.empty() || out_orders.back() != o)\n            out_orders.push_back(o);\n    }\n    // Ensure exactly 50 orders\n    if ((int)out_orders.size() != 50) {\n        // fallback: use the initial selected order list\n        out_orders = order_list;\n    }\n\n    cout << 50;\n    for (int o : out_orders) cout << ' ' << o + 1;\n    cout << '\\n';\n\n    cout << best_route.size();\n    for (int node : best_route) {\n        // Safety clamp (should be within [0,800] always)\n        int x = node_x[node];\n        int y = node_y[node];\n        if (x < 0) x = 0; if (x > 800) x = 800;\n        if (y < 0) y = 0; if (y > 800) y = 800;\n        cout << ' ' << x << ' ' << y;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, rank;\n    DSU(int n) {\n        parent.resize(n);\n        rank.resize(n, 0);\n        for (int i = 0; i < n; ++i) parent[i] = i;\n    }\n    int find(int x) {\n        if (parent[x] != x) parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) swap(x, y);\n        parent[y] = x;\n        if (rank[x] == rank[y]) ++rank[x];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    // read vertex coordinates\n    vector<pair<int, int>> coord(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> coord[i].first >> coord[i].second;\n    }\n\n    // read edges (only endpoints)\n    struct Edge { int u, v, d; };\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        int dx = coord[u].first - coord[v].first;\n        int dy = coord[u].second - coord[v].second;\n        double dist = sqrt(dx * dx + dy * dy);\n        int d = round(dist);\n        edges[i] = {u, v, d};\n    }\n\n    // build MST based on the rounded Euclidean distance d\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return edges[a].d < edges[b].d;\n    });\n\n    DSU dsu(N);\n    vector<bool> in_mst(M, false);\n    int accepted = 0;\n    for (int idx : order) {\n        auto &e = edges[idx];\n        if (dsu.unite(e.u, e.v)) {\n            in_mst[idx] = true;\n            ++accepted;\n            if (accepted == N - 1) break;\n        }\n    }\n\n    // online phase \u2013 adopt exactly the edges of the precomputed MST\n    for (int i = 0; i < M; ++i) {\n        long long l;\n        cin >> l;                // read true length\n        if (in_mst[i]) {\n            cout << \"1\\n\";\n        } else {\n            cout << \"0\\n\";\n        }\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int MAXT = 300;\nconst int MAXN = 20;\nconst int MAXM = 10;\n\nint N, M;\nint pet_x[MAXN], pet_y[MAXN], pet_type[MAXN];\nint human_x[MAXM], human_y[MAXM];\n\nbool impassable[GRID+2][GRID+2]; // 1-indexed\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char move_ch[4] = {'U','D','L','R'};\nconst char block_ch[4] = {'u','d','l','r'};\n\ninline bool inside(int x, int y) {\n    return 1 <= x && x <= GRID && 1 <= y && y <= GRID;\n}\n\n// BFS structure\nstruct BFSResult {\n    int area;\n    int pet_cnt;\n    vector<pair<int,int>> boundary; // cells in region with at least one neighbor outside region\n};\n\n// BFS from (sx,sy) on the given impassable grid. Returns area, pet count, and boundary.\nBFSResult bfs(int sx, int sy, const bool tmp_impassable[GRID+2][GRID+2],\n              const int start_pet_x[], const int start_pet_y[]) {\n    static bool visited[GRID+2][GRID+2];\n    static int visited_turn = 0; // timestamp to avoid memset\n    ++visited_turn;\n\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    visited[sx][sy] = true;\n    int area = 1;\n    BFSResult res;\n    res.boundary.clear();\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        // check if this cell is a boundary (any neighbor outside region)\n        bool is_boundary = false;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_impassable[nx][ny]) continue;\n            if (visited[nx][ny] == true) continue; // already visited\n            // neighbor not yet visited: it is inside the region, will be visited later\n        }\n        // Actually, we need to detect boundary: a cell is boundary if at least one adjacent cell is either impassable or outside grid (impassable) or not visited (but will be visited). The boundary definition: cells that have at least one neighbor that is not passable (i.e., impassable or outside). Since we haven't visited all neighbors yet, we can check after BFS.\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny) || tmp_impassable[nx][ny]) {\n                is_boundary = true;\n                break;\n            }\n        }\n        if (is_boundary) res.boundary.push_back({x, y});\n\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_impassable[nx][ny]) continue;\n            if (visited[nx][ny]) continue;\n            visited[nx][ny] = true;\n            q.push({nx, ny});\n            ++area;\n        }\n    }\n\n    // Count pets inside region\n    int pet_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        if (visited[start_pet_x[i]][start_pet_y[i]]) ++pet_cnt;\n    }\n    res.area = area;\n    res.pet_cnt = pet_cnt;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N;\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_x[i] >> pet_y[i] >> pet_type[i];\n    }\n    cin >> M;\n    for (int i = 0; i < M; ++i) {\n        cin >> human_x[i] >> human_y[i];\n    }\n\n    // Initialize impassable (all passable)\n    memset(impassable, 0, sizeof(impassable));\n\n    for (int turn = 0; turn < MAXT; ++turn) {\n        // Record start positions\n        int start_hx[MAXM], start_hy[MAXM];\n        int start_px[MAXN], start_py[MAXN];\n        for (int i = 0; i < M; ++i) {\n            start_hx[i] = human_x[i];\n            start_hy[i] = human_y[i];\n        }\n        for (int i = 0; i < N; ++i) {\n            start_px[i] = pet_x[i];\n            start_py[i] = pet_y[i];\n        }\n\n        // copy current impassable\n        bool cur_impassable[GRID+2][GRID+2];\n        memcpy(cur_impassable, impassable, sizeof(impassable));\n\n        int cur_hx[MAXM], cur_hy[MAXM];\n        memcpy(cur_hx, start_hx, sizeof(int)*M);\n        memcpy(cur_hy, start_hy, sizeof(int)*M);\n\n        char actions[MAXM];\n\n        // Process each human sequentially\n        for (int i = 0; i < M; ++i) {\n            int sx = cur_hx[i], sy = cur_hy[i];\n            BFSResult br = bfs(sx, sy, cur_impassable, start_px, start_py);\n\n            char best_action = '.';\n            // Decide action\n            if (br.pet_cnt > 0) {\n                // Try to block a boundary cell that is adjacent to a pet (outside)\n                // Also try to move away from pets? For now, just try to block.\n                bool found = false;\n                for (auto [bx, by] : br.boundary) {\n                    // Check if this boundary cell is adjacent to any pet (outside region)\n                    bool adj_pet = false;\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = bx + dx[d], ay = by + dy[d];\n                        if (!inside(ax, ay)) continue;\n                        // Check if a pet is at (ax,ay) (start positions)\n                        for (int p = 0; p < N; ++p) {\n                            if (start_px[p] == ax && start_py[p] == ay) {\n                                adj_pet = true;\n                                break;\n                            }\n                        }\n                        if (adj_pet) break;\n                    }\n                    if (adj_pet) {\n                        // We want to block this boundary cell to prevent pet from entering\n                        // Verify block conditions: cell must be passable, not contain human/pet at start, not adjacent to any pet\n                        if (cur_impassable[bx][by]) continue;\n                        // must not contain any start human or pet\n                        bool occupied = false;\n                        for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                        if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                        if (occupied) continue;\n                        // must not be adjacent to any pet (the block rule)\n                        bool adj_pet2 = false;\n                        for (int d = 0; d < 4; ++d) {\n                            int ax = bx + dx[d], ay = by + dy[d];\n                            if (!inside(ax, ay)) continue;\n                            for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet2 = true; break; }\n                            if (adj_pet2) break;\n                        }\n                        if (adj_pet2) continue;\n                        // Found a valid block\n                        // Determine direction relative to human (sx,sy)\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = block_ch[d];\n                                found = true;\n                                break;\n                            }\n                        }\n                        if (found) break;\n                    }\n                }\n                if (!found) {\n                    // If no good block, try to move to a boundary cell that is not adjacent to any pet inside? Just stay.\n                    // Maybe move to a boundary cell to expand region? But region already has pets, moving won't help.\n                    best_action = '.';\n                }\n            } else {\n                // No pet inside region. We want to expand or seal.\n                // First, try to block any boundary cell that is adjacent to an outside pet to prevent entry.\n                bool blocked = false;\n                for (auto [bx, by] : br.boundary) {\n                    // Check adjacent pets (outside region)\n                    bool adj_pet = false;\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = bx + dx[d], ay = by + dy[d];\n                        if (!inside(ax, ay)) continue;\n                        for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet = true; break; }\n                        if (adj_pet) break;\n                    }\n                    if (adj_pet) {\n                        // Try to block this boundary cell\n                        // Check conditions\n                        if (cur_impassable[bx][by]) continue;\n                        bool occupied = false;\n                        for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                        if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                        if (occupied) continue;\n                        bool adj_pet2 = false;\n                        for (int d = 0; d < 4; ++d) {\n                            int ax = bx + dx[d], ay = by + dy[d];\n                            if (!inside(ax, ay)) continue;\n                            for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet2 = true; break; }\n                            if (adj_pet2) break;\n                        }\n                        if (adj_pet2) continue;\n                        // valid block\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = block_ch[d];\n                                blocked = true;\n                                break;\n                            }\n                        }\n                        if (blocked) break;\n                    }\n                }\n                if (!blocked) {\n                    // No pet adjacent to boundary. Try to move to a boundary cell to expand.\n                    // Choose a boundary cell that is not occupied at start, and not adjacent to any pet (to avoid bringing one in).\n                    pair<int,int> best_move = {-1, -1};\n                    for (auto [bx, by] : br.boundary) {\n                        // check if this cell is passable and reachable by move (adjacent to human)\n                        if (abs(bx - sx) + abs(by - sy) == 1 && !cur_impassable[bx][by]) {\n                            // Check not occupied at start\n                            bool occupied = false;\n                            for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                            if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                            if (occupied) continue;\n                            // Check if this boundary cell is adjacent to any pet (outside)\n                            bool adj_pet = false;\n                            for (int d = 0; d < 4; ++d) {\n                                int ax = bx + dx[d], ay = by + dy[d];\n                                if (!inside(ax, ay)) continue;\n                                for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet = true; break; }\n                                if (adj_pet) break;\n                            }\n                            if (adj_pet) continue; // don't move to a cell adjacent to a pet (might bring it in)\n                            // Accept this move\n                            best_move = {bx, by};\n                            break;\n                        }\n                    }\n                    if (best_move.first != -1) {\n                        int bx = best_move.first, by = best_move.second;\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = move_ch[d];\n                                break;\n                            }\n                        }\n                    } else {\n                        // Can't move; try to block a random boundary cell? Or stay.\n                        best_action = '.';\n                    }\n                }\n            }\n\n            // Execute action\n            if (best_action == '.') {\n                // do nothing\n            } else {\n                bool is_move = false;\n                int d = -1;\n                for (int k = 0; k < 4; ++k) {\n                    if (best_action == move_ch[k]) { is_move = true; d = k; break; }\n                    if (best_action == block_ch[k]) { d = k; break; }\n                }\n                int nx = sx + dx[d], ny = sy + dy[d];\n                if (is_move) {\n                    cur_hx[i] = nx;\n                    cur_hy[i] = ny;\n                } else {\n                    cur_impassable[nx][ny] = true;\n                }\n            }\n            actions[i] = best_action;\n        }\n\n        // Output actions\n        for (int i = 0; i < M; ++i) cout << actions[i];\n        cout << endl;\n        cout.flush();\n\n        // Read pet moves\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            if (s == \".\") continue;\n            int x = pet_x[i], y = pet_y[i];\n            for (char c : s) {\n                if (c == 'U') { x -= 1; }\n                else if (c == 'D') { x += 1; }\n                else if (c == 'L') { y -= 1; }\n                else if (c == 'R') { y += 1; }\n            }\n            pet_x[i] = x;\n            pet_y[i] = y;\n        }\n\n        // Update global impassable\n        memcpy(impassable, cur_impassable, sizeof(impassable));\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nint si, sj, ti, tj;\ndouble p;\nvector<string> h(20), v(19);\nint dr[4] = {1, 0, -1, 0};\nint dc[4] = {0, 1, 0, -1};\nchar dir_chars[4] = {'D', 'R', 'U', 'L'};\n\nbool can_move(int i, int j, int d) {\n    int ni = i + dr[d], nj = j + dc[d];\n    if (ni < 0 || ni >= 20 || nj < 0 || nj >= 20) return false;\n    if (d == 0) return v[i][j] == '0';\n    if (d == 1) return h[i][j] == '0';\n    if (d == 2) return v[i-1][j] == '0';\n    return h[i][j-1] == '0';\n}\n\ndouble evaluate(const string &s) {\n    int L = (int)s.size();\n    const int N = 400;\n    vector<double> dp(N, 0.0);\n    // base: after all steps\n    for (int i = 0; i < 20; ++i) for (int j = 0; j < 20; ++j) {\n        int id = i*20+j;\n        if (i == ti && j == tj) dp[id] = 401.0 - L;\n    }\n    for (int t = L-1; t >= 0; --t) {\n        int d = 0;\n        char c = s[t];\n        if (c == 'D') d = 0;\n        else if (c == 'R') d = 1;\n        else if (c == 'U') d = 2;\n        else d = 3;\n        vector<double> ndp(N, 0.0);\n        for (int i = 0; i < 20; ++i) {\n            for (int j = 0; j < 20; ++j) {\n                int id = i*20+j;\n                if (i == ti && j == tj) {\n                    ndp[id] = 401.0 - t;\n                } else {\n                    double val;\n                    if (can_move(i, j, d)) {\n                        int ni = i + dr[d], nj = j + dc[d];\n                        int nid = ni*20+nj;\n                        val = p * dp[id] + (1.0-p) * dp[nid];\n                    } else {\n                        val = dp[id];\n                    }\n                    ndp[id] = val;\n                }\n            }\n        }\n        dp.swap(ndp);\n    }\n    return dp[si*20+sj];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj >> ti >> tj >> p;\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i];\n\n    const int MAX_STEPS = 200;\n    const int N = 400;\n\n    // Precompute optimal adaptive value V[k][id] (using optimal decisions)\n    vector<vector<double>> V(MAX_STEPS+1, vector<double>(N, 0.0));\n    // base k=0\n    for (int i = 0; i < 20; ++i) for (int j = 0; j < 20; ++j) {\n        int id = i*20+j;\n        if (i == ti && j == tj) V[0][id] = 201.0;\n    }\n    for (int k = 1; k <= MAX_STEPS; ++k) {\n        for (int i = 0; i < 20; ++i) {\n            for (int j = 0; j < 20; ++j) {\n                int id = i*20+j;\n                if (i == ti && j == tj) {\n                    V[k][id] = 201.0 + k;\n                    continue;\n                }\n                double best = 0.0;\n                for (int d = 0; d < 4; ++d) {\n                    double val;\n                    if (!can_move(i, j, d)) {\n                        val = V[k-1][id];\n                    } else {\n                        int ni = i+dr[d], nj = j+dc[d];\n                        int nid = ni*20+nj;\n                        val = p * V[k-1][id] + (1.0-p) * V[k-1][nid];\n                    }\n                    if (val > best) best = val;\n                }\n                V[k][id] = best;\n            }\n        }\n    }\n\n    // Greedy construction\n    string ans;\n    vector<double> dist(N, 0.0);\n    dist[si*20+sj] = 1.0;\n\n    for (int step = 0; step < MAX_STEPS; ++step) {\n        int remaining = MAX_STEPS - step - 1;\n        double best_val = -1e100;\n        int best_d = -1;\n        for (int d = 0; d < 4; ++d) {\n            double total = 0.0;\n            for (int id = 0; id < N; ++id) {\n                if (dist[id] == 0.0) continue;\n                int i = id/20, j = id%20;\n                double base;\n                if (can_move(i, j, d)) {\n                    int ni = i+dr[d], nj = j+dc[d];\n                    int nid = ni*20+nj;\n                    base = p * V[remaining][id] + (1.0-p) * V[remaining][nid];\n                } else {\n                    base = V[remaining][id];\n                }\n                total += dist[id] * base;\n            }\n            if (total > best_val) {\n                best_val = total;\n                best_d = d;\n            }\n        }\n        ans.push_back(dir_chars[best_d]);\n\n        // update distribution\n        vector<double> new_dist(N, 0.0);\n        for (int id = 0; id < N; ++id) {\n            if (dist[id] == 0.0) continue;\n            int i = id/20, j = id%20;\n            new_dist[id] += p * dist[id];\n            if (can_move(i, j, best_d)) {\n                int ni = i+dr[best_d], nj = j+dc[best_d];\n                int nid = ni*20+nj;\n                new_dist[nid] += (1.0-p) * dist[id];\n            } else {\n                new_dist[id] += (1.0-p) * dist[id];\n            }\n        }\n        dist.swap(new_dist);\n    }\n\n    double current_score = evaluate(ans);\n\n    // Hill climbing (single character changes)\n    const int HILL_CLIMB_PASSES = 5;\n    for (int pass = 0; pass < HILL_CLIMB_PASSES; ++pass) {\n        bool improved = false;\n        for (int pos = 0; pos < MAX_STEPS; ++pos) {\n            char orig = ans[pos];\n            double best_local = current_score;\n            int best_d = -1;\n            for (int d = 0; d < 4; ++d) {\n                char nc = dir_chars[d];\n                if (nc == orig) continue;\n                ans[pos] = nc;\n                double score = evaluate(ans);\n                if (score > best_local + 1e-12) {\n                    best_local = score;\n                    best_d = d;\n                }\n                ans[pos] = orig;\n            }\n            if (best_d != -1) {\n                ans[pos] = dir_chars[best_d];\n                current_score = best_local;\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Random perturbations (swapping two positions)\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int iter = 0; iter < 200; ++iter) {\n        int a = uniform_int_distribution<int>(0, MAX_STEPS-1)(rng);\n        int b = uniform_int_distribution<int>(0, MAX_STEPS-1)(rng);\n        if (a == b) continue;\n        swap(ans[a], ans[b]);\n        double score = evaluate(ans);\n        if (score > current_score + 1e-12) {\n            current_score = score;\n        } else {\n            swap(ans[a], ans[b]);\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nconst int N = 30;\nconst int M = N * N;  // 900\nconst int H = M * 4;  // number of half-edges\n\n// direction arrays: 0:left, 1:up, 2:right, 3:down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to[t][d] = exit direction when entering tile t from direction d, -1 if invalid\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0\n    {3, -1, -1, 0},  // 1\n    {-1, -1, 3, 2},  // 2\n    {-1, 2, 1, -1},  // 3\n    {1, 0, 3, 2},    // 4\n    {3, 2, 1, 0},    // 5\n    {2, -1, 0, -1},  // 6\n    {-1, 3, -1, 1}   // 7\n};\n\n// precomputed rotated tile types\nint rot_type[8][4];\n\nint evaluate(const int* state) {\n    static int visited[H];\n    static int gen = 0;\n    ++gen;  // new generation\n    int best = 0, second = 0;\n\n    for (int idx = 0; idx < M; ++idx) {\n        int t = state[idx];\n        int i = idx / N, j = idx % N;\n        for (int d = 0; d < 4; ++d) {\n            if (to[t][d] == -1) continue;\n            int he = (idx << 2) | d;\n            if (visited[he] == gen) continue;\n\n            // trace this path\n            int ci = i, cj = j, cd = d;\n            int len = 0;\n            bool is_cycle = false;\n            while (true) {\n                int cur_he = (ci * N + cj) * 4 + cd;\n                visited[cur_he] = gen;\n                int d2 = to[state[ci * N + cj]][cd];\n                if (d2 == -1) break;\n                int ni = ci + di[d2];\n                int nj = cj + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                cd = (d2 + 2) & 3;\n                ci = ni;\n                cj = nj;\n                ++len;\n                if (ci == i && cj == j && cd == d) {\n                    is_cycle = true;\n                    break;\n                }\n            }\n            if (is_cycle) {\n                if (len > best) {\n                    second = best;\n                    best = len;\n                } else if (len > second) {\n                    second = len;\n                }\n            }\n        }\n    }\n    return best * second;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // precompute rotated tile types\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            if (t < 4) rot_type[t][r] = (t + r) % 4;\n            else if (t < 6) rot_type[t][r] = 4 + ((t - 4 + r) % 2);\n            else rot_type[t][r] = 6 + ((t - 6 + r) % 2);\n        }\n    }\n\n    // read original tile types\n    vector<int> orig(M);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            orig[i * N + j] = s[j] - '0';\n        }\n    }\n\n    // random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist4(0, 3);\n    uniform_int_distribution<int> dist900(0, M - 1);\n\n    // current and best state\n    vector<int> state(M), rot(M);\n    vector<int> best_rot(M);\n    int best_score = 0;\n\n    // Phase 1: many random trials (reduced number, using fast evaluate with timestamp)\n    const int TRIALS = 20000;\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // early time check every 2000 trials\n        if (trial % 2000 == 0) {\n            static auto start = chrono::steady_clock::now();\n            auto now = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start).count();\n            if (elapsed > 1200) break; // leave time for phase 2\n        }\n        for (int i = 0; i < M; ++i) {\n            int r = dist4(rng);\n            rot[i] = r;\n            state[i] = rot_type[orig[i]][r];\n        }\n        int score = evaluate(state.data());\n        if (score > best_score) {\n            best_score = score;\n            best_rot = rot;\n        }\n    }\n\n    // Phase 2: greedy hill climbing on best found\n    // restore best state\n    for (int i = 0; i < M; ++i) {\n        rot[i] = best_rot[i];\n        state[i] = rot_type[orig[i]][rot[i]];\n    }\n    int cur_score = best_score;\n\n    // greedy passes: try all rotations for each tile, keep if improves\n    bool improved = true;\n    int pass = 0;\n    while (improved && pass < 30) { // limit passes\n        improved = false;\n        ++pass;\n        // random order to avoid bias\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            int r_old = rot[idx];\n            int best_val = cur_score;\n            int best_r = r_old;\n            for (int r = 0; r < 4; ++r) {\n                if (r == r_old) continue;\n                int new_s = rot_type[orig[idx]][r];\n                state[idx] = new_s;\n                int val = evaluate(state.data());\n                if (val > best_val) {\n                    best_val = val;\n                    best_r = r;\n                }\n            }\n            if (best_val > cur_score) {\n                cur_score = best_val;\n                rot[idx] = best_r;\n                state[idx] = rot_type[orig[idx]][best_r];\n                improved = true;\n                if (best_val > best_score) {\n                    best_score = best_val;\n                    best_rot = rot;\n                }\n            } else {\n                // restore\n                state[idx] = rot_type[orig[idx]][r_old];\n            }\n        }\n        // quick time check after each pass\n        static auto start2 = chrono::steady_clock::now();\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start2).count();\n        if (elapsed > 1900) break;\n    }\n\n    // output best rotation string\n    for (int i = 0; i < M; ++i) cout << best_rot[i];\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- union-find (identical to before) ----------\nstruct DSU {\n    vector<int> parent, sz, edges;\n    DSU(int n) : parent(n), sz(n, 1), edges(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (x != parent[x]) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) {\n            edges[a]++;\n            return;\n        }\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        edges[a] += edges[b] + 1;\n    }\n};\n\nint largest_tree(const vector<int>& board, int N) {\n    DSU dsu(N * N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            int tile = board[id];\n            if (tile == 0) continue;\n            // right\n            if (j + 1 < N && board[id + 1] != 0 &&\n                (tile & 4) && (board[id + 1] & 1)) {\n                dsu.unite(id, id + 1);\n            }\n            // down\n            if (i + 1 < N && board[id + N] != 0 &&\n                (tile & 8) && (board[id + N] & 2)) {\n                dsu.unite(id, id + N);\n            }\n        }\n    }\n    int best = 0;\n    for (int i = 0; i < N * N; ++i) {\n        if (board[i] == 0) continue;\n        if (dsu.find(i) == i) {\n            if (dsu.edges[i] == dsu.sz[i] - 1) {\n                best = max(best, dsu.sz[i]);\n            }\n        }\n    }\n    return best;\n}\n\n// ---------- beam search ----------\nstruct State {\n    vector<int> board;\n    int ei, ej;\n    string moves;\n    int score; // largest tree size\n\n    bool operator<(const State& o) const {\n        if (score != o.score) return score > o.score;\n        return moves.size() < o.moves.size();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    int total_cells = N * N;\n    int full = total_cells - 1;\n\n    vector<string> raw(N);\n    vector<int> init_board(total_cells);\n    int ei = -1, ej = -1;\n    for (int i = 0; i < N; ++i) {\n        cin >> raw[i];\n        for (int j = 0; j < N; ++j) {\n            char c = raw[i][j];\n            int val;\n            if (isdigit(c)) val = c - '0';\n            else val = 10 + (c - 'a');\n            init_board[i * N + j] = val;\n            if (val == 0) { ei = i; ej = j; }\n        }\n    }\n\n    int init_score = largest_tree(init_board, N);\n    if (init_score == full) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    const char dir_ch[] = {'U', 'D', 'L', 'R'};\n\n    // beam width\n    const int BEAM_WIDTH = 30;\n\n    vector<State> cur;\n    cur.push_back({init_board, ei, ej, \"\", init_score});\n\n    int best_score = init_score;\n    string best_moves = \"\";\n\n    unordered_set<size_t> seen_this_step;\n\n    for (int step = 0; step < T; ++step) {\n        if (best_score == full) break;\n\n        vector<State> candidates;\n        seen_this_step.clear();\n\n        for (auto& s : cur) {\n            for (int d = 0; d < 4; ++d) {\n                int ni = s.ei + di[d];\n                int nj = s.ej + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n\n                // apply move\n                vector<int> nb = s.board;\n                int src_id = s.ei * N + s.ej;\n                int dst_id = ni * N + nj;\n                swap(nb[src_id], nb[dst_id]);\n\n                // hash to avoid duplicates in this step\n                size_t h = 0;\n                for (int v : nb) h = h * 1000000007 + v; // simple hash\n                if (seen_this_step.count(h)) continue;\n                seen_this_step.insert(h);\n\n                int new_score = largest_tree(nb, N);\n                string new_moves = s.moves + dir_ch[d];\n                if ((int)new_moves.size() > T) continue;\n\n                candidates.push_back({move(nb), ni, nj, move(new_moves), new_score});\n\n                if (new_score > best_score) {\n                    best_score = new_score;\n                    best_moves = s.moves + dir_ch[d];\n                    if (best_score == full) break; // found perfect solution\n                }\n            }\n            if (best_score == full) break;\n        }\n\n        if (best_score == full) break;\n\n        if (candidates.empty()) break;\n\n        // sort and keep best\n        sort(candidates.begin(), candidates.end());\n        if ((int)candidates.size() > BEAM_WIDTH)\n            candidates.resize(BEAM_WIDTH);\n        cur.swap(candidates);\n    }\n\n    if (best_score == full) {\n        cout << best_moves << endl;\n    } else {\n        // if not full, output the best found\n        cout << best_moves << endl;\n    }\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nusing ll = long long;\nusing i128 = __int128_t;\nconst ll R = 10000;\nconst ll R_SQ = (ll)R * R;\n\nstruct Line {\n    ll px, py, qx, qy;\n};\n\n// Check if line cuts the circle (distance from origin < R)\nbool lineCutsCircle(const Line& l) {\n    ll dx = l.qx - l.px;\n    ll dy = l.qy - l.py;\n    if (dx == 0 && dy == 0) return false;\n    i128 cross = (i128)dx * l.py - (i128)dy * l.px;\n    i128 dsq = (i128)dx * dx + (i128)dy * dy;\n    i128 left = cross * cross;\n    i128 right = R_SQ * dsq;\n    return left < right;\n}\n\n// Generate a random line that cuts the circle\nLine genRandomLine(mt19937& rng) {\n    static uniform_int_distribution<ll> dist(-20000, 20000);\n    while (true) {\n        ll px = dist(rng), py = dist(rng);\n        ll qx = dist(rng), qy = dist(rng);\n        if (px == qx && py == qy) continue;\n        Line l{px, py, qx, qy};\n        if (lineCutsCircle(l)) return l;\n    }\n}\n\n// Evaluate score from a set of lines and point masks (final)\nint evaluateFromMasks(const vector<pair<uint64_t,uint64_t>>& masks, const int a[11]) {\n    int n = masks.size();\n    vector<pair<uint64_t,uint64_t>> sorted(masks.begin(), masks.end());\n    sort(sorted.begin(), sorted.end());\n    int b[11] = {0};\n    for (int i = 0; i < n; ) {\n        int j = i;\n        while (j < n && sorted[j] == sorted[i]) ++j;\n        int cnt = j - i;\n        if (cnt >= 1 && cnt <= 10) b[cnt]++;\n        i = j;\n    }\n    int tot = 0;\n    for (int d = 1; d <= 10; ++d) tot += min(a[d], b[d]);\n    return tot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    for (int d = 1; d <= 10; ++d) cin >> a[d];\n    vector<pair<int,int>> pts(N);\n    for (int i = 0; i < N; ++i) cin >> pts[i].first >> pts[i].second;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Current masks for each point (low and high parts)\n    vector<uint64_t> mask_low(N, 0), mask_high(N, 0);\n    // Current lines\n    vector<Line> lines;\n    // Temporary array for new masks (reused)\n    vector<pair<uint64_t,uint64_t>> new_masks(N);\n\n    const int TRIALS = 60;          // number of candidate lines per step\n    const int MAX_LINES = min(K, 100); // K is 100, but we may stop early\n\n    for (int step = 0; step < MAX_LINES; ++step) {\n        int best_score = -1;\n        Line best_line;\n        bool found = false;\n\n        // Try candidate lines\n        for (int t = 0; t < TRIALS; ++t) {\n            Line cand = genRandomLine(rng);\n            ll dx = cand.qx - cand.px;\n            ll dy = cand.qy - cand.py;\n            bool valid = true;\n\n            // Compute new masks\n            for (int i = 0; i < N; ++i) {\n                ll cross = dx * (pts[i].second - cand.py) - dy * (pts[i].first - cand.px);\n                if (cross == 0) { valid = false; break; }\n                int side = (cross > 0) ? 1 : 0;\n                uint64_t new_low = mask_low[i];\n                uint64_t new_high = mask_high[i];\n                if (step < 64) {\n                    new_low |= (uint64_t)side << step;\n                } else {\n                    new_high |= (uint64_t)side << (step - 64);\n                }\n                new_masks[i] = {new_low, new_high};\n            }\n            if (!valid) continue;\n\n            // Sort and compute b_d\n            sort(new_masks.begin(), new_masks.end());\n            int b[11] = {0};\n            for (int i = 0; i < N; ) {\n                int j = i;\n                while (j < N && new_masks[j] == new_masks[i]) ++j;\n                int cnt = j - i;\n                if (cnt >= 1 && cnt <= 10) b[cnt]++;\n                i = j;\n            }\n            int score = 0;\n            for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n\n            if (score > best_score) {\n                best_score = score;\n                best_line = cand;\n                found = true;\n            }\n        }\n\n        // If no improvement, stop\n        if (!found || best_score <= evaluateFromMasks(new_masks, a)) {\n            // Here we need current score; but we can break if no improvement\n            // However, we don't have current score easily. Since we didn't update masks yet,\n            // we need to compute current score. We'll compute it once.\n            // Since this is only for stopping condition, we can compute after each step.\n            // For simplicity, we break if no line was found.\n            break;\n        }\n\n        // Add the best line\n        lines.push_back(best_line);\n        // Update masks globally\n        ll dx = best_line.qx - best_line.px;\n        ll dy = best_line.qy - best_line.py;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (pts[i].second - best_line.py) - dy * (pts[i].first - best_line.px);\n            int side = (cross > 0) ? 1 : 0;\n            if (step < 64) {\n                mask_low[i] |= (uint64_t)side << step;\n            } else {\n                mask_high[i] |= (uint64_t)side << (step - 64);\n            }\n        }\n    }\n\n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const auto& l : lines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 61;\nint N, M;\nbool dot[MAXN][MAXN];\nvector<int> rowDots[MAXN];      // by y, sorted x\nvector<int> colDots[MAXN];      // by x, sorted y\nvector<int> diag1Dots[2*MAXN];  // index = y - x + N-1, sorted x\nvector<int> diag2Dots[2*MAXN];  // index = y + x, sorted x\n\nint64_t weight[MAXN][MAXN];\nvector<pair<int,int>> sortedPoints; // by weight descending\n\n// ---------- Unit edge management (set of keys) ----------\nusing u64 = uint64_t;\nunordered_set<u64> usedEdges;\n\nenum EdgeType { H=0, V=1, D1=2, D2=3 };\n\ninline u64 makeKey(int type, int x, int y) {\n    return ((u64)type << 20) | ((u64)x << 10) | (u64)y;\n}\n\nvoid genH(int x1, int y, int x2, vector<u64>& out) {\n    int step = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += step) {\n        int ux = min(x, x+step);\n        out.push_back(makeKey(H, ux, y));\n    }\n}\nvoid genV(int x, int y1, int y2, vector<u64>& out) {\n    int step = (y2 > y1) ? 1 : -1;\n    for (int y = y1; y != y2; y += step) {\n        int uy = min(y, y+step);\n        out.push_back(makeKey(V, x, uy));\n    }\n}\nvoid genD1(int x1, int y1, int x2, int /*y2*/, vector<u64>& out) {\n    int dx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += dx) {\n        int y = y1 + (x - x1);\n        int ux = min(x, x+dx);\n        int uy = min(y, y+dx);\n        out.push_back(makeKey(D1, ux, uy));\n    }\n}\nvoid genD2(int x1, int y1, int x2, int /*y2*/, vector<u64>& out) {\n    int dx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += dx) {\n        int y = y1 - (x - x1);\n        int ux = min(x, x+dx);\n        int uy = min(y, y-dx);\n        out.push_back(makeKey(D2, ux, uy));\n    }\n}\n\nbool checkEdges(const vector<u64>& edges) {\n    for (auto e : edges) if (usedEdges.count(e)) return false;\n    return true;\n}\nvoid insertEdges(const vector<u64>& edges) {\n    for (auto e : edges) usedEdges.insert(e);\n}\n\n// ---------- Checks for dots on line segments ----------\ninline bool hasDotRow(int y, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = rowDots[y];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotCol(int x, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = colDots[x];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotDiag1(int c, int lx, int rx) {\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag1Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\ninline bool hasDotDiag2(int c, int lx, int rx) {\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag2Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\n\n// ---------- Try to place a dot at (x,y) ----------\nbool tryPlace(int x, int y, int rect[4][2], vector<u64>& outEdges) {\n    outEdges.clear();\n\n    // ----- Axis\u2011aligned rectangles -----\n    {\n        const auto& row = rowDots[y];\n        const auto& col = colDots[x];\n        for (int x2 : row) {\n            if (x2 == x) continue;\n            int xmin = min(x,x2), xmax = max(x,x2);\n            for (int y4 : col) {\n                if (y4 == y) continue;\n                if (!dot[x2][y4]) continue;\n                int ymin = min(y,y4), ymax = max(y,y4);\n\n                // check dots on perimeter\n                if (hasDotRow(y, xmin, xmax)) continue;\n                if (hasDotRow(y4, xmin, xmax)) continue;\n                if (hasDotCol(x, ymin, ymax)) continue;\n                if (hasDotCol(x2, ymin, ymax)) continue;\n\n                // check unit edges\n                vector<u64> edges;\n                genH(x, y, x2, edges);\n                genV(x2, y, y4, edges);\n                genH(x, y4, x2, edges); // p4 -> p3 (x,y4) to (x2,y4)\n                genV(x, y, y4, edges); // p4->p1? Actually p4->p1: same x, from y4 to y\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y;\n                rect[2][0]=x2; rect[2][1]=y4;\n                rect[3][0]=x; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    // ----- Diagonal type1: p1->p2 slope=1, p2->p3 slope=-1 -----\n    {\n        int c1 = y - x + N-1;  // diag1 constant\n        int c2 = y + x;        // diag2 constant\n        for (int x2 : diag1Dots[c1]) {\n            if (x2 == x) continue;\n            int y2 = x2 + (y - x); // on diag1\n            for (int x4 : diag2Dots[c2]) {\n                if (x4 == x) continue;\n                int y4 = c2 - x4; // on diag2\n                int x3 = x2 + (x4 - x);\n                int y3 = y2 - (x4 - x);\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n\n                // check dots on perimeter\n                int lx12 = min(x,x2), rx12 = max(x,x2);\n                if (hasDotDiag1(c1, lx12, rx12)) continue;\n                int c23 = y2 + x2;\n                int lx23 = min(x2,x3), rx23 = max(x2,x3);\n                if (hasDotDiag2(c23, lx23, rx23)) continue;\n                int c34 = y3 - x3 + N-1;\n                int lx34 = min(x3,x4), rx34 = max(x3,x4);\n                if (hasDotDiag1(c34, lx34, rx34)) continue;\n                int c41 = y4 + x4;\n                int lx41 = min(x4,x), rx41 = max(x4,x);\n                if (hasDotDiag2(c41, lx41, rx41)) continue;\n\n                // check unit edges\n                vector<u64> edges;\n                genD1(x,y,x2,y2, edges);\n                genD2(x2,y2,x3,y3, edges);\n                genD1(x3,y3,x4,y4, edges);\n                genD2(x4,y4,x,y, edges);\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y2;\n                rect[2][0]=x3; rect[2][1]=y3;\n                rect[3][0]=x4; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    // ----- Diagonal type2: p1->p2 slope=-1, p2->p3 slope=1 -----\n    {\n        int c1 = y - x + N-1;\n        int c2 = y + x;\n        for (int x2 : diag2Dots[c2]) {\n            if (x2 == x) continue;\n            int y2 = c2 - x2; // on diag2\n            for (int x4 : diag1Dots[c1]) {\n                if (x4 == x) continue;\n                int y4 = x4 + (y - x); // on diag1\n                int x3 = x2 + (x4 - x);\n                int y3 = y2 + (x4 - x);\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n\n                int lx12 = min(x,x2), rx12 = max(x,x2);\n                if (hasDotDiag2(c2, lx12, rx12)) continue;\n                int c23 = y2 - x2 + N-1;\n                int lx23 = min(x2,x3), rx23 = max(x2,x3);\n                if (hasDotDiag1(c23, lx23, rx23)) continue;\n                int c34 = y3 + x3;\n                int lx34 = min(x3,x4), rx34 = max(x3,x4);\n                if (hasDotDiag2(c34, lx34, rx34)) continue;\n                int c41 = y4 - x4 + N-1;\n                int lx41 = min(x4,x), rx41 = max(x4,x);\n                if (hasDotDiag1(c41, lx41, rx41)) continue;\n\n                vector<u64> edges;\n                genD2(x,y,x2,y2, edges);\n                genD1(x2,y2,x3,y3, edges);\n                genD2(x3,y3,x4,y4, edges);\n                genD1(x4,y4,x,y, edges);\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y2;\n                rect[2][0]=x3; rect[2][1]=y3;\n                rect[3][0]=x4; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n\nvoid placeDot(int x, int y) {\n    dot[x][y] = true;\n    auto ins = [](vector<int>& v, int val) {\n        v.insert(lower_bound(v.begin(), v.end(), val), val);\n    };\n    ins(rowDots[y], x);\n    ins(colDots[x], y);\n    ins(diag1Dots[y - x + N-1], x);\n    ins(diag2Dots[y + x], x);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    for (int i=0; i<N; ++i)\n        for (int j=0; j<N; ++j)\n            dot[i][j] = false;\n    for (int i=0; i<M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        placeDot(x, y);\n    }\n    int c = (N-1)/2;\n    for (int y=0; y<N; ++y) {\n        for (int x=0; x<N; ++x) {\n            weight[x][y] = (x-c)*(x-c) + (y-c)*(y-c) + 1;\n            sortedPoints.emplace_back(x, y);\n        }\n    }\n    sort(sortedPoints.begin(), sortedPoints.end(),\n         [](const pair<int,int>& a, const pair<int,int>& b) {\n             return weight[a.first][a.second] > weight[b.first][b.second];\n         });\n\n    vector<array<int,8>> operations;\n    vector<u64> edgeBuffer;\n    while (true) {\n        bool placed = false;\n        int rect[4][2];\n        for (const auto& p : sortedPoints) {\n            int x = p.first, y = p.second;\n            if (dot[x][y]) continue;\n            if (tryPlace(x, y, rect, edgeBuffer)) {\n                // perform operation\n                placeDot(rect[0][0], rect[0][1]);\n                insertEdges(edgeBuffer);\n                operations.push_back({rect[0][0], rect[0][1],\n                                      rect[1][0], rect[1][1],\n                                      rect[2][0], rect[2][1],\n                                      rect[3][0], rect[3][1]});\n                placed = true;\n                break;\n            }\n        }\n        if (!placed) break;\n    }\n    cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        for (int i=0; i<8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\nconst int SIZE = N * N;\n\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\n\n// Tilt the box in the given direction.\narray<int, SIZE> tilt(const array<int, SIZE>& g, char dir) {\n    array<int, SIZE> ng = {0};\n    if (dir == 'F') {\n        for (int j = 0; j < N; ++j) {\n            int r = 0;\n            for (int i = 0; i < N; ++i)\n                if (g[i * N + j]) ng[(r++) * N + j] = g[i * N + j];\n        }\n    } else if (dir == 'B') {\n        for (int j = 0; j < N; ++j) {\n            int r = N - 1;\n            for (int i = N - 1; i >= 0; --i)\n                if (g[i * N + j]) ng[(r--) * N + j] = g[i * N + j];\n        }\n    } else if (dir == 'L') {\n        for (int i = 0; i < N; ++i) {\n            int c = 0;\n            for (int j = 0; j < N; ++j)\n                if (g[i * N + j]) ng[i * N + (c++)] = g[i * N + j];\n        }\n    } else { // 'R'\n        for (int i = 0; i < N; ++i) {\n            int c = N - 1;\n            for (int j = N - 1; j >= 0; --j)\n                if (g[i * N + j]) ng[i * N + (c--)] = g[i * N + j];\n        }\n    }\n    return ng;\n}\n\n// Compute the sum of squares of connected component sizes.\nint compute_score(const array<int, SIZE>& g) {\n    bool vis[SIZE] = {false};\n    int total = 0;\n    vector<int> stk;\n    stk.reserve(SIZE);\n    for (int idx = 0; idx < SIZE; ++idx) {\n        if (g[idx] && !vis[idx]) {\n            int flavor = g[idx];\n            int cnt = 0;\n            stk.push_back(idx);\n            vis[idx] = true;\n            while (!stk.empty()) {\n                int cur = stk.back();\n                stk.pop_back();\n                ++cnt;\n                int x = cur / N, y = cur % N;\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        int nidx = nx * N + ny;\n                        if (!vis[nidx] && g[nidx] == flavor) {\n                            vis[nidx] = true;\n                            stk.push_back(nidx);\n                        }\n                    }\n                }\n            }\n            total += cnt * cnt;\n        }\n    }\n    return total;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> flavors(100);\n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n\n    array<int, SIZE> grid = {0};\n    const char dirs[4] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n\n        // Place the t-th candy at the p-th empty cell.\n        int zero_cnt = 0;\n        for (int i = 0; i < SIZE; ++i) {\n            if (grid[i] == 0) {\n                ++zero_cnt;\n                if (zero_cnt == p) {\n                    grid[i] = flavors[t];\n                    break;\n                }\n            }\n        }\n\n        // For the 100th candy we can skip the tilt.\n        if (t == 99) {\n            cout << \"F\\n\" << flush;\n            break;\n        }\n\n        // Evaluate each tilt direction using a one\u2011step lookahead.\n        char best_dir = 'F';\n        double best_val = -1e18;\n\n        for (char d : dirs) {\n            auto after_tilt = tilt(grid, d);\n\n            // Collect empty cells in this state.\n            vector<int> empties;\n            for (int i = 0; i < SIZE; ++i)\n                if (after_tilt[i] == 0) empties.push_back(i);\n            int M = empties.size();\n\n            // Sample at most 10 random placements to estimate future score.\n            int sample = min(M, 10);\n            shuffle(empties.begin(), empties.end(), rng);\n            long long sum_best = 0;\n\n            for (int s = 0; s < sample; ++s) {\n                auto next_grid = after_tilt;\n                next_grid[empties[s]] = flavors[t + 1];\n\n                int best_next = 0;\n                for (char d2 : dirs) {\n                    auto g2 = tilt(next_grid, d2);\n                    best_next = max(best_next, compute_score(g2));\n                }\n                sum_best += best_next;\n            }\n\n            double avg = (double)sum_best / sample;\n            if (avg > best_val) {\n                best_val = avg;\n                best_dir = d;\n            }\n        }\n\n        // Apply the chosen tilt.\n        grid = tilt(grid, best_dir);\n        cout << best_dir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n#include <cstdint>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    // Choose smallest N such that number of unlabeled graphs >= M\n    int N;\n    if (M <= 11) N = 4;\n    else if (M <= 34) N = 5;\n    else N = 6;   // 156 graphs, enough for M <= 100\n\n    int L = N * (N - 1) / 2;\n    const int total_masks = 1 << L;\n\n    // Precompute all permutations once\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    vector<vector<uint8_t>> perms_bit;  // each permutation-> mapping original bit -> new bit\n    vector<vector<int>> perms_order;    // actual permutation array for later use (not needed)\n    {\n        vector<int> p(N);\n        iota(p.begin(), p.end(), 0);\n        do {\n            // Precompute bit_perm[orig_index] = new_index\n            vector<uint8_t> bit_perm(L);\n            int ptr = 0;\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    int u = p[i], v = p[j];\n                    if (u > v) swap(u, v);\n                    // (u,v) is the edge in original labeling\n                    // Its index in the original bit order is: u*(2*N-u-1)/2 + (v-u-1)\n                    int idx = u * (2*N - u - 1) / 2 + (v - u - 1);\n                    bit_perm[ptr] = (uint8_t)idx;\n                    ++ptr;\n                }\n            }\n            perms_bit.push_back(bit_perm);\n        } while (next_permutation(p.begin(), p.end()));\n    }\n\n    // Compute canonical mask for every possible mask (graph)\n    vector<uint16_t> can_mask(total_masks);\n    {\n        for (int mask = 0; mask < total_masks; ++mask) {\n            uint16_t best = UINT16_MAX;\n            for (const auto& bit_perm : perms_bit) {\n                uint16_t new_mask = 0;\n                // iterate over each original bit\n                for (int k = 0; k < L; ++k) {\n                    if ((mask >> k) & 1) {\n                        new_mask |= (1 << bit_perm[k]);\n                    }\n                }\n                if (new_mask < best) best = new_mask;\n            }\n            can_mask[mask] = best;\n        }\n    }\n\n    // Collect all distinct canonical masks\n    unordered_map<uint16_t, int> canon_to_idx;\n    vector<uint16_t> canonical_masks;\n    for (int m = 0; m < total_masks; ++m) {\n        uint16_t cm = can_mask[m];\n        if (canon_to_idx.find(cm) == canon_to_idx.end()) {\n            int id = (int)canonical_masks.size();\n            canon_to_idx[cm] = id;\n            canonical_masks.push_back(cm);\n        }\n    }\n    int K = (int)canonical_masks.size(); // number of unlabeled graphs\n\n    // Greedy selection of M graphs maximizing minimum Hamming distance\n    // Precompute distances between canonical masks\n    vector<vector<int>> dist(K, vector<int>(K, 0));\n    for (int i = 0; i < K; ++i) {\n        for (int j = i + 1; j < K; ++j) {\n            int d = __builtin_popcount(canonical_masks[i] ^ canonical_masks[j]);\n            dist[i][j] = dist[j][i] = d;\n        }\n    }\n\n    vector<int> selected;\n    vector<bool> used(K, false);\n    // start with the mask having largest total distance? simple: start with index 0\n    selected.push_back(0);\n    used[0] = true;\n    while ((int)selected.size() < M) {\n        int best_idx = -1;\n        int best_min = -1;\n        for (int i = 0; i < K; ++i) {\n            if (used[i]) continue;\n            int cur_min = L + 1;\n            for (int j : selected) {\n                if (dist[i][j] < cur_min) cur_min = dist[i][j];\n            }\n            if (cur_min > best_min) {\n                best_min = cur_min;\n                best_idx = i;\n            }\n        }\n        selected.push_back(best_idx);\n        used[best_idx] = true;\n    }\n\n    // Build lookup table: for each canonical mask, the index of nearest selected mask\n    vector<int> lookup(total_masks, 0); // total_masks <= 2^15 = 32768\n    for (int cm = 0; cm < total_masks; ++cm) {\n        int best_d = L + 1;\n        int best_idx = 0;\n        for (int i = 0; i < M; ++i) {\n            int d = __builtin_popcount(cm ^ canonical_masks[selected[i]]);\n            if (d < best_d) {\n                best_d = d;\n                best_idx = i;\n            }\n        }\n        lookup[cm] = best_idx;\n    }\n\n    // Output\n    cout << N << '\\n';\n    for (int idx : selected) {\n        uint16_t mask = canonical_masks[idx];\n        string s;\n        for (int b = 0; b < L; ++b) {\n            s.push_back(((mask >> b) & 1) ? '1' : '0');\n        }\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // Process queries\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n        int mask = 0;\n        for (int b = 0; b < L; ++b) {\n            if (H[b] == '1') mask |= (1 << b);\n        }\n        int canonical = can_mask[mask];\n        int ans = lookup[canonical];\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nconst ll INF = 1e18;\n\nstruct Neighbor {\n    int to, weight, idx;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<tuple<int,int,int>> edges(M); // u, v, w\n    vector<vector<Neighbor>> g(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u, v, w};\n        g[u].push_back({v, w, i});\n        g[v].push_back({u, w, i});\n    }\n\n    // skip vertex coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. edge betweenness centrality (Brandes) ----------\n    vector<ld> betweenness(M, 0.0);\n    for (int s = 0; s < N; ++s) {\n        vector<ll> dist(N, INF);\n        vector<ld> cnt(N, 0.0);\n        vector<vector<pair<int,int>>> pred(N); // (prev, edge_idx)\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        dist[s] = 0;\n        cnt[s] = 1.0;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            for (const auto& nb : g[u]) {\n                int v = nb.to;\n                ll nd = d + nb.weight;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    cnt[v] = cnt[u];\n                    pred[v].clear();\n                    pred[v].emplace_back(u, nb.idx);\n                    pq.emplace(nd, v);\n                } else if (nd == dist[v]) {\n                    cnt[v] += cnt[u];\n                    pred[v].emplace_back(u, nb.idx);\n                }\n            }\n        }\n\n        // collect reachable vertices ordered by distance\n        vector<int> order;\n        for (int i = 0; i < N; ++i)\n            if (dist[i] < INF)\n                order.push_back(i);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return dist[a] < dist[b];\n        });\n\n        vector<ld> dep(N, 0.0);\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int v = order[i];\n            if (v == s) continue;\n            if (pred[v].empty()) continue;\n            ld sigma_v = cnt[v];\n            for (auto [p, eidx] : pred[v]) {\n                ld contrib = (cnt[p] / sigma_v) * (1.0 + dep[v]);\n                dep[p] += contrib;\n                betweenness[eidx] += contrib;\n            }\n        }\n    }\n\n    // ---------- 2. alternative path cost for each edge ----------\n    vector<ll> alt_cost(M, INF);\n    for (int e = 0; e < M; ++e) {\n        auto [u, v, w] = edges[e];\n        vector<ll> dist(N, INF);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        dist[u] = 0;\n        pq.emplace(0, u);\n        while (!pq.empty()) {\n            auto [d, x] = pq.top();\n            pq.pop();\n            if (d != dist[x]) continue;\n            if (x == v) break;\n            for (const auto& nb : g[x]) {\n                if (nb.idx == e) continue;\n                ll nd = d + nb.weight;\n                if (nd < dist[nb.to]) {\n                    dist[nb.to] = nd;\n                    pq.emplace(nd, nb.to);\n                }\n            }\n        }\n        alt_cost[e] = dist[v];\n    }\n\n    // ---------- 3. edge impact = betweenness * (alt_cost - weight) ----------\n    vector<ld> impact(M);\n    for (int e = 0; e < M; ++e) {\n        auto [u, v, w] = edges[e];\n        if (alt_cost[e] >= INF/2) {\n            impact[e] = betweenness[e] * 1e12;\n        } else {\n            impact[e] = betweenness[e] * (alt_cost[e] - w);\n        }\n    }\n\n    // ---------- 4. initial greedy assignment (load balancing) ----------\n    vector<pair<ld,int>> sorted_edges(M);\n    for (int i = 0; i < M; ++i) sorted_edges[i] = {impact[i], i};\n    sort(sorted_edges.rbegin(), sorted_edges.rend());\n\n    vector<int> day_of_edge(M, -1);\n    vector<ld> day_load(D, 0.0);\n    vector<int> day_cnt(D, 0);\n    vector<vector<int>> day_edges(D);\n\n    for (auto [imp, eidx] : sorted_edges) {\n        int best_day = -1;\n        ld best_load = 1e100;\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_load[d] < best_load) {\n                best_load = day_load[d];\n                best_day = d;\n            }\n        }\n        day_of_edge[eidx] = best_day;\n        day_load[best_day] += imp;\n        day_cnt[best_day]++;\n        day_edges[best_day].push_back(eidx);\n    }\n\n    // ---------- 5. local search (move edges from max-load to min-load) ----------\n    const int MAX_MOVES = 2000;\n    for (int iter = 0; iter < MAX_MOVES; ++iter) {\n        int max_day = -1, min_day = -1;\n        ld max_load = -1e100, min_load = 1e100;\n        for (int d = 0; d < D; ++d) {\n            if (day_load[d] > max_load) { max_load = day_load[d]; max_day = d; }\n            if (day_load[d] < min_load) { min_load = day_load[d]; min_day = d; }\n        }\n        if (max_day == min_day || day_cnt[min_day] >= K) break;\n\n        // find edge with largest impact on max_day\n        int best_edge = -1;\n        ld best_imp = -1e100;\n        for (int eidx : day_edges[max_day]) {\n            if (impact[eidx] > best_imp) {\n                best_imp = impact[eidx];\n                best_edge = eidx;\n            }\n        }\n        if (best_edge == -1) break;\n\n        // move the edge\n        // remove from max_day\n        auto& vec = day_edges[max_day];\n        for (auto it = vec.begin(); it != vec.end(); ++it) {\n            if (*it == best_edge) {\n                vec.erase(it);\n                break;\n            }\n        }\n        // add to min_day\n        day_edges[min_day].push_back(best_edge);\n        day_load[max_day] -= impact[best_edge];\n        day_load[min_day] += impact[best_edge];\n        day_cnt[max_day]--;\n        day_cnt[min_day]++;\n        day_of_edge[best_edge] = min_day;\n    }\n\n    // ---------- 6. output ----------\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << day_of_edge[i] + 1;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// 24 proper rotations (det=1)\nvector<array<array<int,3>,3>> rotations;\n\nvoid init_rotations() {\n    int perm[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n    int parity[6] = {1,-1,-1,1,1,-1};\n    int signs[8][3] = {{1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},\n                       {-1,1,1},{-1,1,-1},{-1,-1,1},{-1,-1,-1}};\n    for (int p=0;p<6;p++) {\n        for (auto s : signs) {\n            int det = s[0]*s[1]*s[2] * parity[p];\n            if (det != 1) continue;\n            array<array<int,3>,3> mat;\n            for (int i=0;i<3;i++) {\n                for (int j=0;j<3;j++) {\n                    mat[i][j] = (j == perm[p][i]) ? s[i] : 0;\n                }\n            }\n            rotations.push_back(mat);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    init_rotations();\n\n    int D; cin >> D;\n    int N = D*D*D;               // total voxels per object\n    vector<string> f[2], r[2];\n    for (int t=0;t<2;t++) {\n        f[t].resize(D);\n        for (int i=0;i<D;i++) cin >> f[t][i];\n        r[t].resize(D);\n        for (int i=0;i<D;i++) cin >> r[t][i];\n    }\n\n    // occupancy per object (flattened)\n    vector<char> occ[2];\n    for (int t=0;t<2;t++) occ[t].resize(N, 0);\n\n    for (int t=0;t<2;t++) {\n        for (int z=0;z<D;z++) {\n            for (int x=0;x<D;x++) {\n                if (f[t][z][x] == '0') continue;\n                for (int y=0;y<D;y++) {\n                    if (r[t][z][y] == '1') {\n                        int idx = x*D*D + y*D + z;\n                        occ[t][idx] = 1;\n                    }\n                }\n            }\n        }\n    }\n\n    // connected components for each object\n    vector<vector<tuple<int,int,int>>> comps[2]; // list of points per component\n    vector<int> compSize[2];                     // volume per component\n    vector<char> vis[2];\n    for (int t=0;t<2;t++) vis[t].resize(N, 0);\n\n    for (int t=0;t<2;t++) {\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || vis[t][start]) continue;\n            queue<int> q; q.push(start);\n            vis[t][start] = 1;\n            vector<tuple<int,int,int>> pts;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                pts.emplace_back(x,y,z);\n                static int dx[] = {1,-1,0,0,0,0};\n                static int dy[] = {0,0,1,-1,0,0};\n                static int dz[] = {0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n                    if (nx<0 || nx>=D || ny<0 || ny>=D || nz<0 || nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !vis[t][nid]) {\n                        vis[t][nid] = 1;\n                        q.push(nid);\n                    }\n                }\n            }\n            comps[t].push_back(pts);\n            compSize[t].push_back((int)pts.size());\n        }\n    }\n\n    // used cells for both objects\n    vector<char> used[2];\n    for (int t=0;t<2;t++) used[t].resize(N, 0);\n\n    // final block assignments\n    vector<int> b1(N,0), b2(N,0);\n    int blockId = 1;\n\n    // candidate components: (volume, object, component index)\n    vector<tuple<int,int,int>> candidates;\n    for (int t=0;t<2;t++) {\n        for (size_t i=0;i<comps[t].size();i++) {\n            candidates.emplace_back(compSize[t][i], t, (int)i);\n        }\n    }\n    sort(candidates.rbegin(), candidates.rend()); // largest first\n\n    // lambda to find a placement of a component from source object into the other object\n    auto findPlacement = [&](const vector<tuple<int,int,int>>& srcPts, int otherObj,\n                             vector<tuple<int,int,int>>& outPts) -> bool {\n        // srcPts are absolute coordinates in the source object\n        for (const auto& rot : rotations) {\n            // apply rotation to srcPts\n            vector<tuple<int,int,int>> rotated;\n            int mnx=1e9, mny=1e9, mnz=1e9;\n            int mxx=-1e9, mxy=-1e9, mxz=-1e9;\n            for (auto [x,y,z] : srcPts) {\n                int nx = rot[0][0]*x + rot[0][1]*y + rot[0][2]*z;\n                int ny = rot[1][0]*x + rot[1][1]*y + rot[1][2]*z;\n                int nz = rot[2][0]*x + rot[2][1]*y + rot[2][2]*z;\n                rotated.emplace_back(nx,ny,nz);\n                mnx = min(mnx, nx); mxx = max(mxx, nx);\n                mny = min(mny, ny); mxy = max(mxy, ny);\n                mnz = min(mnz, nz); mxz = max(mxz, nz);\n            }\n            int sx = mxx - mnx, sy = mxy - mny, sz = mxz - mnz;\n            // bounding box must fit in [0,D-1]\n            for (int tx=0; tx+sx < D; tx++) {\n                for (int ty=0; ty+sy < D; ty++) {\n                    for (int tz=0; tz+sz < D; tz++) {\n                        bool ok = true;\n                        for (auto [nx,ny,nz] : rotated) {\n                            int gx = nx - mnx + tx;\n                            int gy = ny - mny + ty;\n                            int gz = nz - mnz + tz;\n                            int idx = gx*D*D + gy*D + gz;\n                            if (!occ[otherObj][idx] || used[otherObj][idx]) {\n                                ok = false;\n                                break;\n                            }\n                        }\n                        if (ok) {\n                            outPts.clear();\n                            for (auto [nx,ny,nz] : rotated) {\n                                int gx = nx - mnx + tx;\n                                int gy = ny - mny + ty;\n                                int gz = nz - mnz + tz;\n                                outPts.emplace_back(gx,gy,gz);\n                            }\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n        return false;\n    };\n\n    for (auto [vol, obj, compIdx] : candidates) {\n        const auto& pts = comps[obj][compIdx];\n        // check if any cell already used in its own object\n        bool anyUsed = false;\n        for (auto [x,y,z] : pts) {\n            int idx = x*D*D + y*D + z;\n            if (used[obj][idx]) { anyUsed = true; break; }\n        }\n        if (anyUsed) continue;\n\n        int other = 1 - obj;\n        vector<tuple<int,int,int>> placement;\n        if (!findPlacement(pts, other, placement)) continue;\n\n        // assign a new common block\n        // mark used in source object\n        for (auto [x,y,z] : pts) {\n            int idx = x*D*D + y*D + z;\n            used[obj][idx] = 1;\n            if (obj == 0) b1[idx] = blockId;\n            else          b2[idx] = blockId;\n        }\n        // mark used in other object\n        for (auto [x,y,z] : placement) {\n            int idx = x*D*D + y*D + z;\n            used[other][idx] = 1;\n            if (other == 0) b1[idx] = blockId;\n            else            b2[idx] = blockId;\n        }\n        blockId++;\n    }\n\n    // handle residual cells (single-use blocks)\n    for (int t=0;t<2;t++) {\n        vector<char> seen(N, 0);\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || used[t][start] || seen[start]) continue;\n            // BFS to collect component\n            queue<int> q; q.push(start);\n            seen[start] = 1;\n            vector<int> compIndices;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                compIndices.push_back(cur);\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                static int dx[] = {1,-1,0,0,0,0};\n                static int dy[] = {0,0,1,-1,0,0};\n                static int dz[] = {0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx = x+dx[d], ny = y+dy[d], nz = z+dz[d];\n                    if (nx<0 || nx>=D || ny<0 || ny>=D || nz<0 || nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !used[t][nid] && !seen[nid]) {\n                        seen[nid] = 1;\n                        q.push(nid);\n                    }\n                }\n            }\n            // assign new block id\n            for (int idx : compIndices) {\n                if (t == 0) b1[idx] = blockId;\n                else        b2[idx] = blockId;\n            }\n            blockId++;\n        }\n    }\n\n    int n = blockId - 1;\n    cout << n << '\\n';\n    for (int i=0;i<N;i++) cout << b1[i] << \" \\n\"[i==N-1];\n    for (int i=0;i<N;i++) cout << b2[i] << \" \\n\"[i==N-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing ll = long long;\nconst ll INF = 1LL << 60;\n\nstruct UnionFind {\n    vector<int> parent, rank;\n    UnionFind(int n) : parent(n), rank(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) parent[x] = y;\n        else if (rank[x] > rank[y]) parent[y] = x;\n        else { parent[y] = x; rank[x]++; }\n        return true;\n    }\n};\n\nint ceil_sqrt(ll sq) {\n    if (sq <= 0) return 0;\n    double d = sqrt((double)sq);\n    int r = (int)ceil(d);\n    if ((ll)r * r < sq) ++r;\n    return min(r, 5000);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::steady_clock::now();\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<tuple<int,int,ll>> edges(M);\n    vector<vector<pair<int,ll>>> adj(N);\n    for (int j = 0; j < M; ++j) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].emplace_back(v, w);\n        adj[v].emplace_back(u, w);\n    }\n\n    vector<int> ax(K), ay(K);\n    for (int k = 0; k < K; ++k) {\n        cin >> ax[k] >> ay[k];\n    }\n\n    // Precompute squared distances between residents and nodes\n    vector<vector<ll>> dist2_res(K, vector<ll>(N));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            ll dx = ax[k] - x[i];\n            ll dy = ay[k] - y[i];\n            dist2_res[k][i] = dx*dx + dy*dy;\n        }\n    }\n\n    // For each resident, sort nodes by distance\n    vector<vector<int>> sorted_nodes(K);\n    for (int k = 0; k < K; ++k) {\n        vector<pair<ll,int>> tmp;\n        for (int i = 0; i < N; ++i) {\n            tmp.emplace_back(dist2_res[k][i], i);\n        }\n        sort(tmp.begin(), tmp.end());\n        sorted_nodes[k].reserve(N);\n        for (auto &p : tmp) {\n            sorted_nodes[k].push_back(p.second);\n        }\n    }\n\n    // All-pairs shortest paths\n    vector<vector<ll>> dist_sh(N, vector<ll>(N, INF));\n    vector<vector<int>> prev(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        dist_sh[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist_sh[s][u]) continue;\n            for (auto &[v, w] : adj[u]) {\n                if (dist_sh[s][v] > d + w) {\n                    dist_sh[s][v] = d + w;\n                    prev[s][v] = u;\n                    pq.push({dist_sh[s][v], v});\n                }\n            }\n        }\n    }\n\n    // Edge index map\n    vector<vector<int>> edge_idx(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        auto [u, v, w] = edges[j];\n        edge_idx[u][v] = edge_idx[v][u] = j;\n    }\n\n    // Quick coverage test\n    auto can_cover = [&](const vector<bool>& active) -> bool {\n        for (int k = 0; k < K; ++k) {\n            bool found = false;\n            for (int i : sorted_nodes[k]) {\n                if (active[i] && dist2_res[k][i] <= 5000LL*5000LL) {\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                // If no station within 5000, but input guarantees at least one station overall,\n                // we must have incorrectly removed the covering station.\n                return false;\n            }\n        }\n        return true;\n    };\n\n    // Cost evaluation function given active set (bool)\n    auto computeCost = [&](const vector<bool>& active) -> ll {\n        // Check coverage\n        for (int k = 0; k < K; ++k) {\n            bool found = false;\n            for (int i : sorted_nodes[k]) {\n                if (active[i] && dist2_res[k][i] <= 5000LL*5000LL) {\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) return LLONG_MAX;\n        }\n\n        vector<ll> maxDistSq(N, 0);\n        for (int k = 0; k < K; ++k) {\n            ll best_d2 = LLONG_MAX;\n            int best_node = -1;\n            for (int i : sorted_nodes[k]) {\n                if (active[i]) {\n                    best_d2 = dist2_res[k][i];\n                    best_node = i;\n                    break;\n                }\n            }\n            if (best_node == -1) return LLONG_MAX; // should not happen\n            if (best_d2 > maxDistSq[best_node])\n                maxDistSq[best_node] = best_d2;\n        }\n        ll sumP2 = 0;\n        for (int i = 0; i < N; ++i) {\n            if (active[i] && maxDistSq[i] > 0) {\n                int r = ceil_sqrt(maxDistSq[i]);\n                sumP2 += (ll)r * r;\n            }\n        }\n\n        vector<int> terms;\n        for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n        ll mst_cost = 0;\n        if (terms.size() > 1) {\n            vector<tuple<ll,int,int>> metric_edges;\n            for (int a = 0; a < (int)terms.size(); ++a) {\n                for (int b = a+1; b < (int)terms.size(); ++b) {\n                    int u = terms[a], v = terms[b];\n                    metric_edges.emplace_back(dist_sh[u][v], u, v);\n                }\n            }\n            sort(metric_edges.begin(), metric_edges.end());\n            UnionFind uf(N);\n            for (auto &[w, u, v] : metric_edges) {\n                if (uf.unite(u, v)) mst_cost += w;\n            }\n        }\n        return sumP2 + mst_cost;\n    };\n\n    // Build initial set: for each resident, add its closest station that is within 5000\n    vector<bool> active(N, false);\n    for (int k = 0; k < K; ++k) {\n        for (int i : sorted_nodes[k]) {\n            if (dist2_res[k][i] <= 5000LL*5000LL) {\n                active[i] = true;\n                break;\n            }\n        }\n    }\n    // Ensure station 1 is active\n    active[0] = true;\n    // Remove redundant stations: try to remove each station while coverage maintained\n    // This is a simple greedy\n    for (int i = 1; i < N; ++i) {\n        if (!active[i]) continue;\n        active[i] = false;\n        if (can_cover(active)) {\n            // keep it off\n        } else {\n            active[i] = true;\n        }\n    }\n\n    ll best_cost = computeCost(active);\n    vector<bool> best_active = active;\n\n    // Simulated Annealing\n    double temp = 5e6;\n    double cooling = 0.9999;\n    int max_iters = 30000;\n    int iters = 0;\n    while (iters < max_iters) {\n        // Check time\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1800) {\n            break;\n        }\n\n        // Pick a random station to flip (excluding 0)\n        int flip = uniform_int_distribution<int>(1, N-1)(rng);\n        vector<bool> new_active = active;\n        new_active[flip] = !new_active[flip];\n        // Keep 0 always active\n        new_active[0] = true;\n\n        // Compute cost\n        ll new_cost = computeCost(new_active);\n        if (new_cost == LLONG_MAX) {\n            // Invalid, reject\n            temp *= cooling;\n            iters++;\n            continue;\n        }\n\n        if (new_cost < best_cost) {\n            best_cost = new_cost;\n            best_active = new_active;\n        }\n\n        double delta = (double)(new_cost - best_cost);\n        if (delta < 0 || exp(-delta / temp) > uniform_real_distribution<double>(0,1)(rng)) {\n            active = new_active;\n            best_cost = new_cost; // update current best for acceptance\n        }\n\n        temp *= cooling;\n        iters++;\n    }\n\n    // Assign powers based on best_active\n    vector<ll> maxDistSq(N, 0);\n    vector<int> P(N, 0);\n    for (int k = 0; k < K; ++k) {\n        for (int i : sorted_nodes[k]) {\n            if (best_active[i] && dist2_res[k][i] <= 5000LL*5000LL) {\n                if (dist2_res[k][i] > maxDistSq[i])\n                    maxDistSq[i] = dist2_res[k][i];\n                break;\n            }\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        if (best_active[i] && maxDistSq[i] > 0) {\n            P[i] = ceil_sqrt(maxDistSq[i]);\n        }\n    }\n\n    // Build Steiner tree for best_active\n    vector<int> terms;\n    for (int i = 0; i < N; ++i) if (best_active[i]) terms.push_back(i);\n    vector<bool> edge_on(M, false);\n\n    if (terms.size() >= 2) {\n        vector<tuple<ll,int,int>> metric_edges;\n        for (int a = 0; a < (int)terms.size(); ++a) {\n            for (int b = a+1; b < (int)terms.size(); ++b) {\n                int u = terms[a], v = terms[b];\n                metric_edges.emplace_back(dist_sh[u][v], u, v);\n            }\n        }\n        sort(metric_edges.begin(), metric_edges.end());\n        UnionFind uf1(N);\n        vector<pair<int,int>> mst_pairs;\n        for (auto &[w, u, v] : metric_edges) {\n            if (uf1.unite(u, v)) {\n                mst_pairs.emplace_back(u, v);\n            }\n        }\n\n        // Add edges along shortest paths of MST pairs\n        for (auto &[u, v] : mst_pairs) {\n            int cur = v;\n            while (cur != u) {\n                int par = prev[u][cur];\n                int idx = edge_idx[par][cur];\n                if (idx != -1) {\n                    edge_on[idx] = true;\n                }\n                cur = par;\n            }\n        }\n\n        // Build spanning tree on these candidate edges\n        vector<int> candidate_edges;\n        for (int j = 0; j < M; ++j) {\n            if (edge_on[j]) candidate_edges.push_back(j);\n        }\n        sort(candidate_edges.begin(), candidate_edges.end(), [&](int a, int b) {\n            return get<2>(edges[a]) < get<2>(edges[b]);\n        });\n        UnionFind uf2(N);\n        fill(edge_on.begin(), edge_on.end(), false);\n        for (int idx : candidate_edges) {\n            auto [u, v, w] = edges[idx];\n            if (uf2.unite(u, v)) {\n                edge_on[idx] = true;\n            }\n        }\n    } else if (terms.size() == 1) {\n        // No edges needed\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (edge_on[j] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    vector<tuple<int, int, int, int>> ops;\n\n    // bottom-up heapify\n    for (int x = N - 2; x >= 0; --x) {\n        for (int y = 0; y <= x; ++y) {\n            int cx = x, cy = y;\n            while (cx < N - 1) {\n                int left_val  = a[cx + 1][cy];\n                int right_val = a[cx + 1][cy + 1];\n                int cur_val   = a[cx][cy];\n\n                if (cur_val > left_val || cur_val > right_val) {\n                    // swap with the smaller child\n                    int child_y = (left_val < right_val) ? cy : cy + 1;\n                    swap(a[cx][cy], a[cx + 1][child_y]);\n                    ops.emplace_back(cx, cy, cx + 1, child_y);\n                    cx = cx + 1;\n                    cy = child_y;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // output\n    cout << ops.size() << \"\\n\";\n    for (const auto& [x1, y1, x2, y2] : ops) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int D = 9;\n    int N;\n    cin >> D >> N; // D is always 9\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // precompute BFS distances from entrance (0,4) ignoring containers\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int, int>> q;\n    dist[0][4] = 0;\n    q.emplace(0, 4);\n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            if (obstacle[nx][ny] || dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            q.emplace(nx, ny);\n        }\n    }\n\n    // list of all usable cells (excluding entrance), sorted by distance\n    vector<tuple<int, int, int>> cells; // (distance, row, col)\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == 0 && j == 4) continue;          // entrance itself\n            if (obstacle[i][j]) continue;\n            cells.emplace_back(dist[i][j], i, j);\n        }\n    }\n    sort(cells.begin(), cells.end());\n    const int total = cells.size();   // = D*D - 1 - N\n\n    // index of each cell in the sorted order (0 .. total-1)\n    vector<vector<int>> order(D, vector<int>(D, -1));\n    for (int idx = 0; idx < total; ++idx) {\n        auto [d, i, j] = cells[idx];\n        order[i][j] = idx;\n    }\n\n    // container number stored at each cell (-1 if empty)\n    vector<vector<int>> container(D, vector<int>(D, -1));\n    vector<vector<bool>> occupied(D, vector<bool>(D, false));\n\n    // BFS from entrance on empty cells (obstacles + occupied cells are walls)\n    auto bfs_reachable = [&]() -> vector<vector<bool>> {\n        vector<vector<bool>> reachable(D, vector<bool>(D, false));\n        queue<pair<int, int>> q;\n        if (!obstacle[0][4] && !occupied[0][4]) {\n            reachable[0][4] = true;\n            q.emplace(0, 4);\n        }\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k], ny = y + dy[k];\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n                if (obstacle[nx][ny] || occupied[nx][ny]) continue;\n                if (reachable[nx][ny]) continue;\n                reachable[nx][ny] = true;\n                q.emplace(nx, ny);\n            }\n        }\n        return reachable;\n    };\n\n    // ---------- placement phase ----------\n    for (int d = 0; d < total; ++d) {\n        int t;\n        cin >> t;\n\n        auto reachable = bfs_reachable();\n\n        // choose the reachable empty cell whose order is closest to t\n        int best_i = -1, best_j = -1;\n        int best_diff = INT_MAX;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || occupied[i][j]) continue;\n                if (i == 0 && j == 4) continue;      // entrance cannot be used\n                if (!reachable[i][j]) continue;\n                int diff = abs(order[i][j] - t);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // place the container\n        occupied[best_i][best_j] = true;\n        container[best_i][best_j] = t;\n        cout << best_i << \" \" << best_j << endl << flush;\n    }\n\n    // ---------- retrieval phase ----------\n    for (int step = 0; step < total; ++step) {\n        auto reachable = bfs_reachable();\n\n        // find the reachable container with the smallest number\n        int best_num = INT_MAX;\n        int best_i = -1, best_j = -1;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || container[i][j] == -1) continue;\n                if (!reachable[i][j]) continue;\n                if (container[i][j] < best_num) {\n                    best_num = container[i][j];\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // remove it\n        occupied[best_i][best_j] = false;\n        container[best_i][best_j] = -1;\n        cout << best_i << \" \" << best_j << \"\\n\";\n    }\n    cout << flush;\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\nint n, m;\nvector<vector<int>> grid;\n\n// original adjacency relations (including 0)\nvector<vector<bool>> orig;\n\n// adjacency count between colors (lower triangle, 1..m)\nvector<vector<int>> adjCnt;\n\n// total cells of each color\nvector<int> tot;\n\n// number of boundary cells of each color (adjacent to outside)\nvector<int> zeroCnt;\n\n// whether a color originally touches the boundary\nvector<bool> touchesBoundary;\n\nbool can_remove(int i, int j, int c) {\n    if (c == 0) return false;\n\n    // color must originally touch boundary\n    if (!touchesBoundary[c]) return false;\n\n    // check boundary cell count for c\n    int onBoundary = (i == 0 || i == n-1 || j == 0 || j == n-1) ? 1 : 0;\n    if (onBoundary && zeroCnt[c] <= 1) return false; // would lose all boundary cells\n\n    // neighbours\n    vector<int> neighColors;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        int col = grid[ni][nj];\n        if (col == 0) continue; // neighbour is already zero, no new adjacency\n        // all neighbour colors must originally touch boundary\n        if (!touchesBoundary[col]) return false;\n        // adjacency between c and col must remain\n        int a = min(c, col);\n        int b = max(c, col);\n        if (adjCnt[a][b] < 2) return false; // this cell contributes to the only adjacency\n        neighColors.push_back(col);\n    }\n\n    // connectivity check for color c after removal\n    vector<vector<bool>> visited(n, vector<bool>(n, false));\n    queue<pair<int,int>> q;\n    // find a starting cell (any other cell of same colour)\n    bool found = false;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        if (grid[ni][nj] == c) {\n            q.push({ni, nj});\n            visited[ni][nj] = true;\n            found = true;\n            break;\n        }\n    }\n    if (!found) {\n        // find any other cell of colour c\n        for (int x = 0; x < n; ++x) {\n            for (int y = 0; y < n; ++y) {\n                if ((x != i || y != j) && grid[x][y] == c) {\n                    q.push({x, y});\n                    visited[x][y] = true;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n    }\n    if (!found) return false; // only one cell of colour c (should not happen because tot[c]>1)\n    int cnt = 1;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (nx == i && ny == j) continue;\n            if (!visited[nx][ny] && grid[nx][ny] == c) {\n                visited[nx][ny] = true;\n                cnt++;\n                q.push({nx, ny});\n            }\n        }\n    }\n    if (cnt != tot[c] - 1) return false;\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    const int MAXC = m + 2;\n    orig.assign(MAXC, vector<bool>(MAXC, false));\n    adjCnt.assign(MAXC, vector<int>(MAXC, 0));\n    tot.assign(MAXC, 0);\n    zeroCnt.assign(MAXC, 0);\n    touchesBoundary.assign(MAXC, false);\n\n    // initial data from original map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = grid[i][j];\n            tot[c]++;\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                zeroCnt[c]++;\n                touchesBoundary[c] = true;\n                orig[0][c] = orig[c][0] = true;\n            }\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int col = grid[ni][nj];\n                if (c != col) {\n                    orig[c][col] = orig[col][c] = true;\n                    if (c < col) adjCnt[c][col]++;\n                }\n            }\n        }\n    }\n\n    // BFS from boundary (all cells on grid boundary)\n    deque<pair<int,int>> que;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                if (grid[i][j] != 0) {\n                    que.push_back({i, j});\n                }\n            }\n        }\n    }\n\n    // iterative removal\n    while (!que.empty()) {\n        auto [i, j] = que.front(); que.pop_front();\n        int c = grid[i][j];\n        if (c == 0) continue;\n        if (can_remove(i, j, c)) {\n            // update structures\n            // neighbours\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int col = grid[ni][nj];\n                if (col == 0) continue;\n                // zero adjacency to neighbour increases\n                zeroCnt[col]++;\n                // adjacency between c and col decreases\n                if (col != c) {\n                    int a = min(c, col);\n                    int b = max(c, col);\n                    adjCnt[a][b]--;\n                }\n                // push neighbour for further consideration\n                if (grid[ni][nj] != 0) { // already zero? no\n                    que.push_back({ni, nj});\n                }\n            }\n            // boundary status of c\n            if (i == 0 || i == n-1 || j == 0 || j == n-1) {\n                zeroCnt[c]--;\n            }\n            tot[c]--;\n            grid[i][j] = 0;\n            // also push neighbours of removed cell\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                if (grid[ni][nj] != 0) {\n                    que.push_back({ni, nj});\n                }\n            }\n        }\n    }\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << grid[i][j];\n            if (j < n-1) cout << ' ';\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint queries_left;\nint N, D, Q;\n\n// Perform a comparison and read the result, decrement queries_left\nvoid query(const vector<int>& L, const vector<int>& R, string& res) {\n    // Ensure both sets are non-empty (we guarantee this at call sites)\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    cin >> res;\n    --queries_left;\n}\n\n// Return true if a is strictly lighter than b (a < b)\nbool lighter(int a, int b) {\n    vector<int> L = {a}, R = {b};\n    string res;\n    query(L, R, res);\n    if (res == \"<\") return true;\n    return false;\n}\n\n// Greedy split of a group into two balanced subsets using the balance.\n// Requires that the group has at least 2 items and that there are enough queries left.\npair<vector<int>, vector<int>> split_group(const vector<int>& group, const vector<int>& rank) {\n    vector<int> left, right;\n    // Sort items by estimated weight descending (rank 0 = heaviest)\n    vector<int> sorted_group = group;\n    sort(sorted_group.begin(), sorted_group.end(), [&](int a, int b) {\n        return rank[a] < rank[b];\n    });\n\n    for (int idx = 0; idx < (int)sorted_group.size(); ++idx) {\n        int item = sorted_group[idx];\n        if (left.empty()) {\n            left.push_back(item);\n        } else if (right.empty()) {\n            right.push_back(item);\n        } else {\n            // Try adding item to left and compare with right\n            vector<int> left_candidate = left;\n            left_candidate.push_back(item);\n            string res;\n            query(left_candidate, right, res);\n            if (res == \"<\" || res == \"=\") {\n                left.push_back(item);\n            } else {\n                right.push_back(item);\n            }\n        }\n    }\n    return {left, right};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    queries_left = Q;\n\n    // ---------- 1. Rough ordering using limited comparisons ----------\n    // Use a small number of reference items to compare against.\n    int ref_count = min(10, max(1, Q / (3 * N)));  // at most 10, at least 1\n    vector<int> score(N, 0);\n    vector<int> refs;\n    for (int i = 0; i < min(ref_count, N); ++i) refs.push_back(i);\n\n    // For each item, compare with reference items and count wins (heavier)\n    for (int i = 0; i < N && queries_left > 0; ++i) {\n        for (int r : refs) {\n            if (i == r) continue;\n            if (queries_left <= 0) break;\n            // lighter(i,r) returns true if i < r; we want to count if i is heavier\n            if (!lighter(i, r)) {\n                score[i]++;\n            }\n        }\n    }\n\n    // Sort items by score descending (heaviest first), breaking ties arbitrarily\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (score[a] != score[b]) return score[a] > score[b];\n        return a < b;\n    });\n    vector<int> rank(N);   // rank[item] = position in sorted order, 0 = heaviest\n    for (int i = 0; i < N; ++i) rank[order[i]] = i;\n\n    // ---------- 2. Split into D groups using remaining queries ----------\n    vector<vector<int>> groups;\n    groups.push_back(order);   // initial group is the roughly sorted list\n\n    while ((int)groups.size() < D && queries_left > 0) {\n        // Find the largest group (by number of items)\n        auto it = max_element(groups.begin(), groups.end(),\n                              [](const vector<int>& a, const vector<int>& b) {\n                                  return a.size() < b.size();\n                              });\n        int sz = it->size();\n        if (sz < 2) break;   // cannot split further\n\n        int needed = sz - 2;   // number of queries required for this split\n        if (needed > queries_left) break;   // not enough queries left\n\n        auto [left, right] = split_group(*it, rank);\n        int idx = distance(groups.begin(), it);\n        groups.erase(groups.begin() + idx);\n        groups.push_back(move(left));\n        groups.push_back(move(right));\n    }\n\n    // If we still have fewer than D groups, split arbitrarily (no queries)\n    while ((int)groups.size() < D) {\n        auto it = max_element(groups.begin(), groups.end(),\n                              [](const vector<int>& a, const vector<int>& b) {\n                                  return a.size() < b.size();\n                              });\n        int sz = it->size();\n        if (sz < 2) break;\n        int half = sz / 2;\n        vector<int> left(it->begin(), it->begin() + half);\n        vector<int> right(it->begin() + half, it->end());\n        int idx = distance(groups.begin(), it);\n        groups.erase(groups.begin() + idx);\n        groups.push_back(move(left));\n        groups.push_back(move(right));\n    }\n\n    // ---------- 3. Consume any remaining queries (dummy comparisons) ----------\n    while (queries_left > 0) {\n        cout << \"1 1 0 1\" << endl;\n        string res;\n        cin >> res;\n        --queries_left;\n    }\n\n    // ---------- 4. Output final division ----------\n    vector<int> assign(N, 0);\n    for (int g = 0; g < (int)groups.size(); ++g) {\n        for (int item : groups[g]) assign[item] = g;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << assign[i] << (i == N - 1 ? '\\n' : ' ');\n    }\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// length of decreasing prefix (from bottom)\nint decreasing_prefix_len(const vector<int>& st) {\n    int sz = st.size();\n    if (sz == 0) return 0;\n    int len = 1;\n    for (int i = 1; i < sz; ++i) {\n        if (st[i-1] > st[i]) ++len;\n        else break;\n    }\n    return len;\n}\n\n// score of one stack = number of boxes not in decreasing prefix\nint stack_score(const vector<int>& st) {\n    return (int)st.size() - decreasing_prefix_len(st);\n}\n\n// total score\nint total_score(const vector<vector<int>>& stacks) {\n    int s = 0;\n    for (const auto& st : stacks) s += stack_score(st);\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int per_stack = n / m;\n    vector<vector<int>> stacks(m);\n    vector<pair<int,int>> pos(n+1); // (stack, index)\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < per_stack; ++j) {\n            int box;\n            cin >> box;\n            stacks[i].push_back(box);\n            pos[box] = {i, j};\n        }\n    }\n\n    vector<pair<int,int>> ops;\n    const int GAMMA = 1; // weight for energy cost in the evaluation\n\n    for (int target = 1; target <= n; ++target) {\n        while (true) {\n            int s = pos[target].first;\n            int idx = pos[target].second;\n            auto& src = stacks[s];\n            int top_idx = (int)src.size() - 1;\n\n            // if target is on top, carry out\n            if (idx == top_idx) {\n                ops.emplace_back(target, 0);\n                src.pop_back();\n                // update pos for no box needed (target removed)\n                break;\n            }\n\n            // The only possible move to expose target:\n            // move boxes from idx+1 to top_idx (the box immediately above target and above)\n            int v_idx = idx + 1;\n            int block_size = top_idx - v_idx + 1;\n            int v = src[v_idx]; // box on top of target\n\n            // evaluate each destination\n            struct Candidate {\n                int final_score;\n                int block_size;\n                int dest;\n            };\n            vector<Candidate> candidates;\n\n            // current scores for source and destinations\n            int old_src_score = stack_score(src);\n            vector<int> old_dst_score(m);\n            for (int d = 0; d < m; ++d) if (d != s) old_dst_score[d] = stack_score(stacks[d]);\n\n            for (int d = 0; d < m; ++d) {\n                if (d == s) continue;\n                // simulate final state after move and then carry out target\n                // final source: remove block (indices v_idx ... top_idx) and then pop target (idx)\n                // So final source size = idx\n                vector<int> src_final = src;\n                src_final.resize(idx); // keep only boxes below target\n                int new_src_score = stack_score(src_final);\n\n                // final destination: append the block\n                vector<int> dst_final = stacks[d];\n                dst_final.insert(dst_final.end(), src.begin() + v_idx, src.end());\n                int new_dst_score = stack_score(dst_final);\n\n                int new_total = total_score(stacks) - old_src_score - old_dst_score[d]\n                                + new_src_score + new_dst_score;\n                // note: total_score(stacks) includes current src and dst\n                candidates.push_back({new_total, block_size, d});\n            }\n\n            // choose best candidate: minimize final_score + GAMMA * (block_size+1)\n            auto best = *min_element(candidates.begin(), candidates.end(),\n                [](const Candidate& a, const Candidate& b) {\n                    int obj_a = a.final_score + GAMMA * (a.block_size + 1);\n                    int obj_b = b.final_score + GAMMA * (b.block_size + 1);\n                    if (obj_a != obj_b) return obj_a < obj_b;\n                    if (a.block_size != b.block_size) return a.block_size < b.block_size;\n                    return a.dest < b.dest;\n                });\n\n            // record operation: move block v to best.dest\n            ops.emplace_back(v, best.dest + 1); // 1-indexed\n\n            // execute the move on actual stacks\n            auto& dst = stacks[best.dest];\n            for (int j = v_idx; j < (int)src.size(); ++j) {\n                int box = src[j];\n                dst.push_back(box);\n                pos[box] = {best.dest, (int)dst.size() - 1};\n            }\n            src.resize(v_idx);\n\n            // after move, target is now at top of src (index = src.size() - 1)\n            // But note: src now has indices 0..v_idx-1, and target is at idx (which is v_idx-1)\n            // Actually after move, src.size() = v_idx, and target is at index idx (since idx < v_idx).\n            // The top index is v_idx-1. Since idx < v_idx, target is not at top unless idx == v_idx-1.\n            // Wait, original idx was index of target. After removing block from idx+1 to top_idx,\n            // the source becomes size idx+1 (boxes 0..idx). So target is at top now? Yes, because\n            // indices 0..idx remain, and top index is idx. So target is top.\n            // But we resized to v_idx? v_idx = idx+1, so size after resize is idx+1, top index = idx.\n            // So target is at top. Good.\n            // Now we don't carry out immediately; the while loop will again check condition\n            // and find target on top and carry out.\n        }\n    }\n\n    // output all operations\n    for (const auto& op : ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <cmath>\n#include <stack>\n#include <string>\n#include <vector>\nusing namespace std;\n\nint N;\nvector<vector<int>> graph;\nvector<double> sqrt_d;\nvector<int> parent;\nvector<vector<int>> children;\nvector<char> dir_to_child;  // direction from parent to node\n\nint idx(int i, int j) { return i * N + j; }\nint ix(int id) { return id / N; }\nint jy(int id) { return id % N; }\n\nchar dir_char(int di, int dj) {\n    if (di == -1 && dj == 0) return 'U';\n    if (di == 1 && dj == 0) return 'D';\n    if (di == 0 && dj == -1) return 'L';\n    if (di == 0 && dj == 1) return 'R';\n    return '?';\n}\nchar opposite(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return '?';\n}\n\n// compute f values for a given K, return total_moves = 2 * sum_{v>0} f[v]\npair<vector<int>, int> compute_f(double K) {\n    int M = N * N;\n    vector<int> f(M, 0);\n    // post-order DFS using stack (iterative to avoid recursion depth)\n    // We'll use explicit stack with state: (node, visited flag)\n    // Since tree is small, recursion is fine, but for safety we use iterative.\n    stack<pair<int, bool>> st;  // (node, processed)\n    st.push({0, false});\n    while (!st.empty()) {\n        auto [v, processed] = st.top(); st.pop();\n        if (!processed) {\n            st.push({v, true});\n            for (int c : children[v]) {\n                st.push({c, false});\n            }\n        } else {\n            // post-order\n            if (v == 0) continue;\n            double sq = sqrt_d[v];\n            int target = max(1, (int)round(K * sq));\n            int sum_child = 0;\n            for (int c : children[v]) sum_child += f[c];\n            f[v] = max(1, target - sum_child);\n        }\n    }\n    int total_moves = 0;\n    for (int v = 1; v < M; ++v) total_moves += f[v];\n    total_moves *= 2;\n    return {f, total_moves};\n}\n\nstring build_route(const vector<int>& f) {\n    int M = N * N;\n    vector<int> rem = f;  // rem[0] is unused\n    // stack of nodes (current path)\n    stack<int> st;\n    st.push(0);\n    vector<char> moves;\n    moves.reserve(100000);\n    while (true) {\n        int v = st.top();\n        // find child with maximum remaining visits\n        int best_child = -1;\n        int best_rem = 0;\n        for (int c : children[v]) {\n            if (rem[c] > best_rem) {\n                best_rem = rem[c];\n                best_child = c;\n            }\n        }\n        if (best_child != -1) {\n            // go down to child\n            moves.push_back(dir_to_child[best_child]);\n            rem[best_child]--;\n            st.push(best_child);\n        } else {\n            // no child remaining\n            if (v == 0) break;  // back at root, finish\n            st.pop();\n            char up_dir = opposite(dir_to_child[v]);\n            moves.push_back(up_dir);\n        }\n    }\n    return string(moves.begin(), moves.end());\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    // build graph\n    int M = N * N;\n    graph.assign(M, {});\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = idx(i, j);\n            if (i < N - 1 && h[i][j] == '0') {\n                int id2 = idx(i + 1, j);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n            if (j < N - 1 && v[i][j] == '0') {\n                int id2 = idx(i, j + 1);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n        }\n    }\n\n    // BFS tree from (0,0)\n    parent.assign(M, -1);\n    children.assign(M, {});\n    dir_to_child.assign(M, ' ');\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0; // mark root (self)\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) {\n            if (parent[u] == -1) {\n                parent[u] = v;\n                children[v].push_back(u);\n                int di = ix(u) - ix(v);\n                int dj = jy(u) - jy(v);\n                dir_to_child[u] = dir_char(di, dj);\n                q.push(u);\n            }\n        }\n    }\n    // compute sqrt_d\n    sqrt_d.assign(M, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sqrt_d[idx(i, j)] = sqrt((double)d[i][j]);\n\n    // binary search for maximum K such that total_moves <= 100000\n    double low = 0.0, high = 200.0; // sufficient range\n    vector<int> best_f;\n    for (int iter = 0; iter < 60; ++iter) {\n        double mid = (low + high) / 2.0;\n        auto [f, moves] = compute_f(mid);\n        if (moves <= 100000) {\n            best_f = f;\n            low = mid;\n        } else {\n            high = mid;\n        }\n    }\n    // final route from best_f (guaranteed moves <= 100000)\n    string route = build_route(best_f);\n    cout << route << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing LL = long long;\nconst LL INF = 1e18;\nconst int N = 15;\nconst int SZ = N * N; // 225\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummyN, M;\n    cin >> dummyN >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> patterns(M);\n    for (int i = 0; i < M; ++i) cin >> patterns[i];\n\n    // positions for each letter\n    vector<vector<int>> pos(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            pos[grid[i][j] - 'A'].push_back(i * N + j);\n        }\n    }\n\n    // Manhattan distance matrix\n    array<array<int, SZ>, SZ> dist;\n    for (int i = 0; i < SZ; ++i) {\n        int x1 = i / N, y1 = i % N;\n        for (int j = 0; j < SZ; ++j) {\n            int x2 = j / N, y2 = j % N;\n            dist[i][j] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    int start_idx = si * N + sj;\n    vector<int> best_moves;\n    LL best_total = INF;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    // function to compute full cost and moves given an order of patterns (as indices)\n    auto compute_full_solution = [&](const vector<int>& order) -> pair<LL, vector<int>> {\n        int cur = start_idx;\n        string S;\n        vector<int> moves;\n        for (int idx : order) {\n            const string& t = patterns[idx];\n            // compute best overlap with current S\n            int ol = 0;\n            for (int l = min(5, (int)S.size()); l >= 1; --l) {\n                if (S.compare(S.size() - l, l, t, 0, l) == 0) {\n                    ol = l;\n                    break;\n                }\n            }\n            string rem = t.substr(ol);\n            int len = rem.size();\n            // DP to find best path for this fragment\n            vector<vector<LL>> dp(len, vector<LL>(SZ, INF));\n            vector<vector<int>> prev_step(len, vector<int>(SZ, -1));\n            for (int p : pos[rem[0] - 'A']) {\n                dp[0][p] = dist[cur][p] + 1;\n            }\n            for (int ch = 1; ch < len; ++ch) {\n                int c_idx = rem[ch] - 'A';\n                int p_c_idx = rem[ch-1] - 'A';\n                for (int p : pos[c_idx]) {\n                    LL best = INF;\n                    int best_prev = -1;\n                    for (int q : pos[p_c_idx]) {\n                        if (dp[ch-1][q] >= INF) continue;\n                        LL cand = dp[ch-1][q] + dist[q][p] + 1;\n                        if (cand < best) {\n                            best = cand;\n                            best_prev = q;\n                        }\n                    }\n                    dp[ch][p] = best;\n                    prev_step[ch][p] = best_prev;\n                }\n            }\n            LL bestcost = INF;\n            int final_pos = -1;\n            for (int p : pos[rem.back() - 'A']) {\n                if (dp[len-1][p] < bestcost) {\n                    bestcost = dp[len-1][p];\n                    final_pos = p;\n                }\n            }\n            // reconstruct path\n            vector<int> path(len);\n            int p = final_pos;\n            for (int ch = len-1; ch >= 0; --ch) {\n                path[ch] = p;\n                p = prev_step[ch][p];\n            }\n            for (int x : path) moves.push_back(x);\n            cur = final_pos;\n            S += rem;\n        }\n        LL total = 0;\n        int prev = start_idx;\n        for (int p : moves) {\n            total += dist[prev][p] + 1;\n            prev = p;\n        }\n        return {total, moves};\n    };\n\n    // multiple trials with different greedy strategies\n    for (int trial = 0; trial < 12; ++trial) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.8) break;\n\n        int cur = start_idx;\n        string S;\n        vector<bool> covered(M, false);\n        int uncovered = M;\n        vector<int> order; // order of patterns added\n\n        auto seed = chrono::steady_clock::now().time_since_epoch().count() + trial * 1000;\n        mt19937 local_rng(seed);\n\n        while (uncovered > 0) {\n            vector<pair<LL, int>> candidates;\n            for (int i = 0; i < M; ++i) {\n                if (covered[i]) continue;\n                const string& t = patterns[i];\n                int ol = 0;\n                for (int l = min(5, (int)S.size()); l >= 1; --l) {\n                    if (S.compare(S.size() - l, l, t, 0, l) == 0) {\n                        ol = l;\n                        break;\n                    }\n                }\n                if (ol == 5) {\n                    covered[i] = true;\n                    uncovered--;\n                    continue;\n                }\n                string rem = t.substr(ol);\n                int len = rem.size();\n                vector<LL> prev(SZ, INF);\n                for (int p : pos[rem[0] - 'A']) {\n                    prev[p] = dist[cur][p] + 1;\n                }\n                for (int ch = 1; ch < len; ++ch) {\n                    vector<LL> cur_cost(SZ, INF);\n                    int c_idx = rem[ch] - 'A';\n                    int p_c_idx = rem[ch-1] - 'A';\n                    for (int p : pos[c_idx]) {\n                        LL best = INF;\n                        for (int q : pos[p_c_idx]) {\n                            if (prev[q] >= INF) continue;\n                            LL cand = prev[q] + dist[q][p] + 1;\n                            if (cand < best) best = cand;\n                        }\n                        cur_cost[p] = best;\n                    }\n                    prev = cur_cost;\n                }\n                LL totalcost = INF;\n                for (int p : pos[rem.back() - 'A']) {\n                    totalcost = min(totalcost, prev[p]);\n                }\n                // heuristic: reduce cost by overlap length (encourage longer overlaps)\n                LL adjusted = totalcost - ol * 5;\n                candidates.emplace_back(adjusted, i);\n            }\n            if (candidates.empty()) break;\n\n            int chosen = -1;\n            if (trial == 0) {\n                // deterministic: pick absolute min adjusted cost\n                auto it = min_element(candidates.begin(), candidates.end());\n                chosen = it->second;\n            } else {\n                // random among top 3\n                sort(candidates.begin(), candidates.end());\n                int topk = min(3, (int)candidates.size());\n                uniform_int_distribution<int> uid(0, topk - 1);\n                chosen = candidates[uid(local_rng)].second;\n            }\n\n            const string& t = patterns[chosen];\n            int ol = 0;\n            for (int l = min(5, (int)S.size()); l >= 1; --l) {\n                if (S.compare(S.size() - l, l, t, 0, l) == 0) {\n                    ol = l;\n                    break;\n                }\n            }\n            string rem = t.substr(ol);\n            int len = rem.size();\n            vector<vector<LL>> dp(len, vector<LL>(SZ, INF));\n            vector<vector<int>> prev_step(len, vector<int>(SZ, -1));\n            for (int p : pos[rem[0] - 'A']) {\n                dp[0][p] = dist[cur][p] + 1;\n            }\n            for (int ch = 1; ch < len; ++ch) {\n                int c_idx = rem[ch] - 'A';\n                int p_c_idx = rem[ch-1] - 'A';\n                for (int p : pos[c_idx]) {\n                    LL best = INF;\n                    int best_prev = -1;\n                    for (int q : pos[p_c_idx]) {\n                        if (dp[ch-1][q] >= INF) continue;\n                        LL cand = dp[ch-1][q] + dist[q][p] + 1;\n                        if (cand < best) {\n                            best = cand;\n                            best_prev = q;\n                        }\n                    }\n                    dp[ch][p] = best;\n                    prev_step[ch][p] = best_prev;\n                }\n            }\n            LL bestcost = INF;\n            int final_pos = -1;\n            for (int p : pos[rem.back() - 'A']) {\n                if (dp[len-1][p] < bestcost) {\n                    bestcost = dp[len-1][p];\n                    final_pos = p;\n                }\n            }\n            vector<int> path(len);\n            int p = final_pos;\n            for (int ch = len-1; ch >= 0; --ch) {\n                path[ch] = p;\n                p = prev_step[ch][p];\n            }\n            // record order\n            order.push_back(chosen);\n            cur = final_pos;\n            S += rem;\n            covered[chosen] = true;\n            uncovered--;\n\n            // check other patterns that may now be contained\n            if ((int)S.size() >= 5) {\n                for (int i = 0; i < M; ++i) {\n                    if (covered[i]) continue;\n                    if (S.find(patterns[i]) != string::npos) {\n                        covered[i] = true;\n                        uncovered--;\n                    }\n                }\n            }\n        }\n\n        // compute cost for this trial\n        auto [total, moves] = compute_full_solution(order);\n        if (total < best_total) {\n            best_total = total;\n            best_moves = moves;\n        }\n    }\n\n    // Local search on best sequence: try swapping pairs in the order\n    // We'll perform a few iterations (10000 swaps) to try to improve\n    {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() < 1.9) {\n            // reconstruct current order from best_moves? Actually we need the order of patterns.\n            // We can build order from best_moves by scanning? Not trivial. We'll skip this step.\n            // Instead, we can just output best_moves as is.\n        }\n    }\n\n    // output best solution\n    for (int p : best_moves) {\n        cout << p / N << ' ' << p % N << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int MAX_CELLS = MAX_N * MAX_N;\n\nint N, M;\ndouble eps;\n\n// Pre-define structures\nstruct Placement {\n    vector<int> cells; // indices of covered cells (i*N+j)\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    vector<Placement> placements;\n    vector<bool> active; // true if placement still possible\n    int active_cnt;\n};\n\nvector<Field> fields;\nint drilled_v[MAX_CELLS]; // -1 unknown, else exact value\nint cover_count[MAX_CELLS]; // number of active placements covering this cell\nint ops = 0;\nconst int MAX_OPS = 2 * MAX_N * MAX_N;\n\n// For each cell, list of (field_index, placement_index)\nvector<pair<int,int>> cell_placements[MAX_CELLS];\n\n// For backtracking\nint cur_sum[MAX_CELLS];\nint found_solutions;\nvector<int> cur_assign; // placement index for each field\nvector<int> best_assign;\n\nvoid flush_output() {\n    cout.flush();\n}\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        vector<pair<int,int>> shape(d);\n        for (int l = 0; l < d; ++l) {\n            cin >> shape[l].first >> shape[l].second;\n        }\n        fields[k].shape = shape;\n    }\n}\n\nvoid generate_placements() {\n    for (int f = 0; f < M; ++f) {\n        const auto& shape = fields[f].shape;\n        int max_i = 0, max_j = 0;\n        for (const auto& p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int di = 0; di <= N - h; ++di) {\n            for (int dj = 0; dj <= N - w; ++dj) {\n                Placement pl;\n                for (const auto& p : shape) {\n                    int i = di + p.first;\n                    int j = dj + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                fields[f].placements.push_back(move(pl));\n            }\n        }\n        fields[f].active.assign(fields[f].placements.size(), true);\n        fields[f].active_cnt = fields[f].placements.size();\n    }\n}\n\nvoid build_cell_cover() {\n    for (int cell = 0; cell < N * N; ++cell) {\n        cell_placements[cell].clear();\n    }\n    for (int f = 0; f < M; ++f) {\n        int pid = 0;\n        for (const auto& pl : fields[f].placements) {\n            for (int cell : pl.cells) {\n                cell_placements[cell].push_back({f, pid});\n            }\n            ++pid;\n        }\n    }\n    // initial cover counts\n    memset(cover_count, 0, sizeof(cover_count));\n    for (int cell = 0; cell < N * N; ++cell) {\n        cover_count[cell] = cell_placements[cell].size();\n    }\n}\n\nint find_best_cell() {\n    int best_cell = -1, best_cnt = -1;\n    for (int cell = 0; cell < N * N; ++cell) {\n        if (drilled_v[cell] != -1) continue;\n        if (cover_count[cell] > best_cnt) {\n            best_cnt = cover_count[cell];\n            best_cell = cell;\n        }\n    }\n    return best_cell;\n}\n\nvoid eliminate_placement(int f, int pid) {\n    if (!fields[f].active[pid]) return;\n    fields[f].active[pid] = false;\n    fields[f].active_cnt--;\n    for (int cell : fields[f].placements[pid].cells) {\n        cover_count[cell]--;\n    }\n}\n\nvoid drill_cell(int cell) {\n    int i = cell / N, j = cell % N;\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    drilled_v[cell] = resp;\n    ops++;\n    if (resp == 0) {\n        // eliminate all placements covering this cell\n        for (auto [f, pid] : cell_placements[cell]) {\n            eliminate_placement(f, pid);\n        }\n    }\n}\n\n// ---- Backtracking ----\nbool can_place(int f, int pid) {\n    for (int cell : fields[f].placements[pid].cells) {\n        if (drilled_v[cell] != -1 && cur_sum[cell] + 1 > drilled_v[cell]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid dfs(int step, const vector<int>& order) {\n    if (found_solutions >= 2) return;\n    if (step == (int)order.size()) {\n        // check all drilled cells exactly\n        for (int cell = 0; cell < N * N; ++cell) {\n            if (drilled_v[cell] != -1 && cur_sum[cell] != drilled_v[cell]) {\n                return;\n            }\n        }\n        found_solutions++;\n        if (found_solutions == 1) {\n            best_assign = cur_assign;\n        }\n        return;\n    }\n    int f = order[step];\n    const auto& placements = fields[f].placements;\n    const auto& active = fields[f].active;\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        if (!active[pid]) continue;\n        if (!can_place(f, pid)) continue;\n        // place\n        cur_assign[f] = pid;\n        for (int cell : placements[pid].cells) {\n            cur_sum[cell]++;\n        }\n        dfs(step + 1, order);\n        // undo\n        for (int cell : placements[pid].cells) {\n            cur_sum[cell]--;\n        }\n        cur_assign[f] = -1;\n        if (found_solutions >= 2) return;\n    }\n}\n\nbool find_unique() {\n    found_solutions = 0;\n    // order fields by number of active placements (ascending)\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return fields[a].active_cnt < fields[b].active_cnt;\n    });\n    memset(cur_sum, 0, sizeof(cur_sum));\n    cur_assign.assign(M, -1);\n    best_assign.assign(M, -1);\n    dfs(0, order);\n    return (found_solutions == 1);\n}\n\nbool estimate_small() {\n    long long prod = 1;\n    for (int f = 0; f < M; ++f) {\n        int cnt = fields[f].active_cnt;\n        if (cnt == 0) return false;\n        prod *= cnt;\n        if (prod > 100000) return false;\n    }\n    return true;\n}\n\nvoid guess_and_check() {\n    // compute set of positive cells from best_assign\n    vector<int> pos_cells;\n    for (int f = 0; f < M; ++f) {\n        int pid = best_assign[f];\n        if (pid == -1) continue;\n        for (int cell : fields[f].placements[pid].cells) {\n            pos_cells.push_back(cell);\n        }\n    }\n    sort(pos_cells.begin(), pos_cells.end());\n    pos_cells.erase(unique(pos_cells.begin(), pos_cells.end()), pos_cells.end());\n    cout << \"a \" << pos_cells.size();\n    for (int cell : pos_cells) {\n        cout << \" \" << cell / N << \" \" << cell % N;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    ops++;\n    if (resp == 1) {\n        exit(0); // success, terminate\n    }\n    // else: wrong guess, continue\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n    generate_placements();\n    build_cell_cover();\n    memset(drilled_v, -1, sizeof(drilled_v));\n    ops = 0;\n\n    // Optional: perform row/col divine queries to gather information (can be used for pruning, but we will just ignore the answers)\n    // These are cheap (cost 2*N queries), but they may help later. We'll keep them.\n    // Note: The results are not used in the current pruning, but we can record them if needed.\n    // For now, we skip to avoid complexity. (They might add extra info but also cost extra operations.)\n    // Since we are in the early stage of drilling, we can skip them to reduce branching.\n\n    while (ops < MAX_OPS) {\n        // Try to guess if product of active placements is small\n        if (ops >= 10 && estimate_small()) {\n            if (find_unique()) {\n                guess_and_check();\n                // if guess fails, we continue drilling\n            }\n        }\n        int cell = find_best_cell();\n        if (cell == -1) break; // all cells drilled\n        drill_cell(cell);\n    }\n\n    // Fallback: drill any remaining cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int cell = i * N + j;\n            if (drilled_v[cell] == -1) {\n                drill_cell(cell);\n                if (ops >= MAX_OPS) break;\n            }\n        }\n        if (ops >= MAX_OPS) break;\n    }\n\n    // Now we have exact v for every cell, output answer\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (drilled_v[i * N + j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    cout << \"a \" << ans.size();\n    for (auto [i,j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <cassert>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n    int width() const { return i1 - i0; }\n    int height() const { return j1 - j0; }\n    int area() const { return width() * height(); }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // For each day, sort a and store ranked values.\n    vector<vector<int>> a_sorted(D, vector<int>(N));\n    vector<vector<int>> rank_of(D, vector<int>(N)); // original index -> rank after sorting\n    for (int d = 0; d < D; ++d) {\n        vector<pair<int, int>> tmp(N);\n        for (int k = 0; k < N; ++k) tmp[k] = {a[d][k], k};\n        sort(tmp.begin(), tmp.end());\n        for (int k = 0; k < N; ++k) {\n            a_sorted[d][k] = tmp[k].first;\n            rank_of[d][tmp[k].second] = k;\n        }\n    }\n\n    // Collect values for each rank (sorted per day) across days.\n    vector<vector<int>> val_per_rank(N);\n    for (int k = 0; k < N; ++k) {\n        val_per_rank[k].reserve(D);\n        for (int d = 0; d < D; ++d) {\n            val_per_rank[k].push_back(a_sorted[d][k]);\n        }\n        sort(val_per_rank[k].begin(), val_per_rank[k].end());\n    }\n\n    // Greedy allocation of areas to ranks (sorted b).\n    const long long MAX_AREA = W * W;\n    vector<long long> b(N, 0);\n    long long used_area = 0;\n\n    // Each entry: (gain, rank, next_break)\n    priority_queue<pair<long long, int>> pq; // gain = 100 * (D - idx), we store as positive.\n    vector<int> idx(N, 0);\n    vector<long long> next_break(N, 0);\n\n    auto push_rank = [&](int k) {\n        if (idx[k] < D) {\n            long long gain = 100LL * (D - idx[k]);\n            int next_val = val_per_rank[k][idx[k]];\n            pq.push({gain, k});\n            next_break[k] = next_val;\n        }\n    };\n    for (int k = 0; k < N; ++k) push_rank(k);\n\n    while (used_area < MAX_AREA && !pq.empty()) {\n        auto [gain, k] = pq.top(); pq.pop();\n        if (gain <= 0) break;\n        // current b[k] is before next_break\n        long long diff = next_break[k] - b[k];\n        if (diff <= 0) {\n            // already reached this breakpoint, update and push again\n            idx[k]++;\n            push_rank(k);\n            continue;\n        }\n        long long delta = min(diff, MAX_AREA - used_area);\n        b[k] += delta;\n        used_area += delta;\n        if (delta == diff) {\n            // reached breakpoint\n            idx[k]++;\n            push_rank(k);\n        } else {\n            // area exhausted\n            break;\n        }\n    }\n\n    // b now may not be sorted. We must work with sorted b for packing.\n    vector<long long> b_sorted = b;\n    sort(b_sorted.begin(), b_sorted.end());\n\n    // Pack rectangles of areas b_sorted (ascending). We will place largest first.\n    vector<long long> b_desc = b_sorted;\n    reverse(b_desc.begin(), b_desc.end());\n\n    vector<Rect> placed; // in order of b_desc\n    vector<Rect> free_list;\n    free_list.push_back({0, 0, W, W});\n\n    auto place_rect = [&](long long area, int free_idx, int w, int h) {\n        Rect r = free_list[free_idx];\n        // place at top-left corner of free rectangle\n        Rect new_rect = {r.i0, r.j0, r.i0 + w, r.j0 + h};\n        placed.push_back(new_rect);\n        // remove this free rectangle\n        free_list.erase(free_list.begin() + free_idx);\n        // add up to two new free rectangles\n        // right part (same height)\n        if (r.i0 + w < r.i1) {\n            free_list.push_back({r.i0 + w, r.j0, r.i1, r.j0 + h});\n        }\n        // bottom part (full width)\n        if (r.j0 + h < r.j1) {\n            free_list.push_back({r.i0, r.j0 + h, r.i1, r.j1});\n        }\n    };\n\n    for (long long area : b_desc) {\n        bool ok = false;\n        // iterate free rectangles in order (any order)\n        for (int fi = 0; fi < (int)free_list.size(); ++fi) {\n            Rect r = free_list[fi];\n            int w_avail = r.width();\n            int h_avail = r.height();\n            // try to factor area into w*h with integer coordinates\n            bool found = false;\n            int best_w = -1, best_h = -1;\n            // iterate divisors up to sqrt\n            for (int w = 1; w * w <= area; ++w) {\n                if (area % w == 0) {\n                    int h = area / w;\n                    // try w <= w_avail, h <= h_avail\n                    if (w <= w_avail && h <= h_avail) {\n                        best_w = w; best_h = h; found = true; break;\n                    }\n                    // try swapped\n                    int w2 = h, h2 = w;\n                    if (w2 <= w_avail && h2 <= h_avail) {\n                        best_w = w2; best_h = h2; found = true; break;\n                    }\n                }\n            }\n            if (found) {\n                place_rect(area, fi, best_w, best_h);\n                ok = true;\n                break;\n            }\n        }\n        if (!ok) {\n            // fallback: reduce area by 1 and try again (should rarely happen)\n            long long reduced = area - 1;\n            while (reduced > 0) {\n                for (int fi = 0; fi < (int)free_list.size(); ++fi) {\n                    Rect r = free_list[fi];\n                    int w_avail = r.width();\n                    int h_avail = r.height();\n                    for (int w = 1; w * w <= reduced; ++w) {\n                        if (reduced % w == 0) {\n                            int h = reduced / w;\n                            if (w <= w_avail && h <= h_avail) {\n                                place_rect(reduced, fi, w, h);\n                                ok = true;\n                                break;\n                            }\n                            int w2 = h, h2 = w;\n                            if (w2 <= w_avail && h2 <= h_avail) {\n                                place_rect(reduced, fi, w2, h2);\n                                ok = true;\n                                break;\n                            }\n                        }\n                    }\n                    if (ok) break;\n                }\n                if (ok) break;\n                reduced--;\n            }\n            if (!ok) {\n                // Very rare: fallback to 1x1 rectangle (area 1)\n                place_rect(1, 0, 1, 1);\n            }\n        }\n    }\n\n    // placed rectangles are in order of b_desc. Map to rank (ascending area).\n    // placed[i] corresponds to b_desc[i] => rank = N-1-i.\n    vector<Rect> rect_by_rank(N);\n    for (int i = 0; i < N; ++i) {\n        rect_by_rank[N - 1 - i] = placed[i];\n    }\n\n    // Output for each day\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            int r = rank_of[d][k]; // rank of this reservation's desired area\n            const Rect& rr = rect_by_rank[r];\n            cout << rr.i0 << ' ' << rr.j0 << ' ' << rr.i1 << ' ' << rr.j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\n\nstruct Operation {\n    int m, p, q;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n    // n=9, m=20, k=81 always\n\n    vector<vector<ll>> board(N, vector<ll>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> board[i][j];\n\n    vector<vector<vector<ll>>> stamps(M, vector<vector<ll>>(3, vector<ll>(3)));\n    for (int id = 0; id < M; ++id)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamps[id][i][j];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    // initial score (sum of remainders)\n    ll initial_score = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            initial_score += board[i][j] % MOD;\n\n    pair<ll, vector<Operation>> best = {0, {}};\n    const int TRIALS = 15; // enough time\n\n    // helper lambda: compute gain of applying a stamp (without changing board)\n    auto compute_gain = [&](const vector<vector<ll>>& cur, int m, int p, int q) -> ll {\n        ll gain = 0;\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j) {\n                ll x = cur[p + i][q + j];\n                gain += ((x + stamps[m][i][j]) % MOD) - (x % MOD);\n            }\n        return gain;\n    };\n\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // check time limit\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() > 1900)\n            break;\n\n        vector<vector<ll>> cur = board;\n        vector<Operation> ops;\n        ll cur_score = initial_score;\n\n        // ---------- greedy construction ----------\n        while ((int)ops.size() < K) {\n            vector<pair<ll, Operation>> candidates;\n            ll best_gain = -1e18;\n            for (int mm = 0; mm < M; ++mm) {\n                for (int p = 0; p + 2 < N; ++p) {\n                    for (int q = 0; q + 2 < N; ++q) {\n                        ll gain = compute_gain(cur, mm, p, q);\n                        if (gain > best_gain) {\n                            best_gain = gain;\n                            candidates.clear();\n                            candidates.push_back({gain, {mm, p, q}});\n                        } else if (gain == best_gain && gain > 0) {\n                            candidates.push_back({gain, {mm, p, q}});\n                        }\n                    }\n                }\n            }\n            if (candidates.empty()) break;\n            uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);\n            auto op = candidates[dist(rng)].second;\n            // apply stamp\n            for (int i = 0; i < 3; ++i)\n                for (int j = 0; j < 3; ++j)\n                    cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n            cur_score += best_gain;\n            ops.push_back(op);\n        }\n\n        // ---------- local search ----------\n        bool improved = true;\n        int max_passes = 20;\n        while (improved && max_passes-- > 0) {\n            improved = false;\n\n            // ---- A: replace each operation with the best possible ----\n            vector<int> indices(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                Operation old_op = ops[idx];\n                // remove old_op (subtract stamp)\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[old_op.p + i][old_op.q + j] -= stamps[old_op.m][i][j];\n                // recompute score delta for this 3x3 area\n                // we can recompute whole score quickly but we just recompute the area effect\n                ll old_area_sum = 0, new_area_sum = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        // old before removal = (cur after removal) + stamp value\n                        ll after = cur[old_op.p + i][old_op.q + j];\n                        old_area_sum += (after + stamps[old_op.m][i][j]) % MOD;\n                        new_area_sum += after % MOD;\n                    }\n                ll delta = new_area_sum - old_area_sum; // negative if removal is good\n                cur_score += delta;\n\n                // find best stamp to add now\n                ll best_gain = -1e18;\n                Operation best_op;\n                for (int mm = 0; mm < M; ++mm) {\n                    for (int p = 0; p + 2 < N; ++p) {\n                        for (int q = 0; q + 2 < N; ++q) {\n                            ll gain = compute_gain(cur, mm, p, q);\n                            if (gain > best_gain) {\n                                best_gain = gain;\n                                best_op = {mm, p, q};\n                            }\n                        }\n                    }\n                }\n                if (best_gain > 0 && best_gain > -delta) {\n                    // apply best_op\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[best_op.p + i][best_op.q + j] += stamps[best_op.m][i][j];\n                    cur_score += best_gain;\n                    ops[idx] = best_op;\n                    improved = true;\n                } else {\n                    // restore old_op\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[old_op.p + i][old_op.q + j] += stamps[old_op.m][i][j];\n                    cur_score -= delta; // revert the score change\n                }\n            }\n\n            // ---- B: remove operations that have negative contribution ----\n            indices.resize(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                if (ops.empty()) break;\n                Operation op = ops[idx];\n                // remove\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[op.p + i][op.q + j] -= stamps[op.m][i][j];\n                ll old_area = 0, new_area = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        ll after = cur[op.p + i][op.q + j];\n                        old_area += (after + stamps[op.m][i][j]) % MOD;\n                        new_area += after % MOD;\n                    }\n                ll delta = new_area - old_area;\n                cur_score += delta;\n                if (delta > 0) { // removal increased total score\n                    ops.erase(ops.begin() + idx);\n                    improved = true;\n                } else {\n                    // restore\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n                    cur_score -= delta;\n                }\n            }\n\n            // ---- C: fill empty slots (if any) with greedy addition ----\n            while ((int)ops.size() < K) {\n                ll best_gain = -1e18;\n                Operation best_op;\n                for (int mm = 0; mm < M; ++mm) {\n                    for (int p = 0; p + 2 < N; ++p) {\n                        for (int q = 0; q + 2 < N; ++q) {\n                            ll gain = compute_gain(cur, mm, p, q);\n                            if (gain > best_gain) {\n                                best_gain = gain;\n                                best_op = {mm, p, q};\n                            }\n                        }\n                    }\n                }\n                if (best_gain <= 0) break;\n                // apply best\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[best_op.p + i][best_op.q + j] += stamps[best_op.m][i][j];\n                cur_score += best_gain;\n                ops.push_back(best_op);\n                improved = true;\n            }\n        }\n\n        // keep best solution\n        if (cur_score > best.first) {\n            best = {cur_score, ops};\n        }\n    }\n\n    // output answer\n    cout << best.second.size() << \"\\n\";\n    for (const auto& op : best.second) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;                     // N is always 5\nint A[N][N];\nint targetRow[25];                   // targetRow[num] = num/5\nint arrivalRow[25];\nint arrivalIdx[25];\n\n// State\nint craneR = 0, craneC = 0;\nbool holding = false;\nint heldContainer = -1;\nint storageTargetR = -1, storageTargetC = -1;\nint nextDispatch = 0;\nbool dispatched[25] = {false};\n\nint grid[N][N];                      // -1 = empty, else container number\n\nint gateCurrent[N];\nint nextIdx[N];\n\n// Helper functions\nvoid placeContainer(int num, int r, int c) {\n    grid[r][c] = num;\n}\n\nvoid removeContainer(int r, int c) {\n    grid[r][c] = -1;\n}\n\npair<int,int> findStorageCell(int targetR) {\n    int bestDist = 100;\n    pair<int,int> best = {-1,-1};\n    for (int r = 0; r < N; ++r) {\n        for (int c = 1; c <= 3; ++c) {\n            if (grid[r][c] == -1 && !(r == craneR && c == craneC)) {\n                int dist = abs(r - targetR) + abs(c - 4);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    best = {r, c};\n                }\n            }\n        }\n    }\n    return best;\n}\n\nchar getAction() {\n    if (holding) {\n        int targetGateR = targetRow[heldContainer];\n        if (craneR == targetGateR && craneC == 4) {\n            return 'Q';\n        }\n        if (heldContainer == nextDispatch) {\n            if (craneR < targetGateR) return 'D';\n            if (craneR > targetGateR) return 'U';\n            if (craneC < 4) return 'R';\n            if (craneC > 4) return 'L';\n        } else {\n            if (craneR < storageTargetR) return 'D';\n            if (craneR > storageTargetR) return 'U';\n            if (craneC < storageTargetC) return 'R';\n            if (craneC > storageTargetC) return 'L';\n        }\n        return '.';\n    } else {\n        if (nextDispatch >= 25) return '.';\n        if (grid[craneR][craneC] == nextDispatch) {\n            return 'P';\n        }\n        bool found = false;\n        int pr = -1, pc = -1;\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                if (grid[r][c] == nextDispatch) {\n                    pr = r; pc = c;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n        if (found) {\n            if (craneR < pr) return 'D';\n            if (craneR > pr) return 'U';\n            if (craneC < pc) return 'R';\n            if (craneC > pc) return 'L';\n        }\n        int ar = arrivalRow[nextDispatch];\n        if (gateCurrent[ar] != -1 && gateCurrent[ar] != nextDispatch) {\n            if (craneR == ar && craneC == 0) {\n                return 'P';\n            } else {\n                if (craneR < ar) return 'D';\n                if (craneR > ar) return 'U';\n                if (craneC > 0) return 'L';\n                return '.';\n            }\n        }\n        return '.';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read N (always 5, ignore)\n    int dummyN;\n    cin >> dummyN;\n    // Read the N x N container numbers\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Precompute targetRow, arrivalRow, arrivalIdx\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int num = A[i][j];\n            targetRow[num] = num / N;\n            arrivalRow[num] = i;\n            arrivalIdx[num] = j;\n        }\n    }\n\n    memset(grid, -1, sizeof(grid));\n    memset(gateCurrent, -1, sizeof(gateCurrent));\n    memset(nextIdx, 0, sizeof(nextIdx));\n\n    vector<string> out(N);\n\n    // Turn 1: bomb small cranes\n    out[0] += '.';\n    for (int i = 1; i < N; ++i) {\n        out[i] += 'B';\n    }\n\n    // Main loop\n    for (int turn = 2; turn <= 10000; ++turn) {\n        // Step 1: place new containers at receiving gates\n        for (int i = 0; i < N; ++i) {\n            if (gateCurrent[i] == -1 && nextIdx[i] < N) {\n                int num = A[i][nextIdx[i]++];\n                gateCurrent[i] = num;\n                placeContainer(num, i, 0);\n            }\n        }\n\n        // Step 2: decide action for the large crane\n        char action = getAction();\n\n        // Execute action\n        if (action == 'P') {\n            int num = grid[craneR][craneC];\n            if (num != -1) {\n                holding = true;\n                heldContainer = num;\n                removeContainer(craneR, craneC);\n                if (craneC == 0) {\n                    int row = craneR;\n                    if (gateCurrent[row] == num) {\n                        gateCurrent[row] = -1;\n                    }\n                }\n                if (num != nextDispatch) {\n                    auto [sr, sc] = findStorageCell(targetRow[num]);\n                    storageTargetR = sr;\n                    storageTargetC = sc;\n                }\n            } else {\n                action = '.';\n            }\n        } else if (action == 'Q') {\n            if (holding) {\n                int num = heldContainer;\n                grid[craneR][craneC] = num;\n                holding = false;\n            } else {\n                action = '.';\n            }\n        } else if (action == 'U') {\n            if (craneR > 0) craneR--;\n        } else if (action == 'D') {\n            if (craneR < N-1) craneR++;\n        } else if (action == 'L') {\n            if (craneC > 0) craneC--;\n        } else if (action == 'R') {\n            if (craneC < N-1) craneC++;\n        }\n\n        out[0] += action;\n        for (int i = 1; i < N; ++i) {\n            out[i] += '.';\n        }\n\n        // Step 3: dispatch containers at right edge\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][4] != -1) {\n                int num = grid[i][4];\n                grid[i][4] = -1;\n                dispatched[num] = true;\n                if (num == nextDispatch) {\n                    while (nextDispatch < 25 && dispatched[nextDispatch]) {\n                        nextDispatch++;\n                    }\n                }\n            }\n        }\n\n        if (nextDispatch >= 25) break;\n    }\n\n    // Pad all output strings to the same length and print\n    size_t maxLen = 0;\n    for (int i = 0; i < N; ++i) {\n        maxLen = max(maxLen, out[i].size());\n    }\n    for (int i = 0; i < N; ++i) {\n        while (out[i].size() < maxLen) out[i] += '.';\n        cout << out[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\nusing ll = long long;\n\nstruct Node {\n    int x, y, delta;\n};\n\nint N;\nvector<Node> nodes;          // cells with non-zero height\nvector<vector<int>> dist;    // pairwise Manhattan distances between nodes\nvector<int> dist_start;      // distance from (0,0) to each node\nint M;                       // number of nodes\n\n// compute total movement cost for a given order (list of node indices)\nll compute_cost(const vector<int>& order) {\n    ll cost = 0;\n    int load = 0;\n    // move from start to first node\n    cost += (100LL + load) * dist_start[order[0]];\n    load += nodes[order[0]].delta;\n    // move between nodes\n    for (size_t i = 1; i < order.size(); ++i) {\n        int prev = order[i-1];\n        int cur = order[i];\n        cost += (100LL + load) * dist[prev][cur];\n        load += nodes[cur].delta;\n    }\n    return cost;\n}\n\n// check if the order is feasible: cumulative load never negative\nbool feasible(const vector<int>& order) {\n    int load = 0;\n    for (int idx : order) {\n        load += nodes[idx].delta;\n        if (load < 0) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ---------- Input ----------\n    cin >> N;\n    vector<vector<int>> height(N, vector<int>(N));\n    ll base = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> height[i][j];\n            base += abs(height[i][j]);\n            if (height[i][j] != 0) {\n                nodes.push_back({i, j, height[i][j]});\n            }\n        }\n    }\n    M = nodes.size();\n\n    // If all heights are already zero, output nothing\n    if (M == 0) {\n        return 0;\n    }\n\n    // ---------- Precompute distances ----------\n    dist.assign(M, vector<int>(M, 0));\n    dist_start.assign(M, 0);\n    for (int i = 0; i < M; ++i) {\n        dist_start[i] = nodes[i].x + nodes[i].y; // Manhattan from (0,0)\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            dist[i][j] = abs(nodes[i].x - nodes[j].x) + abs(nodes[i].y - nodes[j].y);\n        }\n    }\n\n    // ---------- Build initial feasible order (greedy with load) ----------\n    // At each step, among all feasible next nodes, pick the one that minimizes\n    // (100 + current_load) * distance from current position.\n    vector<int> order;\n    order.reserve(M);\n    vector<bool> used(M, false);\n    int load = 0;\n\n    for (int step = 0; step < M; ++step) {\n        int best = -1;\n        ll best_cost = 1e18;\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            // feasibility: cannot unload more than we have\n            if (nodes[i].delta < 0 && load < -nodes[i].delta) continue;\n            int d = (step == 0) ? dist_start[i] : dist[order.back()][i];\n            ll cost = (100LL + load) * d;\n            if (cost < best_cost) {\n                best_cost = cost;\n                best = i;\n            }\n        }\n        order.push_back(best);\n        used[best] = true;\n        load += nodes[best].delta;\n    }\n\n    // ---------- Simulated Annealing ----------\n    ll best_cost = compute_cost(order);\n    vector<int> best_order = order;\n    vector<int> cur_order = order;\n    ll cur_cost = best_cost;\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    const double T_start = 1e6;\n    const double T_end = 0.1;\n    const int iterations = 2000000;   // up to 2 million moves, time-controlled\n    double T = T_start;\n    auto start_time = chrono::steady_clock::now();\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        // Time check every 1000 iterations\n        if (iter % 1000 == 0) {\n            if (chrono::duration_cast<chrono::milliseconds>(\n                    chrono::steady_clock::now() - start_time).count() > 1850) break;\n        }\n\n        // Generate neighbor: swap or reverse\n        vector<int> new_order = cur_order;\n        int type = rng() % 2;\n        if (type == 0) {\n            // swap two random positions\n            int i = uniform_int_distribution<int>(0, M-1)(rng);\n            int j = uniform_int_distribution<int>(0, M-1)(rng);\n            if (i == j) continue;\n            swap(new_order[i], new_order[j]);\n        } else {\n            // reverse a random segment\n            int l = uniform_int_distribution<int>(0, M-1)(rng);\n            int r = uniform_int_distribution<int>(0, M-1)(rng);\n            if (l > r) swap(l, r);\n            reverse(new_order.begin() + l, new_order.begin() + r + 1);\n        }\n\n        if (!feasible(new_order)) continue;\n\n        ll new_cost = compute_cost(new_order);\n        double delta = new_cost - cur_cost;\n        if (delta < 0 ||\n            exp(-delta / T) > uniform_real_distribution<double>(0.0, 1.0)(rng)) {\n            cur_order = move(new_order);\n            cur_cost = new_cost;\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_order = cur_order;\n            }\n        }\n\n        // Cool down\n        double progress = (double)iter / iterations;\n        T = T_start * pow(T_end / T_start, progress);\n    }\n\n    // ---------- Output ----------\n    vector<string> ops;\n    int cx = 0, cy = 0; // current position\n\n    for (int idx : best_order) {\n        int nx = nodes[idx].x;\n        int ny = nodes[idx].y;\n        // Move step by step\n        while (cx < nx) { ops.push_back(\"D\"); cx++; }\n        while (cx > nx) { ops.push_back(\"U\"); cx--; }\n        while (cy < ny) { ops.push_back(\"R\"); cy++; }\n        while (cy > ny) { ops.push_back(\"L\"); cy--; }\n        // Perform operation\n        int d = nodes[idx].delta;\n        if (d > 0) {\n            ops.push_back(\"+\" + to_string(d));\n        } else if (d < 0) {\n            ops.push_back(\"-\" + to_string(-d));\n        }\n    }\n\n    // Output\n    for (const string& s : ops) {\n        cout << s << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <unordered_set>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int SEED_COUNT = 2 * N * (N - 1); // 60\n    const int GRID_SIZE = N * N;           // 36\n\n    vector<vector<int>> X(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> X[i][j];\n        }\n    }\n\n    for (int turn = 0; turn < T; ++turn) {\n        // 1. Evaluate current seeds\n        vector<int> sumX(SEED_COUNT, 0);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            sumX[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // best overall seed (max sum)\n        int bestIdx = max_element(sumX.begin(), sumX.end()) - sumX.begin();\n\n        // per\u2011dimension best seeds\n        vector<int> dimMax(M, -1), dimIdx(M, -1);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int l = 0; l < M; ++l) {\n                if (X[i][l] > dimMax[l]) {\n                    dimMax[l] = X[i][l];\n                    dimIdx[l] = i;\n                }\n            }\n        }\n\n        // 2. Build the set of elite seeds (best overall + per\u2011dimension best)\n        unordered_set<int> eliteSet;\n        eliteSet.insert(bestIdx);\n        for (int l = 0; l < M; ++l) {\n            eliteSet.insert(dimIdx[l]);\n        }\n        vector<int> elite(eliteSet.begin(), eliteSet.end());\n\n        // 3. Select 36 seeds: all elites + top sum among the rest\n        vector<bool> used(SEED_COUNT, false);\n        for (int idx : elite) used[idx] = true;\n        vector<int> additional;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (!used[i]) additional.push_back(i);\n        }\n        sort(additional.begin(), additional.end(), [&](int a, int b) {\n            return sumX[a] > sumX[b];\n        });\n        int needFromAdd = GRID_SIZE - (int)elite.size();\n        // selected = elite + first needFromAdd of additional\n        vector<int> selected = elite;\n        selected.insert(selected.end(), additional.begin(), additional.begin() + needFromAdd);\n\n        // 4. Partition into interior (16) and border (20) seeds\n        int interiorSize = (N - 2) * (N - 2); // 16\n        int eliteSize = (int)elite.size();\n        int takeFromAdd = min(interiorSize - eliteSize, needFromAdd);\n        vector<int> interiorSeeds(elite.begin(), elite.end());\n        interiorSeeds.insert(interiorSeeds.end(), additional.begin(), additional.begin() + takeFromAdd);\n        // borderSeeds: the rest of selected\n        vector<int> borderSeeds(additional.begin() + takeFromAdd, additional.begin() + needFromAdd);\n        // sanity: (int)selected.size() == GRID_SIZE\n        // (int)interiorSeeds.size() == interiorSize\n        // borderSeeds.size() == GRID_SIZE - interiorSize\n\n        // 5. Build the placement grid\n        vector<vector<int>> A(N, vector<int>(N, -1));\n\n        // 5a. Define interior positions (1,\u2026,N-2)\n        vector<pair<int,int>> interiorPos;\n        for (int i = 1; i <= N-2; ++i)\n            for (int j = 1; j <= N-2; ++j)\n                interiorPos.push_back({i, j});\n\n        // 5b. Place the best overall at the centre (2,2)\n        int centre_i = 2, centre_j = 2; // 0\u2011based, inside interior\n        A[centre_i][centre_j] = bestIdx;\n\n        // Remove bestIdx from interiorSeeds (it's the first one)\n        auto it = find(interiorSeeds.begin(), interiorSeeds.end(), bestIdx);\n        if (it != interiorSeeds.end()) interiorSeeds.erase(it);\n        // Now interiorSeeds has size = interiorSize - 1 = 15\n\n        // Compute complement scores with bestIdx\n        vector<pair<int,int>> compScores; // (score, seedIdx)\n        for (int idx : interiorSeeds) {\n            int score = 0;\n            for (int l = 0; l < M; ++l) {\n                score += max(X[bestIdx][l], X[idx][l]);\n            }\n            compScores.push_back({-score, idx}); // negative for descending sort\n        }\n        sort(compScores.begin(), compScores.end());\n        // Top 4 become neighbours\n        vector<pair<int,int>> neighPos = {{centre_i-1, centre_j},\n                                          {centre_i+1, centre_j},\n                                          {centre_i, centre_j-1},\n                                          {centre_i, centre_j+1}};\n        unordered_set<int> usedInterior;\n        usedInterior.insert(bestIdx);\n        for (int k = 0; k < 4; ++k) {\n            int idx = compScores[k].second;\n            int ni = neighPos[k].first, nj = neighPos[k].second;\n            A[ni][nj] = idx;\n            usedInterior.insert(idx);\n        }\n\n        // 5d. Assign remaining interior seeds to remaining interior positions\n        // Remaining interior positions (exclude centre and neighbours)\n        vector<pair<int,int>> restInteriorPos;\n        for (auto [i,j] : interiorPos) {\n            if (i == centre_i && j == centre_j) continue;\n            bool isNeigh = false;\n            for (auto [ni,nj] : neighPos) if (ni==i && nj==j) { isNeigh = true; break; }\n            if (!isNeigh) restInteriorPos.push_back({i,j});\n        }\n        // Get the remaining seeds (not used)\n        vector<int> restSeeds;\n        for (int idx : interiorSeeds) {\n            if (!usedInterior.count(idx)) restSeeds.push_back(idx);\n        }\n        // restSeeds.size() should be 11\n        for (size_t k = 0; k < restInteriorPos.size(); ++k) {\n            A[restInteriorPos[k].first][restInteriorPos[k].second] = restSeeds[k];\n        }\n\n        // 5e. Fill border cells with borderSeeds\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (A[i][j] == -1) {\n                    A[i][j] = borderSeeds.back();\n                    borderSeeds.pop_back();\n                }\n            }\n        }\n\n        // 6. Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << A[i][j];\n                if (j < N-1) cout << ' ';\n            }\n            cout << '\\n';\n        }\n        cout << flush;\n\n        // 7. Read the new generation of seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<string> s_str, t_str;\nvector<vector<bool>> source, target;\n\nint root_x = 0, root_y = 0;\nint V_used;\nvector<int> parent, length;\nvector<int> dir;        // 0:right, 1:down, 2:left, 3:up\nvector<bool> holding;\n\nvector<string> commands;\n\nconst vector<pair<int,int>> offset_dir = {{0,1}, {1,0}, {0,-1}, {-1,0}};\n\nvoid rotate_leaf(int i, char c) {\n    if (c == 'R') dir[i] = (dir[i] + 1) % 4;\n    else if (c == 'L') dir[i] = (dir[i] + 3) % 4;\n}\n\n// get all four possible positions for a leaf of length L from (rx,ry)\nvector<pair<int,int>> get_positions(int rx, int ry, int L) {\n    vector<pair<int,int>> res;\n    for (int d = 0; d < 4; ++d) {\n        int nx = rx + offset_dir[d].first * L;\n        int ny = ry + offset_dir[d].second * L;\n        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n            res.emplace_back(nx, ny);\n        }\n    }\n    return res;\n}\n\n// Kuhn DFS for bipartite matching\nbool dfs(int u, const vector<vector<int>>& adj, vector<int>& matchR, vector<bool>& visited) {\n    for (int v : adj[u]) {\n        if (!visited[v]) {\n            visited[v] = true;\n            if (matchR[v] == -1 || dfs(matchR[v], adj, matchR, visited)) {\n                matchR[v] = u;\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n    s_str.resize(N);\n    t_str.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n\n    source.assign(N, vector<bool>(N, false));\n    target.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') source[i][j] = true;\n            if (t_str[i][j] == '1') target[i][j] = true;\n        }\n    }\n\n    // ---- design tree (star with lengths 1..V-1) ----\n    V_used = V;\n    parent.assign(V_used, 0);\n    length.assign(V_used, 0);\n    for (int i = 1; i < V_used; ++i) {\n        parent[i] = 0;\n        length[i] = i;\n    }\n\n    cout << V_used << '\\n';\n    for (int i = 1; i < V_used; ++i) {\n        cout << parent[i] << ' ' << length[i] << '\\n';\n    }\n    root_x = 0; root_y = 0;\n    cout << root_x << ' ' << root_y << '\\n';\n\n    dir.assign(V_used, 0);\n    holding.assign(V_used, false);\n\n    int total_source = M;\n    int total_target = M;\n    int turn_count = 0;\n    const int MAX_TURNS = 100000;\n\n    while ((total_source > 0 || total_target > 0) && turn_count < MAX_TURNS) {\n        // find best root position (max immediate actions, then min distance)\n        int best_cnt = -1;\n        int best_rx = -1, best_ry = -1;\n        for (int rx = 0; rx < N; ++rx) {\n            for (int ry = 0; ry < N; ++ry) {\n                int cnt = 0;\n                for (int i = 1; i < V_used; ++i) {\n                    int L = length[i];\n                    auto pos = get_positions(rx, ry, L);\n                    for (auto [cx, cy] : pos) {\n                        if (!holding[i] && source[cx][cy] && !target[cx][cy]) { cnt++; break; }\n                        if ( holding[i] && target[cx][cy] && !source[cx][cy]) { cnt++; break; }\n                    }\n                }\n                if (cnt > best_cnt) {\n                    best_cnt = cnt;\n                    best_rx = rx;\n                    best_ry = ry;\n                } else if (cnt == best_cnt) {\n                    int dist = abs(rx - root_x) + abs(ry - root_y);\n                    int best_dist = abs(best_rx - root_x) + abs(best_ry - root_y);\n                    if (dist < best_dist) {\n                        best_rx = rx; best_ry = ry;\n                    }\n                }\n            }\n        }\n        if (best_cnt == 0) break; // no valid actions left (should not happen)\n\n        // move root to best position\n        while ((root_x != best_rx || root_y != best_ry) && turn_count < MAX_TURNS) {\n            char move_char = '.';\n            int dx = best_rx - root_x, dy = best_ry - root_y;\n            if (dx > 0) { move_char = 'D'; root_x++; }\n            else if (dx < 0) { move_char = 'U'; root_x--; }\n            else if (dy > 0) { move_char = 'R'; root_y++; }\n            else if (dy < 0) { move_char = 'L'; root_y--; }\n\n            string rot(V_used - 1, '.');\n            string action(V_used, '.');\n            commands.push_back(move_char + rot + action);\n            turn_count++;\n        }\n        if (turn_count >= MAX_TURNS) break;\n\n        // perform actions at current root until no more matches\n        while (turn_count < MAX_TURNS) {\n            // build bipartite graph: leaves -> cells\n            map<pair<int,int>, int> cell_id;\n            vector<pair<int,int>> id_cell;\n            vector<vector<int>> adj(V_used);\n\n            for (int i = 1; i < V_used; ++i) {\n                int L = length[i];\n                auto pos = get_positions(best_rx, best_ry, L);\n                for (auto [cx, cy] : pos) {\n                    bool ok = false;\n                    if (!holding[i] && source[cx][cy] && !target[cx][cy]) ok = true;\n                    if ( holding[i] && target[cx][cy] && !source[cx][cy]) ok = true;\n                    if (ok) {\n                        auto key = make_pair(cx, cy);\n                        if (cell_id.find(key) == cell_id.end()) {\n                            cell_id[key] = id_cell.size();\n                            id_cell.push_back(key);\n                        }\n                        adj[i].push_back(cell_id[key]);\n                    }\n                }\n            }\n\n            int item_cnt = id_cell.size();\n            vector<int> matchR(item_cnt, -1);\n            int matching = 0;\n            for (int i = 1; i < V_used; ++i) {\n                vector<bool> visited(item_cnt, false);\n                if (dfs(i, adj, matchR, visited)) matching++;\n            }\n            if (matching == 0) break;\n\n            // assign cells to leaves\n            vector<pair<int,int>> leaf_target(V_used, {-1, -1});\n            for (int v = 0; v < item_cnt; ++v) {\n                if (matchR[v] != -1) {\n                    leaf_target[matchR[v]] = id_cell[v];\n                }\n            }\n\n            // compute target directions for matched leaves\n            vector<int> target_dir(V_used, -1);\n            for (int i = 1; i < V_used; ++i) {\n                auto [cx, cy] = leaf_target[i];\n                if (cx == -1) continue;\n                int L = length[i];\n                int dx = cx - best_rx, dy = cy - best_ry;\n                if (dx == 0 && dy == L) target_dir[i] = 0;\n                else if (dx == L && dy == 0) target_dir[i] = 1;\n                else if (dx == 0 && dy == -L) target_dir[i] = 2;\n                else if (dx == -L && dy == 0) target_dir[i] = 3;\n            }\n\n            // rotate leaves to target directions\n            while (true) {\n                if (turn_count >= MAX_TURNS) break;\n                bool all_aligned = true;\n                string rot = \"\";\n                for (int i = 1; i < V_used; ++i) {\n                    if (target_dir[i] == -1) { rot += '.'; continue; }\n                    int cur = dir[i];\n                    int tgt = target_dir[i];\n                    int diff = (tgt - cur + 4) % 4;\n                    char c = '.';\n                    if (diff == 1) c = 'R';\n                    else if (diff == 2) { c = 'R'; } // two rotations: can do R twice, but one turn only one rotation? Actually we can rotate by 180? The operation allows rotating by 90 degrees either direction. Two rotations would require two turns. So we need to do one rotation per turn. So we can only rotate 90 or -90 each turn. For diff==2, we need two turns. But our loop will continue. However, the direction change is done in the loop by repeatedly applying rotations. So we need to handle diff==2 as requiring two separate turns. Our code currently sets c='R' for diff==2, which rotates 90 clockwise, but we need to rotate 180. Better to choose any single rotation; the loop will then check again. So it's fine.\n                    else if (diff == 3) c = 'L';\n                    rot += c;\n                    if (c != '.') all_aligned = false;\n                    rotate_leaf(i, c);\n                }\n                if (all_aligned) break;\n                string action(V_used, '.');\n                commands.push_back('.' + rot + action);\n                turn_count++;\n            }\n            if (turn_count >= MAX_TURNS) break;\n\n            // action turn: pick or place\n            string rot(V_used - 1, '.');\n            string action = \".\";\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) action += 'P';\n                else action += '.';\n            }\n            commands.push_back('.' + rot + action);\n            turn_count++;\n\n            // update state\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) {\n                    auto [cx, cy] = leaf_target[i];\n                    if (!holding[i]) {\n                        source[cx][cy] = false;\n                        holding[i] = true;\n                        total_source--;\n                    } else {\n                        target[cx][cy] = false;\n                        holding[i] = false;\n                        total_target--;\n                    }\n                }\n            }\n            if (total_source == 0 && total_target == 0) break;\n        }\n    }\n\n    // output all commands\n    for (const string& cmd : commands) {\n        cout << cmd << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\n#include <atcoder/dsu>\nusing namespace std;\nusing ll = long long;\n\nconst int COORD_MAX = 100000;\nconst int PERIMETER_LIMIT = 400000;\nconst int TILE_SIZE = 500;          // tune between 250 and 1000\nconst int TILES = (COORD_MAX / TILE_SIZE) + 1; // 201\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<pair<int,int>> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].first >> mackerels[i].second;\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].first >> sardines[i].second;\n    }\n\n    // Build tile grid with weights (+1 for mackerel, -1 for sardine)\n    vector<vector<ll>> score(TILES, vector<ll>(TILES, 0));\n    for (auto [x, y] : mackerels) {\n        int tx = x / TILE_SIZE;\n        int ty = y / TILE_SIZE;\n        score[tx][ty] += 1;\n    }\n    for (auto [x, y] : sardines) {\n        int tx = x / TILE_SIZE;\n        int ty = y / TILE_SIZE;\n        score[tx][ty] -= 1;\n    }\n\n    // Prefix sum for tile grid\n    vector<vector<ll>> pref(TILES+1, vector<ll>(TILES+1, 0));\n    for (int i = 0; i < TILES; ++i) {\n        for (int j = 0; j < TILES; ++j) {\n            pref[i+1][j+1] = pref[i][j+1] + pref[i+1][j] - pref[i][j] + score[i][j];\n        }\n    }\n\n    // Find best rectangle of tiles under perimeter constraint\n    ll best_sum = -1e18;\n    int best_r1 = 0, best_r2 = 0, best_c1 = 0, best_c2 = 0;\n\n    for (int r1 = 0; r1 < TILES; ++r1) {\n        vector<ll> colSum(TILES, 0);\n        for (int r2 = r1; r2 < TILES; ++r2) {\n            // add current row to column sums\n            for (int c = 0; c < TILES; ++c) {\n                colSum[c] += score[r2][c];\n            }\n            int dx = r2 - r1 + 1;               // number of rows\n            int max_dy = (PERIMETER_LIMIT / (2 * TILE_SIZE)) - dx; // max allowed columns\n            if (max_dy <= 0) continue;\n            max_dy = min(max_dy, TILES);\n\n            // Find maximum subarray sum of colSum with length <= max_dy\n            // Using prefix sums and a deque (monotonic queue)\n            vector<ll> prefCol(TILES + 1, 0);\n            for (int i = 0; i < TILES; ++i) prefCol[i+1] = prefCol[i] + colSum[i];\n\n            deque<int> dq;\n            ll local_best = -1e18;\n            int local_c1 = -1, local_c2 = -1;\n\n            for (int i = 0; i <= TILES; ++i) {\n                // remove indices out of window [i-max_dy, i]\n                while (!dq.empty() && dq.front() < i - max_dy)\n                    dq.pop_front();\n\n                if (!dq.empty()) {\n                    ll cur = prefCol[i] - prefCol[dq.front()];\n                    if (cur > local_best) {\n                        local_best = cur;\n                        local_c1 = dq.front();   // leftmost column index (in prefCol)\n                        local_c2 = i - 1;        // rightmost column index\n                    }\n                }\n\n                // maintain increasing prefCol values in deque\n                while (!dq.empty() && prefCol[dq.back()] >= prefCol[i])\n                    dq.pop_back();\n                dq.push_back(i);\n            }\n\n            if (local_best > best_sum) {\n                best_sum = local_best;\n                best_r1 = r1;\n                best_r2 = r2;\n                best_c1 = local_c1;\n                best_c2 = local_c2;\n            }\n        }\n    }\n\n    // If no positive rectangle found (shouldn't happen), fallback to a single tile containing at least one mackerel\n    if (best_sum <= 0) {\n        // find any tile with positive net weight\n        for (int i = 0; i < TILES; ++i) {\n            for (int j = 0; j < TILES; ++j) {\n                if (score[i][j] > 0) {\n                    best_sum = score[i][j];\n                    best_r1 = best_r2 = i;\n                    best_c1 = best_c2 = j;\n                    break;\n                }\n            }\n            if (best_sum > 0) break;\n        }\n    }\n\n    // Convert tile rectangle to actual coordinates (tighten using mackerels)\n    int x_low = best_c1 * TILE_SIZE;\n    int x_high = min(COORD_MAX, (best_c2 + 1) * TILE_SIZE);\n    int y_low = best_r1 * TILE_SIZE;\n    int y_high = min(COORD_MAX, (best_r2 + 1) * TILE_SIZE);\n\n    // Collect mackerels inside the tile rectangle to get tight bounding box\n    int tight_x_min = COORD_MAX + 1, tight_x_max = -1;\n    int tight_y_min = COORD_MAX + 1, tight_y_max = -1;\n    for (auto [x, y] : mackerels) {\n        if (x >= x_low && x <= x_high && y >= y_low && y <= y_high) {\n            tight_x_min = min(tight_x_min, x);\n            tight_x_max = max(tight_x_max, x);\n            tight_y_min = min(tight_y_min, y);\n            tight_y_max = max(tight_y_max, y);\n        }\n    }\n\n    // If there are mackerels inside, use tight box; otherwise use the tile rectangle itself.\n    if (tight_x_min <= COORD_MAX) {\n        x_low = tight_x_min;\n        x_high = tight_x_max;\n        y_low = tight_y_min;\n        y_high = tight_y_max;\n    }\n\n    // Ensure rectangle has positive area (at least 1 unit)\n    if (x_low == x_high) x_high = min(COORD_MAX, x_low + 1);\n    if (y_low == y_high) y_high = min(COORD_MAX, y_low + 1);\n\n    // Output polygon (a simple rectangle)\n    int m = 4;\n    cout << m << '\\n';\n    // Order: counterclockwise (or clockwise) - here we output (x_low, y_low) -> (x_high, y_low) -> (x_high, y_high) -> (x_low, y_high)\n    cout << x_low << \" \" << y_low << '\\n';\n    cout << x_high << \" \" << y_low << '\\n';\n    cout << x_high << \" \" << y_high << '\\n';\n    cout << x_low << \" \" << y_high << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nstruct Rect {\n    int orig;\n    ll x, y, w, h;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<ll> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i) cin >> w_obs[i] >> h_obs[i];\n\n    // initialise estimate sums with the given noisy values\n    vector<ld> sum_w(N), sum_h(N);\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    int measure_turns = T - 1;     // last turn is for the final packing\n    int cur_measure = 0;           // index of the next rectangle to measure\n\n    for (int turn = 0; turn < T; ++turn) {\n        if (turn < measure_turns) {\n            // ===== measurement turn: place a single rectangle =====\n            int idx = cur_measure % N;\n            ++cur_measure;\n            cout << \"1\\n\";\n            cout << idx << \" 0 U -1\" << endl;   // flush with endl\n\n            // read noisy bounding box\n            ll Wp, Hp;\n            cin >> Wp >> Hp;\n\n            // update statistics\n            sum_w[idx] += Wp;\n            sum_h[idx] += Hp;\n            cnt[idx]++;\n        } else {\n            // ===== final packing turn =====\n            // compute final estimates (rounded to nearest integer)\n            vector<ll> est_w(N), est_h(N);\n            for (int i = 0; i < N; ++i) {\n                est_w[i] = (ll)llround(sum_w[i] / cnt[i]);\n                est_h[i] = (ll)llround(sum_h[i] / cnt[i]);\n                if (est_w[i] < 1) est_w[i] = 1;\n                if (est_h[i] < 1) est_h[i] = 1;\n            }\n\n            // greedy packing: place rectangles in index order, trying all possibilities\n            vector<Rect> placed;\n            ll curW = 0, curH = 0;\n            vector<tuple<int, int, char, int>> ops;   // (original index, rotation, direction, reference)\n\n            for (int i = 0; i < N; ++i) {\n                struct Option {\n                    int rot;\n                    char dir;\n                    int ref;     // index inside 'placed' vector (-1 for axis)\n                    ll newW, newH;\n                    ll x, y;     // position of the new rectangle\n                };\n                Option best;\n                best.newW = LLONG_MAX;   // large sentinel\n\n                // try both rotations\n                for (int rot = 0; rot <= 1; ++rot) {\n                    ll w = (rot == 0) ? est_w[i] : est_h[i];\n                    ll h = (rot == 0) ? est_h[i] : est_w[i];\n\n                    // try both directions\n                    for (char dir : {'U', 'L'}) {\n                        // all possible references: -1 and every already placed rectangle\n                        vector<int> refs = {-1};\n                        for (int j = 0; j < (int)placed.size(); ++j) refs.push_back(j);\n\n                        for (int ref : refs) {\n                            ll x, y;\n                            if (dir == 'U') {\n                                // horizontal alignment\n                                x = (ref == -1) ? 0 : placed[ref].x + placed[ref].w;\n                                // move upwards (decreasing y) until touching bottom of some rectangle\n                                y = 0;\n                                for (auto &p : placed) {\n                                    if (x < p.x + p.w && x + w > p.x) {\n                                        y = max(y, p.y + p.h);\n                                    }\n                                }\n                            } else { // 'L'\n                                // vertical alignment\n                                y = (ref == -1) ? 0 : placed[ref].y + placed[ref].h;\n                                // move leftwards (decreasing x) until touching right side of some rectangle\n                                x = 0;\n                                for (auto &p : placed) {\n                                    if (y < p.y + p.h && y + h > p.y) {\n                                        x = max(x, p.x + p.w);\n                                    }\n                                }\n                            }\n\n                            ll newW = max(curW, x + w);\n                            ll newH = max(curH, y + h);\n                            ll score = newW + newH;\n                            if (score < best.newW + best.newH) {\n                                best = {rot, dir, ref, newW, newH, x, y};\n                            }\n                        }\n                    }\n                }\n\n                // apply the best option\n                ll w_used = (best.rot == 0) ? est_w[i] : est_h[i];\n                ll h_used = (best.rot == 0) ? est_h[i] : est_w[i];\n                int ref_orig = (best.ref == -1) ? -1 : placed[best.ref].orig;\n\n                placed.push_back({i, best.x, best.y, w_used, h_used});\n                curW = best.newW;\n                curH = best.newH;\n                ops.emplace_back(i, best.rot, best.dir, ref_orig);\n            }\n\n            // output the packing\n            cout << N << \"\\n\";\n            for (auto &[p, r, d, b] : ops) {\n                cout << p << \" \" << r << \" \" << d << \" \" << b << \"\\n\";\n            }\n            cout.flush();\n\n            // consume the measured feedback (irrelevant for our algorithm)\n            ll dummyW, dummyH;\n            cin >> dummyW >> dummyH;\n        }\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing namespace std::chrono;\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<vector<int>> graph(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        graph[u].push_back(v);\n        graph[v].push_back(u);\n    }\n    // read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. All-pairs shortest distances ----------\n    const int INF = 1e9;\n    vector<vector<int>> dist(N, vector<int>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        queue<int> q;\n        dist[s][s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int u : graph[v]) if (dist[s][u] == INF) {\n                dist[s][u] = dist[s][v] + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    // ---------- 2. For each vertex, list of all vertices sorted by distance ----------\n    vector<vector<int>> order(N, vector<int>(N));\n    vector<vector<int>> pos(N, vector<int>(N)); // pos[v][u] = index in order[v]\n    for (int v = 0; v < N; ++v) {\n        iota(order[v].begin(), order[v].end(), 0);\n        sort(order[v].begin(), order[v].end(), [&](int a, int b) {\n            return dist[v][a] < dist[v][b];\n        });\n        for (int i = 0; i < N; ++i) pos[v][order[v][i]] = i;\n    }\n\n    // ---------- 3. Greedy removal of roots ----------\n    vector<bool> active(N, true);\n    vector<int> best_root(N), best_dist(N), best_idx(N);\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        best_root[v] = v;\n        best_dist[v] = 0;\n        best_idx[v] = 0;\n        children[v].push_back(v);\n    }\n\n    while (true) {\n        // compute gain and feasibility for each root\n        vector<ll> gain(N, 0);\n        vector<bool> feasible(N, true);\n        for (int r = 0; r < N; ++r) if (active[r]) {\n            for (int v : children[r]) {\n                int idx = best_idx[v] + 1;\n                while (idx < N && !active[order[v][idx]]) ++idx;\n                if (idx == N || dist[v][order[v][idx]] > H) {\n                    feasible[r] = false;\n                    break;\n                }\n                int new_root = order[v][idx];\n                int new_dist = dist[v][new_root];\n                gain[r] += (ll)(new_dist - best_dist[v]) * A[v];\n            }\n        }\n\n        // choose root with maximum gain (prefer positive, accept zero)\n        int best = -1;\n        ll best_gain = -1;\n        for (int r = 0; r < N; ++r) if (active[r] && feasible[r] && gain[r] >= 0) {\n            if (gain[r] > best_gain) {\n                best_gain = gain[r];\n                best = r;\n            }\n        }\n        if (best == -1) break; // no improvement\n\n        // remove root best\n        active[best] = false;\n        for (int v : children[best]) {\n            int idx = best_idx[v] + 1;\n            while (!active[order[v][idx]]) ++idx;\n            int new_root = order[v][idx];\n            int new_dist = dist[v][new_root];\n            best_idx[v] = idx;\n            best_dist[v] = new_dist;\n            best_root[v] = new_root;\n            children[new_root].push_back(v);\n        }\n        children[best].clear();\n    }\n\n    // ---------- 4. Build BFS forest from final roots ----------\n    vector<int> parent(N, -1), depth(N, -1);\n    queue<int> q;\n    for (int r = 0; r < N; ++r) if (active[r]) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) if (depth[u] == -1) {\n            depth[u] = depth[v] + 1;\n            parent[u] = v;\n            q.push(u);\n        }\n    }\n\n    // ---------- 5. Post-processing: increase depth of leaves ----------\n    // compute child counts\n    vector<int> child_cnt(N, 0);\n    for (int v = 0; v < N; ++v) if (parent[v] != -1) child_cnt[parent[v]]++;\n\n    // sort vertices by beauty descending\n    vector<int> vorder(N);\n    iota(vorder.begin(), vorder.end(), 0);\n    sort(vorder.begin(), vorder.end(), [&](int i, int j) { return A[i] > A[j]; });\n\n    // repeat several passes\n    for (int pass = 0; pass < 20; ++pass) {\n        bool changed = false;\n        for (int v : vorder) {\n            if (depth[v] == H || child_cnt[v] > 0) continue; // only leaves with depth < H\n            int best_u = -1, best_d = depth[v];\n            for (int u : graph[v]) {\n                if (depth[u] >= depth[v] && depth[u] < H && depth[u] + 1 > best_d) {\n                    best_u = u;\n                    best_d = depth[u] + 1;\n                }\n            }\n            if (best_u != -1) {\n                // update parent and depth\n                if (parent[v] != -1) child_cnt[parent[v]]--;\n                parent[v] = best_u;\n                child_cnt[best_u]++;\n                depth[v] = best_d;\n                changed = true;\n            }\n        }\n        if (!changed) break;\n    }\n\n    // ---------- 6. Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << parent[i] << (i+1 == N ? \"\\n\" : \" \");\n    }\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\nint main() {\n    int N = 20;\n    cin >> N;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // Collect all Oni positions (initial)\n    vector<pair<int, int>> oni_pos;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'x')\n                oni_pos.emplace_back(i, j);\n\n    // Precompute for each Oni the best safe direction and distance (to edge)\n    struct Info { int dir; int dist; }; // 0:Up, 1:Down, 2:Left, 3:Right\n    vector<Info> oni_info(oni_pos.size());\n\n    for (size_t idx = 0; idx < oni_pos.size(); ++idx) {\n        int r = oni_pos[idx].first;\n        int c = oni_pos[idx].second;\n\n        bool safe[4] = {true, true, true, true};\n\n        // up\n        for (int i = 0; i < r; ++i)\n            if (grid[i][c] == 'o') { safe[0] = false; break; }\n        // down\n        for (int i = r + 1; i < N; ++i)\n            if (grid[i][c] == 'o') { safe[1] = false; break; }\n        // left\n        for (int j = 0; j < c; ++j)\n            if (grid[r][j] == 'o') { safe[2] = false; break; }\n        // right\n        for (int j = c + 1; j < N; ++j)\n            if (grid[r][j] == 'o') { safe[3] = false; break; }\n\n        int best_dir = -1;\n        int best_dist = N + 1;\n        int dists[4] = {r + 1, N - r, c + 1, N - c};\n        for (int d = 0; d < 4; ++d) {\n            if (safe[d] && dists[d] < best_dist) {\n                best_dist = dists[d];\n                best_dir = d;\n            }\n        }\n        // guaranteed to be valid\n        oni_info[idx] = {best_dir, best_dist};\n    }\n\n    vector<pair<char, int>> ops;\n\n    // Shift functions (modify grid in place)\n    auto shift_left = [&](int r) {\n        // remove leftmost piece\n        for (int j = 0; j < N - 1; ++j) grid[r][j] = grid[r][j + 1];\n        grid[r][N - 1] = '.';\n    };\n    auto shift_right = [&](int r) {\n        for (int j = N - 1; j > 0; --j) grid[r][j] = grid[r][j - 1];\n        grid[r][0] = '.';\n    };\n    auto shift_up = [&](int c) {\n        for (int i = 0; i < N - 1; ++i) grid[i][c] = grid[i + 1][c];\n        grid[N - 1][c] = '.';\n    };\n    auto shift_down = [&](int c) {\n        for (int i = N - 1; i > 0; --i) grid[i][c] = grid[i - 1][c];\n        grid[0][c] = '.';\n    };\n\n    // ---------- Phase 1: clear rows that contain no Fukunokami ----------\n    for (int i = 0; i < N; ++i) {\n        bool has_o = false;\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'o') { has_o = true; break; }\n        if (has_o) continue;\n\n        // find Oni in this row\n        int min_x = N, max_x = -1;\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == 'x') {\n                min_x = min(min_x, j);\n                max_x = max(max_x, j);\n            }\n        if (max_x == -1) continue;   // no Oni\n\n        int left_cost = max_x + 1;     // shifts to remove rightmost Oni\n        int right_cost = N - min_x;    // shifts to remove leftmost Oni\n        if (left_cost <= right_cost) {\n            for (int k = 0; k < left_cost; ++k) {\n                shift_left(i);\n                ops.emplace_back('L', i);\n            }\n        } else {\n            for (int k = 0; k < right_cost; ++k) {\n                shift_right(i);\n                ops.emplace_back('R', i);\n            }\n        }\n    }\n\n    // ---------- Phase 2: clear columns that contain no Fukunokami ----------\n    for (int j = 0; j < N; ++j) {\n        bool has_o = false;\n        for (int i = 0; i < N; ++i)\n            if (grid[i][j] == 'o') { has_o = true; break; }\n        if (has_o) continue;\n\n        int min_x = N, max_x = -1;\n        for (int i = 0; i < N; ++i)\n            if (grid[i][j] == 'x') {\n                min_x = min(min_x, i);\n                max_x = max(max_x, i);\n            }\n        if (max_x == -1) continue;\n\n        int up_cost = max_x + 1;\n        int down_cost = N - min_x;\n        if (up_cost <= down_cost) {\n            for (int k = 0; k < up_cost; ++k) {\n                shift_up(j);\n                ops.emplace_back('U', j);\n            }\n        } else {\n            for (int k = 0; k < down_cost; ++k) {\n                shift_down(j);\n                ops.emplace_back('D', j);\n            }\n        }\n    }\n\n    // ---------- Phase 3: remove remaining Oni individually ----------\n    for (size_t idx = 0; idx < oni_pos.size(); ++idx) {\n        int r = oni_pos[idx].first;\n        int c = oni_pos[idx].second;\n        if (grid[r][c] != 'x') continue;   // already removed\n\n        int dir = oni_info[idx].dir;\n        int dist = oni_info[idx].dist;\n\n        if (dir == 0) {      // up\n            for (int k = 0; k < dist; ++k) { shift_up(c); ops.emplace_back('U', c); }\n            for (int k = 0; k < dist; ++k) { shift_down(c); ops.emplace_back('D', c); }\n        } else if (dir == 1) { // down\n            for (int k = 0; k < dist; ++k) { shift_down(c); ops.emplace_back('D', c); }\n            for (int k = 0; k < dist; ++k) { shift_up(c); ops.emplace_back('U', c); }\n        } else if (dir == 2) { // left\n            for (int k = 0; k < dist; ++k) { shift_left(r); ops.emplace_back('L', r); }\n            for (int k = 0; k < dist; ++k) { shift_right(r); ops.emplace_back('R', r); }\n        } else {               // right\n            for (int k = 0; k < dist; ++k) { shift_right(r); ops.emplace_back('R', r); }\n            for (int k = 0; k < dist; ++k) { shift_left(r); ops.emplace_back('L', r); }\n        }\n    }\n\n    // Output\n    for (const auto &op : ops) {\n        cout << op.first << ' ' << op.second << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\nuniform_int_distribution<int> dist_emp(0, N-1);\nuniform_real_distribution<double> dist_prob(0.0, 1.0);\n\nstruct Solution {\n    int a[N], b[N];\n};\n\nint simulate(const Solution& sol, int cnt[]) {\n    fill(cnt, cnt + N, 0);\n    int cur = 0;\n    cnt[0] = 1; // week 1\n    for (int w = 2; w <= L; ++w) {\n        int t = cnt[cur];\n        int nxt = (t & 1) ? sol.a[cur] : sol.b[cur];\n        cnt[nxt]++;\n        cur = nxt;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) {\n        err += abs(cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution: uniform cycle\n    Solution sol;\n    for (int i = 0; i < N; ++i) {\n        sol.a[i] = (i + 1) % N;\n        sol.b[i] = (i + 1) % N;\n    }\n\n    int cnt[N];\n    int best_err = simulate(sol, cnt);\n    Solution best_sol = sol;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    double temperature = 1000.0;\n    const double cooling_rate = 0.9995;\n    int iterations = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n\n        // random modification\n        Solution new_sol = sol;\n        int i = dist_emp(rng);\n        if (dist_prob(rng) < 0.5) {\n            new_sol.a[i] = dist_emp(rng);\n        } else {\n            new_sol.b[i] = dist_emp(rng);\n        }\n\n        int new_err = simulate(new_sol, cnt);\n        int delta = new_err - best_err;\n\n        if (delta < 0 || dist_prob(rng) < exp(-delta / temperature)) {\n            sol = new_sol;\n            if (new_err < best_err) {\n                best_err = new_err;\n                best_sol = new_sol;\n            }\n        }\n\n        temperature *= cooling_rate;\n        iterations++;\n    }\n\n    // Output best solution\n    for (int i = 0; i < N; ++i) {\n        cout << best_sol.a[i] << \" \" << best_sol.b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\n// ---------- DSU ----------\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rank_[a] < rank_[b]) swap(a, b);\n        parent[b] = a;\n        if (rank_[a] == rank_[b]) rank_[a]++;\n        return true;\n    }\n};\n\n// ---------- query helper ----------\nvector<pair<int,int>> do_query(const vector<int>& subset) {\n    int l = subset.size();\n    cout << \"? \" << l;\n    for (int v : subset) cout << ' ' << v;\n    cout << endl;\n    vector<pair<int,int>> res;\n    for (int i = 0; i < l-1; ++i) {\n        int a, b; cin >> a >> b;\n        if (a > b) swap(a, b);\n        res.emplace_back(a, b);\n    }\n    return res;\n}\n\n// ---------- Hilbert index (14 bits) ----------\nuint64_t hilbertIndex(uint32_t x, uint32_t y, int bits = 14) {\n    uint32_t n = 1u << bits;\n    uint64_t d = 0;\n    uint32_t s, rx, ry;\n    for (s = n >> 1; s; s >>= 1) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d = (d << 2) | ((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = (n - 1) - x;\n                y = (n - 1) - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<ll> lx(N), rx(N), ly(N), ry(N);\n    vector<ll> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // ---- order cities by Hilbert index (using center) ----\n    auto scale = [](ll v) -> uint32_t { return (uint32_t)clamp(v, 0LL, 16383LL); };\n    vector<uint64_t> hi(N);\n    for (int i = 0; i < N; ++i) hi[i] = hilbertIndex(scale(cx[i]), scale(cy[i]));\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) { return hi[a] < hi[b]; });\n\n    // ---- assign groups by consecutive blocks ----\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        groups[k].reserve(G[k]);\n        for (int j = 0; j < G[k]; ++j) groups[k].push_back(order[idx++]);\n    }\n\n    // ---- plan queries: small groups first, then proportional for large ----\n    vector<int> q_per_group(M, 0);\n    int used_q = 0;\n\n    // small groups (size <= L)\n    for (int k = 0; k < M; ++k) {\n        int sz = groups[k].size();\n        if (sz <= L && used_q < Q) {\n            q_per_group[k] = 1;\n            ++used_q;\n        }\n    }\n\n    // large groups \u2013 allocate remaining queries proportionally to (sz - L + 1)\n    int remaining = Q - used_q;\n    if (remaining > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) {\n            if (groups[k].size() > L) large.push_back(k);\n        }\n        ll total_needed = 0;\n        for (int k : large) total_needed += max(1, (int)groups[k].size() - L + 1);\n        for (int k : large) {\n            int need = max(1, (int)groups[k].size() - L + 1);\n            int alloc = (int)((ll)remaining * need / total_needed);\n            if (alloc == 0) alloc = 1;\n            q_per_group[k] = alloc;\n        }\n        // adjust to not exceed remaining\n        int sum = 0;\n        for (int k : large) sum += q_per_group[k];\n        while (sum > remaining) {\n            for (int k : large) {\n                if (sum <= remaining) break;\n                if (q_per_group[k] > 1) {\n                    --q_per_group[k];\n                    --sum;\n                }\n            }\n        }\n    }\n\n    // ---- execute queries and build MST per group ----\n    vector<vector<pair<int,int>>> answer_edges(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int sz = cities.size();\n        if (sz <= 1) continue;\n\n        // collect query edges\n        vector<pair<int,int>> query_edges;\n        int nq = q_per_group[k];\n        if (nq > 0) {\n            if (sz <= L) {\n                // whole group query\n                auto edges = do_query(cities);\n                for (auto e : edges) query_edges.push_back(e);\n            } else {\n                // sliding windows with step to achieve nq queries\n                int step = max(1, (sz - L + 1 + nq - 1) / nq);\n                for (int start = 0; start + L <= sz && nq > 0; start += step, --nq) {\n                    vector<int> subset(cities.begin() + start, cities.begin() + start + L);\n                    auto edges = do_query(subset);\n                    for (auto e : edges) query_edges.push_back(e);\n                }\n            }\n        }\n\n        // ---- build MST ----\n        // use query edges first, then complete graph for missing connections\n        struct Edge { int u, v; ll w; };\n        auto estimated_weight = [&](int a, int b) -> ll {\n            ll dx = cx[a] - cx[b];\n            ll dy = cy[a] - cy[b];\n            return (ll)sqrt(dx*dx + dy*dy);\n        };\n\n        DSU dsu(N);\n        vector<pair<int,int>> mst;\n\n        // 1) process query edges (sorted by estimated weight)\n        vector<Edge> cand;\n        for (auto& p : query_edges) {\n            ll w = estimated_weight(p.first, p.second);\n            cand.push_back({p.first, p.second, w});\n        }\n        sort(cand.begin(), cand.end(), [](const Edge& a, const Edge& b) { return a.w < b.w; });\n        for (auto& e : cand) {\n            if (dsu.unite(e.u, e.v)) mst.emplace_back(e.u, e.v);\n            if ((int)mst.size() == sz - 1) break;\n        }\n\n        // 2) if still not connected, add edges from complete graph (estimated)\n        if ((int)mst.size() < sz - 1) {\n            cand.clear();\n            for (int i = 0; i < sz; ++i) {\n                for (int j = i+1; j < sz; ++j) {\n                    int u = cities[i], v = cities[j];\n                    if (dsu.find(u) == dsu.find(v)) continue;\n                    ll w = estimated_weight(u, v);\n                    cand.push_back({u, v, w});\n                }\n            }\n            sort(cand.begin(), cand.end(), [](const Edge& a, const Edge& b) { return a.w < b.w; });\n            for (auto& e : cand) {\n                if (dsu.unite(e.u, e.v)) mst.emplace_back(e.u, e.v);\n                if ((int)mst.size() == sz - 1) break;\n            }\n        }\n\n        for (auto& e : mst) answer_edges[k].push_back(e);\n    }\n\n    // ---- output answer ----\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        for (int v : groups[k]) cout << v << ' ';\n        cout << endl;\n        for (auto& e : answer_edges[k]) cout << e.first << ' ' << e.second << endl;\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nconst int dy[4] = {-1, 1, 0, 0}; // U, D, L, R\nconst int dx[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\n// BFS to find shortest path from (si,sj) to (ti,tj) using only Move and Slide.\n// Returns vector of (action, direction) pairs.\nvector<pair<char, char>> get_path(int si, int sj, int ti, int tj) {\n    int start = si * N + sj, goal = ti * N + tj;\n    vector<int> dist(N * N, -1), prev(N * N, -1), act(N * N, -1), dir(N * N, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        if (u == goal) break;\n        int i = u / N, j = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move one step\n            int ni = i + dy[d], nj = j + dx[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int v = ni * N + nj;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 0; // Move\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n\n            // Slide to the edge in direction d\n            // Only valid if the first square in that direction is inside (otherwise slide does nothing)\n            if (d == 0 && i > 0) { // up\n                int v = 0 * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1; // Slide\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 1 && i < N - 1) { // down\n                int v = (N - 1) * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 2 && j > 0) { // left\n                int v = i * N + 0;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 3 && j < N - 1) { // right\n                int v = i * N + (N - 1);\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n        }\n    }\n\n    // Reconstruct path from goal to start\n    vector<pair<char, char>> rev;\n    int cur = goal;\n    while (cur != start) {\n        int a = act[cur];\n        int d = dir[cur];\n        rev.push_back({(a == 0 ? 'M' : 'S'), dir_char[d]});\n        cur = prev[cur];\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int, int>> points(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    int cur_i = points[0].first, cur_j = points[0].second;\n\n    for (int t = 1; t < M; ++t) {\n        int ti = points[t].first, tj = points[t].second;\n        auto path = get_path(cur_i, cur_j, ti, tj);\n        for (auto [act, dir] : path) {\n            cout << act << \" \" << dir << \"\\n\";\n        }\n        cur_i = ti;\n        cur_j = tj;\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Rect { int a, b, c, d; }; // [a,c) x [b,d)\nstruct Region { int x0, y0, x1, y1; vector<int> ids; };\nstruct SplitResult { \n    int axis; \n    int s; \n    vector<int> left, right; \n    double metric;\n};\n\nint n;\nvector<int> xi, yi, ri;\n\ndouble calc_p(int idx, long long area) {\n    long long r = ri[idx];\n    long long s = area;\n    long long mn = min(r, s);\n    long long mx = max(r, s);\n    double ratio = (double)mn / mx;\n    return ratio * (2.0 - ratio);\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return max(a.a, b.a) < min(a.c, b.c) && max(a.b, b.b) < min(a.d, b.d);\n}\nbool contains(const Rect& rect, int xi, int yi) {\n    return rect.a <= xi && xi < rect.c && rect.b <= yi && yi < rect.d;\n}\n\ndouble total_score(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; ++i) {\n        long long area = (long long)(rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        sum += calc_p(i, area);\n    }\n    return sum;\n}\n\nSplitResult choose_split(const Region& reg) {\n    int m = reg.ids.size();\n    const auto& ids = reg.ids;\n    int x0 = reg.x0, y0 = reg.y0, x1 = reg.x1, y1 = reg.y1;\n    vector<SplitResult> candidates;\n\n    // ---- vertical split (axis 0) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, xi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, xi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int height = y1 - y0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / height + x0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - x0) * height;\n            long long right_area = (long long)(x1 - s) * height;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({0, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    // ---- horizontal split (axis 1) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return yi[i] < yi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, yi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, yi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int width = x1 - x0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / width + y0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - y0) * width;\n            long long right_area = (long long)(y1 - s) * width;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({1, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    if (candidates.empty()) {\n        // fallback: split vertically at median\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        int mid = m / 2;\n        int split_x = (xi[order[mid-1]] + xi[order[mid]] + 1) / 2;\n        if (split_x <= x0) split_x = x0+1;\n        if (split_x >= x1) split_x = x1-1;\n        vector<int> left(order.begin(), order.begin()+mid);\n        vector<int> right(order.begin()+mid, order.end());\n        double left_sum = accumulate(left.begin(), left.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double right_sum = accumulate(right.begin(), right.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double metric = 0; // unused but set to avoid warning\n        return {0, split_x, move(left), move(right), metric};\n    }\n\n    // stochastic selection with softmax\n    double temperature = 0.02;\n    double max_metric = 1e100;\n    for (auto& c : candidates) if (c.metric < max_metric) max_metric = c.metric;\n    vector<double> weights(candidates.size());\n    double sum_weights = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        weights[i] = exp(- (candidates[i].metric - max_metric) * temperature);\n        sum_weights += weights[i];\n    }\n    uniform_real_distribution<double> dist(0.0, sum_weights);\n    double r = dist(rng);\n    double cum = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        cum += weights[i];\n        if (r <= cum) return move(candidates[i]);\n    }\n    return move(candidates.back());\n}\n\nvoid recursive_split(const Region& reg, vector<Rect>& rects) {\n    if (reg.ids.size() == 1) {\n        int idx = reg.ids[0];\n        rects[idx] = {reg.x0, reg.y0, reg.x1, reg.y1};\n        return;\n    }\n    SplitResult split = choose_split(reg);\n    if (split.axis == 0) {\n        Region left{reg.x0, reg.y0, split.s, reg.y1, move(split.left)};\n        Region right{split.s, reg.y0, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    } else {\n        Region left{reg.x0, reg.y0, reg.x1, split.s, move(split.left)};\n        Region right{reg.x0, split.s, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    }\n}\n\nvoid improve(vector<Rect>& rects) {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < n; ++i) {\n            Rect cur = rects[i];\n            // try expand in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c >= 10000) continue;\n                    newr.c++;\n                } else if (dir == 1) { // left\n                    if (newr.a <= 0) continue;\n                    newr.a--;\n                } else if (dir == 2) { // top\n                    if (newr.d >= 10000) continue;\n                    newr.d++;\n                } else { // bottom\n                    if (newr.b <= 0) continue;\n                    newr.b--;\n                }\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n            // try shrink in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c - 1 <= newr.a) continue;\n                    newr.c--;\n                } else if (dir == 1) { // left\n                    if (newr.a + 1 >= newr.c) continue;\n                    newr.a++;\n                } else if (dir == 2) { // top\n                    if (newr.d - 1 <= newr.b) continue;\n                    newr.d--;\n                } else { // bottom\n                    if (newr.b + 1 >= newr.d) continue;\n                    newr.b++;\n                }\n                // must still contain the point\n                if (!contains(newr, xi[i], yi[i])) continue;\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(15);\n\n    cin >> n;\n    xi.resize(n); yi.resize(n); ri.resize(n);\n    for (int i = 0; i < n; ++i) cin >> xi[i] >> yi[i] >> ri[i];\n\n    vector<Rect> best_rects(n);\n    double best_score = -1.0;\n\n    const int TRIALS = 200; // number of random constructions\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        vector<int> all_ids(n);\n        iota(all_ids.begin(), all_ids.end(), 0);\n        Region full{0, 0, 10000, 10000, move(all_ids)};\n        vector<Rect> rects(n);\n        recursive_split(full, rects);\n        double score = total_score(rects);\n        if (score > best_score) {\n            best_score = score;\n            best_rects = move(rects);\n        }\n    }\n\n    // post-processing on best solution\n    improve(best_rects);\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n             << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <chrono>\n#include <bitset>\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_CELLS = N * N;\nconst int MAX_TILES = 2500;\n\nusing Bitset = bitset<MAX_TILES>;\n\n// Global arrays\nint tile_id[MAX_CELLS];          // tile id for each cell\nint p_val[MAX_CELLS];            // value\nvector<int> neighbors[MAX_CELLS]; // neighbor cell indices (different tile)\nchar dir_char[MAX_CELLS][4];     // direction character for each neighbor (max 4)\nint neighbor_cnt[MAX_CELLS];     // number of neighbors\n\n// Precomputed max neighbor value for each cell? We'll compute on the fly.\n\nstruct State {\n    int pos;          // current cell index (0..2499)\n    Bitset vis;       // visited tiles\n    int sum;          // total score so far\n    vector<char> path; // path as characters (for efficiency)\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- Input -----\n    int si, sj;\n    cin >> si >> sj;\n    int start_pos = si * N + sj;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i * N + j];\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p_val[i * N + j];\n\n    // Determine number of tiles M\n    int M = 0;\n    for (int i = 0; i < MAX_CELLS; ++i)\n        if (tile_id[i] + 1 > M) M = tile_id[i] + 1;\n    // safety: M <= 2500\n\n    // ----- Build adjacency -----\n    const int dr[] = {-1, 1, 0, 0};\n    const int dc[] = {0, 0, -1, 1};\n    const char dirs[] = {'U', 'D', 'L', 'R'};\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int me = i * N + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dr[d];\n                int nj = j + dc[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int other = ni * N + nj;\n                if (tile_id[me] != tile_id[other]) {\n                    neighbors[me].push_back(other);\n                    dir_char[me][neighbor_cnt[me]] = dirs[d];\n                    neighbor_cnt[me]++;\n                }\n            }\n        }\n    }\n\n    // ----- Beam Search -----\n    const int BEAM_WIDTH = 1500;\n    const double TIME_LIMIT_MS = 1900.0;\n    auto start_time = chrono::high_resolution_clock::now();\n\n    // Initial state\n    State init;\n    init.pos = start_pos;\n    init.vis.reset();\n    init.vis.set(tile_id[start_pos]);\n    init.sum = p_val[start_pos];\n    init.path.clear();\n\n    vector<State> beam;\n    beam.push_back(move(init));\n    State best = beam[0];\n\n    // Heuristic: sum + max value among unvisited neighbor cells\n    auto heuristic = [&](const State& s) -> int {\n        int add = 0;\n        for (int nb : neighbors[s.pos]) {\n            if (!s.vis.test(tile_id[nb])) {\n                add = max(add, p_val[nb]);\n            }\n        }\n        return s.sum + add;\n    };\n\n    while (!beam.empty()) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > TIME_LIMIT_MS) break;\n\n        vector<pair<int, State>> candidates;\n        candidates.reserve(beam.size() * 3); // typical branching\n\n        for (const auto& s : beam) {\n            for (int k = 0; k < neighbor_cnt[s.pos]; ++k) {\n                int nb = neighbors[s.pos][k];\n                int nt = tile_id[nb];\n                if (s.vis.test(nt)) continue; // tile already visited\n\n                State ns;\n                ns.pos = nb;\n                ns.vis = s.vis;\n                ns.vis.set(nt);\n                ns.sum = s.sum + p_val[nb];\n                // copy path and append char\n                ns.path = s.path;\n                ns.path.push_back(dir_char[s.pos][k]);\n\n                int val = heuristic(ns);\n                candidates.emplace_back(val, move(ns));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        // Keep top BEAM_WIDTH by heuristic score\n        int keep = min((int)candidates.size(), BEAM_WIDTH);\n        partial_sort(candidates.begin(), candidates.begin() + keep, candidates.end(),\n                     [](const auto& a, const auto& b) { return a.first > b.first; });\n\n        beam.clear();\n        for (int i = 0; i < keep; ++i) {\n            beam.push_back(move(candidates[i].second));\n            // Update global best by actual sum\n            if (beam.back().sum > best.sum) best = beam.back();\n        }\n    }\n\n    // ---- Greedy extension from best state (1-ply) ----\n    auto extend_greedy = [&](State cur) -> State {\n        while (true) {\n            int best_val = -1;\n            int best_nb = -1;\n            char best_dir = 0;\n            for (int k = 0; k < neighbor_cnt[cur.pos]; ++k) {\n                int nb = neighbors[cur.pos][k];\n                int nt = tile_id[nb];\n                if (cur.vis.test(nt)) continue;\n                if (p_val[nb] > best_val) {\n                    best_val = p_val[nb];\n                    best_nb = nb;\n                    best_dir = dir_char[cur.pos][k];\n                }\n            }\n            if (best_val == -1) break;\n            cur.pos = best_nb;\n            cur.vis.set(tile_id[best_nb]);\n            cur.sum += best_val;\n            cur.path.push_back(best_dir);\n        }\n        return cur;\n    };\n\n    // ---- Greedy extension from best state (2-ply) ----\n    auto extend_greedy2 = [&](State cur) -> State {\n        while (true) {\n            int best_total = -1;\n            int best_nb = -1;\n            char best_dir = 0;\n            for (int k = 0; k < neighbor_cnt[cur.pos]; ++k) {\n                int nb = neighbors[cur.pos][k];\n                int nt = tile_id[nb];\n                if (cur.vis.test(nt)) continue;\n                int val1 = p_val[nb];\n                int best_next = 0;\n                // look one step ahead from nb\n                for (int k2 = 0; k2 < neighbor_cnt[nb]; ++k2) {\n                    int nb2 = neighbors[nb][k2];\n                    int nt2 = tile_id[nb2];\n                    if (cur.vis.test(nt2) || nt2 == nt) continue;\n                    best_next = max(best_next, p_val[nb2]);\n                }\n                int total = val1 + best_next;\n                if (total > best_total) {\n                    best_total = total;\n                    best_nb = nb;\n                    best_dir = dir_char[cur.pos][k];\n                }\n            }\n            if (best_total == -1) break;\n            cur.pos = best_nb;\n            cur.vis.set(tile_id[best_nb]);\n            cur.sum += p_val[best_nb];\n            cur.path.push_back(best_dir);\n        }\n        return cur;\n    };\n\n    // ---- Try greedy extensions from the top few states ----\n    State best_ext = best;\n    // also consider other states in beam that might be better after extension\n    if (!beam.empty()) {\n        // sort beam by sum descending\n        sort(beam.begin(), beam.end(),\n             [](const State& a, const State& b) { return a.sum > b.sum; });\n        int limit = min(10, (int)beam.size());\n        for (int i = 0; i < limit; ++i) {\n            State ext1 = extend_greedy(beam[i]);\n            if (ext1.sum > best_ext.sum) best_ext = ext1;\n            State ext2 = extend_greedy2(beam[i]);\n            if (ext2.sum > best_ext.sum) best_ext = ext2;\n        }\n    }\n    // also extend the already best state\n    State best1 = extend_greedy(best);\n    if (best1.sum > best_ext.sum) best_ext = best1;\n    State best2 = extend_greedy2(best);\n    if (best2.sum > best_ext.sum) best_ext = best2;\n\n    // ---- Output ----\n    string out(best_ext.path.begin(), best_ext.path.end());\n    cout << out << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n#include <sstream>\n#include <iomanip>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int H_EDGES = 29; // number of horizontal edges per row\nconst int V_EDGES = 29; // number of vertical edges per column (30 rows -> 29 vertical edges per column)\n\nconst double INIT_EST = 4500.0;\nconst double MIN_EDGE = 1000.0;\nconst double MAX_EDGE = 9000.0;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // estimates, counts, and sum of squared gradients for AdaGrad\n    vector<vector<double>> h_est(GRID_SIZE, vector<double>(H_EDGES, INIT_EST));\n    vector<vector<int>> h_cnt(GRID_SIZE, vector<int>(H_EDGES, 0));\n    vector<vector<double>> h_grad_sq(GRID_SIZE, vector<double>(H_EDGES, 0.0));\n\n    vector<vector<double>> v_est(V_EDGES, vector<double>(GRID_SIZE, INIT_EST));\n    vector<vector<int>> v_cnt(V_EDGES, vector<int>(GRID_SIZE, 0));\n    vector<vector<double>> v_grad_sq(V_EDGES, vector<double>(GRID_SIZE, 0.0));\n\n    // hyperparameters\n    const double lr0 = 0.5;\n    const double C_explore = 500.0;\n    const int explore_until = 400;\n\n    int T = 1000;\n    for (int k = 0; k < T; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        // exploration factor: decays linearly to 0 over first explore_until queries\n        double explore_factor = max(0.0, 1.0 - (double)k / explore_until);\n        double t_weight = sqrt(log(k + 1.0) + 1.0); // UCB time factor\n\n        // ----------------------- Dijkstra with UCB-adjusted weights -----------------------\n        const double INF = 1e18;\n        vector<vector<double>> dist(GRID_SIZE, vector<double>(GRID_SIZE, INF));\n        vector<vector<pair<int,int>>> prev(GRID_SIZE, vector<pair<int,int>>(GRID_SIZE, {-1, -1}));\n        // priority queue: (distance, (i,j))\n        priority_queue<pair<double, pair<int,int>>, vector<pair<double, pair<int,int>>>, greater<>> pq;\n        dist[si][sj] = 0.0;\n        pq.push({0.0, {si, sj}});\n\n        while (!pq.empty()) {\n            auto [d, node] = pq.top(); pq.pop();\n            int i = node.first, j = node.second;\n            if (d > dist[i][j] + 1e-9) continue;\n            if (i == ti && j == tj) break; // reached target\n\n            // neighbor: up (i-1, j) -> vertical edge (i-1, j)\n            if (i > 0) {\n                double w = v_est[i-1][j] - C_explore * t_weight / sqrt(v_cnt[i-1][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i-1][j] - 1e-9) {\n                    dist[i-1][j] = d + w;\n                    prev[i-1][j] = {i, j};\n                    pq.push({dist[i-1][j], {i-1, j}});\n                }\n            }\n            // neighbor: down (i+1, j) -> vertical edge (i, j)\n            if (i < GRID_SIZE - 1) {\n                double w = v_est[i][j] - C_explore * t_weight / sqrt(v_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i+1][j] - 1e-9) {\n                    dist[i+1][j] = d + w;\n                    prev[i+1][j] = {i, j};\n                    pq.push({dist[i+1][j], {i+1, j}});\n                }\n            }\n            // neighbor: left (i, j-1) -> horizontal edge (i, j-1)\n            if (j > 0) {\n                double w = h_est[i][j-1] - C_explore * t_weight / sqrt(h_cnt[i][j-1] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j-1] - 1e-9) {\n                    dist[i][j-1] = d + w;\n                    prev[i][j-1] = {i, j};\n                    pq.push({dist[i][j-1], {i, j-1}});\n                }\n            }\n            // neighbor: right (i, j+1) -> horizontal edge (i, j)\n            if (j < GRID_SIZE - 1) {\n                double w = h_est[i][j] - C_explore * t_weight / sqrt(h_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                if (d + w < dist[i][j+1] - 1e-9) {\n                    dist[i][j+1] = d + w;\n                    prev[i][j+1] = {i, j};\n                    pq.push({dist[i][j+1], {i, j+1}});\n                }\n            }\n        }\n\n        // backtrack to retrieve the path\n        vector<pair<int,int>> path;\n        int ci = ti, cj = tj;\n        while (!(ci == si && cj == sj)) {\n            path.push_back({ci, cj});\n            auto p = prev[ci][cj];\n            ci = p.first;\n            cj = p.second;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n\n        // construct output string (moves)\n        string out;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int di = path[idx].first - path[idx-1].first;\n            int dj = path[idx].second - path[idx-1].second;\n            if (di == -1) out += 'U';\n            else if (di == 1) out += 'D';\n            else if (dj == -1) out += 'L';\n            else if (dj == 1) out += 'R';\n        }\n        cout << out << endl; // flush included\n\n        // read feedback: observed (noisy) path length\n        int feedback;\n        cin >> feedback;\n\n        // ----------------------- Update estimates -----------------------\n        // compute predicted length using current (unadjusted) estimates\n        double L_pred = 0.0;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                L_pred += h_est[i1][jmin];\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                L_pred += v_est[imin][j1];\n            }\n        }\n\n        double error = feedback - L_pred;\n        double rel_error = error / max(L_pred, 1.0);\n        // clamp to avoid extreme updates from large mispredictions\n        rel_error = clamp(rel_error, -3.0, 3.0);\n\n        // update each edge on the path\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n\n            if (i1 == i2) { // horizontal edge\n                int jmin = min(j1, j2);\n                // accumulate squared gradient\n                h_grad_sq[i1][jmin] += rel_error * rel_error;\n                double lr = lr0 / sqrt(h_grad_sq[i1][jmin] + 1e-8);\n                double new_val = h_est[i1][jmin] + lr * rel_error;\n                h_est[i1][jmin] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                h_cnt[i1][jmin]++;\n            } else { // vertical edge\n                int imin = min(i1, i2);\n                v_grad_sq[imin][j1] += rel_error * rel_error;\n                double lr = lr0 / sqrt(v_grad_sq[imin][j1] + 1e-8);\n                double new_val = v_est[imin][j1] + lr * rel_error;\n                v_est[imin][j1] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                v_cnt[imin][j1]++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPH = 8;\n\nint M;\nvector<string> strs;\nvector<uint64_t> hashes;\nunordered_map<uint64_t, vector<int>> hash_to_ids;\n\nvector<string> mat; // current matrix\nvector<int> occ;    // occurrences per input string\nint matched = 0;    // number of input strings with occ>0\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// encode a string to a 64-bit integer (3 bits per character)\nuint64_t encode(const string &s) {\n    uint64_t h = 0;\n    for (char c : s) {\n        h = (h << 3) | (c - 'A');\n    }\n    return h;\n}\n\n// generate all substrings that include cell (r,c) under the assumption that\n// mat[r][c] has the given character (used for delta computation)\nvoid collect_hashes(int r, int c, char cell_char, vector<uint64_t> &out_hashes) {\n    out_hashes.clear();\n    auto get_char = [&](int i, int j) -> char {\n        if (i == r && j == c) return cell_char;\n        return mat[i][j];\n    };\n    // horizontal substrings\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_col = (c - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int col = (start_col + t) % N;\n                char ch = get_char(r, col);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out_hashes.push_back(h);\n        }\n    }\n    // vertical substrings\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_row = (r - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int row = (start_row + t) % N;\n                char ch = get_char(row, c);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out_hashes.push_back(h);\n        }\n    }\n}\n\n// compute the change in 'matched' if we set (r,c) from old_char to new_char\nint compute_delta(int r, int c, char old_char, char new_char) {\n    static vector<uint64_t> old_hashes, new_hashes;\n    static vector<int> delta_occ(M, 0);\n    static vector<int> affected_ids;\n    affected_ids.clear();\n\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]--;\n            }\n        }\n    }\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]++;\n            }\n        }\n    }\n\n    int delta_matched = 0;\n    for (int id : affected_ids) {\n        int new_occ = occ[id] + delta_occ[id];\n        if (occ[id] == 0 && new_occ > 0) delta_matched++;\n        if (occ[id] > 0 && new_occ == 0) delta_matched--;\n    }\n    // clean up\n    for (int id : affected_ids) delta_occ[id] = 0;\n    return delta_matched;\n}\n\n// apply the change: update matrix and global occ/matched\nvoid apply_change(int r, int c, char new_char) {\n    char old_char = mat[r][c];\n    if (old_char == new_char) return;\n    static vector<uint64_t> old_hashes, new_hashes;\n    // remove old substrings\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                occ[id]--;\n                if (occ[id] == 0) matched--;\n            }\n        }\n    }\n    // set new character\n    mat[r][c] = new_char;\n    // add new substrings\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (occ[id] == 0) matched++;\n                occ[id]++;\n            }\n        }\n    }\n}\n\n// compute initial occ and matched by scanning the whole matrix\nvoid compute_initial_state() {\n    fill(occ.begin(), occ.end(), 0);\n    matched = 0;\n    // horizontal substrings\n    for (int r = 0; r < N; ++r) {\n        for (int len = 2; len <= 12; ++len) {\n            for (int start_col = 0; start_col < N; ++start_col) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int col = (start_col + t) % N;\n                    char ch = mat[r][col];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    // vertical substrings\n    for (int c = 0; c < N; ++c) {\n        for (int len = 2; len <= 12; ++len) {\n            for (int start_row = 0; start_row < N; ++start_row) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int row = (start_row + t) % N;\n                    char ch = mat[row][c];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n// structure for a placement (for greedy)\nstruct Placement {\n    vector<int> cells;   // linear indices (r*20 + c)\n    vector<char> letters;\n};\n\n// greedy initialisation: fill matrix with as many strings as possible\nvoid greedy_initialization(vector<vector<Placement>> &placements) {\n    mat.assign(N, string(N, '.'));\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int idx : order) {\n        int best_score = -1;\n        int best_p = -1;\n        for (int p = 0; p < (int)placements[idx].size(); ++p) {\n            auto &pl = placements[idx][p];\n            int score = 0;\n            bool ok = true;\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                char cur = mat[r][c];\n                if (cur == '.') {\n                    // fine\n                } else if (cur != pl.letters[t]) {\n                    ok = false;\n                    break;\n                } else {\n                    score++;\n                }\n            }\n            if (ok && score > best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        if (best_p != -1) {\n            auto &pl = placements[idx][best_p];\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                mat[r][c] = pl.letters[t];\n            }\n        }\n    }\n    compute_initial_state();\n}\n\n// remove cells that are not essential for any string (safe removal)\nvoid remove_redundant_cells() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int cell = 0; cell < N * N; ++cell) {\n            int r = cell / N, c = cell % N;\n            if (mat[r][c] == '.') continue;\n            // check if this cell is essential for any string (occ==1)\n            bool essential = false;\n            static vector<uint64_t> hashes_cell;\n            collect_hashes(r, c, mat[r][c], hashes_cell);\n            for (uint64_t h : hashes_cell) {\n                auto it = hash_to_ids.find(h);\n                if (it == hash_to_ids.end()) continue;\n                for (int id : it->second) {\n                    if (occ[id] == 1) {\n                        essential = true;\n                        break;\n                    }\n                }\n                if (essential) break;\n            }\n            if (!essential) {\n                apply_change(r, c, '.');\n                changed = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummy;\n    cin >> dummy; // read N (always 20) and ignore\n    cin >> M;\n\n    strs.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> strs[i];\n    }\n\n    // compute hashes and mapping\n    hashes.resize(M);\n    for (int i = 0; i < M; ++i) {\n        hashes[i] = encode(strs[i]);\n        hash_to_ids[hashes[i]].push_back(i);\n    }\n\n    // Precompute all placements for each string\n    vector<vector<Placement>> placements(M);\n    for (int i = 0; i < M; ++i) {\n        const string &s = strs[i];\n        int len = s.size();\n        placements[i].reserve(800);\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                // horizontal\n                Placement ph;\n                ph.cells.reserve(len);\n                ph.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int col = (c + t) % N;\n                    ph.cells.push_back(r * N + col);\n                    ph.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(ph));\n                // vertical\n                Placement pv;\n                pv.cells.reserve(len);\n                pv.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int row = (r + t) % N;\n                    pv.cells.push_back(row * N + c);\n                    pv.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(pv));\n            }\n        }\n    }\n\n    // Resize global occ\n    occ.resize(M, 0);\n\n    // Try several greedy initializations and keep the best one\n    const int TRIES = 8;\n    int best_matched = -1;\n    vector<string> best_mat;\n    for (int t = 0; t < TRIES; ++t) {\n        greedy_initialization(placements);\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n        if (best_matched == M) break;\n    }\n    // set state to best found\n    mat = best_mat;\n    compute_initial_state();\n\n    // Simulated Annealing\n    const double TIME_LIMIT = 2.85; // seconds\n    auto start_time = chrono::steady_clock::now();\n    int iter = 0;\n    double T = 1.0;\n    const double COOLING = 0.99999;\n    const double MIN_T = 1e-4;\n    while (matched < M) {\n        double elapsed = chrono::duration_cast<chrono::duration<double>>(\n                             chrono::steady_clock::now() - start_time)\n                             .count();\n        if (elapsed >= TIME_LIMIT) break;\n        if (T < MIN_T) break;\n\n        int r = uniform_int_distribution<int>(0, N-1)(rng);\n        int c = uniform_int_distribution<int>(0, N-1)(rng);\n        char oldc = mat[r][c];\n        char newc;\n        do {\n            newc = 'A' + uniform_int_distribution<int>(0, ALPH-1)(rng);\n        } while (newc == oldc);\n\n        int delta = compute_delta(r, c, oldc, newc);\n        if (delta > 0) {\n            apply_change(r, c, newc);\n        } else if (delta == 0) {\n            if (uniform_real_distribution<double>(0,1)(rng) < 0.1) {\n                apply_change(r, c, newc);\n            }\n        } else {\n            double prob = exp(delta / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                apply_change(r, c, newc);\n            }\n        }\n        T *= COOLING;\n        iter++;\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n        }\n    }\n\n    // If we have all strings, try to remove cells to increase score\n    if (best_matched == M) {\n        mat = best_mat;\n        compute_initial_state();\n        remove_redundant_cells();\n        best_mat = mat;\n    }\n\n    // output\n    for (int i = 0; i < N; ++i) {\n        cout << best_mat[i] << \"\\n\";\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\nconst int MAXR = 5000;\n\nint N, si, sj;\nvector<string> grid;\nint R;\nvector<pair<int,int>> pos;\nvector<int> weight;\nvector<vector<int>> adj;\nint id[70][70];\n\nvoid read_input() {\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    R = 0;\n    memset(id, -1, sizeof(id));\n    pos.clear(); weight.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R;\n                pos.emplace_back(i, j);\n                weight.push_back(grid[i][j] - '0');\n                ++R;\n            }\n        }\n    }\n    adj.assign(R, vector<int>());\n    int di[] = {-1,1,0,0}, dj[] = {0,0,-1,1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == '#') continue;\n            int u = id[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && grid[ni][nj] != '#') {\n                    adj[u].push_back(id[ni][nj]);\n                }\n            }\n        }\n    }\n}\n\nvector<vector<int>> compute_all_pairs() {\n    vector<vector<int>> dist(R, vector<int>(R, INF));\n    for (int s = 0; s < R; ++s) {\n        vector<int> d(R, INF);\n        d[s] = 0;\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top(); pq.pop();\n            if (cd != d[u]) continue;\n            for (int v : adj[u]) {\n                int nd = cd + weight[v];\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n        dist[s] = d;\n    }\n    return dist;\n}\n\nvector<vector<int>> extract_segments(int orient) {\n    vector<vector<int>> segs;\n    if (orient == 0) {\n        for (int i = 0; i < N; ++i) {\n            int j = 0;\n            while (j < N) {\n                if (grid[i][j] == '#') { ++j; continue; }\n                int start = j;\n                while (j < N && grid[i][j] != '#') ++j;\n                vector<int> seg;\n                for (int k = start; k < j; ++k) seg.push_back(id[i][k]);\n                segs.push_back(seg);\n            }\n        }\n    } else {\n        for (int j = 0; j < N; ++j) {\n            int i = 0;\n            while (i < N) {\n                if (grid[i][j] == '#') { ++i; continue; }\n                int start = i;\n                while (i < N && grid[i][j] != '#') ++i;\n                vector<int> seg;\n                for (int k = start; k < i; ++k) seg.push_back(id[k][j]);\n                segs.push_back(seg);\n            }\n        }\n    }\n    return segs;\n}\n\nvector<vector<int>> build_all_groups(const vector<vector<int>>& h,\n                                     const vector<vector<int>>& v,\n                                     int start_id) {\n    vector<vector<int>> groups = h;\n    groups.insert(groups.end(), v.begin(), v.end());\n    groups.push_back({start_id});\n    return groups;\n}\n\nvector<int> greedy_set_cover(const vector<vector<int>>& groups, mt19937& rng) {\n    int G = groups.size();\n    vector<bitset<MAXR>> cover(G);\n    for (int g = 0; g < G; ++g) {\n        bitset<MAXR> bs;\n        for (int u : groups[g]) bs.set(u);\n        cover[g] = bs;\n    }\n    bitset<MAXR> uncovered;\n    for (int u = 0; u < R; ++u) uncovered.set(u);\n    vector<int> selected;\n    int start_group = G-1;\n    selected.push_back(start_group);\n    uncovered &= ~cover[start_group];\n    while (uncovered.any()) {\n        vector<int> candidates;\n        int best_cnt = 0;\n        for (int g = 0; g < G; ++g) {\n            if (find(selected.begin(), selected.end(), g) != selected.end()) continue;\n            int cnt = (cover[g] & uncovered).count();\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                candidates = {g};\n            } else if (cnt == best_cnt) {\n                candidates.push_back(g);\n            }\n        }\n        if (candidates.empty()) break;\n        int pick = candidates[rng() % candidates.size()];\n        selected.push_back(pick);\n        uncovered &= ~cover[pick];\n    }\n    return selected;\n}\n\nvector<vector<int>> build_group_dist(const vector<int>& sel,\n                                     const vector<vector<int>>& groups,\n                                     const vector<vector<int>>& dist) {\n    int S = sel.size();\n    vector<vector<int>> D(S, vector<int>(S, INF));\n    for (int i = 0; i < S; ++i) {\n        D[i][i] = 0;\n        for (int j = i+1; j < S; ++j) {\n            int best = INF;\n            for (int u : groups[sel[i]]) {\n                for (int v : groups[sel[j]]) {\n                    best = min(best, dist[u][v]);\n                }\n            }\n            D[i][j] = D[j][i] = best;\n        }\n    }\n    return D;\n}\n\nvector<int> nearest_neighbour_order(const vector<vector<int>>& D) {\n    int S = D.size();\n    if (S == 0) return {};\n    vector<bool> used(S, false);\n    vector<int> order;\n    order.push_back(0);\n    used[0] = true;\n    int cur = 0;\n    for (int step = 1; step < S; ++step) {\n        int best = -1, bestd = INF;\n        for (int v = 0; v < S; ++v) {\n            if (!used[v] && D[cur][v] < bestd) {\n                bestd = D[cur][v];\n                best = v;\n            }\n        }\n        order.push_back(best);\n        used[best] = true;\n        cur = best;\n    }\n    return order;\n}\n\nvoid two_opt(vector<int>& order, const vector<vector<int>>& D) {\n    int S = order.size();\n    bool improved;\n    do {\n        improved = false;\n        for (int i = 1; i < S-1; ++i) {\n            for (int j = i+1; j < S; ++j) {\n                int a = order[i-1];\n                int b = order[i];\n                int c = order[j];\n                int d = (j+1 < S) ? order[j+1] : order[0];\n                int old = D[a][b] + D[c][d];\n                int nw = D[a][c] + D[b][d];\n                if (nw < old) {\n                    reverse(order.begin() + i, order.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    } while (improved);\n}\n\nvoid three_opt(vector<int>& order, const vector<vector<int>>& D) {\n    int S = order.size();\n    bool improved;\n    do {\n        improved = false;\n        for (int i = 1; i < S-2; ++i) {\n            for (int j = i+1; j < S-1; ++j) {\n                for (int k = j+1; k < S; ++k) {\n                    int a = order[i-1];\n                    int b = order[i];\n                    int c = order[j];\n                    int d = order[j+1];\n                    int e = order[k];\n                    int f = (k+1 < S) ? order[k+1] : order[0];\n                    int cur = D[a][b] + D[c][d] + D[e][f];\n                    // case1: reverse segment b..c\n                    int cand1 = D[a][c] + D[b][d] + D[e][f];\n                    if (cand1 < cur) {\n                        reverse(order.begin() + i, order.begin() + j + 1);\n                        improved = true;\n                        goto restart;\n                    }\n                    // case2: reverse d..e\n                    {\n                        int cand2 = D[a][b] + D[c][e] + D[d][f];\n                        if (cand2 < cur) {\n                            reverse(order.begin() + j+1, order.begin() + k+1);\n                            improved = true;\n                            goto restart;\n                        }\n                    }\n                    restart:;\n                }\n            }\n        }\n    } while (improved);\n}\n\npair<int, vector<int>> select_nodes(const vector<int>& order,\n                                     const vector<int>& sel,\n                                     const vector<vector<int>>& groups,\n                                     const vector<vector<int>>& dist,\n                                     int start_id) {\n    int S = order.size();\n    if (S == 0) return {0, {}};\n    vector<const vector<int>*> grps(S);\n    for (int i = 0; i < S; ++i) grps[i] = &groups[sel[order[i]]];\n    vector<vector<int>> dp(S);\n    vector<vector<int>> prev(S);\n    const auto& g0 = *grps[0];\n    int sz0 = g0.size();\n    dp[0].assign(sz0, INF);\n    int start_idx = -1;\n    for (int i = 0; i < sz0; ++i) if (g0[i] == start_id) { start_idx = i; break; }\n    if (start_idx == -1) {\n        start_idx = 0;\n        dp[0][0] = 0;\n    } else {\n        dp[0][start_idx] = 0;\n    }\n    for (int pos = 1; pos < S; ++pos) {\n        const auto& cur = *grps[pos];\n        const auto& prv = *grps[pos-1];\n        int cs = cur.size(), ps = prv.size();\n        dp[pos].assign(cs, INF);\n        prev[pos].assign(cs, -1);\n        for (int vi = 0; vi < cs; ++vi) {\n            int v = cur[vi];\n            int best = INF, best_ui = -1;\n            for (int ui = 0; ui < ps; ++ui) {\n                int u = prv[ui];\n                int cand = dp[pos-1][ui] + dist[u][v];\n                if (cand < best) { best = cand; best_ui = ui; }\n            }\n            dp[pos][vi] = best;\n            prev[pos][vi] = best_ui;\n        }\n    }\n    const auto& last = *grps[S-1];\n    int ls = last.size();\n    int best_final = INF, best_li = -1;\n    for (int vi = 0; vi < ls; ++vi) {\n        int v = last[vi];\n        int cand = dp[S-1][vi] + dist[v][start_id];\n        if (cand < best_final) { best_final = cand; best_li = vi; }\n    }\n    vector<int> selected(S);\n    selected[S-1] = last[best_li];\n    for (int pos = S-1; pos >= 1; --pos) {\n        int ui = prev[pos][best_li];\n        selected[pos-1] = (*grps[pos-1])[ui];\n        best_li = ui;\n    }\n    return {best_final, selected};\n}\n\nstring get_path(int from, int to, const vector<vector<int>>&) {\n    if (from == to) return \"\";\n    vector<int> d(R, INF);\n    vector<int> parent(R, -1);\n    vector<char> move_char(R, 0);\n    d[from] = 0;\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    pq.emplace(0, from);\n    while (!pq.empty()) {\n        auto [cd, u] = pq.top(); pq.pop();\n        if (cd != d[u]) continue;\n        if (u == to) break;\n        for (int v : adj[u]) {\n            int nd = cd + weight[v];\n            if (nd < d[v]) {\n                d[v] = nd;\n                parent[v] = u;\n                int dx = pos[v].first - pos[u].first;\n                int dy = pos[v].second - pos[u].second;\n                if (dx == -1) move_char[v] = 'U';\n                else if (dx == 1) move_char[v] = 'D';\n                else if (dy == -1) move_char[v] = 'L';\n                else if (dy == 1) move_char[v] = 'R';\n                pq.emplace(nd, v);\n            }\n        }\n    }\n    string path;\n    int cur = to;\n    while (cur != from) {\n        path.push_back(move_char[cur]);\n        cur = parent[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n    auto dist = compute_all_pairs();\n    int start_id = id[si][sj];\n    auto h_segs = extract_segments(0);\n    auto v_segs = extract_segments(1);\n    auto groups = build_all_groups(h_segs, v_segs, start_id);\n\n    mt19937 rng(1234567);\n    const int TRIALS = 5;\n    int best_total = INF;\n    string best_output;\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        auto sel = greedy_set_cover(groups, rng);\n        // iterative removal of unnecessary groups\n        bool removed = true;\n        while (removed) {\n            removed = false;\n            bitset<MAXR> covered;\n            for (int idx : sel) {\n                for (int u : groups[idx]) covered.set(u);\n            }\n            for (int i = (int)sel.size()-2; i >= 0; --i) {\n                int idx = sel[i];\n                bitset<MAXR> tmp = covered;\n                for (int u : groups[idx]) tmp.reset(u);\n                if (tmp.count() == (size_t)R) {\n                    sel.erase(sel.begin() + i);\n                    removed = true;\n                    break;\n                }\n            }\n        }\n        if (sel.empty()) continue;\n        auto D = build_group_dist(sel, groups, dist);\n        auto order = nearest_neighbour_order(D);\n        if (order.empty()) continue;\n        two_opt(order, D);\n        three_opt(order, D);\n        auto [cost, selected_nodes] = select_nodes(order, sel, groups, dist, start_id);\n        if (cost < best_total) {\n            best_total = cost;\n            string ans;\n            for (int k = 0; k < (int)order.size()-1; ++k) {\n                ans += get_path(selected_nodes[k], selected_nodes[k+1], dist);\n            }\n            ans += get_path(selected_nodes.back(), selected_nodes[0], dist);\n            best_output = ans;\n        }\n    }\n    if (best_output.empty()) {\n        best_output = \"\";\n    }\n    cout << best_output << endl;\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ========== constants ==========\nconst double INF = 1e9;\nconst double LR0 = 0.5;           // base learning rate\nconst double EXPLORE = 1.0;       // exploration coefficient for UCB\n\nint N, M, K, R;\nvector<vector<int>> d;           // N x K difficulty\nvector<vector<int>> preds, succs;\nvector<int> rem_pred;\n\n// state\nvector<int> status;              // -1: not started, 0: in progress, 1: done\nvector<int> start_day;\nvector<int> worker_of_task;\nvector<int> actual_dur;\nvector<double> pred_dur_at_start;\nvector<int> cur_task;            // -1 if idle\nvector<vector<double>> skill_est; // M x K\nvector<vector<int>> skill_cnt;   // how many times each skill was updated (per worker)\n\n// estimates\nvector<double> est_dur;          // current estimated duration of each task (for scheduling)\n\n// ========== helpers ==========\ninline double predict_dur(int task, int worker) {\n    double w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) w += diff;\n    }\n    return (w == 0.0) ? 1.0 : (1.0 + w);\n}\n\ninline double ucb_score(int task, int worker, int day) {\n    double base = predict_dur(task, worker);\n    double exploration = EXPLORE * sqrt(log(day + 1.0) / (1.0 + skill_cnt[worker][0])); // count total assignments roughly\n    return base - exploration;   // lower is better\n}\n\n// update skill estimates after observing actual duration\nvoid update_skills(int worker, int task, int actual_t) {\n    int obs_w = max(0, actual_t - 1);\n    // predicted w before task\n    double pred_w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) pred_w += diff;\n    }\n    double error = pred_w - obs_w;   // positive -> overestimate\n    // per-skill learning rate\n    auto lr = [&](int k) -> double {\n        return LR0 / sqrt(1.0 + skill_cnt[worker][k]);\n    };\n    if (obs_w == 0) {\n        // no deficiency -> increase skills that were lacking\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                skill_est[worker][k] += lr(k) * (d[task][k] - skill_est[worker][k]);\n                skill_cnt[worker][k]++;\n            }\n        }\n    } else {\n        // deficiency existed\n        double scale = (pred_w > 0) ? error / pred_w : 0.0;\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                skill_est[worker][k] += lr(k) * scale;\n                skill_cnt[worker][k]++;\n            }\n        }\n        // case: predicted no deficiency but actually deficiency existed\n        if (pred_w == 0.0 && obs_w > 0) {\n            for (int k = 0; k < K; ++k) {\n                if (skill_est[worker][k] > d[task][k]) {\n                    skill_est[worker][k] = max(0.0, skill_est[worker][k] - lr(k) * 0.5);\n                    skill_cnt[worker][k]++;\n                }\n            }\n        }\n    }\n    // clamp\n    for (int k = 0; k < K; ++k) {\n        if (skill_est[worker][k] < 0) skill_est[worker][k] = 0;\n        if (skill_est[worker][k] > 200) skill_est[worker][k] = 200;\n    }\n}\n\n// ========== main ==========\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    cin >> N >> M >> K >> R;\n    d.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < K; ++j)\n            cin >> d[i][j];\n\n    preds.assign(N, vector<int>());\n    succs.assign(N, vector<int>());\n    rem_pred.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        preds[v].push_back(u);\n        succs[u].push_back(v);\n        rem_pred[v]++;\n    }\n\n    // initialize state\n    status.assign(N, -1);\n    start_day.assign(N, 0);\n    worker_of_task.assign(N, -1);\n    actual_dur.assign(N, 0);\n    pred_dur_at_start.assign(N, 0.0);\n    cur_task.assign(M, -1);\n    skill_est.assign(M, vector<double>(K, 0.0));\n    skill_cnt.assign(M, vector<int>(K, 0));\n\n    // better initial skill: use average task difficulty per dimension\n    vector<double> avg_skill(K, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            avg_skill[k] += d[i][k];\n    for (int k = 0; k < K; ++k) avg_skill[k] /= N;\n    for (int j = 0; j < M; ++j)\n        for (int k = 0; k < K; ++k)\n            skill_est[j][k] = avg_skill[k] * (0.8 + 0.4 * (double)rand() / RAND_MAX); // perturb\n\n    // main loop\n    int day = 1;\n    while (true) {\n        // ---- compute estimated duration and critical path weights ----\n        est_dur.assign(N, 0.0);\n        vector<double> finish_time(N, 0.0);\n        // forward pass (topological order)\n        for (int i = 0; i < N; ++i) {\n            double max_pred_finish = 0.0;\n            for (int p : preds[i]) {\n                if (finish_time[p] > max_pred_finish)\n                    max_pred_finish = finish_time[p];\n            }\n            double est_start_i = max_pred_finish + 1.0;\n            if (status[i] == 1) {\n                est_dur[i] = actual_dur[i];\n                finish_time[i] = start_day[i] + actual_dur[i] - 1.0;\n            } else if (status[i] == 0) {\n                double remain = max(0.0, pred_dur_at_start[i] - (day - start_day[i]));\n                est_dur[i] = remain;\n                // finish_time remains same? We'll keep it consistent: started tasks are already scheduled.\n                finish_time[i] = day + remain - 1.0;\n            } else {\n                // unstarted: find the best worker (optimistic)\n                double best = INF;\n                for (int j = 0; j < M; ++j) {\n                    double ddd = predict_dur(i, j);\n                    if (ddd < best) best = ddd;\n                }\n                est_dur[i] = best;\n                finish_time[i] = est_start_i + best - 1.0;\n            }\n        }\n\n        // ---- compute criticality (longest path to leaf) ----\n        vector<double> criticality(N, 0.0);\n        for (int i = N - 1; i >= 0; --i) {\n            double max_succ = 0.0;\n            for (int s : succs[i]) {\n                if (criticality[s] > max_succ) max_succ = criticality[s];\n            }\n            criticality[i] = est_dur[i] + max_succ;\n        }\n\n        // ---- ready tasks ----\n        vector<int> ready;\n        for (int i = 0; i < N; ++i)\n            if (status[i] == -1 && rem_pred[i] == 0) ready.push_back(i);\n\n        // ---- sort by criticality (descending) ----\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (criticality[a] != criticality[b])\n                return criticality[a] > criticality[b];\n            return a < b;\n        });\n\n        // ---- idle workers ----\n        vector<int> idle;\n        for (int j = 0; j < M; ++j) if (cur_task[j] == -1) idle.push_back(j);\n\n        // ---- assignment ----\n        vector<int> assign_out; // flattened: worker, task (0-index)\n        for (int task : ready) {\n            if (idle.empty()) break;\n            // pick best idle worker via UCB\n            int best_w = -1;\n            double best_val = INF;\n            for (int j : idle) {\n                double u = ucb_score(task, j, day);\n                if (u < best_val) {\n                    best_val = u;\n                    best_w = j;\n                }\n            }\n            // assign\n            assign_out.push_back(best_w);\n            assign_out.push_back(task);\n            cur_task[best_w] = task;\n            start_day[task] = day;\n            worker_of_task[task] = best_w;\n            pred_dur_at_start[task] = predict_dur(task, best_w);\n            status[task] = 0;\n            // update counts (roughly)\n            for (int k = 0; k < K; ++k) skill_cnt[best_w][k]++; // increment all\n            // remove worker from idle\n            auto it = find(idle.begin(), idle.end(), best_w);\n            if (it != idle.end()) {\n                *it = idle.back();\n                idle.pop_back();\n            }\n        }\n\n        // ---- output ----\n        int m = assign_out.size() / 2;\n        cout << m;\n        for (int x : assign_out) cout << ' ' << (x + 1);\n        cout << '\\n';\n        cout.flush();\n\n        // ---- read response ----\n        int dummy;\n        cin >> dummy;\n        if (dummy == -1) break;\n\n        // ---- process completions ----\n        for (int i = 0; i < dummy; ++i) {\n            int worker;\n            cin >> worker;\n            --worker;\n            int task = cur_task[worker];\n            int duration = day - start_day[task] + 1;\n\n            status[task] = 1;\n            actual_dur[task] = duration;\n            cur_task[worker] = -1;\n\n            // update skill estimates\n            update_skills(worker, task, duration);\n\n            // update remaining predecessors of successors\n            for (int s : succs[task]) {\n                rem_pred[s]--;\n            }\n        }\n        ++day;\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst int DEPOT_ID = 2000;\nconst int NUM_ORDERS = 1000;\nconst int NUM_SELECT = 50;\nconst int CENTER = 400;\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// Compute total distance of a route (array of node ids)\nint total_distance(const vector<int>& route, const vector<vector<int>>& dist) {\n    int sum = 0;\n    for (size_t i = 0; i + 1 < route.size(); ++i)\n        sum += dist[route[i]][route[i + 1]];\n    return sum;\n}\n\n// Check that for each order, pickup appears before delivery in the route\nbool is_feasible(const vector<int>& route) {\n    vector<int> first(2000, -1), second(2000, -1);\n    for (size_t i = 0; i < route.size(); ++i) {\n        int node = route[i];\n        if (node == DEPOT_ID) continue;\n        int idx = node;\n        if (node % 2 == 0) { // pickup\n            if (first[idx] != -1) return false;\n            first[idx] = (int)i;\n        } else { // delivery\n            if (second[idx] != -1) return false;\n            second[idx] = (int)i;\n        }\n    }\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int p = 2 * i, d = 2 * i + 1;\n        if (first[p] == -1 && second[d] == -1) continue; // order not selected\n        if (first[p] == -1 || second[d] == -1) return false; // incomplete order\n        if (first[p] > second[d]) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    vector<pair<int,int>> pickup(NUM_ORDERS), delivery(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int a, b, c, d;\n        cin >> a >> b >> c >> d;\n        pickup[i] = {a, b};\n        delivery[i] = {c, d};\n    }\n\n    // Node coordinates: order i -> pickup 2*i, delivery 2*i+1, depot = 2000\n    vector<int> node_x(2001), node_y(2001);\n    node_x[DEPOT_ID] = node_y[DEPOT_ID] = CENTER;\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        node_x[2 * i] = pickup[i].first;\n        node_y[2 * i] = pickup[i].second;\n        node_x[2 * i + 1] = delivery[i].first;\n        node_y[2 * i + 1] = delivery[i].second;\n    }\n\n    // Precompute distance matrix (2001 x 2001)\n    vector<vector<int>> dist(2001, vector<int>(2001));\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist[i][j] = manhattan(node_x[i], node_y[i], node_x[j], node_y[j]);\n\n    // ---------- Phase 1: Select 50 orders ----------\n    // Score used: distance(pickup, depot) + distance(delivery, depot)\n    vector<pair<int,int>> order_score(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int s = dist[2 * i][DEPOT_ID] + dist[2 * i + 1][DEPOT_ID];\n        order_score[i] = {s, i};\n    }\n    sort(order_score.begin(), order_score.end());\n    vector<bool> selected(NUM_ORDERS, false);\n    for (int k = 0; k < NUM_SELECT; ++k)\n        selected[order_score[k].second] = true;\n\n    // ---------- Phase 2: Greedy Cheapest Insertion ----------\n    vector<int> route = {DEPOT_ID, DEPOT_ID};\n    int total = 0;\n    for (int iter = 0; iter < NUM_SELECT; ++iter) {\n        // find the order (among unselected) that minimizes insertion cost\n        int best_o = -1, best_pos = -1, best_inc = INT_MAX;\n        for (int i = 0; i < NUM_ORDERS; ++i) {\n            if (!selected[i]) continue; // already in route? need to track used\n        }\n        // Actually we need to process only the selected orders\n        // Build a list of selected order indices\n    }\n    // Better: use list of selected orders\n    vector<int> order_list;\n    for (auto& p : order_score)\n        if (selected[p.second]) order_list.push_back(p.second);\n\n    for (int o : order_list) {\n        int p = 2 * o;\n        int d = 2 * o + 1;\n        int L = route.size();\n        int best_pos = -1, best_inc = INT_MAX;\n        for (int pos = 0; pos < L - 1; ++pos) {\n            int left = route[pos];\n            int right = route[pos + 1];\n            int inc = -dist[left][right] + dist[left][p] + dist[p][d] + dist[d][right];\n            if (inc < best_inc) {\n                best_inc = inc;\n                best_pos = pos;\n            }\n        }\n        route.insert(route.begin() + best_pos + 1, {p, d});\n        total += best_inc;\n        selected[o] = false; // mark as used (but we iterate each once)\n    }\n    // After insertion, route size = 102 (2 depots + 100 nodes)\n    // Verify feasibility\n    if (!is_feasible(route)) {\n        cerr << \"ERROR: Infeasible initial route\" << endl;\n        return 1;\n    }\n\n    // ---------- Phase 3: Local Search (Simulated Annealing) ----------\n    vector<int> best_route = route;\n    int best_total = total;\n    double temperature = 500.0;\n    double cooling = 0.9999;\n    auto start_time = chrono::steady_clock::now();\n    double elapsed = 0.0;\n    int iteration = 0;\n\n    while (elapsed < 1.9 && iteration < 100000) {\n        ++iteration;\n        // pick random move: 0 = relocate node, 1 = swap two nodes\n        int move_type = rng() % 2;\n        vector<int> new_route = route;\n        int n = (int)new_route.size();\n        // only consider positions 1..n-2 (non-depot)\n        int i = rng() % (n - 2) + 1;\n        int j = rng() % (n - 2) + 1;\n        if (i == j) continue;\n\n        if (move_type == 0) {\n            // relocate node at i to position j\n            int node = new_route[i];\n            new_route.erase(new_route.begin() + i);\n            // adjust j if necessary (since size decreased by 1)\n            if (j > (int)new_route.size()) j = new_route.size();\n            new_route.insert(new_route.begin() + j, node);\n        } else {\n            // swap nodes at i and j\n            swap(new_route[i], new_route[j]);\n        }\n\n        // feasibility check\n        if (!is_feasible(new_route)) continue;\n\n        int new_total = total_distance(new_route, dist);\n        int delta = new_total - total;\n\n        // acceptance criterion\n        if (delta < 0 || (exp(-delta / temperature) > (double)rng() / rng.max())) {\n            route = new_route;\n            total = new_total;\n            if (total < best_total) {\n                best_total = total;\n                best_route = route;\n            }\n        }\n\n        temperature *= cooling;\n        elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    }\n\n    // ---------- Phase 4: Output ----------\n    // Extract order indices in appearance order from best_route\n    vector<int> out_orders;\n    for (int node : best_route) {\n        if (node == DEPOT_ID) continue;\n        int o = node / 2;\n        if (out_orders.empty() || out_orders.back() != o)\n            out_orders.push_back(o);\n    }\n    // Ensure exactly 50 orders\n    if ((int)out_orders.size() != 50) {\n        // fallback: use the initial selected order list\n        out_orders = order_list;\n    }\n\n    cout << 50;\n    for (int o : out_orders) cout << ' ' << o + 1;\n    cout << '\\n';\n\n    cout << best_route.size();\n    for (int node : best_route) {\n        // Safety clamp (should be within [0,800] always)\n        int x = node_x[node];\n        int y = node_y[node];\n        if (x < 0) x = 0; if (x > 800) x = 800;\n        if (y < 0) y = 0; if (y > 800) y = 800;\n        cout << ' ' << x << ' ' << y;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, rank;\n    DSU(int n) : parent(n), rank(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) swap(x, y);\n        parent[y] = x;\n        if (rank[x] == rank[y]) ++rank[x];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400, M = 1995;\n\n    // read coordinates\n    vector<pair<int,int>> coord(N);\n    for (int i = 0; i < N; ++i) cin >> coord[i].first >> coord[i].second;\n\n    struct Edge { int u, v, d; };\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v; cin >> u >> v;\n        int dx = coord[u].first - coord[v].first;\n        int dy = coord[u].second - coord[v].second;\n        double dist = sqrt(dx*dx + dy*dy);\n        int d = round(dist);\n        edges[i] = {u, v, d};\n    }\n\n    // ---------- build MST based on d ----------\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return edges[a].d < edges[b].d;\n    });\n\n    DSU dsu_mst(N);\n    vector<bool> in_mst(M, false);\n    vector<int> tree_edges;  // store indices of tree edges\n    for (int idx : order) {\n        auto& e = edges[idx];\n        if (dsu_mst.unite(e.u, e.v)) {\n            in_mst[idx] = true;\n            tree_edges.push_back(idx);\n            if ((int)tree_edges.size() == N-1) break;\n        }\n    }\n\n    // ---------- build tree adjacency and LCA ----------\n    vector<vector<pair<int,int>>> adj(N);\n    for (int idx : tree_edges) {\n        auto& e = edges[idx];\n        adj[e.u].push_back({e.v, idx});\n        adj[e.v].push_back({e.u, idx});\n    }\n\n    vector<int> parent(N, -1), depth(N, 0), parent_edge(N, -1);\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [v, eid] : adj[u]) {\n            if (v == parent[u]) continue;\n            parent[v] = u;\n            depth[v] = depth[u] + 1;\n            parent_edge[v] = eid;\n            q.push(v);\n        }\n    }\n\n    auto get_path_edges = [&](int u, int v) -> vector<int> {\n        vector<int> path;\n        while (depth[u] > depth[v]) {\n            path.push_back(parent_edge[u]);\n            u = parent[u];\n        }\n        while (depth[v] > depth[u]) {\n            path.push_back(parent_edge[v]);\n            v = parent[v];\n        }\n        while (u != v) {\n            path.push_back(parent_edge[u]);\n            path.push_back(parent_edge[v]);\n            u = parent[u];\n            v = parent[v];\n        }\n        return path;\n    };\n\n    // ---------- compute best alternative for each tree edge ----------\n    vector<int> best_alt_id(M, -1);\n    vector<int> best_alt_d(M, INT_MAX);\n    for (int i = 0; i < M; ++i) {\n        if (in_mst[i]) continue;\n        auto& e = edges[i];\n        auto path = get_path_edges(e.u, e.v);\n        for (int tid : path) {\n            if (edges[i].d < best_alt_d[tid]) {\n                best_alt_d[tid] = edges[i].d;\n                best_alt_id[tid] = i;\n            }\n        }\n    }\n\n    // for each non-tree edge, list tree edges for which it is the best alternative\n    vector<vector<int>> candidates(M);\n    for (int tid : tree_edges) {\n        if (best_alt_id[tid] != -1) {\n            candidates[best_alt_id[tid]].push_back(tid);\n        }\n    }\n\n    // ---------- online decision ----------\n    DSU dsu(N);\n    vector<bool> adopted_tree(M, false);\n    vector<bool> redundant_tree(M, false);\n\n    for (int i = 0; i < M; ++i) {\n        long long l; cin >> l;\n        auto& e = edges[i];\n        int u = e.u, v = e.v;\n\n        if (in_mst[i]) {\n            // tree edge\n            if (redundant_tree[i]) {\n                cout << 0 << endl;\n                continue;\n            }\n            if (dsu.find(u) == dsu.find(v)) {\n                redundant_tree[i] = true;\n                cout << 0 << endl;\n                continue;\n            }\n            // adopt it\n            cout << 1 << endl;\n            dsu.unite(u, v);\n            adopted_tree[i] = true;\n            // check if any other tree edges become redundant\n            for (int t : tree_edges) {\n                if (!adopted_tree[t] && !redundant_tree[t]) {\n                    if (dsu.find(edges[t].u) == dsu.find(edges[t].v)) {\n                        redundant_tree[t] = true;\n                    }\n                }\n            }\n        } else {\n            // non-tree edge\n            bool adopt = false;\n            for (int t : candidates[i]) {\n                if (adopted_tree[t] || redundant_tree[t]) continue;\n                // if the tree edge's endpoints are already connected, mark redundant\n                if (dsu.find(edges[t].u) == dsu.find(edges[t].v)) {\n                    redundant_tree[t] = true;\n                    continue;\n                }\n                // adopt this non-tree edge if its cost is not greater than the tree edge's d (safe threshold)\n                // using a small factor (1.3) to allow some risk for better score\n                if (l <= 1.3 * edges[t].d) {\n                    if (dsu.find(u) != dsu.find(v)) {\n                        adopt = true;\n                        break;\n                    }\n                }\n            }\n            if (adopt) {\n                cout << 1 << endl;\n                dsu.unite(u, v);\n                // update redundant status for tree edges\n                for (int t : tree_edges) {\n                    if (!adopted_tree[t] && !redundant_tree[t]) {\n                        if (dsu.find(edges[t].u) == dsu.find(edges[t].v)) {\n                            redundant_tree[t] = true;\n                        }\n                    }\n                }\n            } else {\n                cout << 0 << endl;\n            }\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int MAXT = 300;\nconst int MAXN = 20;\nconst int MAXM = 10;\n\nint N, M;\nint pet_x[MAXN], pet_y[MAXN], pet_type[MAXN];\nint human_x[MAXM], human_y[MAXM];\n\nbool impassable[GRID+2][GRID+2]; // 1-indexed\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char move_ch[4] = {'U','D','L','R'};\nconst char block_ch[4] = {'u','d','l','r'};\n\ninline bool inside(int x, int y) {\n    return 1 <= x && x <= GRID && 1 <= y && y <= GRID;\n}\n\n// BFS structure\nstruct BFSResult {\n    int area;\n    int pet_cnt;\n    vector<pair<int,int>> boundary; // cells in region with at least one neighbor outside region\n};\n\n// BFS from (sx,sy) on the given impassable grid. Returns area, pet count, and boundary.\nBFSResult bfs(int sx, int sy, const bool tmp_impassable[GRID+2][GRID+2],\n              const int start_pet_x[], const int start_pet_y[]) {\n    static bool visited[GRID+2][GRID+2];\n    static int visited_turn = 0; // timestamp to avoid memset\n    ++visited_turn;\n\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    visited[sx][sy] = true;\n    int area = 1;\n    BFSResult res;\n    res.boundary.clear();\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        // check if this cell is a boundary (any neighbor outside region)\n        bool is_boundary = false;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_impassable[nx][ny]) continue;\n            if (visited[nx][ny] == true) continue; // already visited\n            // neighbor not yet visited: it is inside the region, will be visited later\n        }\n        // Actually, we need to detect boundary: a cell is boundary if at least one adjacent cell is either impassable or outside grid (impassable) or not visited (but will be visited). The boundary definition: cells that have at least one neighbor that is not passable (i.e., impassable or outside). Since we haven't visited all neighbors yet, we can check after BFS.\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny) || tmp_impassable[nx][ny]) {\n                is_boundary = true;\n                break;\n            }\n        }\n        if (is_boundary) res.boundary.push_back({x, y});\n\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_impassable[nx][ny]) continue;\n            if (visited[nx][ny]) continue;\n            visited[nx][ny] = true;\n            q.push({nx, ny});\n            ++area;\n        }\n    }\n\n    // Count pets inside region\n    int pet_cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        if (visited[start_pet_x[i]][start_pet_y[i]]) ++pet_cnt;\n    }\n    res.area = area;\n    res.pet_cnt = pet_cnt;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N;\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_x[i] >> pet_y[i] >> pet_type[i];\n    }\n    cin >> M;\n    for (int i = 0; i < M; ++i) {\n        cin >> human_x[i] >> human_y[i];\n    }\n\n    // Initialize impassable (all passable)\n    memset(impassable, 0, sizeof(impassable));\n\n    for (int turn = 0; turn < MAXT; ++turn) {\n        // Record start positions\n        int start_hx[MAXM], start_hy[MAXM];\n        int start_px[MAXN], start_py[MAXN];\n        for (int i = 0; i < M; ++i) {\n            start_hx[i] = human_x[i];\n            start_hy[i] = human_y[i];\n        }\n        for (int i = 0; i < N; ++i) {\n            start_px[i] = pet_x[i];\n            start_py[i] = pet_y[i];\n        }\n\n        // copy current impassable\n        bool cur_impassable[GRID+2][GRID+2];\n        memcpy(cur_impassable, impassable, sizeof(impassable));\n\n        int cur_hx[MAXM], cur_hy[MAXM];\n        memcpy(cur_hx, start_hx, sizeof(int)*M);\n        memcpy(cur_hy, start_hy, sizeof(int)*M);\n\n        char actions[MAXM];\n\n        // Process each human sequentially\n        for (int i = 0; i < M; ++i) {\n            int sx = cur_hx[i], sy = cur_hy[i];\n            BFSResult br = bfs(sx, sy, cur_impassable, start_px, start_py);\n\n            char best_action = '.';\n            // Decide action\n            if (br.pet_cnt > 0) {\n                // Try to block a boundary cell that is adjacent to a pet (outside)\n                // Also try to move away from pets? For now, just try to block.\n                bool found = false;\n                for (auto [bx, by] : br.boundary) {\n                    // Check if this boundary cell is adjacent to any pet (outside region)\n                    bool adj_pet = false;\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = bx + dx[d], ay = by + dy[d];\n                        if (!inside(ax, ay)) continue;\n                        // Check if a pet is at (ax,ay) (start positions)\n                        for (int p = 0; p < N; ++p) {\n                            if (start_px[p] == ax && start_py[p] == ay) {\n                                adj_pet = true;\n                                break;\n                            }\n                        }\n                        if (adj_pet) break;\n                    }\n                    if (adj_pet) {\n                        // We want to block this boundary cell to prevent pet from entering\n                        // Verify block conditions: cell must be passable, not contain human/pet at start, not adjacent to any pet\n                        if (cur_impassable[bx][by]) continue;\n                        // must not contain any start human or pet\n                        bool occupied = false;\n                        for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                        if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                        if (occupied) continue;\n                        // must not be adjacent to any pet (the block rule)\n                        bool adj_pet2 = false;\n                        for (int d = 0; d < 4; ++d) {\n                            int ax = bx + dx[d], ay = by + dy[d];\n                            if (!inside(ax, ay)) continue;\n                            for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet2 = true; break; }\n                            if (adj_pet2) break;\n                        }\n                        if (adj_pet2) continue;\n                        // Found a valid block\n                        // Determine direction relative to human (sx,sy)\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = block_ch[d];\n                                found = true;\n                                break;\n                            }\n                        }\n                        if (found) break;\n                    }\n                }\n                if (!found) {\n                    // If no good block, try to move to a boundary cell that is not adjacent to any pet inside? Just stay.\n                    // Maybe move to a boundary cell to expand region? But region already has pets, moving won't help.\n                    best_action = '.';\n                }\n            } else {\n                // No pet inside region. We want to expand or seal.\n                // First, try to block any boundary cell that is adjacent to an outside pet to prevent entry.\n                bool blocked = false;\n                for (auto [bx, by] : br.boundary) {\n                    // Check adjacent pets (outside region)\n                    bool adj_pet = false;\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = bx + dx[d], ay = by + dy[d];\n                        if (!inside(ax, ay)) continue;\n                        for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet = true; break; }\n                        if (adj_pet) break;\n                    }\n                    if (adj_pet) {\n                        // Try to block this boundary cell\n                        // Check conditions\n                        if (cur_impassable[bx][by]) continue;\n                        bool occupied = false;\n                        for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                        if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                        if (occupied) continue;\n                        bool adj_pet2 = false;\n                        for (int d = 0; d < 4; ++d) {\n                            int ax = bx + dx[d], ay = by + dy[d];\n                            if (!inside(ax, ay)) continue;\n                            for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet2 = true; break; }\n                            if (adj_pet2) break;\n                        }\n                        if (adj_pet2) continue;\n                        // valid block\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = block_ch[d];\n                                blocked = true;\n                                break;\n                            }\n                        }\n                        if (blocked) break;\n                    }\n                }\n                if (!blocked) {\n                    // No pet adjacent to boundary. Try to move to a boundary cell to expand.\n                    // Choose a boundary cell that is not occupied at start, and not adjacent to any pet (to avoid bringing one in).\n                    pair<int,int> best_move = {-1, -1};\n                    for (auto [bx, by] : br.boundary) {\n                        // check if this cell is passable and reachable by move (adjacent to human)\n                        if (abs(bx - sx) + abs(by - sy) == 1 && !cur_impassable[bx][by]) {\n                            // Check not occupied at start\n                            bool occupied = false;\n                            for (int j = 0; j < M; ++j) if (start_hx[j] == bx && start_hy[j] == by) { occupied = true; break; }\n                            if (!occupied) for (int p = 0; p < N; ++p) if (start_px[p] == bx && start_py[p] == by) { occupied = true; break; }\n                            if (occupied) continue;\n                            // Check if this boundary cell is adjacent to any pet (outside)\n                            bool adj_pet = false;\n                            for (int d = 0; d < 4; ++d) {\n                                int ax = bx + dx[d], ay = by + dy[d];\n                                if (!inside(ax, ay)) continue;\n                                for (int p = 0; p < N; ++p) if (start_px[p] == ax && start_py[p] == ay) { adj_pet = true; break; }\n                                if (adj_pet) break;\n                            }\n                            if (adj_pet) continue; // don't move to a cell adjacent to a pet (might bring it in)\n                            // Accept this move\n                            best_move = {bx, by};\n                            break;\n                        }\n                    }\n                    if (best_move.first != -1) {\n                        int bx = best_move.first, by = best_move.second;\n                        for (int d = 0; d < 4; ++d) {\n                            if (bx == sx + dx[d] && by == sy + dy[d]) {\n                                best_action = move_ch[d];\n                                break;\n                            }\n                        }\n                    } else {\n                        // Can't move; try to block a random boundary cell? Or stay.\n                        best_action = '.';\n                    }\n                }\n            }\n\n            // Execute action\n            if (best_action == '.') {\n                // do nothing\n            } else {\n                bool is_move = false;\n                int d = -1;\n                for (int k = 0; k < 4; ++k) {\n                    if (best_action == move_ch[k]) { is_move = true; d = k; break; }\n                    if (best_action == block_ch[k]) { d = k; break; }\n                }\n                int nx = sx + dx[d], ny = sy + dy[d];\n                if (is_move) {\n                    cur_hx[i] = nx;\n                    cur_hy[i] = ny;\n                } else {\n                    cur_impassable[nx][ny] = true;\n                }\n            }\n            actions[i] = best_action;\n        }\n\n        // Output actions\n        for (int i = 0; i < M; ++i) cout << actions[i];\n        cout << endl;\n        cout.flush();\n\n        // Read pet moves\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            if (s == \".\") continue;\n            int x = pet_x[i], y = pet_y[i];\n            for (char c : s) {\n                if (c == 'U') { x -= 1; }\n                else if (c == 'D') { x += 1; }\n                else if (c == 'L') { y -= 1; }\n                else if (c == 'R') { y += 1; }\n            }\n            pet_x[i] = x;\n            pet_y[i] = y;\n        }\n\n        // Update global impassable\n        memcpy(impassable, cur_impassable, sizeof(impassable));\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nint si, sj, ti, tj;\ndouble p;\nvector<string> h(20), v(19);\nint dr[4] = {1, 0, -1, 0};\nint dc[4] = {0, 1, 0, -1};\nchar dir_chars[4] = {'D', 'R', 'U', 'L'};\nbool can[20][20][4];\n\nvoid precompute_can() {\n    for (int i = 0; i < 20; ++i)\n        for (int j = 0; j < 20; ++j)\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dr[d], nj = j + dc[d];\n                if (ni < 0 || ni >= 20 || nj < 0 || nj >= 20) {\n                    can[i][j][d] = false;\n                } else {\n                    if (d == 0) can[i][j][d] = (v[i][j] == '0');\n                    else if (d == 1) can[i][j][d] = (h[i][j] == '0');\n                    else if (d == 2) can[i][j][d] = (v[i-1][j] == '0');\n                    else can[i][j][d] = (h[i][j-1] == '0');\n                }\n            }\n}\n\ndouble evaluate(const string &s) {\n    int L = (int)s.size();\n    const int N = 400;\n    vector<double> dp(N, 0.0);\n    for (int i = 0; i < 20; ++i) for (int j = 0; j < 20; ++j) {\n        int id = i*20+j;\n        if (i == ti && j == tj) dp[id] = 401.0 - L;\n    }\n    for (int t = L-1; t >= 0; --t) {\n        int d;\n        char c = s[t];\n        if (c == 'D') d = 0;\n        else if (c == 'R') d = 1;\n        else if (c == 'U') d = 2;\n        else d = 3;\n        vector<double> ndp(N, 0.0);\n        for (int i = 0; i < 20; ++i)\n            for (int j = 0; j < 20; ++j) {\n                int id = i*20+j;\n                if (i == ti && j == tj) {\n                    ndp[id] = 401.0 - t;\n                } else {\n                    double val;\n                    if (can[i][j][d]) {\n                        int ni = i + dr[d], nj = j + dc[d];\n                        int nid = ni*20+nj;\n                        val = p * dp[id] + (1.0-p) * dp[nid];\n                    } else {\n                        val = dp[id];\n                    }\n                    ndp[id] = val;\n                }\n            }\n        dp.swap(ndp);\n    }\n    return dp[si*20+sj];\n}\n\nstring generate_greedy(bool random_tie, mt19937 &rng) {\n    const int MAX_STEPS = 200;\n    const int N = 400;\n    static vector<vector<double>> V(MAX_STEPS+1, vector<double>(N, 0.0));\n    static bool computed = false;\n    if (!computed) {\n        for (int i = 0; i < 20; ++i) for (int j = 0; j < 20; ++j) {\n            int id = i*20+j;\n            if (i == ti && j == tj) V[0][id] = 201.0;\n        }\n        for (int k = 1; k <= MAX_STEPS; ++k) {\n            for (int i = 0; i < 20; ++i)\n                for (int j = 0; j < 20; ++j) {\n                    int id = i*20+j;\n                    if (i == ti && j == tj) {\n                        V[k][id] = 201.0 + k;\n                        continue;\n                    }\n                    double best = 0.0;\n                    for (int d = 0; d < 4; ++d) {\n                        double val;\n                        if (!can[i][j][d]) {\n                            val = V[k-1][id];\n                        } else {\n                            int ni = i+dr[d], nj = j+dc[d];\n                            int nid = ni*20+nj;\n                            val = p * V[k-1][id] + (1.0-p) * V[k-1][nid];\n                        }\n                        if (val > best) best = val;\n                    }\n                    V[k][id] = best;\n                }\n        }\n        computed = true;\n    }\n\n    string ans;\n    vector<double> dist(N, 0.0);\n    dist[si*20+sj] = 1.0;\n\n    for (int step = 0; step < MAX_STEPS; ++step) {\n        int remaining = MAX_STEPS - step - 1;\n        double best_val = -1e100;\n        vector<int> candidates;\n        for (int d = 0; d < 4; ++d) {\n            double total = 0.0;\n            for (int id = 0; id < N; ++id) {\n                if (dist[id] == 0.0) continue;\n                int i = id/20, j = id%20;\n                double base;\n                if (can[i][j][d]) {\n                    int ni = i+dr[d], nj = j+dc[d];\n                    int nid = ni*20+nj;\n                    base = p * V[remaining][id] + (1.0-p) * V[remaining][nid];\n                } else {\n                    base = V[remaining][id];\n                }\n                total += dist[id] * base;\n            }\n            if (total > best_val + 1e-12) {\n                best_val = total;\n                candidates.clear();\n                candidates.push_back(d);\n            } else if (fabs(total - best_val) < 1e-12) {\n                candidates.push_back(d);\n            }\n        }\n        int best_d;\n        if (random_tie && !candidates.empty())\n            best_d = candidates[uniform_int_distribution<int>(0, (int)candidates.size()-1)(rng)];\n        else\n            best_d = candidates[0];\n        ans.push_back(dir_chars[best_d]);\n\n        vector<double> new_dist(N, 0.0);\n        for (int id = 0; id < N; ++id) {\n            if (dist[id] == 0.0) continue;\n            int i = id/20, j = id%20;\n            new_dist[id] += p * dist[id];\n            if (can[i][j][best_d]) {\n                int ni = i+dr[best_d], nj = j+dc[best_d];\n                int nid = ni*20+nj;\n                new_dist[nid] += (1.0-p) * dist[id];\n            } else {\n                new_dist[id] += (1.0-p) * dist[id];\n            }\n        }\n        dist.swap(new_dist);\n    }\n    return ans;\n}\n\nvoid hill_climb(string &s, double &score, int passes) {\n    for (int pass = 0; pass < passes; ++pass) {\n        bool improved = false;\n        for (int pos = 0; pos < (int)s.size(); ++pos) {\n            char orig = s[pos];\n            double best_local = score;\n            int best_d = -1;\n            for (int d = 0; d < 4; ++d) {\n                char nc = dir_chars[d];\n                if (nc == orig) continue;\n                s[pos] = nc;\n                double new_score = evaluate(s);\n                if (new_score > best_local + 1e-12) {\n                    best_local = new_score;\n                    best_d = d;\n                }\n                s[pos] = orig;\n            }\n            if (best_d != -1) {\n                s[pos] = dir_chars[best_d];\n                score = best_local;\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj >> ti >> tj >> p;\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i];\n    precompute_can();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    const int RESTARTS = 8;\n    string best_string;\n    double best_score = -1e100;\n    for (int r = 0; r < RESTARTS; ++r) {\n        bool use_random = (r > 0);\n        string cand = generate_greedy(use_random, rng);\n        double score = evaluate(cand);\n        hill_climb(cand, score, 1);\n        if (score > best_score) {\n            best_score = score;\n            best_string = cand;\n        }\n    }\n\n    // Intensive hill climb on best\n    hill_climb(best_string, best_score, 4);\n\n    // Simulated annealing with swaps\n    double T = best_score * 0.001;\n    const double COOL = 0.995;\n    const int SWAP_ITERS = 2000;\n    for (int iter = 0; iter < SWAP_ITERS; ++iter) {\n        int a = uniform_int_distribution<int>(0, (int)best_string.size()-1)(rng);\n        int b = uniform_int_distribution<int>(0, (int)best_string.size()-1)(rng);\n        if (a == b) continue;\n        swap(best_string[a], best_string[b]);\n        double new_score = evaluate(best_string);\n        if (new_score > best_score + 1e-12) {\n            best_score = new_score;\n        } else {\n            double prob = exp((new_score - best_score) / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                best_score = new_score;\n            } else {\n                swap(best_string[a], best_string[b]);\n            }\n        }\n        T *= COOL;\n    }\n\n    // Try suffix removal to shorten string\n    for (int len = (int)best_string.size() - 1; len >= 1; --len) {\n        string cand = best_string.substr(0, len);\n        double sc = evaluate(cand);\n        if (sc > best_score + 1e-12) {\n            best_string = cand;\n            best_score = sc;\n        }\n    }\n\n    // Try prefix removal\n    for (int start = 1; start < (int)best_string.size(); ++start) {\n        string cand = best_string.substr(start);\n        double sc = evaluate(cand);\n        if (sc > best_score + 1e-12) {\n            best_string = cand;\n            best_score = sc;\n        }\n    }\n\n    // Final hill climb after length optimization\n    hill_climb(best_string, best_score, 2);\n\n    cout << best_string << '\\n';\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nconst int N = 30;\nconst int M = N * N;  // 900\nconst int H = M * 4;  // number of half-edges\n\n// direction arrays: 0:left, 1:up, 2:right, 3:down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to[t][d] = exit direction when entering tile t from direction d, -1 if invalid\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0\n    {3, -1, -1, 0},  // 1\n    {-1, -1, 3, 2},  // 2\n    {-1, 2, 1, -1},  // 3\n    {1, 0, 3, 2},    // 4\n    {3, 2, 1, 0},    // 5\n    {2, -1, 0, -1},  // 6\n    {-1, 3, -1, 1}   // 7\n};\n\n// precomputed rotated tile types\nint rot_type[8][4];\n\nint evaluate(const int* state) {\n    static int visited[H];\n    static int gen = 0;\n    ++gen;  // new generation\n    int best = 0, second = 0;\n\n    for (int idx = 0; idx < M; ++idx) {\n        int t = state[idx];\n        int i = idx / N, j = idx % N;\n        for (int d = 0; d < 4; ++d) {\n            if (to[t][d] == -1) continue;\n            int he = (idx << 2) | d;\n            if (visited[he] == gen) continue;\n\n            // trace this path\n            int ci = i, cj = j, cd = d;\n            int len = 0;\n            bool is_cycle = false;\n            while (true) {\n                int cur_he = (ci * N + cj) * 4 + cd;\n                visited[cur_he] = gen;\n                int d2 = to[state[ci * N + cj]][cd];\n                if (d2 == -1) break;\n                int ni = ci + di[d2];\n                int nj = cj + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                cd = (d2 + 2) & 3;\n                ci = ni;\n                cj = nj;\n                ++len;\n                if (ci == i && cj == j && cd == d) {\n                    is_cycle = true;\n                    break;\n                }\n            }\n            if (is_cycle) {\n                if (len > best) {\n                    second = best;\n                    best = len;\n                } else if (len > second) {\n                    second = len;\n                }\n            }\n        }\n    }\n    return best * second;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // precompute rotated tile types\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            if (t < 4) rot_type[t][r] = (t + r) % 4;\n            else if (t < 6) rot_type[t][r] = 4 + ((t - 4 + r) % 2);\n            else rot_type[t][r] = 6 + ((t - 6 + r) % 2);\n        }\n    }\n\n    // read original tile types\n    vector<int> orig(M);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            orig[i * N + j] = s[j] - '0';\n        }\n    }\n\n    // random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist4(0, 3);\n    uniform_int_distribution<int> dist900(0, M - 1);\n\n    // current and best state\n    vector<int> state(M), rot(M);\n    vector<int> best_rot(M);\n    int best_score = 0;\n\n    // Phase 1: many random trials (reduced number, using fast evaluate with timestamp)\n    const int TRIALS = 20000;\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // early time check every 2000 trials\n        if (trial % 2000 == 0) {\n            static auto start = chrono::steady_clock::now();\n            auto now = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start).count();\n            if (elapsed > 1200) break; // leave time for phase 2\n        }\n        for (int i = 0; i < M; ++i) {\n            int r = dist4(rng);\n            rot[i] = r;\n            state[i] = rot_type[orig[i]][r];\n        }\n        int score = evaluate(state.data());\n        if (score > best_score) {\n            best_score = score;\n            best_rot = rot;\n        }\n    }\n\n    // Phase 2: greedy hill climbing on best found\n    // restore best state\n    for (int i = 0; i < M; ++i) {\n        rot[i] = best_rot[i];\n        state[i] = rot_type[orig[i]][rot[i]];\n    }\n    int cur_score = best_score;\n\n    // greedy passes: try all rotations for each tile, keep if improves\n    bool improved = true;\n    int pass = 0;\n    while (improved && pass < 30) { // limit passes\n        improved = false;\n        ++pass;\n        // random order to avoid bias\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            int r_old = rot[idx];\n            int best_val = cur_score;\n            int best_r = r_old;\n            for (int r = 0; r < 4; ++r) {\n                if (r == r_old) continue;\n                int new_s = rot_type[orig[idx]][r];\n                state[idx] = new_s;\n                int val = evaluate(state.data());\n                if (val > best_val) {\n                    best_val = val;\n                    best_r = r;\n                }\n            }\n            if (best_val > cur_score) {\n                cur_score = best_val;\n                rot[idx] = best_r;\n                state[idx] = rot_type[orig[idx]][best_r];\n                improved = true;\n                if (best_val > best_score) {\n                    best_score = best_val;\n                    best_rot = rot;\n                }\n            } else {\n                // restore\n                state[idx] = rot_type[orig[idx]][r_old];\n            }\n        }\n        // quick time check after each pass\n        static auto start2 = chrono::steady_clock::now();\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start2).count();\n        if (elapsed > 1900) break;\n    }\n\n    // output best rotation string\n    for (int i = 0; i < M; ++i) cout << best_rot[i];\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\n// ---------- Union-Find (fast) ----------\nstruct DSU {\n    int parent[100], sz[100], edges[100];\n    int V;\n    DSU() {}\n    void init(int n) {\n        V = n;\n        for (int i = 0; i < n; ++i) {\n            parent[i] = i;\n            sz[i] = 1;\n            edges[i] = 0;\n        }\n    }\n    int find(int x) {\n        while (x != parent[x]) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) { edges[a]++; return; }\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        edges[a] += edges[b] + 1;\n    }\n    void build(const vector<int>& board, int N) {\n        init(N * N);\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int id = i * N + j;\n                int tile = board[id];\n                if (tile == 0) continue;\n                // right\n                if (j + 1 < N && board[id + 1] != 0 &&\n                    (tile & 4) && (board[id + 1] & 1))\n                    unite(id, id + 1);\n                // down\n                if (i + 1 < N && board[id + N] != 0 &&\n                    (tile & 8) && (board[id + N] & 2))\n                    unite(id, id + N);\n            }\n        }\n    }\n};\n\n// ---------- Compute largest tree size (non-const DSU) ----------\ninline int largest_tree(DSU& dsu, const vector<int>& board) {\n    int best = 0;\n    for (int i = 0; i < dsu.V; ++i) {\n        if (board[i] == 0) continue;\n        if (dsu.find(i) == i && dsu.edges[i] == dsu.sz[i] - 1)\n            best = max(best, dsu.sz[i]);\n    }\n    return best;\n}\n\n// ---------- State for beam search ----------\nstruct State {\n    vector<int> board;\n    int empty;\n    string moves;\n    int score;  // largest tree size\n    int edges;  // number of matched adjacent pairs (for tie-breaking)\n    bool operator<(const State& o) const {\n        if (score != o.score) return score > o.score;\n        if (edges != o.edges) return edges > o.edges;\n        return moves.size() < o.moves.size();\n    }\n};\n\n// ---------- Hash function ----------\ninline size_t hash_board(const vector<int>& board) {\n    size_t h = 0;\n    for (int v : board) h = h * 1000000007 + v;\n    return h;\n}\n\n// ---------- Count matched edges ----------\ninline int count_edges(const vector<int>& board, int N) {\n    int cnt = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            int tile = board[id];\n            if (tile == 0) continue;\n            if (j + 1 < N && board[id + 1] != 0 &&\n                (tile & 4) && (board[id + 1] & 1)) cnt++;\n            if (i + 1 < N && board[id + N] != 0 &&\n                (tile & 8) && (board[id + N] & 2)) cnt++;\n        }\n    }\n    return cnt;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    cin >> N >> T;\n    int V = N * N;\n    int full = V - 1;\n\n    vector<int> init_board(V);\n    int ei, ej;\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            char c = s[j];\n            int val = isdigit(c) ? c - '0' : 10 + (c - 'a');\n            init_board[i * N + j] = val;\n            if (val == 0) { ei = i; ej = j; }\n        }\n    }\n\n    // Precompute DSU for initial board\n    DSU init_dsu;\n    init_dsu.build(init_board, N);\n    int init_score = largest_tree(init_dsu, init_board);\n    if (init_score == full) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dir_ch[4] = {'U', 'D', 'L', 'R'};\n    // const int rev[4] = {1, 0, 3, 2}; // not used now\n\n    // Beam search parameters\n    const int BEAM_WIDTH = 800;      // increased for better exploration\n    const int MAX_STEPS = T;         // up to T moves\n    const double TIME_LIMIT = 2.85;  // seconds, leave some margin\n\n    vector<State> cur;\n    cur.push_back({init_board, ei * N + ej, \"\", init_score, count_edges(init_board, N)});\n\n    State best_complete; // full tree solution with minimal moves\n    best_complete.score = 0;\n    State best_partial = cur[0]; // best partial tree\n\n    auto start = chrono::steady_clock::now();\n\n    // Global visited set to avoid revisiting boards (only for last few steps)\n    unordered_set<size_t> global_visited;\n\n    for (int step = 0; step < MAX_STEPS; ++step) {\n        if (best_complete.score == full) break; // already found shortest complete? We continue to find shorter\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        vector<State> candidates;\n        unordered_set<size_t> local_visited;\n\n        for (const auto& s : cur) {\n            int empty_idx = s.empty;\n            int ei = empty_idx / N, ej = empty_idx % N;\n            for (int d = 0; d < 4; ++d) {\n                int ni = ei + di[d], nj = ej + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int new_empty = ni * N + nj;\n\n                // Apply move\n                vector<int> nb = s.board;\n                swap(nb[empty_idx], nb[new_empty]);\n\n                // Global duplicate check (only if we have visited this board before)\n                size_t h = hash_board(nb);\n                if (global_visited.count(h)) continue; // skip global repeats\n                if (local_visited.count(h)) continue;\n                local_visited.insert(h);\n\n                // Compute score\n                DSU dsu;\n                dsu.build(nb, N);\n                int new_score = largest_tree(dsu, nb);\n                int new_edges = 0; // we can compute but skip for speed; score is most important\n                string new_moves = s.moves + dir_ch[d];\n                if ((int)new_moves.size() > T) continue;\n\n                State ns = {move(nb), new_empty, move(new_moves), new_score, new_edges};\n\n                // Check for better partial\n                if (new_score > best_partial.score) {\n                    best_partial = ns;\n                }\n\n                // Check for complete solution\n                if (new_score == full) {\n                    if (best_complete.score == 0 || new_moves.size() < best_complete.moves.size()) {\n                        best_complete = ns;\n                    }\n                }\n\n                candidates.push_back(move(ns));\n            }\n        }\n\n        // Add current board states to global visited to avoid cycling back\n        for (const auto& s : cur) {\n            global_visited.insert(hash_board(s.board));\n        }\n\n        if (best_complete.score == full && best_complete.moves.size() == 0) break;\n        if (candidates.empty()) break;\n\n        // Keep top BEAM_WIDTH candidates\n        if ((int)candidates.size() > BEAM_WIDTH) {\n            partial_sort(candidates.begin(), candidates.begin() + BEAM_WIDTH, candidates.end());\n            candidates.resize(BEAM_WIDTH);\n        } else {\n            sort(candidates.begin(), candidates.end());\n        }\n        cur.swap(candidates);\n    }\n\n    // Output best found\n    if (best_complete.score == full) {\n        cout << best_complete.moves << endl;\n    } else {\n        cout << best_partial.moves << endl;\n    }\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nusing ll = long long;\nusing i128 = __int128_t;\n\nconst ll R = 10000;\nconst double PI = acos(-1.0);\nconst ll TWO_PI_R = ll(2 * PI * R) + 1; // approx 62832\n\n// Custom hash for __int128\nstruct hash_i128 {\n    size_t operator()(i128 x) const {\n        return hash<uint64_t>()(uint64_t(x)) ^ (hash<uint64_t>()(uint64_t(x >> 64)) << 1);\n    }\n};\n\n// Generate random point on circle boundary (integer coordinates)\npair<ll, ll> random_boundary_point(mt19937& rng) {\n    static uniform_int_distribution<ll> dist(0, TWO_PI_R - 1);\n    ll angle = dist(rng);\n    double rad = 2.0 * PI * angle / TWO_PI_R;\n    ll x = ll(R * cos(rad));\n    ll y = ll(R * sin(rad));\n    return {x, y};\n}\n\n// Generate a random line that cuts the circle (both points on boundary)\npair< pair<ll,ll>, pair<ll,ll> > random_line(mt19937& rng) {\n    auto p1 = random_boundary_point(rng);\n    auto p2 = random_boundary_point(rng);\n    while (p1 == p2) p2 = random_boundary_point(rng);\n    return {p1, p2};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    int sum_ad = 0;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        sum_ad += a[d];\n    }\n    vector<ll> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Current masks (bits for each line added so far)\n    vector<i128> cur_mask(N, 0);\n    // Store the lines we selected\n    vector< pair<ll,ll> > line_ends[2]; // endpoints of each line (p and q)\n    line_ends[0].reserve(K);\n    line_ends[1].reserve(K);\n\n    // Candidate evaluation: compute score for a new line\n    auto evaluate_line = [&](ll p1x, ll p1y, ll qx, ll qy) -> int {\n        ll dx = qx - p1x;\n        ll dy = qy - p1y;\n        if (dx == 0 && dy == 0) return -1;\n        // Check if any point lies exactly on the line\n        bool any_on_line = false;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (ys[i] - p1y) - dy * (xs[i] - p1x);\n            if (cross == 0) { any_on_line = true; break; }\n        }\n        if (any_on_line) return -1;\n\n        // Compute new masks and count frequencies\n        unordered_map<i128, int, hash_i128> freq;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (ys[i] - p1y) - dy * (xs[i] - p1x);\n            int side = (cross > 0) ? 1 : 0;\n            i128 new_mask = (cur_mask[i] << 1) | side;\n            freq[new_mask]++;\n        }\n\n        // Compute b_d\n        int b[11] = {0};\n        for (auto& p : freq) {\n            int cnt = p.second;\n            if (cnt >= 1 && cnt <= 10) b[cnt]++;\n        }\n        int score = 0;\n        for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n        return score;\n    };\n\n    // Current score\n    auto compute_cur_score = [&]() {\n        unordered_map<i128, int, hash_i128> freq;\n        for (int i = 0; i < N; ++i) freq[cur_mask[i]]++;\n        int b[11] = {0};\n        for (auto& p : freq) {\n            int cnt = p.second;\n            if (cnt >= 1 && cnt <= 10) b[cnt]++;\n        }\n        int score = 0;\n        for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n        return score;\n    };\n\n    int cur_score = compute_cur_score();\n    const int CANDIDATES = 200;\n    const int MAX_STEPS = K;\n\n    for (int step = 0; step < MAX_STEPS; ++step) {\n        if (cur_score == sum_ad) break; // already optimal\n\n        ll best_px, best_py, best_qx, best_qy;\n        int best_score = cur_score;\n        bool found = false;\n\n        for (int t = 0; t < CANDIDATES; ++t) {\n            auto [p1, p2] = random_line(rng);\n            ll px = p1.first, py = p1.second;\n            ll qx = p2.first, qy = p2.second;\n            int score = evaluate_line(px, py, qx, qy);\n            if (score > best_score) {\n                best_score = score;\n                best_px = px; best_py = py;\n                best_qx = qx; best_qy = qy;\n                found = true;\n            }\n        }\n\n        if (!found || best_score <= cur_score) break;\n\n        // Apply the best line\n        line_ends[0].push_back({best_px, best_py});\n        line_ends[1].push_back({best_qx, best_qy});\n\n        // Update masks\n        ll dx = best_qx - best_px;\n        ll dy = best_qy - best_py;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (ys[i] - best_py) - dy * (xs[i] - best_px);\n            int side = (cross > 0) ? 1 : 0;\n            cur_mask[i] = (cur_mask[i] << 1) | side;\n        }\n        cur_score = best_score;\n    }\n\n    // Output k and lines\n    int k = (int)line_ends[0].size();\n    cout << k << \"\\n\";\n    for (int i = 0; i < k; ++i) {\n        cout << line_ends[0][i].first << \" \" << line_ends[0][i].second << \" \"\n             << line_ends[1][i].first << \" \" << line_ends[1][i].second << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 61;\nint N, M;\nbool dot[MAXN][MAXN];\nvector<int> rowDots[MAXN];      // by y, sorted x\nvector<int> colDots[MAXN];      // by x, sorted y\nvector<int> diag1Dots[2*MAXN];  // index = y - x + N-1, sorted x\nvector<int> diag2Dots[2*MAXN];  // index = y + x, sorted x\n\nint64_t weight[MAXN][MAXN];\nvector<pair<int,int>> sortedPoints; // by weight descending\n\n// ---------- Unit edge management (set of keys) ----------\nusing u64 = uint64_t;\nunordered_set<u64> usedEdges;\n\nenum EdgeType { H=0, V=1, D1=2, D2=3 };\n\ninline u64 makeKey(int type, int x, int y) {\n    return ((u64)type << 20) | ((u64)x << 10) | (u64)y;\n}\n\nvoid genH(int x1, int y, int x2, vector<u64>& out) {\n    int step = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += step) {\n        int ux = min(x, x+step);\n        out.push_back(makeKey(H, ux, y));\n    }\n}\nvoid genV(int x, int y1, int y2, vector<u64>& out) {\n    int step = (y2 > y1) ? 1 : -1;\n    for (int y = y1; y != y2; y += step) {\n        int uy = min(y, y+step);\n        out.push_back(makeKey(V, x, uy));\n    }\n}\nvoid genD1(int x1, int y1, int x2, int /*y2*/, vector<u64>& out) {\n    int dx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += dx) {\n        int y = y1 + (x - x1);\n        int ux = min(x, x+dx);\n        int uy = min(y, y+dx);\n        out.push_back(makeKey(D1, ux, uy));\n    }\n}\nvoid genD2(int x1, int y1, int x2, int /*y2*/, vector<u64>& out) {\n    int dx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += dx) {\n        int y = y1 - (x - x1);\n        int ux = min(x, x+dx);\n        int uy = min(y, y-dx);\n        out.push_back(makeKey(D2, ux, uy));\n    }\n}\n\nbool checkEdges(const vector<u64>& edges) {\n    for (auto e : edges) if (usedEdges.count(e)) return false;\n    return true;\n}\nvoid insertEdges(const vector<u64>& edges) {\n    for (auto e : edges) usedEdges.insert(e);\n}\n\n// ---------- Checks for dots on line segments ----------\ninline bool hasDotRow(int y, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = rowDots[y];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotCol(int x, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = colDots[x];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotDiag1(int c, int lx, int rx) {\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag1Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\ninline bool hasDotDiag2(int c, int lx, int rx) {\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag2Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\n\n// ---------- Try to place a dot at (x,y) ----------\nbool tryPlace(int x, int y, int rect[4][2], vector<u64>& outEdges) {\n    outEdges.clear();\n\n    // ----- Axis\u2011aligned rectangles -----\n    {\n        const auto& row = rowDots[y];\n        const auto& col = colDots[x];\n        for (int x2 : row) {\n            if (x2 == x) continue;\n            int xmin = min(x,x2), xmax = max(x,x2);\n            for (int y4 : col) {\n                if (y4 == y) continue;\n                if (!dot[x2][y4]) continue;\n                int ymin = min(y,y4), ymax = max(y,y4);\n\n                // check dots on perimeter\n                if (hasDotRow(y, xmin, xmax)) continue;\n                if (hasDotRow(y4, xmin, xmax)) continue;\n                if (hasDotCol(x, ymin, ymax)) continue;\n                if (hasDotCol(x2, ymin, ymax)) continue;\n\n                // check unit edges\n                vector<u64> edges;\n                genH(x, y, x2, edges);\n                genV(x2, y, y4, edges);\n                genH(x, y4, x2, edges); // p4 -> p3 (x,y4) to (x2,y4)\n                genV(x, y, y4, edges); // p4->p1? Actually p4->p1: same x, from y4 to y\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y;\n                rect[2][0]=x2; rect[2][1]=y4;\n                rect[3][0]=x; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    // ----- Diagonal type1: p1->p2 slope=1, p2->p3 slope=-1 -----\n    {\n        int c1 = y - x + N-1;  // diag1 constant\n        int c2 = y + x;        // diag2 constant\n        for (int x2 : diag1Dots[c1]) {\n            if (x2 == x) continue;\n            int y2 = x2 + (y - x); // on diag1\n            for (int x4 : diag2Dots[c2]) {\n                if (x4 == x) continue;\n                int y4 = c2 - x4; // on diag2\n                int x3 = x2 + (x4 - x);\n                int y3 = y2 - (x4 - x);\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n\n                // check dots on perimeter\n                int lx12 = min(x,x2), rx12 = max(x,x2);\n                if (hasDotDiag1(c1, lx12, rx12)) continue;\n                int c23 = y2 + x2;\n                int lx23 = min(x2,x3), rx23 = max(x2,x3);\n                if (hasDotDiag2(c23, lx23, rx23)) continue;\n                int c34 = y3 - x3 + N-1;\n                int lx34 = min(x3,x4), rx34 = max(x3,x4);\n                if (hasDotDiag1(c34, lx34, rx34)) continue;\n                int c41 = y4 + x4;\n                int lx41 = min(x4,x), rx41 = max(x4,x);\n                if (hasDotDiag2(c41, lx41, rx41)) continue;\n\n                // check unit edges\n                vector<u64> edges;\n                genD1(x,y,x2,y2, edges);\n                genD2(x2,y2,x3,y3, edges);\n                genD1(x3,y3,x4,y4, edges);\n                genD2(x4,y4,x,y, edges);\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y2;\n                rect[2][0]=x3; rect[2][1]=y3;\n                rect[3][0]=x4; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    // ----- Diagonal type2: p1->p2 slope=-1, p2->p3 slope=1 -----\n    {\n        int c1 = y - x + N-1;\n        int c2 = y + x;\n        for (int x2 : diag2Dots[c2]) {\n            if (x2 == x) continue;\n            int y2 = c2 - x2; // on diag2\n            for (int x4 : diag1Dots[c1]) {\n                if (x4 == x) continue;\n                int y4 = x4 + (y - x); // on diag1\n                int x3 = x2 + (x4 - x);\n                int y3 = y2 + (x4 - x);\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n\n                int lx12 = min(x,x2), rx12 = max(x,x2);\n                if (hasDotDiag2(c2, lx12, rx12)) continue;\n                int c23 = y2 - x2 + N-1;\n                int lx23 = min(x2,x3), rx23 = max(x2,x3);\n                if (hasDotDiag1(c23, lx23, rx23)) continue;\n                int c34 = y3 + x3;\n                int lx34 = min(x3,x4), rx34 = max(x3,x4);\n                if (hasDotDiag2(c34, lx34, rx34)) continue;\n                int c41 = y4 - x4 + N-1;\n                int lx41 = min(x4,x), rx41 = max(x4,x);\n                if (hasDotDiag1(c41, lx41, rx41)) continue;\n\n                vector<u64> edges;\n                genD2(x,y,x2,y2, edges);\n                genD1(x2,y2,x3,y3, edges);\n                genD2(x3,y3,x4,y4, edges);\n                genD1(x4,y4,x,y, edges);\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y2;\n                rect[2][0]=x3; rect[2][1]=y3;\n                rect[3][0]=x4; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n\nvoid placeDot(int x, int y) {\n    dot[x][y] = true;\n    auto ins = [](vector<int>& v, int val) {\n        v.insert(lower_bound(v.begin(), v.end(), val), val);\n    };\n    ins(rowDots[y], x);\n    ins(colDots[x], y);\n    ins(diag1Dots[y - x + N-1], x);\n    ins(diag2Dots[y + x], x);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    for (int i=0; i<N; ++i)\n        for (int j=0; j<N; ++j)\n            dot[i][j] = false;\n    for (int i=0; i<M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        placeDot(x, y);\n    }\n    int c = (N-1)/2;\n    for (int y=0; y<N; ++y) {\n        for (int x=0; x<N; ++x) {\n            weight[x][y] = (x-c)*(x-c) + (y-c)*(y-c) + 1;\n            sortedPoints.emplace_back(x, y);\n        }\n    }\n    sort(sortedPoints.begin(), sortedPoints.end(),\n         [](const pair<int,int>& a, const pair<int,int>& b) {\n             return weight[a.first][a.second] > weight[b.first][b.second];\n         });\n\n    vector<array<int,8>> operations;\n    vector<u64> edgeBuffer;\n    while (true) {\n        bool placed = false;\n        int rect[4][2];\n        for (const auto& p : sortedPoints) {\n            int x = p.first, y = p.second;\n            if (dot[x][y]) continue;\n            if (tryPlace(x, y, rect, edgeBuffer)) {\n                // perform operation\n                placeDot(rect[0][0], rect[0][1]);\n                insertEdges(edgeBuffer);\n                operations.push_back({rect[0][0], rect[0][1],\n                                      rect[1][0], rect[1][1],\n                                      rect[2][0], rect[2][1],\n                                      rect[3][0], rect[3][1]});\n                placed = true;\n                break;\n            }\n        }\n        if (!placed) break;\n    }\n    cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        for (int i=0; i<8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\nconst int SIZE = N * N;\n\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\n\nusing Grid = array<int, SIZE>;\n\n// tilt the box in one of the four directions\nGrid tilt(const Grid& g, char dir) {\n    Grid ng = {0};\n    if (dir == 'F') {\n        for (int j = 0; j < N; ++j) {\n            int r = 0;\n            for (int i = 0; i < N; ++i)\n                if (g[i * N + j]) ng[(r++) * N + j] = g[i * N + j];\n        }\n    } else if (dir == 'B') {\n        for (int j = 0; j < N; ++j) {\n            int r = N - 1;\n            for (int i = N - 1; i >= 0; --i)\n                if (g[i * N + j]) ng[(r--) * N + j] = g[i * N + j];\n        }\n    } else if (dir == 'L') {\n        for (int i = 0; i < N; ++i) {\n            int c = 0;\n            for (int j = 0; j < N; ++j)\n                if (g[i * N + j]) ng[i * N + (c++)] = g[i * N + j];\n        }\n    } else { // 'R'\n        for (int i = 0; i < N; ++i) {\n            int c = N - 1;\n            for (int j = N - 1; j >= 0; --j)\n                if (g[i * N + j]) ng[i * N + (c--)] = g[i * N + j];\n        }\n    }\n    return ng;\n}\n\n// compute sum of squares of connected component sizes\nint score(const Grid& g) {\n    bool vis[SIZE] = {false};\n    int total = 0;\n    vector<int> stk;\n    stk.reserve(SIZE);\n    for (int idx = 0; idx < SIZE; ++idx) {\n        if (g[idx] && !vis[idx]) {\n            int flavor = g[idx];\n            int cnt = 0;\n            stk.push_back(idx);\n            vis[idx] = true;\n            while (!stk.empty()) {\n                int cur = stk.back();\n                stk.pop_back();\n                ++cnt;\n                int x = cur / N, y = cur % N;\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        int nidx = nx * N + ny;\n                        if (!vis[nidx] && g[nidx] == flavor) {\n                            vis[nidx] = true;\n                            stk.push_back(nidx);\n                        }\n                    }\n                }\n            }\n            total += cnt * cnt;\n        }\n    }\n    return total;\n}\n\n// global for flavors and random generator\nvector<int> flavors(100);\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// evaluate expected final score from state g at step, with given lookahead depth\n// depth = number of future steps to simulate with lookahead (max 2)\n// samples = number of random placements to consider at each future step\ndouble evaluate(const Grid& g, int step, int depth, int samples) {\n    if (step >= 100) return score(g);\n    // collect empty cells\n    vector<int> empties;\n    empties.reserve(SIZE);\n    for (int i = 0; i < SIZE; ++i)\n        if (g[i] == 0) empties.push_back(i);\n    int M = empties.size();\n    if (M == 0) return score(g); // should not happen before step 100\n\n    if (depth == 0) return score(g);\n\n    // sample placements for the next candy\n    int S = min(samples, M);\n    double total = 0.0;\n    for (int s = 0; s < S; ++s) {\n        // random placement\n        int pos = empties[rng() % M];\n        Grid g2 = g;\n        g2[pos] = flavors[step];\n\n        // try all tilts at this step (the decision)\n        double best_val = -1e18;\n        const char dirs[4] = {'F','B','L','R'};\n        for (char d : dirs) {\n            Grid g3 = tilt(g2, d);\n            double val = evaluate(g3, step + 1, depth - 1, samples);\n            if (val > best_val) best_val = val;\n        }\n        total += best_val;\n    }\n    return total / S;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n\n    Grid grid = {0};\n    const char dirs[4] = {'F','B','L','R'};\n\n    // time management: get start time\n    auto start = chrono::steady_clock::now();\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the t-th candy at the p-th empty cell\n        int zero_cnt = 0;\n        for (int i = 0; i < SIZE; ++i) {\n            if (grid[i] == 0) {\n                ++zero_cnt;\n                if (zero_cnt == p) {\n                    grid[i] = flavors[t];\n                    break;\n                }\n            }\n        }\n\n        // last tilt does nothing, just output something\n        if (t == 99) {\n            cout << \"F\\n\" << flush;\n            break;\n        }\n\n        // decide lookahead depth and samples based on remaining time and step\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        int depth;\n        int samples;\n        if (elapsed < 0.5) {\n            // early steps: two-step lookahead with moderate samples\n            depth = 2;\n            samples = 5;\n        } else if (elapsed < 1.2) {\n            // mid steps: one-step with many samples\n            depth = 1;\n            samples = 10;\n        } else {\n            // late steps: one-step with fewer samples to avoid TLE\n            depth = 1;\n            samples = 5;\n        }\n\n        // evaluate each candidate tilt\n        char best_dir = 'F';\n        double best_val = -1e18;\n\n        for (char d : dirs) {\n            Grid g1 = tilt(grid, d);\n            double val = evaluate(g1, t + 1, depth, samples);\n            if (val > best_val) {\n                best_val = val;\n                best_dir = d;\n            }\n        }\n\n        // apply the chosen tilt\n        grid = tilt(grid, best_dir);\n        cout << best_dir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ------------------------------------------------------------\n// For epsilon == 0: exact small N (N = 4,5,6)\n// ------------------------------------------------------------\nvoid solve_eps_zero(int M) {\n    int N;\n    if (M <= 11) N = 4;\n    else if (M <= 34) N = 5;\n    else N = 6;\n    int L = N * (N - 1) / 2;\n    int total = 1 << L;\n\n    // all permutations of vertices\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    vector<vector<uint8_t>> perms_bit;\n    do {\n        vector<uint8_t> bit_perm(L);\n        int ptr = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                int u = perm[i], v = perm[j];\n                if (u > v) swap(u, v);\n                int idx = u * (2 * N - u - 1) / 2 + (v - u - 1);\n                bit_perm[ptr] = (uint8_t)idx;\n                ++ptr;\n            }\n        }\n        perms_bit.push_back(bit_perm);\n    } while (next_permutation(perm.begin(), perm.end()));\n\n    // precompute canonical mask for every possible graph\n    vector<uint64_t> can_mask(total);\n    for (int mask = 0; mask < total; ++mask) {\n        uint64_t best = UINT64_MAX;\n        for (const auto& bp : perms_bit) {\n            uint64_t new_mask = 0;\n            for (int b = 0; b < L; ++b)\n                if ((mask >> b) & 1) new_mask |= (1ULL << bp[b]);\n            if (new_mask < best) best = new_mask;\n        }\n        can_mask[mask] = best;\n    }\n\n    // collect all distinct canonical masks (unlabeled graphs)\n    unordered_map<uint64_t, int> uniq_idx;\n    vector<uint64_t> uniq_masks;\n    for (int m = 0; m < total; ++m) {\n        uint64_t cm = can_mask[m];\n        if (uniq_idx.find(cm) == uniq_idx.end()) {\n            uniq_idx[cm] = (int)uniq_masks.size();\n            uniq_masks.push_back(cm);\n        }\n    }\n    int K = (int)uniq_masks.size();\n\n    // pairwise Hamming distances\n    vector<vector<int>> dist(K, vector<int>(K, 0));\n    for (int i = 0; i < K; ++i)\n        for (int j = i + 1; j < K; ++j)\n            dist[i][j] = dist[j][i] = __builtin_popcountll(uniq_masks[i] ^ uniq_masks[j]);\n\n    // greedy selection maximizing min distance\n    vector<int> selected;\n    vector<bool> used(K, false);\n    selected.push_back(0);\n    used[0] = true;\n    while ((int)selected.size() < M) {\n        int best_idx = -1, best_min = -1;\n        for (int i = 0; i < K; ++i) if (!used[i]) {\n            int cur_min = L + 1;\n            for (int j : selected) if (dist[i][j] < cur_min) cur_min = dist[i][j];\n            if (cur_min > best_min) { best_min = cur_min; best_idx = i; }\n        }\n        used[best_idx] = true;\n        selected.push_back(best_idx);\n    }\n\n    // decoder lookup table\n    vector<int> lookup(total);\n    for (int m = 0; m < total; ++m) {\n        uint64_t cm = can_mask[m];\n        int best_d = L + 1, best_idx = 0;\n        for (int i = 0; i < M; ++i) {\n            int d = __builtin_popcountll(cm ^ uniq_masks[selected[i]]);\n            if (d < best_d) { best_d = d; best_idx = i; }\n        }\n        lookup[m] = best_idx;\n    }\n\n    // output graphs\n    cout << N << '\\n';\n    for (int idx : selected) {\n        uint64_t mask = uniq_masks[idx];\n        string s;\n        for (int b = 0; b < L; ++b) s.push_back((mask >> b) & 1 ? '1' : '0');\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    // answer queries\n    for (int q = 0; q < 100; ++q) {\n        string H; cin >> H;\n        int mask = 0;\n        for (int b = 0; b < L; ++b) if (H[b] == '1') mask |= (1 << b);\n        cout << lookup[can_mask[mask]] << '\\n';\n        cout.flush();\n    }\n}\n\n// ------------------------------------------------------------\n// For epsilon > 0: N = 100, disjoint cliques, degree\u2011based decoder\n// ------------------------------------------------------------\nvoid solve_eps_positive(int M, double eps) {\n    const int N = 100;\n    const int L = N * (N - 1) / 2;\n\n    // generate all candidates (partitions into 1 or 2 cliques)\n    struct Candidate {\n        vector<int> clique_sizes;   // sorted decreasing\n    };\n    vector<Candidate> candidates;\n    for (int s = 2; s <= N; ++s) {\n        candidates.push_back({vector<int>(1, s)});\n    }\n    for (int a = 2; a <= N - 2; ++a) {\n        for (int b = 2; b <= a && a + b <= N; ++b) {\n            candidates.push_back({vector<int>{a, b}});\n        }\n    }\n    int K = (int)candidates.size();\n\n    // Precompute expected degree vectors (sorted)\n    const double C = (N - 1) * eps;\n    const double Knoise = 1.0 - 2.0 * eps;\n    vector<vector<double>> expected_sorted(K);\n    for (int i = 0; i < K; ++i) {\n        const auto& sizes = candidates[i].clique_sizes;\n        vector<double> degs;\n        for (int s : sizes) {\n            double base = (double)(s - 1) * Knoise + C;\n            for (int v = 0; v < s; ++v) degs.push_back(base);\n        }\n        int isolated = N;\n        for (int s : sizes) isolated -= s;\n        for (int v = 0; v < isolated; ++v) degs.push_back(C); // isolated degree -> expected C\n        sort(degs.begin(), degs.end());\n        expected_sorted[i] = move(degs);\n    }\n\n    // greedy selection: start with candidate with largest variance (most discriminative)\n    vector<int> selected;\n    vector<bool> used(K, false);\n    double best_var = -1;\n    int start_idx = 0;\n    for (int i = 0; i < K; ++i) {\n        double mean = accumulate(expected_sorted[i].begin(), expected_sorted[i].end(), 0.0) / N;\n        double var = 0;\n        for (double d : expected_sorted[i]) var += (d - mean) * (d - mean);\n        if (var > best_var) { best_var = var; start_idx = i; }\n    }\n    selected.push_back(start_idx);\n    used[start_idx] = true;\n\n    while ((int)selected.size() < M) {\n        double best_min = -1e100;\n        int best_i = -1;\n        for (int i = 0; i < K; ++i) if (!used[i]) {\n            double cur_min = 1e100;\n            for (int j : selected) {\n                double d = 0;\n                for (int p = 0; p < N; ++p) {\n                    double diff = expected_sorted[i][p] - expected_sorted[j][p];\n                    d += diff * diff;\n                }\n                if (d < cur_min) cur_min = d;\n            }\n            if (cur_min > best_min) { best_min = cur_min; best_i = i; }\n        }\n        used[best_i] = true;\n        selected.push_back(best_i);\n    }\n\n    // output graphs\n    cout << N << '\\n';\n    for (int idx : selected) {\n        const auto& sizes = candidates[idx].clique_sizes;\n        string graph_str(L, '0');\n        int offset = 0;\n        for (int clique_size : sizes) {\n            for (int i = offset; i < offset + clique_size; ++i) {\n                for (int j = i + 1; j < offset + clique_size; ++j) {\n                    int edge_idx = i * (2*N - i - 1) / 2 + (j - i - 1);\n                    graph_str[edge_idx] = '1';\n                }\n            }\n            offset += clique_size;\n        }\n        cout << graph_str << '\\n';\n    }\n    cout.flush();\n\n    // store expected degrees for selected graphs\n    vector<vector<double>> sel_expected(M);\n    for (int i = 0; i < M; ++i) sel_expected[i] = expected_sorted[selected[i]];\n\n    // answer queries\n    for (int q = 0; q < 100; ++q) {\n        string H; cin >> H;\n        vector<int> deg(N, 0);\n        int pos = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (H[pos] == '1') { deg[i]++; deg[j]++; }\n                ++pos;\n            }\n        }\n        // sort observed degrees\n        vector<double> degs(N);\n        for (int i = 0; i < N; ++i) degs[i] = (double)deg[i];\n        sort(degs.begin(), degs.end());\n\n        // find nearest by Euclidean distance between sorted degree vectors\n        int best_idx = -1;\n        double best_dist = 1e100;\n        for (int i = 0; i < M; ++i) {\n            double d = 0;\n            for (int p = 0; p < N; ++p) {\n                double diff = degs[p] - sel_expected[i][p];\n                d += diff * diff;\n            }\n            if (d < best_dist) { best_dist = d; best_idx = i; }\n        }\n        cout << best_idx << '\\n';\n        cout.flush();\n    }\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    if (eps == 0.0) {\n        solve_eps_zero(M);\n    } else {\n        solve_eps_positive(M, eps);\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nconst ll INF = 1e18;\nconst double SCALE = 1e-12;\n\nstruct Edge {\n    int u, v, w, idx;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> g(N);\n    vector<vector<int>> edge_idx(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u, v, w, i};\n        g[u].emplace_back(v, w);\n        edge_idx[u].push_back(i);\n        g[v].emplace_back(u, w);\n        edge_idx[v].push_back(i);\n    }\n\n    // skip coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. all-pair shortest paths (for betweenness) ----------\n    vector<vector<ll>> dist_all(N, vector<ll>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        dist_all[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist_all[s][u]) continue;\n            for (int j = 0; j < (int)g[u].size(); ++j) {\n                int v = g[u][j].first;\n                int w = g[u][j].second;\n                ll nd = d + w;\n                if (nd < dist_all[s][v]) {\n                    dist_all[s][v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    }\n\n    // ---------- 2. betweenness centrality (Brandes) ----------\n    vector<ld> betweenness(M, 0.0);\n    for (int s = 0; s < N; ++s) {\n        const vector<ll>& dist = dist_all[s];\n        vector<ld> cnt(N, 0.0);\n        vector<vector<pair<int,int>>> pred(N);\n        cnt[s] = 1.0;\n        // order by distance\n        vector<int> order;\n        for (int i = 0; i < N; ++i)\n            if (dist[i] < INF) order.push_back(i);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] < dist[b]; });\n        for (int u : order) {\n            if (dist[u] >= INF) continue;\n            for (int j = 0; j < (int)g[u].size(); ++j) {\n                int v = g[u][j].first;\n                int w = g[u][j].second;\n                if (dist[v] == dist[u] + w) {\n                    cnt[v] += cnt[u];\n                    pred[v].emplace_back(u, edge_idx[u][j]);\n                }\n            }\n        }\n        vector<ld> dep(N, 0.0);\n        for (int i = (int)order.size()-1; i >= 0; --i) {\n            int v = order[i];\n            if (v == s) continue;\n            if (pred[v].empty()) continue;\n            ld sigma_v = cnt[v];\n            for (auto [p, eidx] : pred[v]) {\n                ld contrib = (cnt[p] / sigma_v) * (1.0 + dep[v]);\n                dep[p] += contrib;\n                betweenness[eidx] += contrib;\n            }\n        }\n    }\n\n    // ---------- 3. alternative path cost ----------\n    vector<ll> alt_cost(M, INF);\n    for (int e = 0; e < M; ++e) {\n        auto [u, v, w, idx] = edges[e];\n        vector<ll> dist(N, INF);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        dist[u] = 0;\n        pq.emplace(0, u);\n        while (!pq.empty()) {\n            auto [d, x] = pq.top(); pq.pop();\n            if (d != dist[x]) continue;\n            if (x == v) break;\n            for (int j = 0; j < (int)g[x].size(); ++j) {\n                int y = g[x][j].first;\n                int ww = g[x][j].second;\n                int eidx = edge_idx[x][j];\n                if (eidx == e) continue;\n                ll nd = d + ww;\n                if (nd < dist[y]) {\n                    dist[y] = nd;\n                    pq.emplace(nd, y);\n                }\n            }\n        }\n        alt_cost[e] = dist[v];\n    }\n\n    // ---------- 4. impact score ----------\n    vector<ld> impact(M);\n    for (int e = 0; e < M; ++e) {\n        if (alt_cost[e] >= INF/2) {\n            impact[e] = betweenness[e] * 1e12;\n        } else {\n            impact[e] = betweenness[e] * (alt_cost[e] - edges[e].w);\n        }\n    }\n\n    // ---------- 5. initial greedy assignment ----------\n    vector<pair<ld,int>> sorted(M);\n    for (int i = 0; i < M; ++i) sorted[i] = {impact[i], i};\n    sort(sorted.rbegin(), sorted.rend());\n\n    vector<int> day_of_edge(M, -1);\n    vector<ld> day_load(D, 0.0);\n    vector<int> day_cnt(D, 0);\n    vector<vector<int>> day_edges(D);\n\n    for (auto [imp, eid] : sorted) {\n        int best_day = -1;\n        ld best_load = INF;\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_load[d] < best_load) {\n                best_load = day_load[d];\n                best_day = d;\n            }\n        }\n        assert(best_day != -1);\n        day_of_edge[eid] = best_day;\n        day_load[best_day] += imp;\n        day_cnt[best_day]++;\n        day_edges[best_day].push_back(eid);\n    }\n\n    // ---------- 6. simple load balancing local search ----------\n    const int MAX_ITER = 5000;\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        int max_day = -1, min_day = -1;\n        ld max_load = -INF, min_load = INF;\n        for (int d = 0; d < D; ++d) {\n            if (day_load[d] > max_load) { max_load = day_load[d]; max_day = d; }\n            if (day_load[d] < min_load) { min_load = day_load[d]; min_day = d; }\n        }\n        if (max_day == min_day || day_cnt[min_day] >= K) break;\n        int best_eid = -1;\n        ld best_imp = -INF;\n        for (int eid : day_edges[max_day]) {\n            if (impact[eid] > best_imp) {\n                best_imp = impact[eid];\n                best_eid = eid;\n            }\n        }\n        if (best_eid == -1) break;\n        // move\n        auto& vec = day_edges[max_day];\n        for (auto it = vec.begin(); it != vec.end(); ++it) {\n            if (*it == best_eid) { vec.erase(it); break; }\n        }\n        day_edges[min_day].push_back(best_eid);\n        day_load[max_day] -= impact[best_eid];\n        day_load[min_day] += impact[best_eid];\n        day_cnt[max_day]--;\n        day_cnt[min_day]++;\n        day_of_edge[best_eid] = min_day;\n    }\n\n    // ---------- 7. refinement using random vertex pairs ----------\n    mt19937 rng(12345);\n    const int NUM_PAIRS = 10;\n    vector<pair<int,int>> pairs;\n    {\n        uniform_int_distribution<int> dist_v(0, N-1);\n        for (int i = 0; i < NUM_PAIRS; ++i) {\n            int a, b;\n            do {\n                a = dist_v(rng);\n                b = dist_v(rng);\n            } while (a == b || dist_all[a][b] >= INF/2);\n            pairs.emplace_back(a, b);\n        }\n    }\n\n    // get unique source vertices from pairs\n    vector<int> src_vertices;\n    for (auto [a,b] : pairs) {\n        src_vertices.push_back(a);\n        src_vertices.push_back(b);\n    }\n    sort(src_vertices.begin(), src_vertices.end());\n    src_vertices.erase(unique(src_vertices.begin(), src_vertices.end()), src_vertices.end());\n    int S = src_vertices.size();\n\n    // precompute original distances for each pair\n    vector<ll> pair_orig(NUM_PAIRS);\n    for (int i = 0; i < NUM_PAIRS; ++i) {\n        auto [a,b] = pairs[i];\n        pair_orig[i] = dist_all[a][b];\n    }\n\n    // function to compute frustration sum for a day given removed edges\n    auto compute_day_frustration = [&](int day, const vector<vector<bool>>& removed) -> ld {\n        // run Dijkstra from each source vertex\n        vector<vector<ll>> dists(S);\n        for (int si = 0; si < S; ++si) {\n            int s = src_vertices[si];\n            vector<ll> dist(N, INF);\n            priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n            dist[s] = 0;\n            pq.emplace(0, s);\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (int j = 0; j < (int)g[u].size(); ++j) {\n                    int v = g[u][j].first;\n                    int w = g[u][j].second;\n                    int eidx = edge_idx[u][j];\n                    if (removed[day][eidx]) continue;\n                    ll nd = d + w;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        pq.emplace(nd, v);\n                    }\n                }\n            }\n            dists[si] = move(dist);\n        }\n        // compute sum over pairs\n        ld total = 0.0;\n        for (int i = 0; i < NUM_PAIRS; ++i) {\n            auto [a,b] = pairs[i];\n            // find index of source in src_vertices\n            int si = lower_bound(src_vertices.begin(), src_vertices.end(), a) - src_vertices.begin();\n            ll cur = dists[si][b];\n            if (cur >= INF/2) cur = 1e9; // unreachable penalty\n            total += (ld)(cur - pair_orig[i]);\n        }\n        return total;\n    };\n\n    // build removed matrix\n    vector<vector<bool>> removed(D, vector<bool>(M, false));\n    for (int e = 0; e < M; ++e) removed[day_of_edge[e]][e] = true;\n\n    // initial frustration per day\n    vector<ld> day_frust(D);\n    ld total_frust = 0.0;\n    for (int d = 0; d < D; ++d) {\n        day_frust[d] = compute_day_frustration(d, removed);\n        total_frust += day_frust[d];\n    }\n\n    const int MAX_REFINE = 100;\n    for (int r = 0; r < MAX_REFINE; ++r) {\n        int worst_day = max_element(day_frust.begin(), day_frust.end()) - day_frust.begin();\n        int best_day = min_element(day_frust.begin(), day_frust.end()) - day_frust.begin();\n        if (worst_day == best_day || day_cnt[best_day] >= K) break;\n\n        // try to move the edge with highest impact on worst_day\n        int best_eid = -1;\n        ld best_improvement = 0.0;\n        // if there are many edges, sample a few\n        int sample_size = min((int)day_edges[worst_day].size(), 5);\n        vector<int> candidates;\n        if ((int)day_edges[worst_day].size() <= 5) {\n            candidates = day_edges[worst_day];\n        } else {\n            shuffle(day_edges[worst_day].begin(), day_edges[worst_day].end(), rng);\n            candidates.assign(day_edges[worst_day].begin(), day_edges[worst_day].begin() + 5);\n        }\n        for (int eid : candidates) {\n            // evaluate move\n            removed[worst_day][eid] = false;\n            removed[best_day][eid] = true;\n            ld new_worst = compute_day_frustration(worst_day, removed);\n            ld new_best = compute_day_frustration(best_day, removed);\n            removed[worst_day][eid] = true;\n            removed[best_day][eid] = false;\n\n            ld old_sum = day_frust[worst_day] + day_frust[best_day];\n            ld new_sum = new_worst + new_best;\n            if (new_sum < old_sum - 1e-12) {\n                ld improvement = old_sum - new_sum;\n                if (improvement > best_improvement) {\n                    best_improvement = improvement;\n                    best_eid = eid;\n                }\n            }\n        }\n        if (best_eid == -1) break;\n\n        // execute move\n        int eid = best_eid;\n        removed[worst_day][eid] = false;\n        removed[best_day][eid] = true;\n        // update data structures\n        auto& vec_w = day_edges[worst_day];\n        for (auto it = vec_w.begin(); it != vec_w.end(); ++it) {\n            if (*it == eid) { vec_w.erase(it); break; }\n        }\n        day_edges[best_day].push_back(eid);\n        day_cnt[worst_day]--;\n        day_cnt[best_day]++;\n        day_of_edge[eid] = best_day;\n        // recompute frustration for updated days\n        day_frust[worst_day] = compute_day_frustration(worst_day, removed);\n        day_frust[best_day] = compute_day_frustration(best_day, removed);\n    }\n\n    // ---------- 8. output ----------\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << day_of_edge[i] + 1;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// 24 proper rotations (det=1)\nvector<array<array<int,3>,3>> rotations;\n\nvoid init_rotations() {\n    int perm[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n    int parity[6] = {1,-1,-1,1,1,-1};\n    int signs[8][3] = {{1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},\n                       {-1,1,1},{-1,1,-1},{-1,-1,1},{-1,-1,-1}};\n    for (int p=0;p<6;p++) {\n        for (auto s : signs) {\n            int det = s[0]*s[1]*s[2] * parity[p];\n            if (det != 1) continue;\n            array<array<int,3>,3> mat;\n            for (int i=0;i<3;i++) {\n                for (int j=0;j<3;j++) {\n                    mat[i][j] = (j == perm[p][i]) ? s[i] : 0;\n                }\n            }\n            rotations.push_back(mat);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    init_rotations();\n\n    int D; cin >> D;\n    int N = D*D*D;               // total voxels per object\n    vector<string> f[2], r[2];\n    for (int t=0;t<2;t++) {\n        f[t].resize(D);\n        for (int i=0;i<D;i++) cin >> f[t][i];\n        r[t].resize(D);\n        for (int i=0;i<D;i++) cin >> r[t][i];\n    }\n\n    // occupancy per object (flattened)\n    vector<char> occ[2];\n    for (int t=0;t<2;t++) occ[t].resize(N, 0);\n\n    for (int t=0;t<2;t++) {\n        for (int z=0;z<D;z++) {\n            for (int x=0;x<D;x++) {\n                if (f[t][z][x] == '0') continue;\n                for (int y=0;y<D;y++) {\n                    if (r[t][z][y] == '1') {\n                        int idx = x*D*D + y*D + z;\n                        occ[t][idx] = 1;\n                    }\n                }\n            }\n        }\n    }\n\n    // connected components for each object\n    vector<vector<tuple<int,int,int>>> comps[2]; // list of points per component\n    vector<int> compSize[2];                     // volume per component\n    vector<char> vis[2];\n    for (int t=0;t<2;t++) vis[t].resize(N, 0);\n\n    for (int t=0;t<2;t++) {\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || vis[t][start]) continue;\n            queue<int> q; q.push(start);\n            vis[t][start] = 1;\n            vector<tuple<int,int,int>> pts;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                pts.emplace_back(x,y,z);\n                static int dx[] = {1,-1,0,0,0,0};\n                static int dy[] = {0,0,1,-1,0,0};\n                static int dz[] = {0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n                    if (nx<0 || nx>=D || ny<0 || ny>=D || nz<0 || nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !vis[t][nid]) {\n                        vis[t][nid] = 1;\n                        q.push(nid);\n                    }\n                }\n            }\n            comps[t].push_back(pts);\n            compSize[t].push_back((int)pts.size());\n        }\n    }\n\n    // used cells for both objects\n    vector<char> used[2];\n    for (int t=0;t<2;t++) used[t].resize(N, 0);\n\n    // final block assignments\n    vector<int> b1(N,0), b2(N,0);\n    int blockId = 1;\n\n    // candidate components: (volume, object, component index)\n    vector<tuple<int,int,int>> candidates;\n    for (int t=0;t<2;t++) {\n        for (size_t i=0;i<comps[t].size();i++) {\n            candidates.emplace_back(compSize[t][i], t, (int)i);\n        }\n    }\n    sort(candidates.rbegin(), candidates.rend()); // largest first\n\n    // lambda to find a placement of a component from source object into the other object\n    auto findPlacement = [&](const vector<tuple<int,int,int>>& srcPts, int otherObj,\n                             vector<tuple<int,int,int>>& outPts) -> bool {\n        // srcPts are absolute coordinates in the source object\n        for (const auto& rot : rotations) {\n            // apply rotation to srcPts\n            vector<tuple<int,int,int>> rotated;\n            int mnx=1e9, mny=1e9, mnz=1e9;\n            int mxx=-1e9, mxy=-1e9, mxz=-1e9;\n            for (auto [x,y,z] : srcPts) {\n                int nx = rot[0][0]*x + rot[0][1]*y + rot[0][2]*z;\n                int ny = rot[1][0]*x + rot[1][1]*y + rot[1][2]*z;\n                int nz = rot[2][0]*x + rot[2][1]*y + rot[2][2]*z;\n                rotated.emplace_back(nx,ny,nz);\n                mnx = min(mnx, nx); mxx = max(mxx, nx);\n                mny = min(mny, ny); mxy = max(mxy, ny);\n                mnz = min(mnz, nz); mxz = max(mxz, nz);\n            }\n            int sx = mxx - mnx, sy = mxy - mny, sz = mxz - mnz;\n            // bounding box must fit in [0,D-1]\n            for (int tx=0; tx+sx < D; tx++) {\n                for (int ty=0; ty+sy < D; ty++) {\n                    for (int tz=0; tz+sz < D; tz++) {\n                        bool ok = true;\n                        for (auto [nx,ny,nz] : rotated) {\n                            int gx = nx - mnx + tx;\n                            int gy = ny - mny + ty;\n                            int gz = nz - mnz + tz;\n                            int idx = gx*D*D + gy*D + gz;\n                            if (!occ[otherObj][idx] || used[otherObj][idx]) {\n                                ok = false;\n                                break;\n                            }\n                        }\n                        if (ok) {\n                            outPts.clear();\n                            for (auto [nx,ny,nz] : rotated) {\n                                int gx = nx - mnx + tx;\n                                int gy = ny - mny + ty;\n                                int gz = nz - mnz + tz;\n                                outPts.emplace_back(gx,gy,gz);\n                            }\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n        return false;\n    };\n\n    for (auto [vol, obj, compIdx] : candidates) {\n        const auto& pts = comps[obj][compIdx];\n        // check if any cell already used in its own object\n        bool anyUsed = false;\n        for (auto [x,y,z] : pts) {\n            int idx = x*D*D + y*D + z;\n            if (used[obj][idx]) { anyUsed = true; break; }\n        }\n        if (anyUsed) continue;\n\n        int other = 1 - obj;\n        vector<tuple<int,int,int>> placement;\n        if (!findPlacement(pts, other, placement)) continue;\n\n        // assign a new common block\n        // mark used in source object\n        for (auto [x,y,z] : pts) {\n            int idx = x*D*D + y*D + z;\n            used[obj][idx] = 1;\n            if (obj == 0) b1[idx] = blockId;\n            else          b2[idx] = blockId;\n        }\n        // mark used in other object\n        for (auto [x,y,z] : placement) {\n            int idx = x*D*D + y*D + z;\n            used[other][idx] = 1;\n            if (other == 0) b1[idx] = blockId;\n            else            b2[idx] = blockId;\n        }\n        blockId++;\n    }\n\n    // handle residual cells (single-use blocks)\n    for (int t=0;t<2;t++) {\n        vector<char> seen(N, 0);\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || used[t][start] || seen[start]) continue;\n            // BFS to collect component\n            queue<int> q; q.push(start);\n            seen[start] = 1;\n            vector<int> compIndices;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                compIndices.push_back(cur);\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                static int dx[] = {1,-1,0,0,0,0};\n                static int dy[] = {0,0,1,-1,0,0};\n                static int dz[] = {0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx = x+dx[d], ny = y+dy[d], nz = z+dz[d];\n                    if (nx<0 || nx>=D || ny<0 || ny>=D || nz<0 || nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !used[t][nid] && !seen[nid]) {\n                        seen[nid] = 1;\n                        q.push(nid);\n                    }\n                }\n            }\n            // assign new block id\n            for (int idx : compIndices) {\n                if (t == 0) b1[idx] = blockId;\n                else        b2[idx] = blockId;\n            }\n            blockId++;\n        }\n    }\n\n    int n = blockId - 1;\n    cout << n << '\\n';\n    for (int i=0;i<N;i++) cout << b1[i] << \" \\n\"[i==N-1];\n    for (int i=0;i<N;i++) cout << b2[i] << \" \\n\"[i==N-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing ll = long long;\nconst ll INF = 1LL << 60;\n\nstruct UnionFind {\n    vector<int> parent, rank;\n    UnionFind(int n) : parent(n), rank(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) parent[x] = y;\n        else if (rank[x] > rank[y]) parent[y] = x;\n        else { parent[y] = x; rank[x]++; }\n        return true;\n    }\n};\n\nint ceil_sqrt(ll sq) {\n    if (sq <= 0) return 0;\n    double d = sqrt((double)sq);\n    int r = (int)ceil(d);\n    if ((ll)r * r < sq) ++r;\n    return min(r, 5000);\n}\n\n// compute total cost given active set (vector<bool>)\nll computeTotalCost(const vector<vector<ll>>& dist2,\n                    const vector<vector<int>>& cover,\n                    const vector<vector<ll>>& dist_sh,\n                    const vector<bool>& active,\n                    int N, int K) {\n    // power cost\n    vector<ll> maxDist(N, 0);\n    for (int k = 0; k < K; ++k) {\n        int best = -1;\n        for (int i : cover[k]) {\n            if (active[i]) {\n                best = i;\n                break;\n            }\n        }\n        if (best == -1) return LLONG_MAX; // not covered\n        ll d = dist2[k][best];\n        if (d > maxDist[best]) maxDist[best] = d;\n    }\n    ll powCost = 0;\n    for (int i = 0; i < N; ++i) {\n        if (active[i] && maxDist[i] > 0) {\n            int r = ceil_sqrt(maxDist[i]);\n            powCost += (ll)r * r;\n        }\n    }\n\n    // cable cost (MST on metric closure)\n    vector<int> terms;\n    for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n    ll cable = 0;\n    int T = terms.size();\n    if (T > 1) {\n        vector<ll> minDist(T, LLONG_MAX);\n        vector<bool> used(T, false);\n        minDist[0] = 0;\n        for (int i = 0; i < T; ++i) {\n            int u = -1;\n            ll best = LLONG_MAX;\n            for (int j = 0; j < T; ++j) {\n                if (!used[j] && minDist[j] < best) {\n                    best = minDist[j];\n                    u = j;\n                }\n            }\n            used[u] = true;\n            cable += best;\n            for (int v = 0; v < T; ++v) {\n                if (!used[v]) {\n                    ll d = dist_sh[terms[u]][terms[v]];\n                    if (d < minDist[v]) minDist[v] = d;\n                }\n            }\n        }\n    }\n    return powCost + cable;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    vector<tuple<int,int,ll>> edges(M);\n    vector<vector<pair<int,ll>>> adj(N);\n    for (int j = 0; j < M; ++j) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].emplace_back(v, w);\n        adj[v].emplace_back(u, w);\n    }\n\n    vector<int> ax(K), ay(K);\n    for (int k = 0; k < K; ++k) cin >> ax[k] >> ay[k];\n\n    // squared distances resident -> station\n    vector<vector<ll>> dist2(K, vector<ll>(N));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            ll dx = ax[k] - x[i], dy = ay[k] - y[i];\n            dist2[k][i] = dx*dx + dy*dy;\n        }\n    }\n\n    // for each resident, stations within 5000 sorted by distance\n    vector<vector<int>> cover(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            if (dist2[k][i] <= 5000LL * 5000LL) cover[k].push_back(i);\n        }\n        sort(cover[k].begin(), cover[k].end(), [&](int a, int b) {\n            return dist2[k][a] < dist2[k][b];\n        });\n    }\n\n    // all-pairs shortest paths (edge weights)\n    vector<vector<ll>> dist_sh(N, vector<ll>(N, INF));\n    vector<vector<int>> prev(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        dist_sh[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist_sh[s][u]) continue;\n            for (auto [v, w] : adj[u]) {\n                if (dist_sh[s][v] > d + w) {\n                    dist_sh[s][v] = d + w;\n                    prev[s][v] = u;\n                    pq.emplace(d + w, v);\n                }\n            }\n        }\n    }\n\n    // edge index\n    vector<vector<int>> edge_idx(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        auto [u, v, w] = edges[j];\n        edge_idx[u][v] = edge_idx[v][u] = j;\n    }\n\n    // ---------------------------------------------\n    // Build initial active set: all stations covering at least one resident\n    vector<bool> active(N, false);\n    for (int k = 0; k < K; ++k) {\n        for (int i : cover[k]) active[i] = true;\n    }\n    active[0] = true; // station 1 must be on\n\n    ll curCost = computeTotalCost(dist2, cover, dist_sh, active, N, K);\n    vector<bool> bestActive = active;\n    ll bestCost = curCost;\n\n    // Greedy forward addition\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        ll bestGain = 0;\n        int bestSt = -1;\n        for (int i = 1; i < N; ++i) {\n            if (active[i]) continue;\n            active[i] = true;\n            ll newCost = computeTotalCost(dist2, cover, dist_sh, active, N, K);\n            active[i] = false;\n            if (newCost < curCost) {\n                ll gain = curCost - newCost;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestSt = i;\n                }\n            }\n        }\n        if (bestSt != -1) {\n            active[bestSt] = true;\n            curCost = curCost - bestGain; // exact\n            if (curCost < bestCost) {\n                bestCost = curCost;\n                bestActive = active;\n            }\n            improved = true;\n        }\n    }\n\n    // Greedy backward removal\n    improved = true;\n    while (improved) {\n        improved = false;\n        ll bestGain = 0;\n        int bestSt = -1;\n        for (int i = 1; i < N; ++i) {\n            if (!active[i]) continue;\n            active[i] = false;\n            ll newCost = computeTotalCost(dist2, cover, dist_sh, active, N, K);\n            active[i] = true;\n            if (newCost < curCost) {\n                ll gain = curCost - newCost;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestSt = i;\n                }\n            }\n        }\n        if (bestSt != -1) {\n            active[bestSt] = false;\n            curCost = curCost - bestGain;\n            if (curCost < bestCost) {\n                bestCost = curCost;\n                bestActive = active;\n            }\n            improved = true;\n        }\n    }\n\n    // Simulated Annealing with random flips\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double T = 1e7;\n    double cooling = 0.9999;\n    int iters = 0;\n    const int MAX_ITERS = 3000;\n    while (iters < MAX_ITERS) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start).count() > 1950) break;\n\n        int flip = uniform_int_distribution<int>(1, N-1)(rng);\n        vector<bool> cand = active;\n        cand[flip] = !cand[flip];\n        cand[0] = true;\n\n        ll candCost = computeTotalCost(dist2, cover, dist_sh, cand, N, K);\n        if (candCost == LLONG_MAX) continue; // invalid\n\n        if (candCost < bestCost) {\n            bestCost = candCost;\n            bestActive = cand;\n        }\n\n        if (candCost < curCost) {\n            active = cand;\n            curCost = candCost;\n        } else {\n            double prob = exp(-(double)(candCost - curCost) / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                active = cand;\n                curCost = candCost;\n            }\n        }\n        T *= cooling;\n        iters++;\n    }\n\n    // Final best active set\n    active = bestActive;\n\n    // Compute powers\n    vector<ll> maxDist(N, 0);\n    for (int k = 0; k < K; ++k) {\n        int best = -1;\n        for (int i : cover[k]) {\n            if (active[i]) { best = i; break; }\n        }\n        ll d = dist2[k][best];\n        if (d > maxDist[best]) maxDist[best] = d;\n    }\n    vector<int> P(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (active[i] && maxDist[i] > 0) {\n            P[i] = ceil_sqrt(maxDist[i]);\n        }\n    }\n\n    // Build Steiner tree (MST on metric closure + shortest paths)\n    vector<int> terms;\n    for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n    vector<bool> edge_on(M, false);\n\n    if (terms.size() >= 2) {\n        int T = terms.size();\n        vector<int> parent_prim(T, -1);\n        vector<ll> minDist(T, LLONG_MAX);\n        vector<bool> used(T, false);\n        minDist[0] = 0;\n        vector<pair<int,int>> mst_pairs;\n        for (int i = 0; i < T; ++i) {\n            int u = -1;\n            ll best = LLONG_MAX;\n            for (int j = 0; j < T; ++j) {\n                if (!used[j] && minDist[j] < best) {\n                    best = minDist[j];\n                    u = j;\n                }\n            }\n            used[u] = true;\n            if (parent_prim[u] != -1) {\n                mst_pairs.emplace_back(terms[parent_prim[u]], terms[u]);\n            }\n            for (int v = 0; v < T; ++v) {\n                if (!used[v]) {\n                    ll d = dist_sh[terms[u]][terms[v]];\n                    if (d < minDist[v]) {\n                        minDist[v] = d;\n                        parent_prim[v] = u;\n                    }\n                }\n            }\n        }\n\n        // Add edges along shortest paths of MST pairs\n        for (auto &[u, v] : mst_pairs) {\n            int cur = v;\n            while (cur != u) {\n                int par = prev[u][cur];\n                int idx = edge_idx[par][cur];\n                if (idx != -1) edge_on[idx] = true;\n                cur = par;\n            }\n        }\n\n        // Prune cycles\n        vector<int> cand_edges;\n        for (int j = 0; j < M; ++j) if (edge_on[j]) cand_edges.push_back(j);\n        sort(cand_edges.begin(), cand_edges.end(), [&](int a, int b) {\n            return get<2>(edges[a]) < get<2>(edges[b]);\n        });\n        UnionFind uf(N);\n        fill(edge_on.begin(), edge_on.end(), false);\n        for (int idx : cand_edges) {\n            auto [u, v, w] = edges[idx];\n            if (uf.unite(u, v)) edge_on[idx] = true;\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (edge_on[j] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    vector<tuple<int, int, int, int>> ops;\n\n    // bottom-up heapify\n    for (int x = N - 2; x >= 0; --x) {\n        for (int y = 0; y <= x; ++y) {\n            int cx = x, cy = y;\n            while (cx < N - 1) {\n                int left_val  = a[cx + 1][cy];\n                int right_val = a[cx + 1][cy + 1];\n                int cur_val   = a[cx][cy];\n\n                if (cur_val > left_val || cur_val > right_val) {\n                    // swap with the smaller child\n                    int child_y = (left_val < right_val) ? cy : cy + 1;\n                    swap(a[cx][cy], a[cx + 1][child_y]);\n                    ops.emplace_back(cx, cy, cx + 1, child_y);\n                    cx = cx + 1;\n                    cy = child_y;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // output\n    cout << ops.size() << \"\\n\";\n    for (const auto& [x1, y1, x2, y2] : ops) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int D = 9;\n    int N;\n    cin >> D >> N; // D is always 9\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    // precompute BFS distances from entrance (0,4) ignoring containers\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int, int>> q;\n    dist[0][4] = 0;\n    q.emplace(0, 4);\n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int k = 0; k < 4; ++k) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n            if (obstacle[nx][ny] || dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            q.emplace(nx, ny);\n        }\n    }\n\n    // list of all usable cells (excluding entrance), sorted by distance\n    vector<tuple<int, int, int>> cells; // (distance, row, col)\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (i == 0 && j == 4) continue;          // entrance itself\n            if (obstacle[i][j]) continue;\n            cells.emplace_back(dist[i][j], i, j);\n        }\n    }\n    sort(cells.begin(), cells.end());\n    const int total = cells.size();   // = D*D - 1 - N\n\n    // index of each cell in the sorted order (0 .. total-1)\n    vector<vector<int>> order(D, vector<int>(D, -1));\n    for (int idx = 0; idx < total; ++idx) {\n        auto [d, i, j] = cells[idx];\n        order[i][j] = idx;\n    }\n\n    // container number stored at each cell (-1 if empty)\n    vector<vector<int>> container(D, vector<int>(D, -1));\n    vector<vector<bool>> occupied(D, vector<bool>(D, false));\n\n    // BFS from entrance on empty cells (obstacles + occupied cells are walls)\n    auto bfs_reachable = [&]() -> vector<vector<bool>> {\n        vector<vector<bool>> reachable(D, vector<bool>(D, false));\n        queue<pair<int, int>> q;\n        if (!obstacle[0][4] && !occupied[0][4]) {\n            reachable[0][4] = true;\n            q.emplace(0, 4);\n        }\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int k = 0; k < 4; ++k) {\n                int nx = x + dx[k], ny = y + dy[k];\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D) continue;\n                if (obstacle[nx][ny] || occupied[nx][ny]) continue;\n                if (reachable[nx][ny]) continue;\n                reachable[nx][ny] = true;\n                q.emplace(nx, ny);\n            }\n        }\n        return reachable;\n    };\n\n    // ---------- placement phase ----------\n    for (int d = 0; d < total; ++d) {\n        int t;\n        cin >> t;\n\n        auto reachable = bfs_reachable();\n\n        // choose the reachable empty cell whose order is closest to t\n        int best_i = -1, best_j = -1;\n        int best_diff = INT_MAX;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || occupied[i][j]) continue;\n                if (i == 0 && j == 4) continue;      // entrance cannot be used\n                if (!reachable[i][j]) continue;\n                int diff = abs(order[i][j] - t);\n                if (diff < best_diff) {\n                    best_diff = diff;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // place the container\n        occupied[best_i][best_j] = true;\n        container[best_i][best_j] = t;\n        cout << best_i << \" \" << best_j << endl << flush;\n    }\n\n    // ---------- retrieval phase ----------\n    for (int step = 0; step < total; ++step) {\n        auto reachable = bfs_reachable();\n\n        // find the reachable container with the smallest number\n        int best_num = INT_MAX;\n        int best_i = -1, best_j = -1;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || container[i][j] == -1) continue;\n                if (!reachable[i][j]) continue;\n                if (container[i][j] < best_num) {\n                    best_num = container[i][j];\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n\n        // remove it\n        occupied[best_i][best_j] = false;\n        container[best_i][best_j] = -1;\n        cout << best_i << \" \" << best_j << \"\\n\";\n    }\n    cout << flush;\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n#include <map>\n\nusing namespace std;\n\nconst int INF = 1e9;\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\nint n, m;\nvector<vector<int>> grid;\n\n// adjacency count between colors (lower triangle, colors 1..m)\nvector<vector<int>> adjCnt;\n\n// total cells of each color\nvector<int> tot;\n\n// number of cells of each color that have at least one zero neighbor (or are on boundary)\nvector<int> zeroCnt;\n\n// whether each cell has a zero neighbor (including boundary)\nvector<vector<bool>> adjZero;\n\n// whether a color originally had any adjacency to zero (boundary)\nvector<bool> origZero;\n\n// check if cell (i,j) of color c can be removed\nbool can_remove(int i, int j, int c) {\n    if (c == 0) return false;\n    if (tot[c] <= 1) return false;\n\n    // count neighbors by color\n    map<int, int> neighCount; // color -> number of neighbors of that color\n    int sameNeighCount = 0;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        int col = grid[ni][nj];\n        if (col == 0) continue;\n        if (col == c) {\n            sameNeighCount++;\n        } else {\n            neighCount[col]++;\n        }\n    }\n\n    // check inter-color adjacency preservation for each neighbor color\n    for (auto &p : neighCount) {\n        int col = p.first;\n        int cnt = p.second;\n        int a = min(c, col);\n        int b = max(c, col);\n        // remaining adjacencies after removing this cell\n        if (adjCnt[a][b] - cnt < 1) return false;\n    }\n\n    // zero adjacency checks\n    // for neighbor colors (other than c): they must already have zero adjacency (or gain it illegally)\n    for (auto &p : neighCount) {\n        int col = p.first;\n        // if the neighbor color currently has NO zero adjacency, gaining one is illegal\n        if (zeroCnt[col] == 0) return false;\n    }\n\n    // compute new zero count for color c after removal\n    int newZeroC = zeroCnt[c] - (adjZero[i][j] ? 1 : 0);\n    // same-color neighbors that don't currently have zero adjacency will gain one\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        if (grid[ni][nj] == c) {\n            if (!adjZero[ni][nj]) newZeroC++;\n        }\n    }\n    // if color originally had zero adjacency, preserve at least one\n    if (origZero[c] && newZeroC == 0) return false;\n\n    // connectivity check for color c after removal\n    vector<vector<bool>> visited(n, vector<bool>(n, false));\n    queue<pair<int,int>> q;\n    // find a starting cell (any other cell of same colour)\n    bool found = false;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        if (grid[ni][nj] == c) {\n            q.push({ni, nj});\n            visited[ni][nj] = true;\n            found = true;\n            break;\n        }\n    }\n    if (!found) {\n        for (int x = 0; x < n; ++x) {\n            for (int y = 0; y < n; ++y) {\n                if ((x != i || y != j) && grid[x][y] == c) {\n                    q.push({x, y});\n                    visited[x][y] = true;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n    }\n    if (!found) return false; // should not happen (tot[c]>1)\n    int cnt = 1;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (nx == i && ny == j) continue;\n            if (!visited[nx][ny] && grid[nx][ny] == c) {\n                visited[nx][ny] = true;\n                cnt++;\n                q.push({nx, ny});\n            }\n        }\n    }\n    if (cnt != tot[c] - 1) return false;\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    grid.assign(n, vector<int>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid[i][j];\n        }\n    }\n\n    const int MAXC = m + 2;\n    adjCnt.assign(MAXC, vector<int>(MAXC, 0));\n    tot.assign(MAXC, 0);\n    zeroCnt.assign(MAXC, 0);\n    adjZero.assign(n, vector<bool>(n, false));\n    origZero.assign(MAXC, false);\n\n    // initial data from original map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = grid[i][j];\n            tot[c]++;\n            bool onBoundary = (i == 0 || i == n-1 || j == 0 || j == n-1);\n            if (onBoundary) {\n                zeroCnt[c]++;\n                adjZero[i][j] = true;\n                origZero[c] = true;\n            }\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n                int col = grid[ni][nj];\n                if (c != col) {\n                    if (c < col) adjCnt[c][col]++;\n                }\n            }\n        }\n    }\n\n    // queue: all cells that are currently adjacent to zero (or on boundary) and non-zero\n    deque<pair<int,int>> que;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (adjZero[i][j] && grid[i][j] != 0) {\n                que.push_back({i, j});\n            }\n        }\n    }\n\n    // Greedy removal\n    while (!que.empty()) {\n        auto [i, j] = que.front(); que.pop_front();\n        int c = grid[i][j];\n        if (c == 0) continue;\n        if (!can_remove(i, j, c)) continue;\n\n        // perform removal\n        // update structures\n        // 1. remove cell itself\n        if (adjZero[i][j]) {\n            zeroCnt[c]--;\n        }\n        tot[c]--;\n\n        // 2. update neighbors\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + dx[d];\n            int nj = j + dy[d];\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n            int col = grid[ni][nj];\n            if (col == 0) continue; // already zero, no change\n            // decrement adjacency count\n            if (col != c) {\n                int a = min(c, col);\n                int b = max(c, col);\n                adjCnt[a][b]--;\n            }\n            // update zero adjacency for neighbor due to new zero cell\n            if (!adjZero[ni][nj]) {\n                adjZero[ni][nj] = true;\n                zeroCnt[col]++;\n            }\n            // push neighbor for further consideration\n            que.push_back({ni, nj});\n        }\n\n        // 3. set cell to zero\n        grid[i][j] = 0;\n    }\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << grid[i][j];\n            if (j < n-1) cout << ' ';\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\n#include <cmath>\n\nusing namespace std;\n\nint queries_left;\nint N, D, Q;\n\nvoid query(const vector<int>& L, const vector<int>& R, string& res) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    cin >> res;\n    --queries_left;\n}\n\nbool lighter(int a, int b) {\n    if (a == b) return false;\n    vector<int> L = {a}, R = {b};\n    string res;\n    query(L, R, res);\n    return res == \"<\";\n}\n\n// Full binary insertion sort, returns sorted order (lightest first)\nvector<int> full_sort() {\n    vector<int> sorted;\n    sorted.push_back(0);\n    for (int i = 1; i < N; ++i) {\n        auto pos = lower_bound(sorted.begin(), sorted.end(), i,\n                               [&](int a, int b) { return lighter(a, b); });\n        sorted.insert(pos, i);\n    }\n    return sorted;\n}\n\n// Quick heuristic ordering using reference items, returns order (heaviest first)\n// Also fills weight[] with estimated \"score\" (larger = heavier)\nvector<int> quick_order(vector<long long>& weight) {\n    int ref_cnt = min(10, max(2, Q / (3 * N)));\n    if (ref_cnt > N) ref_cnt = N;\n    vector<int> refs;\n    for (int i = 0; i < ref_cnt; ++i) refs.push_back(i);\n    vector<int> win(N, 0);\n    for (int i = 0; i < N && queries_left > 0; ++i) {\n        for (int r : refs) {\n            if (i == r) continue;\n            if (queries_left <= 0) break;\n            if (!lighter(i, r)) win[i]++;\n        }\n    }\n    for (int i = 0; i < N; ++i) weight[i] = win[i];\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (win[a] != win[b]) return win[a] > win[b];\n        return a < b;\n    });\n    return idx; // heaviest first\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    queries_left = Q;\n\n    vector<int> order;          // items in descending weight (heaviest first)\n    vector<long long> weight(N, 0); // estimated weight (larger = heavier)\n\n    int sort_cost = N * (int)ceil(log2(N)) + N; // approximate comparisons needed for full sort\n    if (Q >= sort_cost) {\n        // Full binary insertion sort\n        vector<int> sorted = full_sort(); // lightest first\n        for (int i = 0; i < N; ++i) {\n            int item = sorted[i];\n            weight[item] = i; // lightest gets 0, heaviest gets N-1\n        }\n        // order = heaviest first\n        order = sorted;\n        reverse(order.begin(), order.end());\n    } else {\n        // Quick heuristic ordering\n        order = quick_order(weight); // weight is filled inside, heaviest first\n    }\n\n    // ---------- Greedy partition ----------\n    vector<int> assign(N, -1);\n    vector<long long> group_sum(D, 0);\n    for (int item : order) {\n        int best = 0;\n        for (int g = 1; g < D; ++g) {\n            if (group_sum[g] < group_sum[best]) best = g;\n        }\n        assign[item] = best;\n        group_sum[best] += weight[item];\n    }\n\n    // ---------- Build group item lists ----------\n    vector<vector<int>> groups(D);\n    for (int i = 0; i < N; ++i) groups[assign[i]].push_back(i);\n\n    // ---------- Refinement using actual balance comparisons ----------\n    // Keep a copy of estimated sums from initial weight\n    vector<long long> est_sum = group_sum; // already computed\n    while (queries_left > 0) {\n        // Find groups with max and min estimated sum\n        int heavy = 0, light = 0;\n        for (int g = 1; g < D; ++g) {\n            if (est_sum[g] > est_sum[heavy]) heavy = g;\n            if (est_sum[g] < est_sum[light]) light = g;\n        }\n        if (heavy == light) break; // all equal, done\n        if (groups[heavy].empty() || groups[light].empty()) break; // should not happen\n        // Compare actual total weights of heavy and light groups\n        string res;\n        query(groups[heavy], groups[light], res);\n        int actual_heavy, actual_light;\n        if (res == \">\") {\n            actual_heavy = heavy;\n            actual_light = light;\n        } else if (res == \"<\") {\n            actual_heavy = light;\n            actual_light = heavy;\n        } else { // equal weights\n            // No need to move, try other pair? But we break to avoid infinite loop\n            break;\n        }\n        // Ensure actual_heavy has at least 2 items before moving (to avoid empty group)\n        if (groups[actual_heavy].size() <= 1) break;\n        // Pick item with smallest estimated weight from actual_heavy\n        int move_item = -1;\n        long long min_w = LLONG_MAX;\n        for (int item : groups[actual_heavy]) {\n            if (weight[item] < min_w) {\n                min_w = weight[item];\n                move_item = item;\n            }\n        }\n        if (move_item == -1) break;\n        // Perform move\n        auto it = find(groups[actual_heavy].begin(), groups[actual_heavy].end(), move_item);\n        if (it != groups[actual_heavy].end()) groups[actual_heavy].erase(it);\n        groups[actual_light].push_back(move_item);\n        assign[move_item] = actual_light;\n        est_sum[actual_heavy] -= weight[move_item];\n        est_sum[actual_light] += weight[move_item];\n    }\n\n    // ---------- Consume remaining queries ----------\n    while (queries_left > 0) {\n        cout << \"1 1 0 1\" << endl;\n        string res;\n        cin >> res;\n        --queries_left;\n    }\n\n    // ---------- Output final assignment ----------\n    for (int i = 0; i < N; ++i) {\n        cout << assign[i] << (i == N - 1 ? '\\n' : ' ');\n    }\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// length of strictly decreasing prefix from bottom\nint pref_len(const vector<int>& st) {\n    int sz = (int)st.size();\n    if (sz == 0) return 0;\n    int len = 1;\n    for (int i = 1; i < sz; ++i) {\n        if (st[i-1] > st[i]) ++len;\n        else break;\n    }\n    return len;\n}\n\n// score: number of boxes not in the decreasing prefix\nint stack_score(const vector<int>& st) {\n    return (int)st.size() - pref_len(st);\n}\n\n// total score over all stacks\nint total_score(const vector<vector<int>>& stacks) {\n    int s = 0;\n    for (const auto& st : stacks) s += stack_score(st);\n    return s;\n}\n\nstruct State {\n    vector<vector<int>> stacks;\n    int cost;                   // energy used so far\n    vector<pair<int,int>> ops;  // performed operations\n\n    State(const vector<vector<int>>& st, int c) : stacks(st), cost(c) {}\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int per_stack = n / m;\n    vector<vector<int>> init_stacks(m);\n    for (int i = 0; i < m; ++i) {\n        init_stacks[i].resize(per_stack);\n        for (int j = 0; j < per_stack; ++j) {\n            cin >> init_stacks[i][j];\n        }\n    }\n\n    // beam search parameters\n    const int BEAM = 15;\n    const double WEIGHT = 1.5;   // weight for future heuristic\n\n    vector<State> beam;\n    beam.emplace_back(init_stacks, 0);\n\n    for (int target = 1; target <= n; ++target) {\n        vector<State> candidates;\n\n        // for each state in the beam, try to carry out target\n        for (const State& state : beam) {\n            // find target position\n            int s = -1, idx = -1;\n            for (int i = 0; i < m; ++i) {\n                const auto& st = state.stacks[i];\n                for (int j = 0; j < (int)st.size(); ++j) {\n                    if (st[j] == target) {\n                        s = i;\n                        idx = j;\n                        break;\n                    }\n                }\n                if (s != -1) break;\n            }\n\n            int top_idx = (int)state.stacks[s].size() - 1;\n            if (idx == top_idx) {\n                // target already on top \u2192 just carry it out\n                State ns = state;\n                ns.stacks[s].pop_back();\n                ns.ops.emplace_back(target, 0);\n                candidates.push_back(move(ns));\n            } else {\n                // move the entire block above target (starting from idx+1)\n                int v_idx = idx + 1;\n                int block_size = top_idx - v_idx + 1;\n                int v = state.stacks[s][v_idx];   // box that becomes the bottom of the moved block\n\n                for (int d = 0; d < m; ++d) {\n                    if (d == s) continue;\n                    State ns = state;  // deep copy\n                    auto& src = ns.stacks[s];\n                    auto& dst = ns.stacks[d];\n\n                    // move block [v_idx, top_idx] to destination\n                    for (int k = v_idx; k < (int)src.size(); ++k) {\n                        dst.push_back(src[k]);\n                    }\n                    src.resize(v_idx);\n\n                    // now target is on top (src.size() == v_idx and idx == v_idx-1)\n                    src.pop_back();   // carry out target\n\n                    ns.cost += block_size + 1;\n                    ns.ops.emplace_back(v, d + 1);   // move operation (1\u2011based stack)\n                    ns.ops.emplace_back(target, 0);  // carry out\n                    candidates.push_back(move(ns));\n                }\n            }\n        }\n\n        // keep the best BEAM candidates according to cost + WEIGHT * total_score\n        int keep = min(BEAM, (int)candidates.size());\n        partial_sort(candidates.begin(),\n                     candidates.begin() + keep,\n                     candidates.end(),\n                     [WEIGHT](const State& a, const State& b) {\n                         int va = a.cost + (int)(WEIGHT * total_score(a.stacks));\n                         int vb = b.cost + (int)(WEIGHT * total_score(b.stacks));\n                         if (va != vb) return va < vb;\n                         return a.cost < b.cost;  // prefer smaller cost so far\n                     });\n\n        beam.clear();\n        for (int i = 0; i < keep; ++i) {\n            beam.push_back(move(candidates[i]));\n        }\n    }\n\n    // output the operation sequence of the best state\n    const State& best = beam[0];\n    for (const auto& op : best.ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <cmath>\n#include <stack>\n#include <string>\n#include <vector>\nusing namespace std;\n\nint N;\nvector<vector<int>> graph;\nvector<double> sqrt_d;\nvector<int> parent;\nvector<vector<int>> children;\nvector<char> dir_to_child;  // direction from parent to node\n\nint idx(int i, int j) { return i * N + j; }\nint ix(int id) { return id / N; }\nint jy(int id) { return id % N; }\n\nchar dir_char(int di, int dj) {\n    if (di == -1 && dj == 0) return 'U';\n    if (di == 1 && dj == 0) return 'D';\n    if (di == 0 && dj == -1) return 'L';\n    if (di == 0 && dj == 1) return 'R';\n    return '?';\n}\nchar opposite(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return '?';\n}\n\n// compute f values for a given K, return total_moves = 2 * sum_{v>0} f[v]\npair<vector<int>, int> compute_f(double K) {\n    int M = N * N;\n    vector<int> f(M, 0);\n    // post-order DFS using stack (iterative to avoid recursion depth)\n    // We'll use explicit stack with state: (node, visited flag)\n    // Since tree is small, recursion is fine, but for safety we use iterative.\n    stack<pair<int, bool>> st;  // (node, processed)\n    st.push({0, false});\n    while (!st.empty()) {\n        auto [v, processed] = st.top(); st.pop();\n        if (!processed) {\n            st.push({v, true});\n            for (int c : children[v]) {\n                st.push({c, false});\n            }\n        } else {\n            // post-order\n            if (v == 0) continue;\n            double sq = sqrt_d[v];\n            int target = max(1, (int)round(K * sq));\n            int sum_child = 0;\n            for (int c : children[v]) sum_child += f[c];\n            f[v] = max(1, target - sum_child);\n        }\n    }\n    int total_moves = 0;\n    for (int v = 1; v < M; ++v) total_moves += f[v];\n    total_moves *= 2;\n    return {f, total_moves};\n}\n\nstring build_route(const vector<int>& f) {\n    int M = N * N;\n    vector<int> rem = f;  // rem[0] is unused\n    // stack of nodes (current path)\n    stack<int> st;\n    st.push(0);\n    vector<char> moves;\n    moves.reserve(100000);\n    while (true) {\n        int v = st.top();\n        // find child with maximum remaining visits\n        int best_child = -1;\n        int best_rem = 0;\n        for (int c : children[v]) {\n            if (rem[c] > best_rem) {\n                best_rem = rem[c];\n                best_child = c;\n            }\n        }\n        if (best_child != -1) {\n            // go down to child\n            moves.push_back(dir_to_child[best_child]);\n            rem[best_child]--;\n            st.push(best_child);\n        } else {\n            // no child remaining\n            if (v == 0) break;  // back at root, finish\n            st.pop();\n            char up_dir = opposite(dir_to_child[v]);\n            moves.push_back(up_dir);\n        }\n    }\n    return string(moves.begin(), moves.end());\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    // build graph\n    int M = N * N;\n    graph.assign(M, {});\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = idx(i, j);\n            if (i < N - 1 && h[i][j] == '0') {\n                int id2 = idx(i + 1, j);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n            if (j < N - 1 && v[i][j] == '0') {\n                int id2 = idx(i, j + 1);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n        }\n    }\n\n    // BFS tree from (0,0)\n    parent.assign(M, -1);\n    children.assign(M, {});\n    dir_to_child.assign(M, ' ');\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0; // mark root (self)\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) {\n            if (parent[u] == -1) {\n                parent[u] = v;\n                children[v].push_back(u);\n                int di = ix(u) - ix(v);\n                int dj = jy(u) - jy(v);\n                dir_to_child[u] = dir_char(di, dj);\n                q.push(u);\n            }\n        }\n    }\n    // compute sqrt_d\n    sqrt_d.assign(M, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sqrt_d[idx(i, j)] = sqrt((double)d[i][j]);\n\n    // binary search for maximum K such that total_moves <= 100000\n    double low = 0.0, high = 200.0; // sufficient range\n    vector<int> best_f;\n    for (int iter = 0; iter < 60; ++iter) {\n        double mid = (low + high) / 2.0;\n        auto [f, moves] = compute_f(mid);\n        if (moves <= 100000) {\n            best_f = f;\n            low = mid;\n        } else {\n            high = mid;\n        }\n    }\n    // final route from best_f (guaranteed moves <= 100000)\n    string route = build_route(best_f);\n    cout << route << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\nusing LL = long long;\nconst LL INF = 1e18;\nconst int N = 15;\nconst int S = N * N; // 225\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummyN, M;\n    cin >> dummyN >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> pat(M);\n    for (int i = 0; i < M; ++i) cin >> pat[i];\n\n    // positions for each letter\n    vector<vector<int>> pos(26);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            pos[grid[i][j] - 'A'].push_back(i * N + j);\n        }\n    }\n\n    // Manhattan distance\n    array<array<int, S>, S> dist;\n    for (int i = 0; i < S; ++i) {\n        int x1 = i / N, y1 = i % N;\n        for (int j = 0; j < S; ++j) {\n            int x2 = j / N, y2 = j % N;\n            dist[i][j] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    // Precompute cost and end cell for each pattern, each suffix start index (0..4), each start cell\n    // cost[j][k][st] = min cost to type characters from index k to 4 of pattern j starting from st\n    vector<vector<vector<LL>>> cost(M, vector<vector<LL>>(5, vector<LL>(S, INF)));\n    vector<vector<vector<int>>> endCell(M, vector<vector<int>>(5, vector<int>(S, -1)));\n\n    for (int j = 0; j < M; ++j) {\n        const string& s = pat[j];\n        for (int k = 0; k < 5; ++k) {\n            int len = 5 - k;\n            for (int st = 0; st < S; ++st) {\n                // DP over steps\n                vector<LL> dp(S, INF);\n                vector<int> bestPrev(S, -1);\n                int c0 = s[k] - 'A';\n                for (int p : pos[c0]) {\n                    dp[p] = dist[st][p] + 1;\n                }\n                for (int step = 1; step < len; ++step) {\n                    vector<LL> ndp(S, INF);\n                    vector<int> nbestPrev(S, -1);\n                    int curChar = s[k + step] - 'A';\n                    int prevChar = s[k + step - 1] - 'A';\n                    for (int p : pos[curChar]) {\n                        LL best = INF;\n                        int bestP = -1;\n                        for (int q : pos[prevChar]) {\n                            if (dp[q] == INF) continue;\n                            LL cand = dp[q] + dist[q][p] + 1;\n                            if (cand < best) {\n                                best = cand;\n                                bestP = q;\n                            }\n                        }\n                        ndp[p] = best;\n                        nbestPrev[p] = bestP;\n                    }\n                    dp.swap(ndp);\n                    bestPrev.swap(nbestPrev);\n                }\n                int lastChar = s[4] - 'A';\n                LL bestCost = INF;\n                int bestEnd = -1;\n                for (int p : pos[lastChar]) {\n                    if (dp[p] < bestCost) {\n                        bestCost = dp[p];\n                        bestEnd = p;\n                    }\n                }\n                cost[j][k][st] = bestCost;\n                endCell[j][k][st] = bestEnd;\n            }\n        }\n    }\n\n    // Overlap matrix between patterns (suffix of i vs prefix of j)\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            for (int l = 5; l >= 1; --l) {\n                if (pat[i].substr(5 - l) == pat[j].substr(0, l)) {\n                    ov[i][j] = l;\n                    break;\n                }\n            }\n        }\n    }\n\n    int start = si * N + sj;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> best_order;\n    LL best_total = INF;\n\n    // Fast evaluation of total cost for a given permutation (order of patterns)\n    auto evaluate = [&](const vector<int>& order) -> pair<LL, int> {\n        int curCell = start;\n        int last = -1;\n        LL total = 0;\n        for (int idx : order) {\n            int ol = (last == -1) ? 0 : ov[last][idx];\n            // patterns are distinct, so ol < 5 always\n            total += cost[idx][ol][curCell];\n            curCell = endCell[idx][ol][curCell];\n            last = idx;\n        }\n        return {total, curCell}; // curCell is final position (not used)\n    };\n\n    // Generate many random permutations, keep best\n    const int NUM_PERM = 20000; // will adjust based on time\n    int perm_count = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.5 || perm_count >= NUM_PERM) break;\n\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        auto [total, _] = evaluate(order);\n        if (total < best_total) {\n            best_total = total;\n            best_order = order;\n        }\n        perm_count++;\n    }\n\n    // Also run greedy seeds (deterministic and random) to complement\n    const int GREEDY_TRIALS = 20;\n    for (int trial = 0; trial < GREEDY_TRIALS; ++trial) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.8) break;\n\n        vector<bool> covered(M, false);\n        vector<int> order;\n        int curCell = start;\n        int last = -1;\n        LL total = 0;\n        int remaining = M;\n\n        while (remaining > 0) {\n            vector<pair<LL, int>> cand;\n            for (int j = 0; j < M; ++j) {\n                if (covered[j]) continue;\n                int ol = (last == -1) ? 0 : ov[last][j];\n                LL c = cost[j][ol][curCell];\n                // Heuristic: add small bias for overlap\n                cand.emplace_back(c - 2 * ol, j);\n            }\n            if (cand.empty()) break;\n            sort(cand.begin(), cand.end());\n            // Selection: deterministic first trial, otherwise random among top 3\n            int chosen;\n            if (trial == 0) {\n                chosen = cand[0].second;\n            } else {\n                int topk = min(3, (int)cand.size());\n                uniform_int_distribution<int> uid(0, topk - 1);\n                chosen = cand[uid(rng)].second;\n            }\n\n            int ol = (last == -1) ? 0 : ov[last][chosen];\n            total += cost[chosen][ol][curCell];\n            curCell = endCell[chosen][ol][curCell];\n            order.push_back(chosen);\n            covered[chosen] = true;\n            remaining--;\n            last = chosen;\n        }\n        if (total < best_total) {\n            best_total = total;\n            best_order = order;\n        }\n    }\n\n    // Local search on best_order (swap two indices)\n    if (!best_order.empty()) {\n        vector<int> cur_order = best_order;\n        LL cur_cost = best_total;\n        auto evaluate_order = [&](const vector<int>& ord) -> LL {\n            return evaluate(ord).first;\n        };\n\n        // 2-opt: reverse segment\n        for (int it = 0; it < 5000; ++it) {\n            int l = uniform_int_distribution<int>(0, M - 1)(rng);\n            int r = uniform_int_distribution<int>(l, M - 1)(rng);\n            reverse(cur_order.begin() + l, cur_order.begin() + r + 1);\n            LL new_cost = evaluate_order(cur_order);\n            if (new_cost < cur_cost) {\n                cur_cost = new_cost;\n            } else {\n                reverse(cur_order.begin() + l, cur_order.begin() + r + 1); // revert\n            }\n        }\n        if (cur_cost < best_total) {\n            best_total = cur_cost;\n            best_order = cur_order;\n        }\n    }\n\n    // Reconstruct actual moves for the best order (with full DP backtrack)\n    vector<int> final_moves;\n    {\n        int curCell = start;\n        int last = -1;\n        for (int idx : best_order) {\n            int ol = (last == -1) ? 0 : ov[last][idx];\n            const string& s = pat[idx];\n            int len = 5 - ol;\n            // DP with backtrack for this suffix\n            vector<vector<LL>> dp(len, vector<LL>(S, INF));\n            vector<vector<int>> prev(len, vector<int>(S, -1));\n            int firstChar = s[ol] - 'A';\n            for (int p : pos[firstChar]) {\n                dp[0][p] = dist[curCell][p] + 1;\n            }\n            for (int step = 1; step < len; ++step) {\n                int curChar = s[ol + step] - 'A';\n                int prevChar = s[ol + step - 1] - 'A';\n                for (int p : pos[curChar]) {\n                    LL best = INF;\n                    int bestP = -1;\n                    for (int q : pos[prevChar]) {\n                        if (dp[step-1][q] == INF) continue;\n                        LL cand = dp[step-1][q] + dist[q][p] + 1;\n                        if (cand < best) {\n                            best = cand;\n                            bestP = q;\n                        }\n                    }\n                    dp[step][p] = best;\n                    prev[step][p] = bestP;\n                }\n            }\n            int lastChar = s[4] - 'A';\n            LL bestCost = INF;\n            int bestEnd = -1;\n            for (int p : pos[lastChar]) {\n                if (dp[len-1][p] < bestCost) {\n                    bestCost = dp[len-1][p];\n                    bestEnd = p;\n                }\n            }\n            // reconstruct path\n            vector<int> path(len);\n            int p = bestEnd;\n            for (int step = len-1; step >= 0; --step) {\n                path[step] = p;\n                if (step > 0) p = prev[step][p];\n            }\n            for (int x : path) final_moves.push_back(x);\n            curCell = bestEnd;\n            last = idx;\n        }\n    }\n\n    // Output\n    for (int p : final_moves) {\n        cout << p / N << ' ' << p % N << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int MAX_CELLS = MAX_N * MAX_N;\n\nint N, M;\ndouble eps;\n\n// Pre-define structures\nstruct Placement {\n    vector<int> cells; // indices of covered cells (i*N+j)\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    vector<Placement> placements;\n    vector<bool> active; // true if placement still possible\n    int active_cnt;\n};\n\nvector<Field> fields;\nint drilled_v[MAX_CELLS]; // -1 unknown, else exact value\nint cover_count[MAX_CELLS]; // number of active placements covering this cell\nint ops = 0;\nconst int MAX_OPS = 2 * MAX_N * MAX_N;\n\n// For each cell, list of (field_index, placement_index)\nvector<pair<int,int>> cell_placements[MAX_CELLS];\n\n// For backtracking\nint cur_sum[MAX_CELLS];\nint found_solutions;\nvector<int> cur_assign; // placement index for each field\nvector<int> best_assign;\n\nvoid flush_output() {\n    cout.flush();\n}\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        vector<pair<int,int>> shape(d);\n        for (int l = 0; l < d; ++l) {\n            cin >> shape[l].first >> shape[l].second;\n        }\n        fields[k].shape = shape;\n    }\n}\n\nvoid generate_placements() {\n    for (int f = 0; f < M; ++f) {\n        const auto& shape = fields[f].shape;\n        int max_i = 0, max_j = 0;\n        for (const auto& p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int di = 0; di <= N - h; ++di) {\n            for (int dj = 0; dj <= N - w; ++dj) {\n                Placement pl;\n                for (const auto& p : shape) {\n                    int i = di + p.first;\n                    int j = dj + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                fields[f].placements.push_back(move(pl));\n            }\n        }\n        fields[f].active.assign(fields[f].placements.size(), true);\n        fields[f].active_cnt = fields[f].placements.size();\n    }\n}\n\nvoid build_cell_cover() {\n    for (int cell = 0; cell < N * N; ++cell) {\n        cell_placements[cell].clear();\n    }\n    for (int f = 0; f < M; ++f) {\n        int pid = 0;\n        for (const auto& pl : fields[f].placements) {\n            for (int cell : pl.cells) {\n                cell_placements[cell].push_back({f, pid});\n            }\n            ++pid;\n        }\n    }\n    // initial cover counts\n    memset(cover_count, 0, sizeof(cover_count));\n    for (int cell = 0; cell < N * N; ++cell) {\n        cover_count[cell] = cell_placements[cell].size();\n    }\n}\n\nint find_best_cell() {\n    int best_cell = -1, best_cnt = -1;\n    for (int cell = 0; cell < N * N; ++cell) {\n        if (drilled_v[cell] != -1) continue;\n        if (cover_count[cell] > best_cnt) {\n            best_cnt = cover_count[cell];\n            best_cell = cell;\n        }\n    }\n    return best_cell;\n}\n\nvoid eliminate_placement(int f, int pid) {\n    if (!fields[f].active[pid]) return;\n    fields[f].active[pid] = false;\n    fields[f].active_cnt--;\n    for (int cell : fields[f].placements[pid].cells) {\n        cover_count[cell]--;\n    }\n}\n\nvoid drill_cell(int cell) {\n    int i = cell / N, j = cell % N;\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    drilled_v[cell] = resp;\n    ops++;\n    if (resp == 0) {\n        // eliminate all placements covering this cell\n        for (auto [f, pid] : cell_placements[cell]) {\n            eliminate_placement(f, pid);\n        }\n    }\n}\n\n// ---- Backtracking ----\nbool can_place(int f, int pid) {\n    for (int cell : fields[f].placements[pid].cells) {\n        if (drilled_v[cell] != -1 && cur_sum[cell] + 1 > drilled_v[cell]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid dfs(int step, const vector<int>& order) {\n    if (found_solutions >= 2) return;\n    if (step == (int)order.size()) {\n        // check all drilled cells exactly\n        for (int cell = 0; cell < N * N; ++cell) {\n            if (drilled_v[cell] != -1 && cur_sum[cell] != drilled_v[cell]) {\n                return;\n            }\n        }\n        found_solutions++;\n        if (found_solutions == 1) {\n            best_assign = cur_assign;\n        }\n        return;\n    }\n    int f = order[step];\n    const auto& placements = fields[f].placements;\n    const auto& active = fields[f].active;\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        if (!active[pid]) continue;\n        if (!can_place(f, pid)) continue;\n        // place\n        cur_assign[f] = pid;\n        for (int cell : placements[pid].cells) {\n            cur_sum[cell]++;\n        }\n        dfs(step + 1, order);\n        // undo\n        for (int cell : placements[pid].cells) {\n            cur_sum[cell]--;\n        }\n        cur_assign[f] = -1;\n        if (found_solutions >= 2) return;\n    }\n}\n\nbool find_unique() {\n    found_solutions = 0;\n    // order fields by number of active placements (ascending)\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return fields[a].active_cnt < fields[b].active_cnt;\n    });\n    memset(cur_sum, 0, sizeof(cur_sum));\n    cur_assign.assign(M, -1);\n    best_assign.assign(M, -1);\n    dfs(0, order);\n    return (found_solutions == 1);\n}\n\nbool estimate_small() {\n    long long prod = 1;\n    for (int f = 0; f < M; ++f) {\n        int cnt = fields[f].active_cnt;\n        if (cnt == 0) return false;\n        prod *= cnt;\n        if (prod > 100000) return false;\n    }\n    return true;\n}\n\nvoid guess_and_check() {\n    // compute set of positive cells from best_assign\n    vector<int> pos_cells;\n    for (int f = 0; f < M; ++f) {\n        int pid = best_assign[f];\n        if (pid == -1) continue;\n        for (int cell : fields[f].placements[pid].cells) {\n            pos_cells.push_back(cell);\n        }\n    }\n    sort(pos_cells.begin(), pos_cells.end());\n    pos_cells.erase(unique(pos_cells.begin(), pos_cells.end()), pos_cells.end());\n    cout << \"a \" << pos_cells.size();\n    for (int cell : pos_cells) {\n        cout << \" \" << cell / N << \" \" << cell % N;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    ops++;\n    if (resp == 1) {\n        exit(0); // success, terminate\n    }\n    // else: wrong guess, continue\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n    generate_placements();\n    build_cell_cover();\n    memset(drilled_v, -1, sizeof(drilled_v));\n    ops = 0;\n\n    // Optional: perform row/col divine queries to gather information (can be used for pruning, but we will just ignore the answers)\n    // These are cheap (cost 2*N queries), but they may help later. We'll keep them.\n    // Note: The results are not used in the current pruning, but we can record them if needed.\n    // For now, we skip to avoid complexity. (They might add extra info but also cost extra operations.)\n    // Since we are in the early stage of drilling, we can skip them to reduce branching.\n\n    while (ops < MAX_OPS) {\n        // Try to guess if product of active placements is small\n        if (ops >= 10 && estimate_small()) {\n            if (find_unique()) {\n                guess_and_check();\n                // if guess fails, we continue drilling\n            }\n        }\n        int cell = find_best_cell();\n        if (cell == -1) break; // all cells drilled\n        drill_cell(cell);\n    }\n\n    // Fallback: drill any remaining cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int cell = i * N + j;\n            if (drilled_v[cell] == -1) {\n                drill_cell(cell);\n                if (ops >= MAX_OPS) break;\n            }\n        }\n        if (ops >= MAX_OPS) break;\n    }\n\n    // Now we have exact v for every cell, output answer\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (drilled_v[i * N + j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    cout << \"a \" << ans.size();\n    for (auto [i,j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <cmath>\n\nusing namespace std;\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cin >> a[d][k];\n        }\n    }\n\n    // output rectangles per day\n    // we will store previous day's vertical line positions\n    vector<bool> prev_lines(W + 1, false); // true if a vertical partition line exists at that x\n    // initially day -1: no lines (but L0=0, so we don't compute)\n\n    for (int d = 0; d < D; ++d) {\n        // read demands and sort by descending area for efficient allocation\n        vector<pair<int,int>> items(N); // (demand, original_index)\n        for (int k = 0; k < N; ++k) {\n            items[k] = {a[d][k], k};\n        }\n        sort(items.begin(), items.end(),\n             [](const auto& p, const auto& q) { return p.first > q.first; });\n\n        // greedy allocation of widths (initial widths = 1)\n        vector<int> width(N, 1); // width for each rank (ascending demand later)\n        vector<ll> deficit(N);\n        for (int i = 0; i < N; ++i) {\n            deficit[i] = items[i].first - 1LL * 1 * W; // width=1 area = W\n        }\n        int total_width = N;\n        // while not all width used and there is positive deficit\n        while (total_width < W) {\n            // find index with maximum deficit (still positive or zero)\n            int best = -1;\n            ll best_def = LLONG_MIN;\n            for (int i = 0; i < N; ++i) {\n                if (deficit[i] > best_def) {\n                    best_def = deficit[i];\n                    best = i;\n                }\n            }\n            if (best == -1 || best_def <= 0) break; // all saturated\n            // increase width of best\n            width[best]++;\n            total_width++;\n            deficit[best] = items[best].first - 1LL * width[best] * W;\n        }\n        // if still unused width, allocate to the largest demand (index 0)\n        while (total_width < W) {\n            for (int i = 0; i < N && total_width < W; ++i) {\n                width[i]++;\n                total_width++;\n            }\n        }\n\n        // Now width[i] corresponds to the i-th largest demand.\n        // we need to assign to ranks in ascending demand order: rank r (smallest demand) gets width assigned to largest demand? careful.\n        // Build arrays for ascending order.\n        vector<int> width_asc(N); // width for k-th smallest demand (k=0..N-1)\n        vector<int> orig_index_asc(N);\n        // We have sorted descending, so item[i].second is original index, demand descending.\n        // ascending order: the smallest demand corresponds to i=N-1.\n        // We'll fill width_asc from the end of width array.\n        for (int i = 0; i < N; ++i) {\n            int asc_i = N - 1 - i; // rank in ascending order\n            width_asc[asc_i] = width[i];\n            orig_index_asc[asc_i] = items[i].second;\n        }\n\n        // now compute start x for each ascending rank\n        vector<int> start_x(N, 0);\n        for (int i = 1; i < N; ++i) {\n            start_x[i] = start_x[i-1] + width_asc[i-1];\n        }\n\n        // output rectangle for each original index\n        vector<string> out_lines(N);\n        for (int k = 0; k < N; ++k) {\n            // find rank for this original index\n            int rank = -1;\n            for (int r = 0; r < N; ++r) {\n                if (orig_index_asc[r] == k) {\n                    rank = r;\n                    break;\n                }\n            }\n            int x0 = start_x[rank];\n            int x1 = x0 + width_asc[rank];\n            out_lines[k] = to_string(x0) + \" 0 \" + to_string(x1) + \" \" + to_string(W);\n            // output later per day\n        }\n\n        // compute partition cost with previous day (no need to output, but we could compute for analysis)\n        // We'll just output the rectangles.\n        for (int k = 0; k < N; ++k) {\n            cout << out_lines[k] << '\\n';\n        }\n\n        // update previous lines for next day\n        fill(prev_lines.begin(), prev_lines.end(), false);\n        for (int r = 0; r < N; ++r) {\n            int x = start_x[r] + width_asc[r]; // right edge of each strip\n            if (x < W) {\n                prev_lines[x] = true; // interior vertical line (not on perimeter)\n            }\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\n\nstruct Operation {\n    int m, p, q;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n    // n=9, m=20, k=81 always\n\n    vector<vector<ll>> board(N, vector<ll>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> board[i][j];\n\n    vector<vector<vector<ll>>> stamps(M, vector<vector<ll>>(3, vector<ll>(3)));\n    for (int id = 0; id < M; ++id)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamps[id][i][j];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    // initial score (sum of remainders)\n    ll initial_score = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            initial_score += board[i][j] % MOD;\n\n    pair<ll, vector<Operation>> best = {0, {}};\n    const int TRIALS = 15; // enough time\n\n    // helper lambda: compute gain of applying a stamp (without changing board)\n    auto compute_gain = [&](const vector<vector<ll>>& cur, int m, int p, int q) -> ll {\n        ll gain = 0;\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j) {\n                ll x = cur[p + i][q + j];\n                gain += ((x + stamps[m][i][j]) % MOD) - (x % MOD);\n            }\n        return gain;\n    };\n\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // check time limit\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() > 1900)\n            break;\n\n        vector<vector<ll>> cur = board;\n        vector<Operation> ops;\n        ll cur_score = initial_score;\n\n        // ---------- greedy construction ----------\n        while ((int)ops.size() < K) {\n            vector<pair<ll, Operation>> candidates;\n            ll best_gain = -1e18;\n            for (int mm = 0; mm < M; ++mm) {\n                for (int p = 0; p + 2 < N; ++p) {\n                    for (int q = 0; q + 2 < N; ++q) {\n                        ll gain = compute_gain(cur, mm, p, q);\n                        if (gain > best_gain) {\n                            best_gain = gain;\n                            candidates.clear();\n                            candidates.push_back({gain, {mm, p, q}});\n                        } else if (gain == best_gain && gain > 0) {\n                            candidates.push_back({gain, {mm, p, q}});\n                        }\n                    }\n                }\n            }\n            if (candidates.empty()) break;\n            uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);\n            auto op = candidates[dist(rng)].second;\n            // apply stamp\n            for (int i = 0; i < 3; ++i)\n                for (int j = 0; j < 3; ++j)\n                    cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n            cur_score += best_gain;\n            ops.push_back(op);\n        }\n\n        // ---------- local search ----------\n        bool improved = true;\n        int max_passes = 20;\n        while (improved && max_passes-- > 0) {\n            improved = false;\n\n            // ---- A: replace each operation with the best possible ----\n            vector<int> indices(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                Operation old_op = ops[idx];\n                // remove old_op (subtract stamp)\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[old_op.p + i][old_op.q + j] -= stamps[old_op.m][i][j];\n                // recompute score delta for this 3x3 area\n                // we can recompute whole score quickly but we just recompute the area effect\n                ll old_area_sum = 0, new_area_sum = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        // old before removal = (cur after removal) + stamp value\n                        ll after = cur[old_op.p + i][old_op.q + j];\n                        old_area_sum += (after + stamps[old_op.m][i][j]) % MOD;\n                        new_area_sum += after % MOD;\n                    }\n                ll delta = new_area_sum - old_area_sum; // negative if removal is good\n                cur_score += delta;\n\n                // find best stamp to add now\n                ll best_gain = -1e18;\n                Operation best_op;\n                for (int mm = 0; mm < M; ++mm) {\n                    for (int p = 0; p + 2 < N; ++p) {\n                        for (int q = 0; q + 2 < N; ++q) {\n                            ll gain = compute_gain(cur, mm, p, q);\n                            if (gain > best_gain) {\n                                best_gain = gain;\n                                best_op = {mm, p, q};\n                            }\n                        }\n                    }\n                }\n                if (best_gain > 0 && best_gain > -delta) {\n                    // apply best_op\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[best_op.p + i][best_op.q + j] += stamps[best_op.m][i][j];\n                    cur_score += best_gain;\n                    ops[idx] = best_op;\n                    improved = true;\n                } else {\n                    // restore old_op\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[old_op.p + i][old_op.q + j] += stamps[old_op.m][i][j];\n                    cur_score -= delta; // revert the score change\n                }\n            }\n\n            // ---- B: remove operations that have negative contribution ----\n            indices.resize(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                if (ops.empty()) break;\n                Operation op = ops[idx];\n                // remove\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[op.p + i][op.q + j] -= stamps[op.m][i][j];\n                ll old_area = 0, new_area = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        ll after = cur[op.p + i][op.q + j];\n                        old_area += (after + stamps[op.m][i][j]) % MOD;\n                        new_area += after % MOD;\n                    }\n                ll delta = new_area - old_area;\n                cur_score += delta;\n                if (delta > 0) { // removal increased total score\n                    ops.erase(ops.begin() + idx);\n                    improved = true;\n                } else {\n                    // restore\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n                    cur_score -= delta;\n                }\n            }\n\n            // ---- C: fill empty slots (if any) with greedy addition ----\n            while ((int)ops.size() < K) {\n                ll best_gain = -1e18;\n                Operation best_op;\n                for (int mm = 0; mm < M; ++mm) {\n                    for (int p = 0; p + 2 < N; ++p) {\n                        for (int q = 0; q + 2 < N; ++q) {\n                            ll gain = compute_gain(cur, mm, p, q);\n                            if (gain > best_gain) {\n                                best_gain = gain;\n                                best_op = {mm, p, q};\n                            }\n                        }\n                    }\n                }\n                if (best_gain <= 0) break;\n                // apply best\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[best_op.p + i][best_op.q + j] += stamps[best_op.m][i][j];\n                cur_score += best_gain;\n                ops.push_back(best_op);\n                improved = true;\n            }\n        }\n\n        // keep best solution\n        if (cur_score > best.first) {\n            best = {cur_score, ops};\n        }\n    }\n\n    // output answer\n    cout << best.second.size() << \"\\n\";\n    for (const auto& op : best.second) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nint A[N][N];\nint targetRow[25];   // targetRow[num] = num / 5\n\nint craneR = 0, craneC = 0;\nbool holding = false;\nint heldContainer = -1;\n\nint grid[N][N];          // -1 = empty, otherwise container number\nint gateNextIdx[N];       // next index in A[i] to appear\nint gateContainer[N];     // current container at the gate (row,0), -1 if none\n\nvoid placeContainer(int num, int r, int c) {\n    grid[r][c] = num;\n}\n\nvoid removeContainer(int r, int c) {\n    grid[r][c] = -1;\n}\n\n// Manhattan distance (ignoring obstacles)\nint dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// Decide direction (U/D/L/R) to move from (cr,cc) towards (tr,tc),\n// preferring to avoid standing on a gate cell if we are not going to pick immediately.\nchar direction(int cr, int cc, int tr, int tc) {\n    // Prefer vertical movement if far, else horizontal\n    if (cr < tr) return 'D';\n    if (cr > tr) return 'U';\n    if (cc < tc) return 'R';\n    if (cc > tc) return 'L';\n    return '.'; // already at target\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummyN;\n    cin >> dummyN;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Precompute targetRow\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int num = A[i][j];\n            targetRow[num] = num / N;\n        }\n    }\n\n    // Initialize grid, gates\n    memset(grid, -1, sizeof(grid));\n    memset(gateNextIdx, 0, sizeof(gateNextIdx));\n    memset(gateContainer, -1, sizeof(gateContainer));\n\n    vector<string> out(N);  // output strings for each crane\n\n    // Turn 1: free the (0,0) gate and bomb all small cranes\n    out[0] += 'R';          // large crane moves to (0,1)\n    craneC = 1;\n    for (int i = 1; i < N; ++i) {\n        out[i] += 'B';      // small cranes bombed\n    }\n\n    // Main loop (turn = 2 ... )\n    for (int turn = 2; turn <= 10000; ++turn) {\n        // Step 1: place new containers at receiving gates\n        for (int i = 0; i < N; ++i) {\n            if (gateContainer[i] == -1 && gateNextIdx[i] < N) {\n                int num = A[i][gateNextIdx[i]++];\n                gateContainer[i] = num;\n                placeContainer(num, i, 0);\n            }\n        }\n\n        // Step 2: decide action for the large crane\n        char action = '.';\n        if (!holding) {\n            // Find the nearest gate that has a container\n            int bestDist = 1e9, bestRow = -1;\n            for (int r = 0; r < N; ++r) {\n                if (gateContainer[r] != -1) {\n                    int d = dist(craneR, craneC, r, 0);\n                    if (d < bestDist) {\n                        bestDist = d;\n                        bestRow = r;\n                    }\n                }\n            }\n            if (bestRow != -1) {\n                // Move towards that gate, or pick if already there\n                if (craneR == bestRow && craneC == 0) {\n                    // pick the container\n                    action = 'P';\n                } else {\n                    action = direction(craneR, craneC, bestRow, 0);\n                }\n            } else {\n                // No gate has a container: wait at current position (or move to center)\n                // Move towards (2,2) to stay out of way\n                if (craneR != 2 || craneC != 2) {\n                    action = direction(craneR, craneC, 2, 2);\n                }\n            }\n        } else {\n            // Holding a container: go to (targetRow[heldContainer], 4)\n            int tgtR = targetRow[heldContainer];\n            int tgtC = 4;\n            if (craneR == tgtR && craneC == tgtC) {\n                action = 'Q';\n            } else {\n                action = direction(craneR, craneC, tgtR, tgtC);\n            }\n        }\n\n        // Execute action\n        if (action == 'P') {\n            int num = grid[craneR][craneC];\n            if (num != -1) {\n                holding = true;\n                heldContainer = num;\n                int row = craneR;   // which gate we picked from\n                removeContainer(craneR, craneC);\n                gateContainer[row] = -1;  // gate becomes empty\n            } else {\n                action = '.'; // safety\n            }\n        } else if (action == 'Q') {\n            if (holding) {\n                int num = heldContainer;\n                grid[craneR][craneC] = num;\n                holding = false;\n                heldContainer = -1;\n            } else {\n                action = '.';\n            }\n        } else if (action == 'U' && craneR > 0) {\n            craneR--;\n        } else if (action == 'D' && craneR < N-1) {\n            craneR++;\n        } else if (action == 'L' && craneC > 0) {\n            craneC--;\n        } else if (action == 'R' && craneC < N-1) {\n            craneC++;\n        }\n\n        // Record the action (large crane)\n        out[0] += action;\n        // The bombed small cranes do nothing\n        for (int i = 1; i < N; ++i) {\n            out[i] += '.';\n        }\n\n        // Step 3: dispatch containers at right edge\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][4] != -1) {\n                // Container is dispatched, remove from grid\n                grid[i][4] = -1;\n                // We don't track dispatch order, so just ignore.\n            }\n        }\n\n        // Check if all containers have been dispatched (i.e., grid empty and no holding and no gate containers)\n        bool allDone = true;\n        if (holding) allDone = false;\n        else {\n            for (int r = 0; r < N; ++r) {\n                if (gateNextIdx[r] < N || gateContainer[r] != -1) {\n                    allDone = false;\n                    break;\n                }\n                for (int c = 0; c < N; ++c) {\n                    if (grid[r][c] != -1) {\n                        allDone = false;\n                        break;\n                    }\n                }\n            }\n        }\n        if (allDone) break;\n    }\n\n    // Pad all strings to the same length\n    size_t maxLen = 0;\n    for (int i = 0; i < N; ++i) {\n        maxLen = max(maxLen, out[i].size());\n    }\n    for (int i = 0; i < N; ++i) {\n        while (out[i].size() < maxLen) out[i] += '.';\n        cout << out[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\nusing ll = long long;\n\nstruct Node {\n    int x, y, delta;\n};\n\nint N;\nvector<Node> nodes;\nvector<vector<int>> dist;\nvector<int> dist_start;\nint M;\n\n// Compute cost for whole order (used rarely now)\nll compute_cost(const vector<int>& order) {\n    ll cost = 0;\n    ll load = 0;\n    cost += (100 + load) * dist_start[order[0]];\n    load += nodes[order[0]].delta;\n    for (size_t i = 1; i < order.size(); ++i) {\n        int prev = order[i-1];\n        int cur = order[i];\n        cost += (100 + load) * dist[prev][cur];\n        load += nodes[cur].delta;\n    }\n    return cost;\n}\n\n// Check feasibility (prefix sums >= 0)\nbool feasible(const vector<int>& order) {\n    int load = 0;\n    for (int idx : order) {\n        load += nodes[idx].delta;\n        if (load < 0) return false;\n    }\n    return true;\n}\n\n// Greedy initial order (distance only with feasibility)\nvector<int> greedy_initial() {\n    vector<int> order;\n    order.reserve(M);\n    vector<bool> used(M, false);\n    int load = 0;\n    for (int step = 0; step < M; ++step) {\n        int best = -1;\n        int best_dist = 1e9;\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            if (nodes[i].delta < 0 && load < -nodes[i].delta) continue;\n            int d = (step == 0) ? dist_start[i] : dist[order.back()][i];\n            if (d < best_dist) {\n                best_dist = d;\n                best = i;\n            }\n        }\n        if (best == -1) {\n            for (int i = 0; i < M; ++i) if (!used[i]) { best = i; break; }\n        }\n        order.push_back(best);\n        used[best] = true;\n        load += nodes[best].delta;\n    }\n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ---------- Input ----------\n    cin >> N;\n    vector<vector<int>> height(N, vector<int>(N));\n    ll base = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> height[i][j];\n            base += abs(height[i][j]);\n            if (height[i][j] != 0) {\n                nodes.push_back({i, j, height[i][j]});\n            }\n        }\n    }\n    M = nodes.size();\n    if (M == 0) return 0;\n\n    // Precompute distances\n    dist.assign(M, vector<int>(M));\n    dist_start.assign(M, 0);\n    for (int i = 0; i < M; ++i) {\n        dist_start[i] = nodes[i].x + nodes[i].y;\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            dist[i][j] = abs(nodes[i].x - nodes[j].x) + abs(nodes[i].y - nodes[j].y);\n        }\n    }\n\n    // ---------- Greedy initial solution ----------\n    vector<int> order = greedy_initial();\n    ll best_cost = compute_cost(order);\n    vector<int> best_order = order;\n    vector<int> cur_order = order;\n    ll cur_cost = best_cost;\n\n    // ---------- Simulated Annealing ----------\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    const double T_start = 1e6;\n    const double T_end = 0.1;\n    const int iterations = 3000000; // 3 million iterations\n    double T = T_start;\n    auto start_time = chrono::steady_clock::now();\n\n    for (int iter = 0; iter < iterations; ++iter) {\n        // Time check\n        if (iter % 500 == 0) {\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n                chrono::steady_clock::now() - start_time).count();\n            if (elapsed > 1950) break;\n        }\n\n        // Generate neighbor\n        vector<int> new_order = cur_order;\n        int type = rng() % 3;\n        if (type == 0) {\n            // Swap two random positions\n            int i = uniform_int_distribution<int>(0, M-1)(rng);\n            int j = uniform_int_distribution<int>(0, M-1)(rng);\n            if (i == j) continue;\n            swap(new_order[i], new_order[j]);\n        } else if (type == 1) {\n            // Reverse random segment\n            int l = uniform_int_distribution<int>(0, M-1)(rng);\n            int r = uniform_int_distribution<int>(0, M-1)(rng);\n            if (l > r) swap(l, r);\n            reverse(new_order.begin() + l, new_order.begin() + r + 1);\n        } else {\n            // Relocate (remove and insert)\n            int i = uniform_int_distribution<int>(0, M-1)(rng);\n            int val = new_order[i];\n            new_order.erase(new_order.begin() + i);\n            int pos = uniform_int_distribution<int>(0, M-2)(rng);\n            new_order.insert(new_order.begin() + pos, val);\n        }\n\n        if (!feasible(new_order)) continue;\n\n        // Compute cost via incremental update? Here we recompute fully (O(M)) for simplicity\n        ll new_cost = compute_cost(new_order);\n        double delta = new_cost - cur_cost;\n        if (delta < 0 ||\n            exp(-delta / T) > uniform_real_distribution<double>(0.0, 1.0)(rng)) {\n            cur_order = move(new_order);\n            cur_cost = new_cost;\n            if (new_cost < best_cost) {\n                best_cost = new_cost;\n                best_order = cur_order;\n            }\n        }\n\n        // Cool down\n        double progress = (double)iter / iterations;\n        T = T_start * pow(T_end / T_start, progress);\n    }\n\n    // ---------- 2-opt local search ----------\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        if (chrono::duration_cast<chrono::milliseconds>(\n                chrono::steady_clock::now() - start_time).count() > 1950) break;\n        for (int i = 0; i < M - 2; ++i) {\n            for (int j = i + 2; j < M; ++j) {\n                vector<int> test = best_order;\n                reverse(test.begin() + i + 1, test.begin() + j + 1);\n                if (!feasible(test)) continue;\n                ll new_cost = compute_cost(test);\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_order = test;\n                    improved = true;\n                }\n            }\n            if (chrono::duration_cast<chrono::milliseconds>(\n                    chrono::steady_clock::now() - start_time).count() > 1950) break;\n        }\n    }\n\n    // ---------- Output ----------\n    vector<string> ops;\n    int cx = 0, cy = 0;\n    for (int idx : best_order) {\n        int nx = nodes[idx].x;\n        int ny = nodes[idx].y;\n        while (cx < nx) { ops.push_back(\"D\"); cx++; }\n        while (cx > nx) { ops.push_back(\"U\"); cx--; }\n        while (cy < ny) { ops.push_back(\"R\"); cy++; }\n        while (cy > ny) { ops.push_back(\"L\"); cy--; }\n        int d = nodes[idx].delta;\n        if (d > 0) ops.push_back(\"+\" + to_string(d));\n        else if (d < 0) ops.push_back(\"-\" + to_string(-d));\n    }\n    for (const string& s : ops) cout << s << \"\\n\";\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <unordered_set>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int SEED_COUNT = 2 * N * (N - 1); // 60\n    const int GRID_SIZE = N * N;           // 36\n\n    vector<vector<int>> X(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> X[i][j];\n        }\n    }\n\n    for (int turn = 0; turn < T; ++turn) {\n        // 1. Evaluate current seeds\n        vector<int> sumX(SEED_COUNT, 0);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            sumX[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // best overall seed (max sum)\n        int bestIdx = max_element(sumX.begin(), sumX.end()) - sumX.begin();\n\n        // per\u2011dimension best seeds\n        vector<int> dimMax(M, -1), dimIdx(M, -1);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int l = 0; l < M; ++l) {\n                if (X[i][l] > dimMax[l]) {\n                    dimMax[l] = X[i][l];\n                    dimIdx[l] = i;\n                }\n            }\n        }\n\n        // 2. Build the set of elite seeds (best overall + per\u2011dimension best)\n        unordered_set<int> eliteSet;\n        eliteSet.insert(bestIdx);\n        for (int l = 0; l < M; ++l) {\n            eliteSet.insert(dimIdx[l]);\n        }\n        vector<int> elite(eliteSet.begin(), eliteSet.end());\n\n        // 3. Select 36 seeds: all elites + top sum among the rest\n        vector<bool> used(SEED_COUNT, false);\n        for (int idx : elite) used[idx] = true;\n        vector<int> additional;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (!used[i]) additional.push_back(i);\n        }\n        sort(additional.begin(), additional.end(), [&](int a, int b) {\n            return sumX[a] > sumX[b];\n        });\n        int needFromAdd = GRID_SIZE - (int)elite.size();\n        // selected = elite + first needFromAdd of additional\n        vector<int> selected = elite;\n        selected.insert(selected.end(), additional.begin(), additional.begin() + needFromAdd);\n\n        // 4. Partition into interior (16) and border (20) seeds\n        int interiorSize = (N - 2) * (N - 2); // 16\n        int eliteSize = (int)elite.size();\n        int takeFromAdd = min(interiorSize - eliteSize, needFromAdd);\n        vector<int> interiorSeeds(elite.begin(), elite.end());\n        interiorSeeds.insert(interiorSeeds.end(), additional.begin(), additional.begin() + takeFromAdd);\n        // borderSeeds: the rest of selected\n        vector<int> borderSeeds(additional.begin() + takeFromAdd, additional.begin() + needFromAdd);\n        // sanity: (int)selected.size() == GRID_SIZE\n        // (int)interiorSeeds.size() == interiorSize\n        // borderSeeds.size() == GRID_SIZE - interiorSize\n\n        // 5. Build the placement grid\n        vector<vector<int>> A(N, vector<int>(N, -1));\n\n        // 5a. Define interior positions (1,\u2026,N-2)\n        vector<pair<int,int>> interiorPos;\n        for (int i = 1; i <= N-2; ++i)\n            for (int j = 1; j <= N-2; ++j)\n                interiorPos.push_back({i, j});\n\n        // 5b. Place the best overall at the centre (2,2)\n        int centre_i = 2, centre_j = 2; // 0\u2011based, inside interior\n        A[centre_i][centre_j] = bestIdx;\n\n        // Remove bestIdx from interiorSeeds (it's the first one)\n        auto it = find(interiorSeeds.begin(), interiorSeeds.end(), bestIdx);\n        if (it != interiorSeeds.end()) interiorSeeds.erase(it);\n        // Now interiorSeeds has size = interiorSize - 1 = 15\n\n        // Compute complement scores with bestIdx\n        vector<pair<int,int>> compScores; // (score, seedIdx)\n        for (int idx : interiorSeeds) {\n            int score = 0;\n            for (int l = 0; l < M; ++l) {\n                score += max(X[bestIdx][l], X[idx][l]);\n            }\n            compScores.push_back({-score, idx}); // negative for descending sort\n        }\n        sort(compScores.begin(), compScores.end());\n        // Top 4 become neighbours\n        vector<pair<int,int>> neighPos = {{centre_i-1, centre_j},\n                                          {centre_i+1, centre_j},\n                                          {centre_i, centre_j-1},\n                                          {centre_i, centre_j+1}};\n        unordered_set<int> usedInterior;\n        usedInterior.insert(bestIdx);\n        for (int k = 0; k < 4; ++k) {\n            int idx = compScores[k].second;\n            int ni = neighPos[k].first, nj = neighPos[k].second;\n            A[ni][nj] = idx;\n            usedInterior.insert(idx);\n        }\n\n        // 5d. Assign remaining interior seeds to remaining interior positions\n        // Remaining interior positions (exclude centre and neighbours)\n        vector<pair<int,int>> restInteriorPos;\n        for (auto [i,j] : interiorPos) {\n            if (i == centre_i && j == centre_j) continue;\n            bool isNeigh = false;\n            for (auto [ni,nj] : neighPos) if (ni==i && nj==j) { isNeigh = true; break; }\n            if (!isNeigh) restInteriorPos.push_back({i,j});\n        }\n        // Get the remaining seeds (not used)\n        vector<int> restSeeds;\n        for (int idx : interiorSeeds) {\n            if (!usedInterior.count(idx)) restSeeds.push_back(idx);\n        }\n        // restSeeds.size() should be 11\n        for (size_t k = 0; k < restInteriorPos.size(); ++k) {\n            A[restInteriorPos[k].first][restInteriorPos[k].second] = restSeeds[k];\n        }\n\n        // 5e. Fill border cells with borderSeeds\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (A[i][j] == -1) {\n                    A[i][j] = borderSeeds.back();\n                    borderSeeds.pop_back();\n                }\n            }\n        }\n\n        // 6. Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << A[i][j];\n                if (j < N-1) cout << ' ';\n            }\n            cout << '\\n';\n        }\n        cout << flush;\n\n        // 7. Read the new generation of seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<string> s_str, t_str;\nvector<vector<bool>> source, target;\n\nint root_x = 0, root_y = 0;\nint V_used;\nvector<int> parent, length;\nvector<int> dir;        // 0:right, 1:down, 2:left, 3:up\nvector<bool> holding;\n\nvector<string> commands;\n\nconst vector<pair<int,int>> offset_dir = {{0,1}, {1,0}, {0,-1}, {-1,0}};\n\nvoid rotate_leaf(int i, char c) {\n    if (c == 'R') dir[i] = (dir[i] + 1) % 4;\n    else if (c == 'L') dir[i] = (dir[i] + 3) % 4;\n}\n\n// get all four possible positions for a leaf of length L from (rx,ry)\nvector<pair<int,int>> get_positions(int rx, int ry, int L) {\n    vector<pair<int,int>> res;\n    for (int d = 0; d < 4; ++d) {\n        int nx = rx + offset_dir[d].first * L;\n        int ny = ry + offset_dir[d].second * L;\n        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n            res.emplace_back(nx, ny);\n        }\n    }\n    return res;\n}\n\n// Kuhn DFS for bipartite matching\nbool dfs(int u, const vector<vector<int>>& adj, vector<int>& matchR, vector<bool>& visited) {\n    for (int v : adj[u]) {\n        if (!visited[v]) {\n            visited[v] = true;\n            if (matchR[v] == -1 || dfs(matchR[v], adj, matchR, visited)) {\n                matchR[v] = u;\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n    s_str.resize(N);\n    t_str.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n\n    source.assign(N, vector<bool>(N, false));\n    target.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') source[i][j] = true;\n            if (t_str[i][j] == '1') target[i][j] = true;\n        }\n    }\n\n    // ---- design tree (star with lengths 1..V-1) ----\n    V_used = V;\n    parent.assign(V_used, 0);\n    length.assign(V_used, 0);\n    for (int i = 1; i < V_used; ++i) {\n        parent[i] = 0;\n        length[i] = i;\n    }\n\n    cout << V_used << '\\n';\n    for (int i = 1; i < V_used; ++i) {\n        cout << parent[i] << ' ' << length[i] << '\\n';\n    }\n    root_x = 0; root_y = 0;\n    cout << root_x << ' ' << root_y << '\\n';\n\n    dir.assign(V_used, 0);\n    holding.assign(V_used, false);\n\n    int total_source = M;\n    int total_target = M;\n    int turn_count = 0;\n    const int MAX_TURNS = 100000;\n\n    while ((total_source > 0 || total_target > 0) && turn_count < MAX_TURNS) {\n        // find best root position (max immediate actions, then min distance)\n        int best_cnt = -1;\n        int best_rx = -1, best_ry = -1;\n        for (int rx = 0; rx < N; ++rx) {\n            for (int ry = 0; ry < N; ++ry) {\n                int cnt = 0;\n                for (int i = 1; i < V_used; ++i) {\n                    int L = length[i];\n                    auto pos = get_positions(rx, ry, L);\n                    for (auto [cx, cy] : pos) {\n                        if (!holding[i] && source[cx][cy] && !target[cx][cy]) { cnt++; break; }\n                        if ( holding[i] && target[cx][cy] && !source[cx][cy]) { cnt++; break; }\n                    }\n                }\n                if (cnt > best_cnt) {\n                    best_cnt = cnt;\n                    best_rx = rx;\n                    best_ry = ry;\n                } else if (cnt == best_cnt) {\n                    int dist = abs(rx - root_x) + abs(ry - root_y);\n                    int best_dist = abs(best_rx - root_x) + abs(best_ry - root_y);\n                    if (dist < best_dist) {\n                        best_rx = rx; best_ry = ry;\n                    }\n                }\n            }\n        }\n        if (best_cnt == 0) break; // no valid actions left (should not happen)\n\n        // move root to best position\n        while ((root_x != best_rx || root_y != best_ry) && turn_count < MAX_TURNS) {\n            char move_char = '.';\n            int dx = best_rx - root_x, dy = best_ry - root_y;\n            if (dx > 0) { move_char = 'D'; root_x++; }\n            else if (dx < 0) { move_char = 'U'; root_x--; }\n            else if (dy > 0) { move_char = 'R'; root_y++; }\n            else if (dy < 0) { move_char = 'L'; root_y--; }\n\n            string rot(V_used - 1, '.');\n            string action(V_used, '.');\n            commands.push_back(move_char + rot + action);\n            turn_count++;\n        }\n        if (turn_count >= MAX_TURNS) break;\n\n        // perform actions at current root until no more matches\n        while (turn_count < MAX_TURNS) {\n            // build bipartite graph: leaves -> cells\n            map<pair<int,int>, int> cell_id;\n            vector<pair<int,int>> id_cell;\n            vector<vector<int>> adj(V_used);\n\n            for (int i = 1; i < V_used; ++i) {\n                int L = length[i];\n                auto pos = get_positions(best_rx, best_ry, L);\n                for (auto [cx, cy] : pos) {\n                    bool ok = false;\n                    if (!holding[i] && source[cx][cy] && !target[cx][cy]) ok = true;\n                    if ( holding[i] && target[cx][cy] && !source[cx][cy]) ok = true;\n                    if (ok) {\n                        auto key = make_pair(cx, cy);\n                        if (cell_id.find(key) == cell_id.end()) {\n                            cell_id[key] = id_cell.size();\n                            id_cell.push_back(key);\n                        }\n                        adj[i].push_back(cell_id[key]);\n                    }\n                }\n            }\n\n            int item_cnt = id_cell.size();\n            vector<int> matchR(item_cnt, -1);\n            int matching = 0;\n            for (int i = 1; i < V_used; ++i) {\n                vector<bool> visited(item_cnt, false);\n                if (dfs(i, adj, matchR, visited)) matching++;\n            }\n            if (matching == 0) break;\n\n            // assign cells to leaves\n            vector<pair<int,int>> leaf_target(V_used, {-1, -1});\n            for (int v = 0; v < item_cnt; ++v) {\n                if (matchR[v] != -1) {\n                    leaf_target[matchR[v]] = id_cell[v];\n                }\n            }\n\n            // compute target directions for matched leaves\n            vector<int> target_dir(V_used, -1);\n            for (int i = 1; i < V_used; ++i) {\n                auto [cx, cy] = leaf_target[i];\n                if (cx == -1) continue;\n                int L = length[i];\n                int dx = cx - best_rx, dy = cy - best_ry;\n                if (dx == 0 && dy == L) target_dir[i] = 0;\n                else if (dx == L && dy == 0) target_dir[i] = 1;\n                else if (dx == 0 && dy == -L) target_dir[i] = 2;\n                else if (dx == -L && dy == 0) target_dir[i] = 3;\n            }\n\n            // rotate leaves to target directions\n            while (true) {\n                if (turn_count >= MAX_TURNS) break;\n                bool all_aligned = true;\n                string rot = \"\";\n                for (int i = 1; i < V_used; ++i) {\n                    if (target_dir[i] == -1) { rot += '.'; continue; }\n                    int cur = dir[i];\n                    int tgt = target_dir[i];\n                    int diff = (tgt - cur + 4) % 4;\n                    char c = '.';\n                    if (diff == 1) c = 'R';\n                    else if (diff == 2) { c = 'R'; } // two rotations: can do R twice, but one turn only one rotation? Actually we can rotate by 180? The operation allows rotating by 90 degrees either direction. Two rotations would require two turns. So we need to do one rotation per turn. So we can only rotate 90 or -90 each turn. For diff==2, we need two turns. But our loop will continue. However, the direction change is done in the loop by repeatedly applying rotations. So we need to handle diff==2 as requiring two separate turns. Our code currently sets c='R' for diff==2, which rotates 90 clockwise, but we need to rotate 180. Better to choose any single rotation; the loop will then check again. So it's fine.\n                    else if (diff == 3) c = 'L';\n                    rot += c;\n                    if (c != '.') all_aligned = false;\n                    rotate_leaf(i, c);\n                }\n                if (all_aligned) break;\n                string action(V_used, '.');\n                commands.push_back('.' + rot + action);\n                turn_count++;\n            }\n            if (turn_count >= MAX_TURNS) break;\n\n            // action turn: pick or place\n            string rot(V_used - 1, '.');\n            string action = \".\";\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) action += 'P';\n                else action += '.';\n            }\n            commands.push_back('.' + rot + action);\n            turn_count++;\n\n            // update state\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) {\n                    auto [cx, cy] = leaf_target[i];\n                    if (!holding[i]) {\n                        source[cx][cy] = false;\n                        holding[i] = true;\n                        total_source--;\n                    } else {\n                        target[cx][cy] = false;\n                        holding[i] = false;\n                        total_target--;\n                    }\n                }\n            }\n            if (total_source == 0 && total_target == 0) break;\n        }\n    }\n\n    // output all commands\n    for (const string& cmd : commands) {\n        cout << cmd << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing pii = pair<int, int>;\n\nconst int COORD_MAX = 100000;\nconst int PERIMETER_LIMIT = 400000;\n\n// ---------- geometry helpers ----------\nint countInRect(const vector<pii>& pts, int x1, int x2, int y1, int y2) {\n    int cnt = 0;\n    for (auto [x, y] : pts)\n        if (x1 <= x && x <= x2 && y1 <= y && y <= y2) ++cnt;\n    return cnt;\n}\n\nint evaluate(int x1, int x2, int y1, int y2,\n             const vector<pii>& mol, const vector<pii>& sol) {\n    if (x1 > x2 || y1 > y2) return -1;\n    int perim = 2 * (x2 - x1 + y2 - y1);\n    if (perim > PERIMETER_LIMIT) return -1;\n    int a = countInRect(mol, x1, x2, y1, y2);\n    int b = countInRect(sol, x1, x2, y1, y2);\n    return max(0, a - b + 1);\n}\n\n// ---------- tile\u2011based best rectangle ----------\npair<int,pii> bestTileRectangle(const vector<pii>& mol,\n                                const vector<pii>& sol,\n                                int S) {\n    int T = COORD_MAX / S + 1;\n    vector<vector<int>> weight(T, vector<int>(T, 0));\n    for (auto [x, y] : mol) weight[x/S][y/S]++;\n    for (auto [x, y] : sol) weight[x/S][y/S]--;\n\n    // prefix sum\n    vector<vector<int>> pref(T+1, vector<int>(T+1, 0));\n    for (int i=0; i<T; ++i)\n        for (int j=0; j<T; ++j)\n            pref[i+1][j+1] = pref[i][j+1] + pref[i+1][j] - pref[i][j] + weight[i][j];\n\n    int best_sum = -1e9;\n    int best_r1 = -1, best_r2 = -1, best_c1 = -1, best_c2 = -1;\n\n    for (int r1=0; r1<T; ++r1) {\n        vector<int> colSum(T, 0);\n        for (int r2=r1; r2<T; ++r2) {\n            for (int c=0; c<T; ++c) colSum[c] += weight[r2][c];\n            int dy = r2 - r1 + 1;\n            int max_dx = PERIMETER_LIMIT / (2*S) - dy;\n            if (max_dx <= 0) continue;\n            max_dx = min(max_dx, T);\n            // max subarray sum with length <= max_dx\n            vector<int> prefCol(T+1, 0);\n            for (int i=0; i<T; ++i) prefCol[i+1] = prefCol[i] + colSum[i];\n            deque<int> dq;\n            int local_best = -1e9;\n            int lc1=-1, lc2=-1;\n            for (int i=0; i<=T; ++i) {\n                while (!dq.empty() && dq.front() < i - max_dx) dq.pop_front();\n                if (!dq.empty()) {\n                    int val = prefCol[i] - prefCol[dq.front()];\n                    if (val > local_best) {\n                        local_best = val;\n                        lc1 = dq.front();\n                        lc2 = i-1;\n                    }\n                }\n                while (!dq.empty() && prefCol[dq.back()] >= prefCol[i]) dq.pop_back();\n                dq.push_back(i);\n            }\n            if (local_best > best_sum) {\n                best_sum = local_best;\n                best_r1 = r1; best_r2 = r2; best_c1 = lc1; best_c2 = lc2;\n            }\n        }\n    }\n    return {best_sum, {best_r1, best_r2*10000 + best_c1*100 + best_c2}};\n}\n\nvoid tightenToMackerels(const vector<pii>& mol,\n                        int tile_x1, int tile_x2, int tile_y1, int tile_y2,\n                        int &x1, int &x2, int &y1, int &y2) {\n    int min_x = COORD_MAX+1, max_x = -1, min_y = COORD_MAX+1, max_y = -1;\n    bool found = false;\n    for (auto [x, y] : mol) {\n        if (x >= tile_x1 && x <= tile_x2 && y >= tile_y1 && y <= tile_y2) {\n            min_x = min(min_x, x); max_x = max(max_x, x);\n            min_y = min(min_y, y); max_y = max(max_y, y);\n            found = true;\n        }\n    }\n    if (found) {\n        x1 = min_x; x2 = max_x; y1 = min_y; y2 = max_y;\n        if (x1 == x2) x2 = min(COORD_MAX, x2+1);\n        if (y1 == y2) y2 = min(COORD_MAX, y2+1);\n    } else {\n        // fallback \u2013 should not happen if tile rectangle has positive sum\n        auto [mx, my] = mol[0];\n        x1 = mx; x2 = min(COORD_MAX, mx+1);\n        y1 = my; y2 = min(COORD_MAX, my+1);\n    }\n}\n\n// ---------- local search on fish coordinates ----------\nvoid localSearch(const vector<pii>& mol, const vector<pii>& sol,\n                 int &x1, int &x2, int &y1, int &y2) {\n    // collect all distinct coordinates of fish + borders\n    set<int> xs_set, ys_set;\n    xs_set.insert(0); xs_set.insert(COORD_MAX);\n    ys_set.insert(0); ys_set.insert(COORD_MAX);\n    for (auto [x, y] : mol) { xs_set.insert(x); ys_set.insert(y); }\n    for (auto [x, y] : sol) { xs_set.insert(x); ys_set.insert(y); }\n    vector<int> xs(xs_set.begin(), xs_set.end());\n    vector<int> ys(ys_set.begin(), ys_set.end());\n\n    auto get_left = [&](int cur) {\n        auto it = lower_bound(xs.begin(), xs.end(), cur);\n        return it == xs.begin() ? -1 : *prev(it);\n    };\n    auto get_right = [&](int cur) {\n        auto it = upper_bound(xs.begin(), xs.end(), cur);\n        return it == xs.end() ? -1 : *it;\n    };\n    auto get_down = [&](int cur) {\n        auto it = lower_bound(ys.begin(), ys.end(), cur);\n        return it == ys.begin() ? -1 : *prev(it);\n    };\n    auto get_up = [&](int cur) {\n        auto it = upper_bound(ys.begin(), ys.end(), cur);\n        return it == ys.end() ? -1 : *it;\n    };\n\n    bool improved = true;\n    int iter = 0;\n    while (improved && iter < 200) {\n        ++iter;\n        improved = false;\n        int cur_score = evaluate(x1, x2, y1, y2, mol, sol);\n        if (cur_score <= 0) break;  // no hope, fallback later\n        // expand left\n        int cand = get_left(x1);\n        if (cand >= 0 && evaluate(cand, x2, y1, y2, mol, sol) > cur_score) {\n            x1 = cand; improved = true; continue;\n        }\n        // expand right\n        cand = get_right(x2);\n        if (cand >= 0 && evaluate(x1, cand, y1, y2, mol, sol) > cur_score) {\n            x2 = cand; improved = true; continue;\n        }\n        // expand down\n        cand = get_down(y1);\n        if (cand >= 0 && evaluate(x1, x2, cand, y2, mol, sol) > cur_score) {\n            y1 = cand; improved = true; continue;\n        }\n        // expand up\n        cand = get_up(y2);\n        if (cand >= 0 && evaluate(x1, x2, y1, cand, mol, sol) > cur_score) {\n            y2 = cand; improved = true; continue;\n        }\n        // shrink left\n        cand = get_right(x1);\n        if (cand >= 0 && cand <= x2 && evaluate(cand, x2, y1, y2, mol, sol) > cur_score) {\n            x1 = cand; improved = true; continue;\n        }\n        // shrink right\n        cand = get_left(x2);\n        if (cand >= 0 && cand >= x1 && evaluate(x1, cand, y1, y2, mol, sol) > cur_score) {\n            x2 = cand; improved = true; continue;\n        }\n        // shrink down\n        cand = get_up(y1);\n        if (cand >= 0 && cand <= y2 && evaluate(x1, x2, cand, y2, mol, sol) > cur_score) {\n            y1 = cand; improved = true; continue;\n        }\n        // shrink up\n        cand = get_down(y2);\n        if (cand >= 0 && cand >= y1 && evaluate(x1, x2, y1, cand, mol, sol) > cur_score) {\n            y2 = cand; improved = true; continue;\n        }\n    }\n}\n\n// ---------- safe fallback (1x1 cell containing exactly one mackerel and no sardine) ----------\nbool safeTinyRectangle(const vector<pii>& mol, const vector<pii>& sol,\n                       int &x1, int &x2, int &y1, int &y2) {\n    // test each mackerel; check a 1\u00d71 cell [mx, mx+1]\u00d7[my, my+1]\n    for (auto [mx, my] : mol) {\n        int cntS = countInRect(sol, mx, mx+1, my, my+1);\n        if (cntS == 0) {\n            x1 = mx; x2 = min(COORD_MAX, mx+1);\n            y1 = my; y2 = min(COORD_MAX, my+1);\n            return true;\n        }\n    }\n    // if none, just take first mackerel (will contain the mackerel plus possibly sardines -> score may be small)\n    auto [mx, my] = mol[0];\n    x1 = mx; x2 = min(COORD_MAX, mx+1);\n    y1 = my; y2 = min(COORD_MAX, my+1);\n    return false;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<pii> mackerels(N), sardines(N);\n    for (int i=0; i<N; ++i) cin >> mackerels[i].first >> mackerels[i].second;\n    for (int i=0; i<N; ++i) cin >> sardines[i].first >> sardines[i].second;\n\n    // Try multiple tile sizes\n    vector<int> tileSizes = {250, 500, 1000};\n    int best_score = -1e9;\n    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;\n\n    for (int S : tileSizes) {\n        auto [sum, enc] = bestTileRectangle(mackerels, sardines, S);\n        if (sum <= 0) continue;\n        int r1 = enc.first;\n        int r2 = enc.second / 10000;\n        int c1 = (enc.second % 10000) / 100;\n        int c2 = enc.second % 100;\n        int tile_x1 = c1 * S;\n        int tile_x2 = min(COORD_MAX, (c2 + 1) * S);\n        int tile_y1 = r1 * S;\n        int tile_y2 = min(COORD_MAX, (r2 + 1) * S);\n\n        int tx1, tx2, ty1, ty2;\n        tightenToMackerels(mackerels, tile_x1, tile_x2, tile_y1, tile_y2,\n                           tx1, tx2, ty1, ty2);\n        localSearch(mackerels, sardines, tx1, tx2, ty1, ty2);\n        int sc = evaluate(tx1, tx2, ty1, ty2, mackerels, sardines);\n        if (sc > best_score) {\n            best_score = sc;\n            x1 = tx1; x2 = tx2; y1 = ty1; y2 = ty2;\n        }\n    }\n\n    // fallback if no good rectangle found\n    if (best_score <= 0) {\n        safeTinyRectangle(mackerels, sardines, x1, x2, y1, y2);\n    }\n\n    // output rectangle (always 4 vertices)\n    cout << 4 << '\\n';\n    cout << x1 << \" \" << y1 << '\\n';\n    cout << x2 << \" \" << y1 << '\\n';\n    cout << x2 << \" \" << y2 << '\\n';\n    cout << x1 << \" \" << y2 << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\nusing ll = long long;\n\nstruct Rect {\n    ll x, y, w, h;\n    int orig;\n};\n\nstruct State {\n    vector<Rect> placed;\n    vector<tuple<int,int,char,int>> ops; // (p, r, d, b)\n    ll W, H, skipped;\n    ll score() const { return W + H + skipped; }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<ll> w_obs(N), h_obs(N);\n    for (int i=0; i<N; ++i) cin >> w_obs[i] >> h_obs[i];\n\n    // measurement statistics\n    vector<ll> sum_w(N,0), sum_h(N,0);\n    vector<int> cnt(N,0);\n    for (int i=0; i<N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    // measurement turns\n    for (int t=0; t<T-1; ++t) {\n        int p;\n        if (t < N) p = t;\n        else {\n            int min_cnt = cnt[0];\n            p = 0;\n            for (int i=1; i<N; ++i) if (cnt[i] < min_cnt) { min_cnt = cnt[i]; p = i; }\n        }\n        cout << \"1\\n\";\n        cout << p << \" 0 U -1\" << endl;\n        ll Wp, Hp;\n        cin >> Wp >> Hp;\n        sum_w[p] += Wp;\n        sum_h[p] += Hp;\n        cnt[p]++;\n    }\n\n    // estimate true dimensions\n    vector<ll> est_w(N), est_h(N);\n    for (int i=0; i<N; ++i) {\n        long double avg_w = (long double)sum_w[i] / cnt[i];\n        long double avg_h = (long double)sum_h[i] / cnt[i];\n        est_w[i] = (ll)llround(avg_w);\n        est_h[i] = (ll)llround(avg_h);\n        if (est_w[i] < 1) est_w[i] = 1;\n        if (est_h[i] < 1) est_h[i] = 1;\n    }\n\n    // beam search for final packing\n    const int BEAM_WIDTH = 100; // adjust based on time\n    vector<State> beam = {{{}, {}, 0, 0, 0}}; // empty state\n\n    for (int i=0; i<N; ++i) {\n        vector<State> candidates;\n        for (const State& st : beam) {\n            // skip option\n            State skip_st = st;\n            skip_st.skipped += est_w[i] + est_h[i];\n            candidates.push_back(move(skip_st));\n\n            // try both rotations\n            for (int rot=0; rot<=1; ++rot) {\n                ll w = (rot==0) ? est_w[i] : est_h[i];\n                ll h = (rot==0) ? est_h[i] : est_w[i];\n\n                // try both directions\n                for (int dir=0; dir<2; ++dir) {\n                    // find best reference (including -1) that minimizes new score\n                    ll best_score_val = LLONG_MAX;\n                    int best_ref = -1;\n                    ll best_x, best_y, best_newW, best_newH;\n\n                    int placed_cnt = (int)st.placed.size();\n                    // we iterate over all possible references, including -1\n                    for (int ref=-1; ref<placed_cnt; ++ref) {\n                        ll x, y;\n                        if (dir==0) { // U\n                            x = (ref==-1) ? 0 : st.placed[ref].x + st.placed[ref].w;\n                            y = 0;\n                            for (auto &p : st.placed) {\n                                if (x < p.x + p.w && x + w > p.x) {\n                                    y = max(y, p.y + p.h);\n                                }\n                            }\n                        } else { // L\n                            y = (ref==-1) ? 0 : st.placed[ref].y + st.placed[ref].h;\n                            x = 0;\n                            for (auto &p : st.placed) {\n                                if (y < p.y + p.h && y + h > p.y) {\n                                    x = max(x, p.x + p.w);\n                                }\n                            }\n                        }\n                        ll newW = max(st.W, x + w);\n                        ll newH = max(st.H, y + h);\n                        ll score_new = newW + newH + st.skipped;\n                        if (score_new < best_score_val) {\n                            best_score_val = score_new;\n                            best_ref = ref;\n                            best_x = x;\n                            best_y = y;\n                            best_newW = newW;\n                            best_newH = newH;\n                        }\n                    }\n\n                    // create new state\n                    State new_st = st;\n                    new_st.W = best_newW;\n                    new_st.H = best_newH;\n                    int ref_orig = (best_ref==-1) ? -1 : st.placed[best_ref].orig;\n                    new_st.ops.emplace_back(i, rot, (dir==0?'U':'L'), ref_orig);\n                    new_st.placed.push_back({best_x, best_y, w, h, i});\n                    candidates.push_back(move(new_st));\n                }\n            }\n        }\n\n        // sort by score\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.score() < b.score(); });\n        if (candidates.size() > BEAM_WIDTH)\n            candidates.resize(BEAM_WIDTH);\n        beam.swap(candidates);\n    }\n\n    // best state\n    auto best_state = *min_element(beam.begin(), beam.end(),\n        [](const State& a, const State& b) { return a.score() < b.score(); });\n\n    // output final packing\n    int placed_cnt = (int)best_state.ops.size();\n    cout << placed_cnt << \"\\n\";\n    for (auto &[p, r, d, b] : best_state.ops) {\n        cout << p << \" \" << r << \" \" << d << \" \" << b << \"\\n\";\n    }\n    cout.flush();\n\n    // read final measurement (ignored)\n    ll dummyW, dummyH;\n    cin >> dummyW >> dummyH;\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing namespace std::chrono;\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<vector<int>> graph(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        graph[u].push_back(v);\n        graph[v].push_back(u);\n    }\n    // read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. All-pairs shortest distances ----------\n    const int INF = 1e9;\n    vector<vector<int>> dist(N, vector<int>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        queue<int> q;\n        dist[s][s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int u : graph[v]) if (dist[s][u] == INF) {\n                dist[s][u] = dist[s][v] + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    // ---------- 2. For each vertex, list of all vertices sorted by distance ----------\n    vector<vector<int>> order(N, vector<int>(N));\n    vector<vector<int>> pos(N, vector<int>(N)); // pos[v][u] = index in order[v]\n    for (int v = 0; v < N; ++v) {\n        iota(order[v].begin(), order[v].end(), 0);\n        sort(order[v].begin(), order[v].end(), [&](int a, int b) {\n            return dist[v][a] < dist[v][b];\n        });\n        for (int i = 0; i < N; ++i) pos[v][order[v][i]] = i;\n    }\n\n    // ---------- 3. Greedy removal of roots ----------\n    vector<bool> active(N, true);\n    vector<int> best_root(N), best_dist(N), best_idx(N);\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        best_root[v] = v;\n        best_dist[v] = 0;\n        best_idx[v] = 0;\n        children[v].push_back(v);\n    }\n\n    while (true) {\n        // compute gain and feasibility for each root\n        vector<ll> gain(N, 0);\n        vector<bool> feasible(N, true);\n        for (int r = 0; r < N; ++r) if (active[r]) {\n            for (int v : children[r]) {\n                int idx = best_idx[v] + 1;\n                while (idx < N && !active[order[v][idx]]) ++idx;\n                if (idx == N || dist[v][order[v][idx]] > H) {\n                    feasible[r] = false;\n                    break;\n                }\n                int new_root = order[v][idx];\n                int new_dist = dist[v][new_root];\n                gain[r] += (ll)(new_dist - best_dist[v]) * A[v];\n            }\n        }\n\n        // choose root with maximum gain (prefer positive, accept zero)\n        int best = -1;\n        ll best_gain = -1;\n        for (int r = 0; r < N; ++r) if (active[r] && feasible[r] && gain[r] >= 0) {\n            if (gain[r] > best_gain) {\n                best_gain = gain[r];\n                best = r;\n            }\n        }\n        if (best == -1) break; // no improvement\n\n        // remove root best\n        active[best] = false;\n        for (int v : children[best]) {\n            int idx = best_idx[v] + 1;\n            while (!active[order[v][idx]]) ++idx;\n            int new_root = order[v][idx];\n            int new_dist = dist[v][new_root];\n            best_idx[v] = idx;\n            best_dist[v] = new_dist;\n            best_root[v] = new_root;\n            children[new_root].push_back(v);\n        }\n        children[best].clear();\n    }\n\n    // ---------- 4. Build BFS forest from final roots ----------\n    vector<int> parent(N, -1), depth(N, -1);\n    queue<int> q;\n    for (int r = 0; r < N; ++r) if (active[r]) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) if (depth[u] == -1) {\n            depth[u] = depth[v] + 1;\n            parent[u] = v;\n            q.push(u);\n        }\n    }\n\n    // ---------- 5. Post-processing: increase depth of leaves ----------\n    // compute child counts\n    vector<int> child_cnt(N, 0);\n    for (int v = 0; v < N; ++v) if (parent[v] != -1) child_cnt[parent[v]]++;\n\n    // sort vertices by beauty descending\n    vector<int> vorder(N);\n    iota(vorder.begin(), vorder.end(), 0);\n    sort(vorder.begin(), vorder.end(), [&](int i, int j) { return A[i] > A[j]; });\n\n    // repeat several passes\n    for (int pass = 0; pass < 20; ++pass) {\n        bool changed = false;\n        for (int v : vorder) {\n            if (depth[v] == H || child_cnt[v] > 0) continue; // only leaves with depth < H\n            int best_u = -1, best_d = depth[v];\n            for (int u : graph[v]) {\n                if (depth[u] >= depth[v] && depth[u] < H && depth[u] + 1 > best_d) {\n                    best_u = u;\n                    best_d = depth[u] + 1;\n                }\n            }\n            if (best_u != -1) {\n                // update parent and depth\n                if (parent[v] != -1) child_cnt[parent[v]]--;\n                parent[v] = best_u;\n                child_cnt[best_u]++;\n                depth[v] = best_d;\n                changed = true;\n            }\n        }\n        if (!changed) break;\n    }\n\n    // ---------- 6. Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << parent[i] << (i+1 == N ? \"\\n\" : \" \");\n    }\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <climits>\n#include <cstring>\n\nusing namespace std;\n\nint N;\nvector<string> grid;\nvector<pair<char, int>> ops;\n\n// ------------- move helpers (on real grid) -------------\nvoid shift_left(int r) {\n    for (int j = 0; j < N - 1; ++j) grid[r][j] = grid[r][j + 1];\n    grid[r][N - 1] = '.';\n    ops.emplace_back('L', r);\n}\nvoid shift_right(int r) {\n    for (int j = N - 1; j > 0; --j) grid[r][j] = grid[r][j - 1];\n    grid[r][0] = '.';\n    ops.emplace_back('R', r);\n}\nvoid shift_up(int c) {\n    for (int i = 0; i < N - 1; ++i) grid[i][c] = grid[i + 1][c];\n    grid[N - 1][c] = '.';\n    ops.emplace_back('U', c);\n}\nvoid shift_down(int c) {\n    for (int i = N - 1; i > 0; --i) grid[i][c] = grid[i - 1][c];\n    grid[0][c] = '.';\n    ops.emplace_back('D', c);\n}\n\n// ------------ simulation on a copy ------------\nvector<string> apply_batch(const vector<string>& g, char dir, int idx, int shifts) {\n    vector<string> h = g;\n    for (int k = 0; k < shifts; ++k) {\n        if (dir == 'L') {\n            for (int j = 0; j < N - 1; ++j) h[idx][j] = h[idx][j + 1];\n            h[idx][N - 1] = '.';\n        } else if (dir == 'R') {\n            for (int j = N - 1; j > 0; --j) h[idx][j] = h[idx][j - 1];\n            h[idx][0] = '.';\n        } else if (dir == 'U') {\n            for (int i = 0; i < N - 1; ++i) h[i][idx] = h[i + 1][idx];\n            h[N - 1][idx] = '.';\n        } else {\n            for (int i = N - 1; i > 0; --i) h[i][idx] = h[i - 1][idx];\n            h[0][idx] = '.';\n        }\n    }\n    return h;\n}\n\n// -------------- utilities --------------\nint count_oni(const vector<string>& g) {\n    int cnt = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (g[i][j] == 'x') ++cnt;\n    return cnt;\n}\n\nbool all_oni_safe(const vector<string>& g) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (g[i][j] != 'x') continue;\n            bool ok = false;\n            // up\n            bool safe = true;\n            for (int r = i - 1; r >= 0; --r)\n                if (g[r][j] == 'o') { safe = false; break; }\n            if (safe) ok = true;\n            // down\n            if (!ok) {\n                safe = true;\n                for (int r = i + 1; r < N; ++r)\n                    if (g[r][j] == 'o') { safe = false; break; }\n                if (safe) ok = true;\n            }\n            // left\n            if (!ok) {\n                safe = true;\n                for (int c = j - 1; c >= 0; --c)\n                    if (g[i][c] == 'o') { safe = false; break; }\n                if (safe) ok = true;\n            }\n            // right\n            if (!ok) {\n                safe = true;\n                for (int c = j + 1; c < N; ++c)\n                    if (g[i][c] == 'o') { safe = false; break; }\n                if (safe) ok = true;\n            }\n            if (!ok) return false;\n        }\n    }\n    return true;\n}\n\nint heuristic_lower_bnd(const vector<string>& g) {\n    int total = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (g[i][j] != 'x') continue;\n            int best = N + 1;\n            // up\n            bool safe = true;\n            for (int r = i - 1; r >= 0; --r)\n                if (g[r][j] == 'o') { safe = false; break; }\n            if (safe) best = min(best, i + 1);\n            // down\n            safe = true;\n            for (int r = i + 1; r < N; ++r)\n                if (g[r][j] == 'o') { safe = false; break; }\n            if (safe) best = min(best, N - i);\n            // left\n            safe = true;\n            for (int c = j - 1; c >= 0; --c)\n                if (g[i][c] == 'o') { safe = false; break; }\n            if (safe) best = min(best, j + 1);\n            // right\n            safe = true;\n            for (int c = j + 1; c < N; ++c)\n                if (g[i][c] == 'o') { safe = false; break; }\n            if (safe) best = min(best, N - j);\n            total += 2 * best;\n        }\n    }\n    return total;\n}\n\nstruct Candidate {\n    int removals;\n    int shifts;\n    char dir;\n    int idx;\n};\n\nvector<Candidate> get_candidates(const vector<string>& g) {\n    vector<Candidate> cands;\n    // rows\n    for (int i = 0; i < N; ++i) {\n        int left_god = N, right_god = -1;\n        for (int j = 0; j < N; ++j)\n            if (g[i][j] == 'o') {\n                left_god = min(left_god, j);\n                right_god = max(right_god, j);\n            }\n        if (left_god == N) continue;\n        if (left_god > 0) {\n            int cnt = 0;\n            for (int j = 0; j < left_god; ++j)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, left_god, 'L', i});\n        }\n        if (right_god < N - 1) {\n            int cnt = 0;\n            for (int j = right_god + 1; j < N; ++j)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, N - 1 - right_god, 'R', i});\n        }\n    }\n    // columns\n    for (int j = 0; j < N; ++j) {\n        int top_god = N, bottom_god = -1;\n        for (int i = 0; i < N; ++i)\n            if (g[i][j] == 'o') {\n                top_god = min(top_god, i);\n                bottom_god = max(bottom_god, i);\n            }\n        if (top_god == N) continue;\n        if (top_god > 0) {\n            int cnt = 0;\n            for (int i = 0; i < top_god; ++i)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, top_god, 'U', j});\n        }\n        if (bottom_god < N - 1) {\n            int cnt = 0;\n            for (int i = bottom_god + 1; i < N; ++i)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, N - 1 - bottom_god, 'D', j});\n        }\n    }\n    return cands;\n}\n\n// -------------- clear all rows/cols that have no gods --------------\nvoid clear_godless() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        // rows\n        for (int i = 0; i < N; ++i) {\n            bool has_god = false;\n            for (int j = 0; j < N; ++j)\n                if (grid[i][j] == 'o') { has_god = true; break; }\n            if (has_god) continue;\n            int leftmost = N, rightmost = -1;\n            for (int j = 0; j < N; ++j)\n                if (grid[i][j] == 'x') {\n                    leftmost = min(leftmost, j);\n                    rightmost = max(rightmost, j);\n                }\n            if (rightmost == -1) continue;\n            changed = true;\n            int left_cost = rightmost + 1;\n            int right_cost = N - leftmost;\n            if (left_cost <= right_cost) {\n                for (int k = 0; k < left_cost; ++k) shift_left(i);\n            } else {\n                for (int k = 0; k < right_cost; ++k) shift_right(i);\n            }\n        }\n        // columns\n        for (int j = 0; j < N; ++j) {\n            bool has_god = false;\n            for (int i = 0; i < N; ++i)\n                if (grid[i][j] == 'o') { has_god = true; break; }\n            if (has_god) continue;\n            int topmost = N, bottommost = -1;\n            for (int i = 0; i < N; ++i)\n                if (grid[i][j] == 'x') {\n                    topmost = min(topmost, i);\n                    bottommost = max(bottommost, i);\n                }\n            if (bottommost == -1) continue;\n            changed = true;\n            int up_cost = bottommost + 1;\n            int down_cost = N - topmost;\n            if (up_cost <= down_cost) {\n                for (int k = 0; k < up_cost; ++k) shift_up(j);\n            } else {\n                for (int k = 0; k < down_cost; ++k) shift_down(j);\n            }\n        }\n    }\n}\n\n// --------------- main ---------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // initial clear of godless rows/cols\n    clear_godless();\n\n    // main loop\n    while (true) {\n        int total_oni = count_oni(grid);\n        if (total_oni == 0) break;\n\n        // generate candidates\n        vector<Candidate> cands = get_candidates(grid);\n        if (cands.empty()) {\n            // no batch possible \u2192 individual round\u2011trip\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (grid[i][j] != 'x') continue;\n                    int best_dir = -1, best_dist = N + 1;\n                    // up\n                    bool safe = true;\n                    for (int r = i - 1; r >= 0; --r)\n                        if (grid[r][j] == 'o') { safe = false; break; }\n                    if (safe && i + 1 < best_dist) { best_dir = 0; best_dist = i + 1; }\n                    // down\n                    safe = true;\n                    for (int r = i + 1; r < N; ++r)\n                        if (grid[r][j] == 'o') { safe = false; break; }\n                    if (safe && N - i < best_dist) { best_dir = 1; best_dist = N - i; }\n                    // left\n                    safe = true;\n                    for (int c = j - 1; c >= 0; --c)\n                        if (grid[i][c] == 'o') { safe = false; break; }\n                    if (safe && j + 1 < best_dist) { best_dir = 2; best_dist = j + 1; }\n                    // right\n                    safe = true;\n                    for (int c = j + 1; c < N; ++c)\n                        if (grid[i][c] == 'o') { safe = false; break; }\n                    if (safe && N - j < best_dist) { best_dir = 3; best_dist = N - j; }\n\n                    if (best_dir == -1) continue; // should not happen\n\n                    if (best_dir == 0) {\n                        for (int k = 0; k < best_dist; ++k) shift_up(j);\n                        for (int k = 0; k < best_dist; ++k) shift_down(j);\n                    } else if (best_dir == 1) {\n                        for (int k = 0; k < best_dist; ++k) shift_down(j);\n                        for (int k = 0; k < best_dist; ++k) shift_up(j);\n                    } else if (best_dir == 2) {\n                        for (int k = 0; k < best_dist; ++k) shift_left(i);\n                        for (int k = 0; k < best_dist; ++k) shift_right(i);\n                    } else {\n                        for (int k = 0; k < best_dist; ++k) shift_right(i);\n                        for (int k = 0; k < best_dist; ++k) shift_left(i);\n                    }\n                }\n            }\n            // after round\u2011trip, try clearing godless again\n            clear_godless();\n            continue;\n        }\n\n        // evaluate candidates with 2\u2011step lookahead\n        int best_total = INT_MAX;\n        Candidate* best_cand = nullptr;\n\n        for (auto& cand : cands) {\n            vector<string> g1 = apply_batch(grid, cand.dir, cand.idx, cand.shifts);\n            if (!all_oni_safe(g1)) continue;\n            int step1_cost = cand.shifts;\n            // second step\n            vector<Candidate> cands2 = get_candidates(g1);\n            int best_step2 = INT_MAX;\n            for (auto& c2 : cands2) {\n                vector<string> g2 = apply_batch(g1, c2.dir, c2.idx, c2.shifts);\n                if (!all_oni_safe(g2)) continue;\n                int step2_cost = c2.shifts;\n                int rem = heuristic_lower_bnd(g2);\n                best_step2 = min(best_step2, step2_cost + rem);\n            }\n            if (cands2.empty()) {\n                best_step2 = heuristic_lower_bnd(g1);\n            }\n            int total = step1_cost + best_step2;\n            if (total < best_total) {\n                best_total = total;\n                best_cand = &cand;\n            }\n        }\n\n        // fallback if no safe candidate (unlikely)\n        if (best_cand == nullptr) {\n            for (auto& cand : cands) {\n                vector<string> g1 = apply_batch(grid, cand.dir, cand.idx, cand.shifts);\n                if (all_oni_safe(g1)) {\n                    best_cand = &cand;\n                    break;\n                }\n            }\n            if (best_cand == nullptr) break; // impossible\n        }\n\n        // apply chosen candidate\n        for (int k = 0; k < best_cand->shifts; ++k) {\n            if (best_cand->dir == 'L') shift_left(best_cand->idx);\n            else if (best_cand->dir == 'R') shift_right(best_cand->idx);\n            else if (best_cand->dir == 'U') shift_up(best_cand->idx);\n            else shift_down(best_cand->idx);\n        }\n\n        // after moving, clear any newly godless rows/cols\n        clear_godless();\n    }\n\n    // output\n    for (const auto& op : ops)\n        cout << op.first << ' ' << op.second << '\\n';\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\n#include <chrono>\n#include <cmath>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\nint target[N];\ndouble pi_target[N];\n\nstruct Solution {\n    int a[N], b[N];\n};\n\n// Xorshift\nstatic uint32_t x = 123456789, y = 362436069, z = 521288629, w = 88675123;\ninline uint32_t xorshift() {\n    uint32_t t = x ^ (x << 11);\n    x = y; y = z; z = w;\n    w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    return w;\n}\ninline int rand_int(int mod) {\n    return xorshift() % mod;\n}\ninline double rand_double() {\n    return (double)xorshift() / 4294967296.0;\n}\n\n// Compute stationary distribution of random walk (each out-edge prob 0.5)\n// Returns L1 error to pi_target\ndouble stationary_error(const Solution &sol) {\n    double P[N][N] = {0.0};\n    for (int i = 0; i < N; ++i) {\n        P[i][sol.a[i]] += 0.5;\n        P[i][sol.b[i]] += 0.5;\n    }\n    double pi[N], old[N];\n    for (int i = 0; i < N; ++i) pi[i] = 1.0 / N;\n    for (int iter = 0; iter < 2000; ++iter) {\n        for (int i = 0; i < N; ++i) old[i] = pi[i];\n        // pi_new = pi * P\n        double sum = 0.0;\n        for (int j = 0; j < N; ++j) {\n            double s = 0.0;\n            for (int i = 0; i < N; ++i) s += old[i] * P[i][j];\n            pi[j] = s;\n            sum += s;\n        }\n        // normalize\n        for (int j = 0; j < N; ++j) pi[j] /= sum;\n        double diff = 0.0;\n        for (int j = 0; j < N; ++j) diff += fabs(pi[j] - old[j]);\n        if (diff < 1e-12) break;\n    }\n    double err = 0.0;\n    for (int i = 0; i < N; ++i) err += fabs(pi[i] - pi_target[i]);\n    return err;\n}\n\n// Full simulation: returns total error\nint simulate(const Solution &sol, int cnt[]) {\n    const int *a = sol.a;\n    const int *b = sol.b;\n    fill(cnt, cnt + N, 0);\n    int cur = 0;\n    cnt[0] = 1;\n    for (int w = 2; w <= L; ++w) {\n        int t = cnt[cur];\n        int nxt = (t & 1) ? a[cur] : b[cur];\n        ++cnt[nxt];\n        cur = nxt;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) err += abs(cnt[i] - target[i]);\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) {\n        cin >> target[i];\n        pi_target[i] = (double)target[i] / L;\n    }\n\n    // Initial solution: simple cycle (a_i = b_i = (i+1)%N)\n    Solution best_sol;\n    for (int i = 0; i < N; ++i) {\n        best_sol.a[i] = (i + 1) % N;\n        best_sol.b[i] = (i + 1) % N;\n    }\n    int cnt[N];\n    int best_err = simulate(best_sol, cnt);\n    double best_stat_err = stationary_error(best_sol);\n\n    Solution cur_sol = best_sol;\n    double cur_stat_err = best_stat_err;\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n\n    // Phase 1: Simulated annealing on stationary error\n    const int MAX_ITERS = 10000;\n    const double initial_temp = 0.1; // because stationary error is small (0-2)\n    const double final_temp = 0.0001;\n    const double cooling_rate = pow(final_temp / initial_temp, 1.0 / MAX_ITERS);\n    double temperature = initial_temp;\n\n    for (int iter = 0; iter < MAX_ITERS; ++iter) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit * 0.8) break; // leave time for final simulation\n\n        Solution new_sol = cur_sol;\n        int i = rand_int(N);\n        if (rand_int(2) == 0)\n            new_sol.a[i] = rand_int(N);\n        else\n            new_sol.b[i] = rand_int(N);\n\n        double new_stat_err = stationary_error(new_sol);\n        double delta = new_stat_err - cur_stat_err;\n\n        if (delta < 0) {\n            cur_sol = new_sol;\n            cur_stat_err = new_stat_err;\n            if (new_stat_err < best_stat_err) {\n                best_stat_err = new_stat_err;\n                best_sol = new_sol;\n            }\n        } else {\n            double prob = exp(-delta / temperature);\n            if (rand_double() < prob) {\n                cur_sol = new_sol;\n                cur_stat_err = new_stat_err;\n            }\n        }\n\n        temperature *= cooling_rate;\n    }\n\n    // Evaluate actual error of best stationary solution\n    int best_err_stationary = simulate(best_sol, cnt);\n    if (best_err_stationary < best_err) {\n        best_err = best_err_stationary;\n        // best_sol already updated\n    }\n\n    // Phase 2: Simulated annealing on actual error (remainder time)\n    cur_sol = best_sol;\n    int cur_err = best_err;\n    temperature = 500.0;\n    double cooling_factor = 0.999;\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit) break;\n\n        Solution new_sol = cur_sol;\n        int i = rand_int(N);\n        if (rand_int(2) == 0)\n            new_sol.a[i] = rand_int(N);\n        else\n            new_sol.b[i] = rand_int(N);\n\n        int new_err = simulate(new_sol, cnt);\n        int delta = new_err - cur_err;\n\n        if (delta < 0) {\n            cur_sol = new_sol;\n            cur_err = new_err;\n            if (new_err < best_err) {\n                best_err = new_err;\n                best_sol = new_sol;\n            }\n        } else {\n            double prob = exp(-delta / temperature);\n            if (rand_double() < prob) {\n                cur_sol = new_sol;\n                cur_err = new_err;\n            }\n        }\n\n        temperature *= cooling_factor;\n    }\n\n    // Output best solution\n    for (int i = 0; i < N; ++i)\n        cout << best_sol.a[i] << \" \" << best_sol.b[i] << \"\\n\";\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\n// ---------- DSU ----------\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rank_[a] < rank_[b]) swap(a, b);\n        parent[b] = a;\n        if (rank_[a] == rank_[b]) rank_[a]++;\n        return true;\n    }\n};\n\n// ---------- query helper ----------\nvector<pair<int,int>> do_query(const vector<int>& subset) {\n    int l = subset.size();\n    cout << \"? \" << l;\n    for (int v : subset) cout << ' ' << v;\n    cout << endl;\n    vector<pair<int,int>> res;\n    for (int i = 0; i < l-1; ++i) {\n        int a, b; cin >> a >> b;\n        if (a > b) swap(a, b);\n        res.emplace_back(a, b);\n    }\n    return res;\n}\n\n// ---------- Hilbert index (14 bits) ----------\nuint64_t hilbertIndex(uint32_t x, uint32_t y, int bits = 14) {\n    uint32_t n = 1u << bits;\n    uint64_t d = 0;\n    uint32_t s, rx, ry;\n    for (s = n >> 1; s; s >>= 1) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d = (d << 2) | ((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = (n - 1) - x;\n                y = (n - 1) - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<ll> lx(N), rx(N), ly(N), ry(N);\n    vector<ll> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // ---- order cities by Hilbert index (using center) ----\n    auto scale = [](ll v) -> uint32_t { return (uint32_t)clamp(v, 0LL, 16383LL); };\n    vector<uint64_t> hi(N);\n    for (int i = 0; i < N; ++i) hi[i] = hilbertIndex(scale(cx[i]), scale(cy[i]));\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) { return hi[a] < hi[b]; });\n\n    // ---- assign groups by consecutive blocks ----\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        groups[k].reserve(G[k]);\n        for (int j = 0; j < G[k]; ++j) groups[k].push_back(order[idx++]);\n    }\n\n    // ---- plan queries: small groups first, then proportional for large ----\n    vector<int> q_per_group(M, 0);\n    int used_q = 0;\n\n    // small groups (size <= L)\n    for (int k = 0; k < M; ++k) {\n        int sz = groups[k].size();\n        if (sz <= L && used_q < Q) {\n            q_per_group[k] = 1;\n            ++used_q;\n        }\n    }\n\n    // large groups \u2013 allocate remaining queries proportionally to (sz - L + 1)\n    int remaining = Q - used_q;\n    if (remaining > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) {\n            if (groups[k].size() > L) large.push_back(k);\n        }\n        ll total_needed = 0;\n        for (int k : large) total_needed += max(1, (int)groups[k].size() - L + 1);\n        for (int k : large) {\n            int need = max(1, (int)groups[k].size() - L + 1);\n            int alloc = (int)((ll)remaining * need / total_needed);\n            if (alloc == 0) alloc = 1;\n            q_per_group[k] = alloc;\n        }\n        // adjust to not exceed remaining\n        int sum = 0;\n        for (int k : large) sum += q_per_group[k];\n        while (sum > remaining) {\n            for (int k : large) {\n                if (sum <= remaining) break;\n                if (q_per_group[k] > 1) {\n                    --q_per_group[k];\n                    --sum;\n                }\n            }\n        }\n    }\n\n    // ---- execute queries and build MST per group ----\n    vector<vector<pair<int,int>>> answer_edges(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int sz = cities.size();\n        if (sz <= 1) continue;\n\n        // collect query edges\n        vector<pair<int,int>> query_edges;\n        int nq = q_per_group[k];\n        if (nq > 0) {\n            if (sz <= L) {\n                // whole group query\n                auto edges = do_query(cities);\n                for (auto e : edges) query_edges.push_back(e);\n            } else {\n                // sliding windows with step to achieve nq queries\n                int step = max(1, (sz - L + 1 + nq - 1) / nq);\n                for (int start = 0; start + L <= sz && nq > 0; start += step, --nq) {\n                    vector<int> subset(cities.begin() + start, cities.begin() + start + L);\n                    auto edges = do_query(subset);\n                    for (auto e : edges) query_edges.push_back(e);\n                }\n            }\n        }\n\n        // ---- build MST ----\n        // use query edges first, then complete graph for missing connections\n        struct Edge { int u, v; ll w; };\n        auto estimated_weight = [&](int a, int b) -> ll {\n            ll dx = cx[a] - cx[b];\n            ll dy = cy[a] - cy[b];\n            return (ll)sqrt(dx*dx + dy*dy);\n        };\n\n        DSU dsu(N);\n        vector<pair<int,int>> mst;\n\n        // 1) process query edges (sorted by estimated weight)\n        vector<Edge> cand;\n        for (auto& p : query_edges) {\n            ll w = estimated_weight(p.first, p.second);\n            cand.push_back({p.first, p.second, w});\n        }\n        sort(cand.begin(), cand.end(), [](const Edge& a, const Edge& b) { return a.w < b.w; });\n        for (auto& e : cand) {\n            if (dsu.unite(e.u, e.v)) mst.emplace_back(e.u, e.v);\n            if ((int)mst.size() == sz - 1) break;\n        }\n\n        // 2) if still not connected, add edges from complete graph (estimated)\n        if ((int)mst.size() < sz - 1) {\n            cand.clear();\n            for (int i = 0; i < sz; ++i) {\n                for (int j = i+1; j < sz; ++j) {\n                    int u = cities[i], v = cities[j];\n                    if (dsu.find(u) == dsu.find(v)) continue;\n                    ll w = estimated_weight(u, v);\n                    cand.push_back({u, v, w});\n                }\n            }\n            sort(cand.begin(), cand.end(), [](const Edge& a, const Edge& b) { return a.w < b.w; });\n            for (auto& e : cand) {\n                if (dsu.unite(e.u, e.v)) mst.emplace_back(e.u, e.v);\n                if ((int)mst.size() == sz - 1) break;\n            }\n        }\n\n        for (auto& e : mst) answer_edges[k].push_back(e);\n    }\n\n    // ---- output answer ----\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        for (int v : groups[k]) cout << v << ' ';\n        cout << endl;\n        for (auto& e : answer_edges[k]) cout << e.first << ' ' << e.second << endl;\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nconst int dy[4] = {-1, 1, 0, 0}; // U, D, L, R\nconst int dx[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\n// BFS to find shortest path from (si,sj) to (ti,tj) using only Move and Slide.\n// Returns vector of (action, direction) pairs.\nvector<pair<char, char>> get_path(int si, int sj, int ti, int tj) {\n    int start = si * N + sj, goal = ti * N + tj;\n    vector<int> dist(N * N, -1), prev(N * N, -1), act(N * N, -1), dir(N * N, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        if (u == goal) break;\n        int i = u / N, j = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move one step\n            int ni = i + dy[d], nj = j + dx[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int v = ni * N + nj;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 0; // Move\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n\n            // Slide to the edge in direction d\n            // Only valid if the first square in that direction is inside (otherwise slide does nothing)\n            if (d == 0 && i > 0) { // up\n                int v = 0 * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1; // Slide\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 1 && i < N - 1) { // down\n                int v = (N - 1) * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 2 && j > 0) { // left\n                int v = i * N + 0;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 3 && j < N - 1) { // right\n                int v = i * N + (N - 1);\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n        }\n    }\n\n    // Reconstruct path from goal to start\n    vector<pair<char, char>> rev;\n    int cur = goal;\n    while (cur != start) {\n        int a = act[cur];\n        int d = dir[cur];\n        rev.push_back({(a == 0 ? 'M' : 'S'), dir_char[d]});\n        cur = prev[cur];\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int, int>> points(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    int cur_i = points[0].first, cur_j = points[0].second;\n\n    for (int t = 1; t < M; ++t) {\n        int ti = points[t].first, tj = points[t].second;\n        auto path = get_path(cur_i, cur_j, ti, tj);\n        for (auto [act, dir] : path) {\n            cout << act << \" \" << dir << \"\\n\";\n        }\n        cur_i = ti;\n        cur_j = tj;\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Rect { int a, b, c, d; }; // [a,c) x [b,d)\nstruct Region { int x0, y0, x1, y1; vector<int> ids; };\nstruct SplitResult { \n    int axis; \n    int s; \n    vector<int> left, right; \n    double metric;\n};\n\nint n;\nvector<int> xi, yi, ri;\n\ndouble calc_p(int idx, long long area) {\n    long long r = ri[idx];\n    long long s = area;\n    long long mn = min(r, s);\n    long long mx = max(r, s);\n    double ratio = (double)mn / mx;\n    return ratio * (2.0 - ratio);\n}\n\nbool overlap(const Rect& a, const Rect& b) {\n    return max(a.a, b.a) < min(a.c, b.c) && max(a.b, b.b) < min(a.d, b.d);\n}\nbool contains(const Rect& rect, int xi, int yi) {\n    return rect.a <= xi && xi < rect.c && rect.b <= yi && yi < rect.d;\n}\n\ndouble total_score(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; ++i) {\n        long long area = (long long)(rects[i].c - rects[i].a) * (rects[i].d - rects[i].b);\n        sum += calc_p(i, area);\n    }\n    return sum;\n}\n\nSplitResult choose_split(const Region& reg) {\n    int m = reg.ids.size();\n    const auto& ids = reg.ids;\n    int x0 = reg.x0, y0 = reg.y0, x1 = reg.x1, y1 = reg.y1;\n    vector<SplitResult> candidates;\n\n    // ---- vertical split (axis 0) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, xi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, xi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int height = y1 - y0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / height + x0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - x0) * height;\n            long long right_area = (long long)(x1 - s) * height;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({0, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    // ---- horizontal split (axis 1) ----\n    {\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return yi[i] < yi[j]; });\n        vector<long long> pref(m+1, 0);\n        for (int i = 0; i < m; ++i) pref[i+1] = pref[i] + ri[order[i]];\n        long long total = pref[m];\n\n        vector<int> max_left(m), min_right(m);\n        int cur_max = -1;\n        for (int i = 0; i < m; ++i) {\n            cur_max = max(cur_max, yi[order[i]]);\n            max_left[i] = cur_max;\n        }\n        int cur_min = 100000;\n        for (int i = m-1; i >= 0; --i) {\n            cur_min = min(cur_min, yi[order[i]]);\n            min_right[i] = cur_min;\n        }\n\n        int width = x1 - x0;\n        for (int k = 1; k < m; ++k) {\n            long long left_sum = pref[k];\n            long long right_sum = total - left_sum;\n            int low = max_left[k-1] + 1;\n            int high = min_right[k];\n            if (low > high) continue;\n\n            double s_float = (double)left_sum / width + y0;\n            int s = (int)round(s_float);\n            s = max(s, low);\n            s = min(s, high);\n\n            long long left_area = (long long)(s - y0) * width;\n            long long right_area = (long long)(y1 - s) * width;\n            double metric = (double)(left_area - left_sum)*(left_area - left_sum)\n                          + (double)(right_area - right_sum)*(right_area - right_sum);\n\n            vector<int> left_ids(order.begin(), order.begin()+k);\n            vector<int> right_ids(order.begin()+k, order.end());\n            candidates.push_back({1, s, move(left_ids), move(right_ids), metric});\n        }\n    }\n\n    if (candidates.empty()) {\n        // fallback: split vertically at median\n        vector<int> order = ids;\n        sort(order.begin(), order.end(), [](int i, int j) { return xi[i] < xi[j]; });\n        int mid = m / 2;\n        int split_x = (xi[order[mid-1]] + xi[order[mid]] + 1) / 2;\n        if (split_x <= x0) split_x = x0+1;\n        if (split_x >= x1) split_x = x1-1;\n        vector<int> left(order.begin(), order.begin()+mid);\n        vector<int> right(order.begin()+mid, order.end());\n        double left_sum = accumulate(left.begin(), left.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double right_sum = accumulate(right.begin(), right.end(), 0LL, [](long long sum, int i) { return sum + ri[i]; });\n        double metric = 0; // unused but set to avoid warning\n        return {0, split_x, move(left), move(right), metric};\n    }\n\n    // stochastic selection with softmax\n    double temperature = 0.02;\n    double max_metric = 1e100;\n    for (auto& c : candidates) if (c.metric < max_metric) max_metric = c.metric;\n    vector<double> weights(candidates.size());\n    double sum_weights = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        weights[i] = exp(- (candidates[i].metric - max_metric) * temperature);\n        sum_weights += weights[i];\n    }\n    uniform_real_distribution<double> dist(0.0, sum_weights);\n    double r = dist(rng);\n    double cum = 0.0;\n    for (size_t i = 0; i < candidates.size(); ++i) {\n        cum += weights[i];\n        if (r <= cum) return move(candidates[i]);\n    }\n    return move(candidates.back());\n}\n\nvoid recursive_split(const Region& reg, vector<Rect>& rects) {\n    if (reg.ids.size() == 1) {\n        int idx = reg.ids[0];\n        rects[idx] = {reg.x0, reg.y0, reg.x1, reg.y1};\n        return;\n    }\n    SplitResult split = choose_split(reg);\n    if (split.axis == 0) {\n        Region left{reg.x0, reg.y0, split.s, reg.y1, move(split.left)};\n        Region right{split.s, reg.y0, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    } else {\n        Region left{reg.x0, reg.y0, reg.x1, split.s, move(split.left)};\n        Region right{reg.x0, split.s, reg.x1, reg.y1, move(split.right)};\n        recursive_split(left, rects);\n        recursive_split(right, rects);\n    }\n}\n\nvoid improve(vector<Rect>& rects) {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < n; ++i) {\n            Rect cur = rects[i];\n            // try expand in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c >= 10000) continue;\n                    newr.c++;\n                } else if (dir == 1) { // left\n                    if (newr.a <= 0) continue;\n                    newr.a--;\n                } else if (dir == 2) { // top\n                    if (newr.d >= 10000) continue;\n                    newr.d++;\n                } else { // bottom\n                    if (newr.b <= 0) continue;\n                    newr.b--;\n                }\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n            // try shrink in four directions\n            for (int dir = 0; dir < 4; ++dir) {\n                Rect newr = cur;\n                if (dir == 0) { // right\n                    if (newr.c - 1 <= newr.a) continue;\n                    newr.c--;\n                } else if (dir == 1) { // left\n                    if (newr.a + 1 >= newr.c) continue;\n                    newr.a++;\n                } else if (dir == 2) { // top\n                    if (newr.d - 1 <= newr.b) continue;\n                    newr.d--;\n                } else { // bottom\n                    if (newr.b + 1 >= newr.d) continue;\n                    newr.b++;\n                }\n                // must still contain the point\n                if (!contains(newr, xi[i], yi[i])) continue;\n                // check no overlap\n                bool ok = true;\n                for (int j = 0; j < n; ++j) if (j != i) {\n                    if (overlap(newr, rects[j])) { ok = false; break; }\n                }\n                if (!ok) continue;\n                long long new_area = (long long)(newr.c - newr.a) * (newr.d - newr.b);\n                long long old_area = (long long)(cur.c - cur.a) * (cur.d - cur.b);\n                if (calc_p(i, new_area) > calc_p(i, old_area)) {\n                    rects[i] = newr;\n                    improved = true;\n                    break;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout << fixed << setprecision(15);\n\n    cin >> n;\n    xi.resize(n); yi.resize(n); ri.resize(n);\n    for (int i = 0; i < n; ++i) cin >> xi[i] >> yi[i] >> ri[i];\n\n    vector<Rect> best_rects(n);\n    double best_score = -1.0;\n\n    const int TRIALS = 200; // number of random constructions\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        vector<int> all_ids(n);\n        iota(all_ids.begin(), all_ids.end(), 0);\n        Region full{0, 0, 10000, 10000, move(all_ids)};\n        vector<Rect> rects(n);\n        recursive_split(full, rects);\n        double score = total_score(rects);\n        if (score > best_score) {\n            best_score = score;\n            best_rects = move(rects);\n        }\n    }\n\n    // post-processing on best solution\n    improve(best_rects);\n\n    // output\n    for (int i = 0; i < n; ++i) {\n        cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n             << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\n#include <chrono>\n#include <bitset>\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_CELLS = N * N;\nconst int MAX_TILES = 2500;\n\nusing Bitset = bitset<MAX_TILES>;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n    int start_cell = si * N + sj;\n\n    int tile_of_cell[MAX_CELLS];\n    int p_val[MAX_CELLS];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_of_cell[i * N + j];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p_val[i * N + j];\n\n    // Precompute adjacency list (cell -> neighbor cells)\n    const int dr[] = {-1, 1, 0, 0};\n    const int dc[] = {0, 0, -1, 1};\n    vector<int> adj[MAX_CELLS];\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int idx = r * N + c;\n            for (int d = 0; d < 4; ++d) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    adj[idx].push_back(nr * N + nc);\n                }\n            }\n        }\n    }\n\n    // State\n    struct State {\n        int pos;\n        Bitset vis;\n        int sum;\n        string path;\n    };\n\n    const int BEAM_WIDTH = 2000;\n    const double TIME_LIMIT_MS = 1900.0;\n    auto start_time = chrono::high_resolution_clock::now();\n\n    State init;\n    init.pos = start_cell;\n    init.vis.reset();\n    init.vis.set(tile_of_cell[start_cell]);\n    init.sum = p_val[start_cell];\n    init.path = \"\";\n\n    vector<State> beam;\n    beam.push_back(init);\n    State best = init;\n\n    // Heuristic: sum + maximum value among unvisited neighbor cells\n    auto heuristic = [&](const State& s) -> int {\n        int max_neighbor = 0;\n        for (int nb : adj[s.pos]) {\n            int nt = tile_of_cell[nb];\n            if (!s.vis.test(nt)) {\n                max_neighbor = max(max_neighbor, p_val[nb]);\n            }\n        }\n        return s.sum + max_neighbor;\n    };\n\n    while (!beam.empty()) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > TIME_LIMIT_MS) break;\n\n        vector<pair<int, State>> candidates;\n        candidates.reserve(beam.size() * 4);\n\n        for (const auto& s : beam) {\n            for (int nb : adj[s.pos]) {\n                int nt = tile_of_cell[nb];\n                if (s.vis.test(nt)) continue; // tile already visited\n\n                State ns;\n                ns.pos = nb;\n                ns.vis = s.vis;\n                ns.vis.set(nt);\n                ns.sum = s.sum + p_val[nb];\n                // Direction\n                int dr2 = (nb / N) - (s.pos / N);\n                int dc2 = (nb % N) - (s.pos % N);\n                char dir;\n                if (dr2 == -1) dir = 'U';\n                else if (dr2 == 1) dir = 'D';\n                else if (dc2 == -1) dir = 'L';\n                else dir = 'R';\n                ns.path = s.path + dir;\n\n                int h = heuristic(ns);\n                candidates.emplace_back(h, move(ns));\n            }\n        }\n\n        if (candidates.empty()) break;\n\n        int keep = min(BEAM_WIDTH, (int)candidates.size());\n        partial_sort(candidates.begin(), candidates.begin() + keep, candidates.end(),\n                     [](const auto& a, const auto& b) { return a.first > b.first; });\n\n        beam.clear();\n        for (int i = 0; i < keep; ++i) {\n            beam.push_back(move(candidates[i].second));\n            if (beam.back().sum > best.sum) {\n                best = beam.back();\n            }\n        }\n    }\n\n    // Output\n    cout << best.path << endl;\n\n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <string>\n\nusing namespace std;\n\nconst int GRID_SIZE = 30;\nconst int H_EDGES = 29;\nconst int V_EDGES = 29;\n\nconst double INIT_EST = 5000.0;\nconst double MIN_EDGE = 1000.0;\nconst double MAX_EDGE = 9000.0;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // per\u2011edge estimates and visit counts\n    vector<vector<double>> h_est(GRID_SIZE, vector<double>(H_EDGES, INIT_EST));\n    vector<vector<int>> h_cnt(GRID_SIZE, vector<int>(H_EDGES, 0));\n    vector<vector<double>> v_est(V_EDGES, vector<double>(GRID_SIZE, INIT_EST));\n    vector<vector<int>> v_cnt(V_EDGES, vector<int>(GRID_SIZE, 0));\n\n    // hyperparameters (tuned for better early performance)\n    const double lr0 = 0.5;               // base learning rate\n    const double C_explore = 600.0;       // UCB exploration constant (increased)\n    const int explore_until = 500;        // longer exploration phase\n    const double smooth = 0.002;          // lighter smoothing\n\n    const int T = 1000;\n    for (int k = 0; k < T; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n\n        double explore_factor = max(0.0, 1.0 - (double)k / explore_until);\n        double t_weight = sqrt(log(k + 1.0) + 1.0); // UCB time factor\n\n        // A* with Manhattan heuristic (admissible: min edge 1000)\n        const double INF = 1e18;\n        vector<vector<double>> dist(GRID_SIZE, vector<double>(GRID_SIZE, INF));\n        vector<vector<pair<int,int>>> prev(GRID_SIZE, vector<pair<int,int>>(GRID_SIZE, {-1, -1}));\n\n        auto heuristic = [&](int r, int c) -> double {\n            return (abs(r - ti) + abs(c - tj)) * 1000.0;\n        };\n\n        using State = pair<double, pair<int,int>>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        dist[si][sj] = 0.0;\n        pq.push({heuristic(si,sj), {si,sj}});\n\n        while (!pq.empty()) {\n            auto [f, node] = pq.top(); pq.pop();\n            int i = node.first, j = node.second;\n            double g = dist[i][j];\n            if (f > g + heuristic(i,j) + 1e-9) continue;\n            if (i == ti && j == tj) break;\n\n            // up\n            if (i > 0) {\n                double w = v_est[i-1][j] - C_explore * t_weight / sqrt(v_cnt[i-1][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                double ng = g + w;\n                if (ng < dist[i-1][j] - 1e-9) {\n                    dist[i-1][j] = ng;\n                    prev[i-1][j] = {i,j};\n                    pq.push({ng + heuristic(i-1,j), {i-1,j}});\n                }\n            }\n            // down\n            if (i < GRID_SIZE-1) {\n                double w = v_est[i][j] - C_explore * t_weight / sqrt(v_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                double ng = g + w;\n                if (ng < dist[i+1][j] - 1e-9) {\n                    dist[i+1][j] = ng;\n                    prev[i+1][j] = {i,j};\n                    pq.push({ng + heuristic(i+1,j), {i+1,j}});\n                }\n            }\n            // left\n            if (j > 0) {\n                double w = h_est[i][j-1] - C_explore * t_weight / sqrt(h_cnt[i][j-1] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                double ng = g + w;\n                if (ng < dist[i][j-1] - 1e-9) {\n                    dist[i][j-1] = ng;\n                    prev[i][j-1] = {i,j};\n                    pq.push({ng + heuristic(i, j-1), {i,j-1}});\n                }\n            }\n            // right\n            if (j < GRID_SIZE-1) {\n                double w = h_est[i][j] - C_explore * t_weight / sqrt(h_cnt[i][j] + 1.0) * explore_factor;\n                w = max(1.0, w);\n                double ng = g + w;\n                if (ng < dist[i][j+1] - 1e-9) {\n                    dist[i][j+1] = ng;\n                    prev[i][j+1] = {i,j};\n                    pq.push({ng + heuristic(i, j+1), {i,j+1}});\n                }\n            }\n        }\n\n        // reconstruct path\n        vector<pair<int,int>> path;\n        int ci = ti, cj = tj;\n        while (!(ci == si && cj == sj)) {\n            path.push_back({ci, cj});\n            auto p = prev[ci][cj];\n            ci = p.first;\n            cj = p.second;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n\n        // output string\n        string out;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int di = path[idx].first - path[idx-1].first;\n            int dj = path[idx].second - path[idx-1].second;\n            if (di == -1) out += 'U';\n            else if (di == 1) out += 'D';\n            else if (dj == -1) out += 'L';\n            else if (dj == 1) out += 'R';\n        }\n        cout << out << '\\n' << flush;\n\n        // read feedback\n        int feedback;\n        cin >> feedback;\n\n        // compute predicted length using current estimates (without exploration)\n        double L_pred = 0.0;\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n            if (i1 == i2) {\n                int jmin = min(j1, j2);\n                L_pred += h_est[i1][jmin];\n            } else {\n                int imin = min(i1, i2);\n                L_pred += v_est[imin][j1];\n            }\n        }\n\n        double error = feedback - L_pred;\n        double rel_error = error / max(L_pred, 1.0);\n        rel_error = clamp(rel_error, -3.0, 3.0);\n\n        // update each traversed edge with learning rate that decays by count\n        for (size_t idx = 1; idx < path.size(); ++idx) {\n            int i1 = path[idx-1].first, j1 = path[idx-1].second;\n            int i2 = path[idx].first, j2 = path[idx].second;\n            if (i1 == i2) {\n                int jmin = min(j1, j2);\n                double lr = lr0 / sqrt(h_cnt[i1][jmin] + 1.0);   // count-based decay\n                double new_val = h_est[i1][jmin] + lr * rel_error;\n                h_est[i1][jmin] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                h_cnt[i1][jmin]++;\n            } else {\n                int imin = min(i1, i2);\n                double lr = lr0 / sqrt(v_cnt[imin][j1] + 1.0);\n                double new_val = v_est[imin][j1] + lr * rel_error;\n                v_est[imin][j1] = clamp(new_val, MIN_EDGE, MAX_EDGE);\n                v_cnt[imin][j1]++;\n            }\n        }\n\n        // light smoothing: pull each edge toward its row / column mean\n        for (int i = 0; i < GRID_SIZE; ++i) {\n            double sum = 0.0;\n            for (int j = 0; j < H_EDGES; ++j) sum += h_est[i][j];\n            double avg = sum / H_EDGES;\n            for (int j = 0; j < H_EDGES; ++j)\n                h_est[i][j] += smooth * (avg - h_est[i][j]);\n        }\n        for (int j = 0; j < GRID_SIZE; ++j) {\n            double sum = 0.0;\n            for (int i = 0; i < V_EDGES; ++i) sum += v_est[i][j];\n            double avg = sum / V_EDGES;\n            for (int i = 0; i < V_EDGES; ++i)\n                v_est[i][j] += smooth * (avg - v_est[i][j]);\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPH = 8;\n\nint M;\nvector<string> strs;\nvector<uint64_t> hashes;\nunordered_map<uint64_t, vector<int>> hash_to_ids;\n\nvector<string> mat;\nvector<int> occ;\nint matched = 0;\n\n// faster random\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nuint64_t encode(const string &s) {\n    uint64_t h = 0;\n    for (char c : s) h = (h << 3) | (c - 'A');\n    return h;\n}\n\nvoid collect_hashes(int r, int c, char cell_char, vector<uint64_t> &out) {\n    out.clear();\n    auto get_char = [&](int i, int j) -> char {\n        return (i == r && j == c) ? cell_char : mat[i][j];\n    };\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_col = (c - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int col = (start_col + t) % N;\n                char ch = get_char(r, col);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out.push_back(h);\n        }\n    }\n    for (int len = 2; len <= 12; ++len) {\n        for (int offset = 0; offset < len; ++offset) {\n            int start_row = (r - offset + N) % N;\n            uint64_t h = 0;\n            bool ok = true;\n            for (int t = 0; t < len; ++t) {\n                int row = (start_row + t) % N;\n                char ch = get_char(row, c);\n                if (ch == '.') { ok = false; break; }\n                h = (h << 3) | (ch - 'A');\n            }\n            if (ok) out.push_back(h);\n        }\n    }\n}\n\nint compute_delta(int r, int c, char old_char, char new_char) {\n    static vector<uint64_t> old_hashes, new_hashes;\n    static vector<int> delta_occ(M, 0);\n    static vector<int> affected_ids;\n    affected_ids.clear();\n\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]--;\n            }\n        }\n    }\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (delta_occ[id] == 0) affected_ids.push_back(id);\n                delta_occ[id]++;\n            }\n        }\n    }\n\n    int delta_matched = 0;\n    for (int id : affected_ids) {\n        int new_occ = occ[id] + delta_occ[id];\n        if (occ[id] == 0 && new_occ > 0) delta_matched++;\n        if (occ[id] > 0 && new_occ == 0) delta_matched--;\n    }\n    for (int id : affected_ids) delta_occ[id] = 0;\n    return delta_matched;\n}\n\nvoid apply_change(int r, int c, char new_char) {\n    char old_char = mat[r][c];\n    if (old_char == new_char) return;\n    static vector<uint64_t> old_hashes, new_hashes;\n    if (old_char != '.') {\n        collect_hashes(r, c, old_char, old_hashes);\n        for (uint64_t h : old_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                occ[id]--;\n                if (occ[id] == 0) matched--;\n            }\n        }\n    }\n    mat[r][c] = new_char;\n    if (new_char != '.') {\n        collect_hashes(r, c, new_char, new_hashes);\n        for (uint64_t h : new_hashes) {\n            auto it = hash_to_ids.find(h);\n            if (it == hash_to_ids.end()) continue;\n            for (int id : it->second) {\n                if (occ[id] == 0) matched++;\n                occ[id]++;\n            }\n        }\n    }\n}\n\nvoid compute_initial_state() {\n    fill(occ.begin(), occ.end(), 0);\n    matched = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int len = 2; len <= 12; ++len) {\n            for (int start_col = 0; start_col < N; ++start_col) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int col = (start_col + t) % N;\n                    char ch = mat[r][col];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    for (int c = 0; c < N; ++c) {\n        for (int len = 2; len <= 12; ++len) {\n            for (int start_row = 0; start_row < N; ++start_row) {\n                uint64_t h = 0;\n                bool ok = true;\n                for (int t = 0; t < len; ++t) {\n                    int row = (start_row + t) % N;\n                    char ch = mat[row][c];\n                    if (ch == '.') { ok = false; break; }\n                    h = (h << 3) | (ch - 'A');\n                }\n                if (ok) {\n                    auto it = hash_to_ids.find(h);\n                    if (it != hash_to_ids.end()) {\n                        for (int id : it->second) {\n                            if (occ[id] == 0) matched++;\n                            occ[id]++;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nstruct Placement {\n    vector<int> cells;\n    vector<char> letters;\n};\n\nvoid greedy_initialization(const vector<vector<Placement>> &placements) {\n    mat.assign(N, string(N, '.'));\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int idx : order) {\n        int best_score = -1;\n        int best_p = -1;\n        for (int p = 0; p < (int)placements[idx].size(); ++p) {\n            const auto &pl = placements[idx][p];\n            int score = 0;\n            bool ok = true;\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                char cur = mat[r][c];\n                if (cur == '.') continue;\n                if (cur != pl.letters[t]) { ok = false; break; }\n                score++;\n            }\n            if (ok && score > best_score) {\n                best_score = score;\n                best_p = p;\n            }\n        }\n        if (best_p != -1) {\n            const auto &pl = placements[idx][best_p];\n            for (int t = 0; t < (int)pl.cells.size(); ++t) {\n                int cell = pl.cells[t];\n                int r = cell / N, c = cell % N;\n                mat[r][c] = pl.letters[t];\n            }\n        }\n    }\n    compute_initial_state();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummy;\n    cin >> dummy >> M;\n\n    strs.resize(M);\n    for (int i = 0; i < M; ++i) cin >> strs[i];\n\n    hashes.resize(M);\n    for (int i = 0; i < M; ++i) {\n        hashes[i] = encode(strs[i]);\n        hash_to_ids[hashes[i]].push_back(i);\n    }\n\n    vector<vector<Placement>> placements(M);\n    for (int i = 0; i < M; ++i) {\n        const string &s = strs[i];\n        int len = s.size();\n        placements[i].reserve(800);\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                Placement ph;\n                ph.cells.reserve(len);\n                ph.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int col = (c + t) % N;\n                    ph.cells.push_back(r * N + col);\n                    ph.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(ph));\n                Placement pv;\n                pv.cells.reserve(len);\n                pv.letters.reserve(len);\n                for (int t = 0; t < len; ++t) {\n                    int row = (r + t) % N;\n                    pv.cells.push_back(row * N + c);\n                    pv.letters.push_back(s[t]);\n                }\n                placements[i].push_back(move(pv));\n            }\n        }\n    }\n\n    occ.resize(M, 0);\n\n    // Greedy multiple restarts (fixed number)\n    auto start_time = chrono::steady_clock::now();\n    int best_matched = -1;\n    vector<string> best_mat;\n    for (int restart = 0; restart < 8; ++restart) {\n        greedy_initialization(placements);\n        if (matched > best_matched) {\n            best_matched = matched;\n            best_mat = mat;\n            if (matched == M) break;\n        }\n    }\n\n    // SA only if not all matched and time remains\n    if (best_matched < M) {\n        mat = best_mat;\n        compute_initial_state();\n\n        double T = 2.0;\n        double cooling = 0.9999;\n        int iter = 0;\n        const int MAX_ITERS = 80000;\n        // Maintain list of missing strings to bias moves\n        vector<int> missing_ids;\n        for (int i = 0; i < M; ++i) if (occ[i] == 0) missing_ids.push_back(i);\n\n        while (iter < MAX_ITERS && matched < M) {\n            double elapsed = chrono::duration_cast<chrono::duration<double>>(\n                                 chrono::steady_clock::now() - start_time).count();\n            if (elapsed > 2.9) break;\n            // Choose a cell biased toward missing strings\n            int r, c, idx;\n            if (!missing_ids.empty() && (iter % 4) == 0) {\n                // pick a cell from one of the missing strings' placements\n                int missing_idx = uniform_int_distribution<int>(0, (int)missing_ids.size()-1)(rng);\n                int id = missing_ids[missing_idx];\n                int p = uniform_int_distribution<int>(0, (int)placements[id].size()-1)(rng);\n                int cell = placements[id][p].cells[uniform_int_distribution<int>(0, (int)placements[id][p].cells.size()-1)(rng)];\n                r = cell / N;\n                c = cell % N;\n            } else {\n                r = uniform_int_distribution<int>(0, N-1)(rng);\n                c = uniform_int_distribution<int>(0, N-1)(rng);\n            }\n            char oldc = mat[r][c];\n            char newc;\n            do { newc = 'A' + uniform_int_distribution<int>(0, ALPH-1)(rng); } while (newc == oldc);\n            int delta = compute_delta(r, c, oldc, newc);\n            if (delta > 0) {\n                apply_change(r, c, newc);\n                if (matched > best_matched) {\n                    best_matched = matched;\n                    best_mat = mat;\n                    // update missing_ids\n                    missing_ids.clear();\n                    for (int i = 0; i < M; ++i) if (occ[i] == 0) missing_ids.push_back(i);\n                }\n            } else if (delta == 0) {\n                if (uniform_int_distribution<int>(0,9)(rng) == 0) {\n                    apply_change(r, c, newc);\n                }\n            }\n            T *= cooling;\n            iter++;\n        }\n    }\n\n    // If all matched, remove unnecessary cells greedily\n    if (best_matched == M) {\n        mat = best_mat;\n        compute_initial_state();\n        // Try to remove cells that are not essential for any string\n        // We'll use multiple passes\n        vector<int> cells(N * N);\n        iota(cells.begin(), cells.end(), 0);\n        for (int pass = 0; pass < 15; ++pass) {\n            shuffle(cells.begin(), cells.end(), rng);\n            bool any = false;\n            for (int cell : cells) {\n                int r = cell / N, c = cell % N;\n                if (mat[r][c] == '.') continue;\n                int delta = compute_delta(r, c, mat[r][c], '.');\n                if (delta == 0) {\n                    apply_change(r, c, '.');\n                    any = true;\n                }\n            }\n            if (!any) break;\n        }\n        best_mat = mat;\n    }\n\n    for (int i = 0; i < N; ++i) cout << best_mat[i] << \"\\n\";\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing namespace chrono;\n\nconst int INF = 1e9;\nconst int MAXR = 5000;\nconst double TIME_LIMIT = 2.9;\n\nint N, si, sj;\nvector<string> grid;\nint R;\nvector<pair<int,int>> pos;\nvector<int> weight;\nvector<vector<int>> adj;\nint id[70][70];\nvector<bitset<MAXR>> cover_groups;\n\nvoid read_input() {\n    cin >> N >> si >> sj;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    R = 0;\n    memset(id, -1, sizeof(id));\n    pos.clear(); weight.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R;\n                pos.emplace_back(i, j);\n                weight.push_back(grid[i][j] - '0');\n                ++R;\n            }\n        }\n    }\n    adj.assign(R, vector<int>());\n    int di[] = {-1,1,0,0}, dj[] = {0,0,-1,1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == '#') continue;\n            int u = id[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && grid[ni][nj] != '#') {\n                    adj[u].push_back(id[ni][nj]);\n                }\n            }\n        }\n    }\n}\n\nvector<vector<int>> compute_all_pairs() {\n    vector<vector<int>> dist(R, vector<int>(R, INF));\n    for (int s = 0; s < R; ++s) {\n        vector<int> d(R, INF);\n        d[s] = 0;\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top(); pq.pop();\n            if (cd != d[u]) continue;\n            for (int v : adj[u]) {\n                int nd = cd + weight[v];\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n        dist[s] = d;\n    }\n    return dist;\n}\n\nvector<vector<int>> extract_segments(int orient) {\n    vector<vector<int>> segs;\n    if (orient == 0) {\n        for (int i = 0; i < N; ++i) {\n            int j = 0;\n            while (j < N) {\n                if (grid[i][j] == '#') { ++j; continue; }\n                int start = j;\n                while (j < N && grid[i][j] != '#') ++j;\n                vector<int> seg;\n                for (int k = start; k < j; ++k) seg.push_back(id[i][k]);\n                segs.push_back(seg);\n            }\n        }\n    } else {\n        for (int j = 0; j < N; ++j) {\n            int i = 0;\n            while (i < N) {\n                if (grid[i][j] == '#') { ++i; continue; }\n                int start = i;\n                while (i < N && grid[i][j] != '#') ++i;\n                vector<int> seg;\n                for (int k = start; k < i; ++k) seg.push_back(id[k][j]);\n                segs.push_back(seg);\n            }\n        }\n    }\n    return segs;\n}\n\nvector<vector<int>> build_all_groups(const vector<vector<int>>& h,\n                                     const vector<vector<int>>& v,\n                                     int start_id) {\n    vector<vector<int>> groups = h;\n    groups.insert(groups.end(), v.begin(), v.end());\n    groups.push_back({start_id});\n    return groups;\n}\n\nvector<int> greedy_set_cover(const vector<vector<int>>& groups, mt19937& rng) {\n    int G = groups.size();\n    vector<bitset<MAXR>> cover(G);\n    for (int g = 0; g < G; ++g) {\n        bitset<MAXR> bs;\n        for (int u : groups[g]) bs.set(u);\n        cover[g] = bs;\n    }\n    bitset<MAXR> uncovered;\n    for (int u = 0; u < R; ++u) uncovered.set(u);\n    vector<int> selected;\n    int start_group = G-1;\n    selected.push_back(start_group);\n    uncovered &= ~cover[start_group];\n    while (uncovered.any()) {\n        vector<int> candidates;\n        int best_cnt = 0;\n        for (int g = 0; g < G; ++g) {\n            if (find(selected.begin(), selected.end(), g) != selected.end()) continue;\n            int cnt = (cover[g] & uncovered).count();\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                candidates = {g};\n            } else if (cnt == best_cnt) {\n                candidates.push_back(g);\n            }\n        }\n        if (candidates.empty()) break;\n        int pick = candidates[rng() % candidates.size()];\n        selected.push_back(pick);\n        uncovered &= ~cover[pick];\n    }\n    return selected;\n}\n\nvector<int> remove_redundant_cover(const vector<int>& sel, const vector<vector<int>>& groups) {\n    bitset<MAXR> covered;\n    for (int idx : sel) {\n        for (int u : groups[idx]) covered.set(u);\n    }\n    vector<int> new_sel = sel;\n    bool removed = true;\n    while (removed) {\n        removed = false;\n        for (int i = (int)new_sel.size()-2; i >= 0; --i) {\n            int idx = new_sel[i];\n            bitset<MAXR> tmp = covered;\n            for (int u : groups[idx]) tmp.reset(u);\n            if (tmp.count() == (size_t)R) {\n                new_sel.erase(new_sel.begin() + i);\n                removed = true;\n                covered = tmp;\n                break;\n            }\n        }\n    }\n    return new_sel;\n}\n\nvector<int> replace_cover(const vector<int>& sel, const vector<vector<int>>& groups) {\n    bitset<MAXR> covered;\n    for (int idx : sel) {\n        for (int u : groups[idx]) covered.set(u);\n    }\n    vector<int> best_sel = sel;\n    for (int pos = 0; pos < (int)best_sel.size()-1; ++pos) {\n        int idx = best_sel[pos];\n        bitset<MAXR> without = covered;\n        for (int u : groups[idx]) without.reset(u);\n        int need = (int)(covered & ~without).count();\n        if (need == 0) continue;\n        int best_g = -1;\n        int best_new_cover = 0;\n        for (int g = 0; g < (int)groups.size(); ++g) {\n            if (g == idx) continue;\n            if (find(best_sel.begin(), best_sel.end(), g) != best_sel.end()) continue;\n            bitset<MAXR> add = cover_groups[g] & ~without;\n            int cnt = add.count();\n            if (cnt > best_new_cover) {\n                best_new_cover = cnt;\n                best_g = g;\n            }\n        }\n        if (best_g != -1 && best_new_cover >= need) {\n            vector<int> new_sel = best_sel;\n            new_sel[pos] = best_g;\n            bitset<MAXR> new_covered;\n            for (int i : new_sel) new_covered |= cover_groups[i];\n            if (new_covered.count() == (size_t)R) {\n                best_sel = new_sel;\n                covered = new_covered;\n            }\n        }\n    }\n    return best_sel;\n}\n\nvector<vector<int>> build_group_dist(const vector<int>& sel,\n                                     const vector<vector<int>>& groups,\n                                     const vector<vector<int>>& dist) {\n    int S = sel.size();\n    vector<vector<int>> D(S, vector<int>(S, INF));\n    for (int i = 0; i < S; ++i) {\n        D[i][i] = 0;\n        for (int j = i+1; j < S; ++j) {\n            int best = INF;\n            for (int u : groups[sel[i]]) {\n                for (int v : groups[sel[j]]) {\n                    best = min(best, dist[u][v]);\n                }\n            }\n            D[i][j] = D[j][i] = best;\n        }\n    }\n    return D;\n}\n\nvector<int> nearest_neighbour_order(const vector<vector<int>>& D) {\n    int S = D.size();\n    if (S == 0) return {};\n    vector<bool> used(S, false);\n    vector<int> order;\n    order.push_back(0);\n    used[0] = true;\n    int cur = 0;\n    for (int step = 1; step < S; ++step) {\n        int best = -1, bestd = INF;\n        for (int v = 0; v < S; ++v) {\n            if (!used[v] && D[cur][v] < bestd) {\n                bestd = D[cur][v];\n                best = v;\n            }\n        }\n        order.push_back(best);\n        used[best] = true;\n        cur = best;\n    }\n    return order;\n}\n\nvector<int> cheapest_insertion_order(const vector<vector<int>>& D) {\n    int S = D.size();\n    if (S <= 1) return {0};\n    vector<bool> used(S, false);\n    vector<int> tour;\n    tour.push_back(0);\n    used[0] = true;\n    int second = -1;\n    int best_init = INF;\n    for (int v = 1; v < S; ++v) {\n        if (D[0][v] < best_init) {\n            best_init = D[0][v];\n            second = v;\n        }\n    }\n    tour.push_back(second);\n    used[second] = true;\n    for (int step = 2; step < S; ++step) {\n        int best_cost = INF;\n        int best_v = -1;\n        int best_pos = -1;\n        for (int v = 0; v < S; ++v) {\n            if (used[v]) continue;\n            for (size_t pos = 0; pos < tour.size(); ++pos) {\n                int a = tour[pos];\n                int b = (pos+1 < tour.size()) ? tour[pos+1] : tour[0];\n                int increase = D[a][v] + D[v][b] - D[a][b];\n                if (increase < best_cost) {\n                    best_cost = increase;\n                    best_v = v;\n                    best_pos = pos+1;\n                }\n            }\n        }\n        tour.insert(tour.begin() + best_pos, best_v);\n        used[best_v] = true;\n    }\n    return tour;\n}\n\n// 2-opt and 3-opt improvement\nvoid two_opt(vector<int>& order, const vector<vector<int>>& D) {\n    int S = order.size();\n    bool improved;\n    do {\n        improved = false;\n        for (int i = 1; i < S-1; ++i) {\n            for (int j = i+1; j < S; ++j) {\n                int a = order[i-1];\n                int b = order[i];\n                int c = order[j];\n                int d = (j+1 < S) ? order[j+1] : order[0];\n                int old = D[a][b] + D[c][d];\n                int nw = D[a][c] + D[b][d];\n                if (nw < old) {\n                    reverse(order.begin() + i, order.begin() + j + 1);\n                    improved = true;\n                }\n            }\n        }\n    } while (improved);\n}\n\nvoid three_opt(vector<int>& order, const vector<vector<int>>& D) {\n    int S = order.size();\n    bool improved;\n    do {\n        improved = false;\n        for (int i = 1; i < S-2; ++i) {\n            for (int j = i+1; j < S-1; ++j) {\n                for (int k = j+1; k < S; ++k) {\n                    int a = order[i-1];\n                    int b = order[i];\n                    int c = order[j];\n                    int d = order[j+1];\n                    int e = order[k];\n                    int f = (k+1 < S) ? order[k+1] : order[0];\n                    int cur = D[a][b] + D[c][d] + D[e][f];\n                    int cand1 = D[a][c] + D[b][d] + D[e][f];\n                    if (cand1 < cur) {\n                        reverse(order.begin() + i, order.begin() + j + 1);\n                        improved = true;\n                        goto next;\n                    }\n                    {\n                        int cand2 = D[a][b] + D[c][e] + D[d][f];\n                        if (cand2 < cur) {\n                            reverse(order.begin() + j+1, order.begin() + k+1);\n                            improved = true;\n                            goto next;\n                        }\n                    }\n                    next:;\n                }\n            }\n        }\n    } while (improved);\n}\n\n// improve order by SA starting from given init\nvector<int> improve_order(const vector<int>& init, const vector<vector<int>>& D, mt19937& rng, double budget) {\n    int S = init.size();\n    if (S <= 2) return init;\n    vector<int> cur = init;\n    two_opt(cur, D);\n    three_opt(cur, D);\n    vector<int> best = cur;\n    // evaluate initial best cost\n    int best_cost = 0;\n    for (size_t i = 0; i < cur.size(); ++i) {\n        int a = cur[i];\n        int b = (i+1 < cur.size()) ? cur[i+1] : cur[0];\n        best_cost += D[a][b];\n    }\n    auto start_time = high_resolution_clock::now();\n    double temp = 500.0;\n    int steps = 0;\n    const int MAX_STEPS = 8000;\n    while (steps < MAX_STEPS) {\n        double elapsed = duration_cast<duration<double>>(high_resolution_clock::now() - start_time).count();\n        if (elapsed > budget) break;\n        ++steps;\n        int i = uniform_int_distribution<int>(1, S-2)(rng);\n        int j = uniform_int_distribution<int>(i+1, S-1)(rng);\n        vector<int> nxt = cur;\n        reverse(nxt.begin() + i, nxt.begin() + j + 1);\n        int a = cur[i-1], b = cur[i], c = cur[j];\n        int d = (j+1 < S) ? cur[j+1] : cur[0];\n        int old = D[a][b] + D[c][d];\n        int na = nxt[i-1], nb = nxt[i], nc = nxt[j];\n        int nd = (j+1 < S) ? nxt[j+1] : nxt[0];\n        int nw = D[na][nb] + D[nc][nd];\n        if (nw < old || uniform_real_distribution<double>(0,1)(rng) < exp((old-nw)/temp)) {\n            cur = nxt;\n            if (nw < old) {\n                // full tour cost update not needed for acceptance, but we recompute later for best\n            }\n        }\n        temp *= 0.998;\n    }\n    // improve with 3-opt one more time\n    three_opt(cur, D);\n    // evaluate final cost\n    int cur_cost = 0;\n    for (size_t i = 0; i < cur.size(); ++i) {\n        int a = cur[i];\n        int b = (i+1 < cur.size()) ? cur[i+1] : cur[0];\n        cur_cost += D[a][b];\n    }\n    if (cur_cost < best_cost) best = cur;\n    return best;\n}\n\n// local refinement of selected nodes within each segment\npair<int, vector<int>> refine_selected(const vector<int>& order,\n                                        const vector<int>& sel,\n                                        const vector<vector<int>>& groups,\n                                        const vector<vector<int>>& dist,\n                                        const vector<int>& init_selected) {\n    int S = order.size();\n    vector<int> selected = init_selected;\n    // for each intermediate group (1..S-2), try to shift chosen node along the segment\n    for (int pos = 1; pos < S-1; ++pos) {\n        int g = sel[order[pos]];\n        const auto& seg = groups[g];\n        int cur = selected[pos];\n        int prev = selected[pos-1];\n        int nxt = selected[pos+1];\n        int best = dist[prev][cur] + dist[cur][nxt];\n        int best_node = cur;\n        // try all nodes in same segment\n        for (int u : seg) {\n            int cand = dist[prev][u] + dist[u][nxt];\n            if (cand < best) {\n                best = cand;\n                best_node = u;\n            }\n        }\n        selected[pos] = best_node;\n    }\n    // also try the first group (only connection to next and last)\n    if (S > 2) {\n        int g0 = sel[order[0]];\n        const auto& seg0 = groups[g0];\n        int cur0 = selected[0];\n        int nxt0 = selected[1];\n        int last = selected[S-1];\n        int best = dist[last][cur0] + dist[cur0][nxt0];\n        int best_node = cur0;\n        for (int u : seg0) {\n            int cand = dist[last][u] + dist[u][nxt0];\n            if (cand < best) {\n                best = cand;\n                best_node = u;\n            }\n        }\n        selected[0] = best_node;\n    }\n    // compute total cost\n    int total = 0;\n    for (int k = 0; k < S-1; ++k) total += dist[selected[k]][selected[k+1]];\n    total += dist[selected[S-1]][selected[0]];\n    return {total, selected};\n}\n\npair<int, vector<int>> select_nodes(const vector<int>& order,\n                                     const vector<int>& sel,\n                                     const vector<vector<int>>& groups,\n                                     const vector<vector<int>>& dist,\n                                     int start_id) {\n    int S = order.size();\n    if (S == 0) return {0, {}};\n    vector<const vector<int>*> grps(S);\n    for (int i = 0; i < S; ++i) grps[i] = &groups[sel[order[i]]];\n    vector<vector<int>> dp(S);\n    vector<vector<int>> prev(S);\n    const auto& g0 = *grps[0];\n    int sz0 = g0.size();\n    dp[0].assign(sz0, INF);\n    int start_idx = -1;\n    for (int i = 0; i < sz0; ++i) if (g0[i] == start_id) { start_idx = i; break; }\n    if (start_idx == -1) {\n        start_idx = 0;\n        dp[0][0] = 0;\n    } else {\n        dp[0][start_idx] = 0;\n    }\n    for (int pos = 1; pos < S; ++pos) {\n        const auto& cur = *grps[pos];\n        const auto& prv = *grps[pos-1];\n        int cs = cur.size(), ps = prv.size();\n        dp[pos].assign(cs, INF);\n        prev[pos].assign(cs, -1);\n        for (int vi = 0; vi < cs; ++vi) {\n            int v = cur[vi];\n            int best = INF, best_ui = -1;\n            for (int ui = 0; ui < ps; ++ui) {\n                int u = prv[ui];\n                int cand = dp[pos-1][ui] + dist[u][v];\n                if (cand < best) { best = cand; best_ui = ui; }\n            }\n            dp[pos][vi] = best;\n            prev[pos][vi] = best_ui;\n        }\n    }\n    const auto& last = *grps[S-1];\n    int ls = last.size();\n    int best_final = INF, best_li = -1;\n    for (int vi = 0; vi < ls; ++vi) {\n        int v = last[vi];\n        int cand = dp[S-1][vi] + dist[v][start_id];\n        if (cand < best_final) { best_final = cand; best_li = vi; }\n    }\n    vector<int> selected(S);\n    selected[S-1] = last[best_li];\n    for (int pos = S-1; pos >= 1; --pos) {\n        int ui = prev[pos][best_li];\n        selected[pos-1] = (*grps[pos-1])[ui];\n        best_li = ui;\n    }\n    // refine selected nodes locally within each segment\n    auto refined = refine_selected(order, sel, groups, dist, selected);\n    return refined;\n}\n\nstring get_path(int from, int to, const vector<vector<int>>&) {\n    if (from == to) return \"\";\n    vector<int> d(R, INF);\n    vector<int> parent(R, -1);\n    vector<char> move_char(R, 0);\n    d[from] = 0;\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    pq.emplace(0, from);\n    while (!pq.empty()) {\n        auto [cd, u] = pq.top(); pq.pop();\n        if (cd != d[u]) continue;\n        if (u == to) break;\n        for (int v : adj[u]) {\n            int nd = cd + weight[v];\n            if (nd < d[v]) {\n                d[v] = nd;\n                parent[v] = u;\n                int dx = pos[v].first - pos[u].first;\n                int dy = pos[v].second - pos[u].second;\n                if (dx == -1) move_char[v] = 'U';\n                else if (dx == 1) move_char[v] = 'D';\n                else if (dy == -1) move_char[v] = 'L';\n                else if (dy == 1) move_char[v] = 'R';\n                pq.emplace(nd, v);\n            }\n        }\n    }\n    string path;\n    int cur = to;\n    while (cur != from) {\n        path.push_back(move_char[cur]);\n        cur = parent[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto global_start = high_resolution_clock::now();\n    read_input();\n    auto dist = compute_all_pairs();\n    int start_id = id[si][sj];\n    auto h_segs = extract_segments(0);\n    auto v_segs = extract_segments(1);\n    auto groups = build_all_groups(h_segs, v_segs, start_id);\n\n    cover_groups.resize(groups.size());\n    for (size_t g = 0; g < groups.size(); ++g) {\n        bitset<MAXR> bs;\n        for (int u : groups[g]) bs.set(u);\n        cover_groups[g] = bs;\n    }\n\n    mt19937 rng(1234567);\n    int best_total = INF;\n    string best_output;\n    int trial = 0;\n    while (true) {\n        double elapsed = duration_cast<duration<double>>(high_resolution_clock::now() - global_start).count();\n        if (elapsed > TIME_LIMIT) break;\n        if (trial >= 50) break;\n        ++trial;\n        auto sel = greedy_set_cover(groups, rng);\n        sel = remove_redundant_cover(sel, groups);\n        sel = replace_cover(sel, groups);\n        if (sel.empty()) continue;\n        auto D = build_group_dist(sel, groups, dist);\n        // generate initial orders\n        vector<int> order1 = nearest_neighbour_order(D);\n        vector<int> order2 = cheapest_insertion_order(D);\n        double remaining = TIME_LIMIT - elapsed;\n        double sa_budget = min(remaining * 0.25, 0.25);\n        vector<int> improved1 = improve_order(order1, D, rng, sa_budget);\n        vector<int> improved2 = improve_order(order2, D, rng, sa_budget);\n        // evaluate\n        int cost1 = 0;\n        for (size_t i = 0; i < improved1.size(); ++i) {\n            int a = improved1[i];\n            int b = (i+1 < improved1.size()) ? improved1[i+1] : improved1[0];\n            cost1 += D[a][b];\n        }\n        int cost2 = 0;\n        for (size_t i = 0; i < improved2.size(); ++i) {\n            int a = improved2[i];\n            int b = (i+1 < improved2.size()) ? improved2[i+1] : improved2[0];\n            cost2 += D[a][b];\n        }\n        vector<int> best_order = (cost1 < cost2) ? improved1 : improved2;\n        // also try a random order and improve?\n        // but limited time; skip unless we have extra budget\n        auto [cost, selected_nodes] = select_nodes(best_order, sel, groups, dist, start_id);\n        if (cost < best_total) {\n            best_total = cost;\n            string ans;\n            for (size_t k = 0; k < best_order.size()-1; ++k) {\n                ans += get_path(selected_nodes[k], selected_nodes[k+1], dist);\n            }\n            ans += get_path(selected_nodes.back(), selected_nodes[0], dist);\n            best_output = ans;\n        }\n    }\n    if (best_output.empty()) {\n        best_output = \"\";\n    }\n    cout << best_output << endl;\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ========== constants ==========\nconst double INF = 1e9;\nconst double LR0 = 0.5;           // base learning rate\nconst double EXPLORE = 1.0;       // exploration coefficient for UCB\n\nint N, M, K, R;\nvector<vector<int>> d;           // N x K difficulty\nvector<vector<int>> preds, succs;\nvector<int> rem_pred;\n\n// state\nvector<int> status;              // -1: not started, 0: in progress, 1: done\nvector<int> start_day;\nvector<int> worker_of_task;\nvector<int> actual_dur;\nvector<double> pred_dur_at_start;\nvector<int> cur_task;            // -1 if idle\nvector<vector<double>> skill_est; // M x K\nvector<vector<int>> skill_cnt;   // how many times each skill was updated (per worker)\n\n// estimates\nvector<double> est_dur;          // current estimated duration of each task (for scheduling)\n\n// ========== helpers ==========\ninline double predict_dur(int task, int worker) {\n    double w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) w += diff;\n    }\n    return (w == 0.0) ? 1.0 : (1.0 + w);\n}\n\ninline double ucb_score(int task, int worker, int day) {\n    double base = predict_dur(task, worker);\n    double exploration = EXPLORE * sqrt(log(day + 1.0) / (1.0 + skill_cnt[worker][0])); // count total assignments roughly\n    return base - exploration;   // lower is better\n}\n\n// update skill estimates after observing actual duration\nvoid update_skills(int worker, int task, int actual_t) {\n    int obs_w = max(0, actual_t - 1);\n    // predicted w before task\n    double pred_w = 0.0;\n    for (int k = 0; k < K; ++k) {\n        double diff = d[task][k] - skill_est[worker][k];\n        if (diff > 0) pred_w += diff;\n    }\n    double error = pred_w - obs_w;   // positive -> overestimate\n    // per-skill learning rate\n    auto lr = [&](int k) -> double {\n        return LR0 / sqrt(1.0 + skill_cnt[worker][k]);\n    };\n    if (obs_w == 0) {\n        // no deficiency -> increase skills that were lacking\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                skill_est[worker][k] += lr(k) * (d[task][k] - skill_est[worker][k]);\n                skill_cnt[worker][k]++;\n            }\n        }\n    } else {\n        // deficiency existed\n        double scale = (pred_w > 0) ? error / pred_w : 0.0;\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill_est[worker][k]) {\n                skill_est[worker][k] += lr(k) * scale;\n                skill_cnt[worker][k]++;\n            }\n        }\n        // case: predicted no deficiency but actually deficiency existed\n        if (pred_w == 0.0 && obs_w > 0) {\n            for (int k = 0; k < K; ++k) {\n                if (skill_est[worker][k] > d[task][k]) {\n                    skill_est[worker][k] = max(0.0, skill_est[worker][k] - lr(k) * 0.5);\n                    skill_cnt[worker][k]++;\n                }\n            }\n        }\n    }\n    // clamp\n    for (int k = 0; k < K; ++k) {\n        if (skill_est[worker][k] < 0) skill_est[worker][k] = 0;\n        if (skill_est[worker][k] > 200) skill_est[worker][k] = 200;\n    }\n}\n\n// ========== main ==========\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // read input\n    cin >> N >> M >> K >> R;\n    d.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < K; ++j)\n            cin >> d[i][j];\n\n    preds.assign(N, vector<int>());\n    succs.assign(N, vector<int>());\n    rem_pred.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        preds[v].push_back(u);\n        succs[u].push_back(v);\n        rem_pred[v]++;\n    }\n\n    // initialize state\n    status.assign(N, -1);\n    start_day.assign(N, 0);\n    worker_of_task.assign(N, -1);\n    actual_dur.assign(N, 0);\n    pred_dur_at_start.assign(N, 0.0);\n    cur_task.assign(M, -1);\n    skill_est.assign(M, vector<double>(K, 0.0));\n    skill_cnt.assign(M, vector<int>(K, 0));\n\n    // better initial skill: use average task difficulty per dimension\n    vector<double> avg_skill(K, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            avg_skill[k] += d[i][k];\n    for (int k = 0; k < K; ++k) avg_skill[k] /= N;\n    for (int j = 0; j < M; ++j)\n        for (int k = 0; k < K; ++k)\n            skill_est[j][k] = avg_skill[k] * (0.8 + 0.4 * (double)rand() / RAND_MAX); // perturb\n\n    // main loop\n    int day = 1;\n    while (true) {\n        // ---- compute estimated duration and critical path weights ----\n        est_dur.assign(N, 0.0);\n        vector<double> finish_time(N, 0.0);\n        // forward pass (topological order)\n        for (int i = 0; i < N; ++i) {\n            double max_pred_finish = 0.0;\n            for (int p : preds[i]) {\n                if (finish_time[p] > max_pred_finish)\n                    max_pred_finish = finish_time[p];\n            }\n            double est_start_i = max_pred_finish + 1.0;\n            if (status[i] == 1) {\n                est_dur[i] = actual_dur[i];\n                finish_time[i] = start_day[i] + actual_dur[i] - 1.0;\n            } else if (status[i] == 0) {\n                double remain = max(0.0, pred_dur_at_start[i] - (day - start_day[i]));\n                est_dur[i] = remain;\n                // finish_time remains same? We'll keep it consistent: started tasks are already scheduled.\n                finish_time[i] = day + remain - 1.0;\n            } else {\n                // unstarted: find the best worker (optimistic)\n                double best = INF;\n                for (int j = 0; j < M; ++j) {\n                    double ddd = predict_dur(i, j);\n                    if (ddd < best) best = ddd;\n                }\n                est_dur[i] = best;\n                finish_time[i] = est_start_i + best - 1.0;\n            }\n        }\n\n        // ---- compute criticality (longest path to leaf) ----\n        vector<double> criticality(N, 0.0);\n        for (int i = N - 1; i >= 0; --i) {\n            double max_succ = 0.0;\n            for (int s : succs[i]) {\n                if (criticality[s] > max_succ) max_succ = criticality[s];\n            }\n            criticality[i] = est_dur[i] + max_succ;\n        }\n\n        // ---- ready tasks ----\n        vector<int> ready;\n        for (int i = 0; i < N; ++i)\n            if (status[i] == -1 && rem_pred[i] == 0) ready.push_back(i);\n\n        // ---- sort by criticality (descending) ----\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (criticality[a] != criticality[b])\n                return criticality[a] > criticality[b];\n            return a < b;\n        });\n\n        // ---- idle workers ----\n        vector<int> idle;\n        for (int j = 0; j < M; ++j) if (cur_task[j] == -1) idle.push_back(j);\n\n        // ---- assignment ----\n        vector<int> assign_out; // flattened: worker, task (0-index)\n        for (int task : ready) {\n            if (idle.empty()) break;\n            // pick best idle worker via UCB\n            int best_w = -1;\n            double best_val = INF;\n            for (int j : idle) {\n                double u = ucb_score(task, j, day);\n                if (u < best_val) {\n                    best_val = u;\n                    best_w = j;\n                }\n            }\n            // assign\n            assign_out.push_back(best_w);\n            assign_out.push_back(task);\n            cur_task[best_w] = task;\n            start_day[task] = day;\n            worker_of_task[task] = best_w;\n            pred_dur_at_start[task] = predict_dur(task, best_w);\n            status[task] = 0;\n            // update counts (roughly)\n            for (int k = 0; k < K; ++k) skill_cnt[best_w][k]++; // increment all\n            // remove worker from idle\n            auto it = find(idle.begin(), idle.end(), best_w);\n            if (it != idle.end()) {\n                *it = idle.back();\n                idle.pop_back();\n            }\n        }\n\n        // ---- output ----\n        int m = assign_out.size() / 2;\n        cout << m;\n        for (int x : assign_out) cout << ' ' << (x + 1);\n        cout << '\\n';\n        cout.flush();\n\n        // ---- read response ----\n        int dummy;\n        cin >> dummy;\n        if (dummy == -1) break;\n\n        // ---- process completions ----\n        for (int i = 0; i < dummy; ++i) {\n            int worker;\n            cin >> worker;\n            --worker;\n            int task = cur_task[worker];\n            int duration = day - start_day[task] + 1;\n\n            status[task] = 1;\n            actual_dur[task] = duration;\n            cur_task[worker] = -1;\n\n            // update skill estimates\n            update_skills(worker, task, duration);\n\n            // update remaining predecessors of successors\n            for (int s : succs[task]) {\n                rem_pred[s]--;\n            }\n        }\n        ++day;\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst int DEPOT_ID = 2000;\nconst int NUM_ORDERS = 1000;\nconst int NUM_SELECT = 50;\nconst int CENTER = 400;\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// Compute total distance of a route (array of node ids)\nint total_distance(const vector<int>& route, const vector<vector<int>>& dist) {\n    int sum = 0;\n    for (size_t i = 0; i + 1 < route.size(); ++i)\n        sum += dist[route[i]][route[i + 1]];\n    return sum;\n}\n\n// Check that for each order, pickup appears before delivery in the route\nbool is_feasible(const vector<int>& route) {\n    vector<int> first(2000, -1), second(2000, -1);\n    for (size_t i = 0; i < route.size(); ++i) {\n        int node = route[i];\n        if (node == DEPOT_ID) continue;\n        int idx = node;\n        if (node % 2 == 0) { // pickup\n            if (first[idx] != -1) return false;\n            first[idx] = (int)i;\n        } else { // delivery\n            if (second[idx] != -1) return false;\n            second[idx] = (int)i;\n        }\n    }\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int p = 2 * i, d = 2 * i + 1;\n        if (first[p] == -1 && second[d] == -1) continue; // order not selected\n        if (first[p] == -1 || second[d] == -1) return false; // incomplete order\n        if (first[p] > second[d]) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Read input\n    vector<pair<int,int>> pickup(NUM_ORDERS), delivery(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int a, b, c, d;\n        cin >> a >> b >> c >> d;\n        pickup[i] = {a, b};\n        delivery[i] = {c, d};\n    }\n\n    // Node coordinates: order i -> pickup 2*i, delivery 2*i+1, depot = 2000\n    vector<int> node_x(2001), node_y(2001);\n    node_x[DEPOT_ID] = node_y[DEPOT_ID] = CENTER;\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        node_x[2 * i] = pickup[i].first;\n        node_y[2 * i] = pickup[i].second;\n        node_x[2 * i + 1] = delivery[i].first;\n        node_y[2 * i + 1] = delivery[i].second;\n    }\n\n    // Precompute distance matrix (2001 x 2001)\n    vector<vector<int>> dist(2001, vector<int>(2001));\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist[i][j] = manhattan(node_x[i], node_y[i], node_x[j], node_y[j]);\n\n    // ---------- Phase 1: Select 50 orders ----------\n    // Score used: distance(pickup, depot) + distance(delivery, depot)\n    vector<pair<int,int>> order_score(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; ++i) {\n        int s = dist[2 * i][DEPOT_ID] + dist[2 * i + 1][DEPOT_ID];\n        order_score[i] = {s, i};\n    }\n    sort(order_score.begin(), order_score.end());\n    vector<bool> selected(NUM_ORDERS, false);\n    for (int k = 0; k < NUM_SELECT; ++k)\n        selected[order_score[k].second] = true;\n\n    // ---------- Phase 2: Greedy Cheapest Insertion ----------\n    vector<int> route = {DEPOT_ID, DEPOT_ID};\n    int total = 0;\n    for (int iter = 0; iter < NUM_SELECT; ++iter) {\n        // find the order (among unselected) that minimizes insertion cost\n        int best_o = -1, best_pos = -1, best_inc = INT_MAX;\n        for (int i = 0; i < NUM_ORDERS; ++i) {\n            if (!selected[i]) continue; // already in route? need to track used\n        }\n        // Actually we need to process only the selected orders\n        // Build a list of selected order indices\n    }\n    // Better: use list of selected orders\n    vector<int> order_list;\n    for (auto& p : order_score)\n        if (selected[p.second]) order_list.push_back(p.second);\n\n    for (int o : order_list) {\n        int p = 2 * o;\n        int d = 2 * o + 1;\n        int L = route.size();\n        int best_pos = -1, best_inc = INT_MAX;\n        for (int pos = 0; pos < L - 1; ++pos) {\n            int left = route[pos];\n            int right = route[pos + 1];\n            int inc = -dist[left][right] + dist[left][p] + dist[p][d] + dist[d][right];\n            if (inc < best_inc) {\n                best_inc = inc;\n                best_pos = pos;\n            }\n        }\n        route.insert(route.begin() + best_pos + 1, {p, d});\n        total += best_inc;\n        selected[o] = false; // mark as used (but we iterate each once)\n    }\n    // After insertion, route size = 102 (2 depots + 100 nodes)\n    // Verify feasibility\n    if (!is_feasible(route)) {\n        cerr << \"ERROR: Infeasible initial route\" << endl;\n        return 1;\n    }\n\n    // ---------- Phase 3: Local Search (Simulated Annealing) ----------\n    vector<int> best_route = route;\n    int best_total = total;\n    double temperature = 500.0;\n    double cooling = 0.9999;\n    auto start_time = chrono::steady_clock::now();\n    double elapsed = 0.0;\n    int iteration = 0;\n\n    while (elapsed < 1.9 && iteration < 100000) {\n        ++iteration;\n        // pick random move: 0 = relocate node, 1 = swap two nodes\n        int move_type = rng() % 2;\n        vector<int> new_route = route;\n        int n = (int)new_route.size();\n        // only consider positions 1..n-2 (non-depot)\n        int i = rng() % (n - 2) + 1;\n        int j = rng() % (n - 2) + 1;\n        if (i == j) continue;\n\n        if (move_type == 0) {\n            // relocate node at i to position j\n            int node = new_route[i];\n            new_route.erase(new_route.begin() + i);\n            // adjust j if necessary (since size decreased by 1)\n            if (j > (int)new_route.size()) j = new_route.size();\n            new_route.insert(new_route.begin() + j, node);\n        } else {\n            // swap nodes at i and j\n            swap(new_route[i], new_route[j]);\n        }\n\n        // feasibility check\n        if (!is_feasible(new_route)) continue;\n\n        int new_total = total_distance(new_route, dist);\n        int delta = new_total - total;\n\n        // acceptance criterion\n        if (delta < 0 || (exp(-delta / temperature) > (double)rng() / rng.max())) {\n            route = new_route;\n            total = new_total;\n            if (total < best_total) {\n                best_total = total;\n                best_route = route;\n            }\n        }\n\n        temperature *= cooling;\n        elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    }\n\n    // ---------- Phase 4: Output ----------\n    // Extract order indices in appearance order from best_route\n    vector<int> out_orders;\n    for (int node : best_route) {\n        if (node == DEPOT_ID) continue;\n        int o = node / 2;\n        if (out_orders.empty() || out_orders.back() != o)\n            out_orders.push_back(o);\n    }\n    // Ensure exactly 50 orders\n    if ((int)out_orders.size() != 50) {\n        // fallback: use the initial selected order list\n        out_orders = order_list;\n    }\n\n    cout << 50;\n    for (int o : out_orders) cout << ' ' << o + 1;\n    cout << '\\n';\n\n    cout << best_route.size();\n    for (int node : best_route) {\n        // Safety clamp (should be within [0,800] always)\n        int x = node_x[node];\n        int y = node_y[node];\n        if (x < 0) x = 0; if (x > 800) x = 800;\n        if (y < 0) y = 0; if (y > 800) y = 800;\n        cout << ' ' << x << ' ' << y;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> parent, rank;\n    DSU(int n) : parent(n), rank(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int x, int y) {\n        x = find(x);\n        y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) swap(x, y);\n        parent[y] = x;\n        if (rank[x] == rank[y]) ++rank[x];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400, M = 1995;\n\n    vector<pair<int,int>> coord(N);\n    for (int i = 0; i < N; ++i) cin >> coord[i].first >> coord[i].second;\n\n    struct Edge { int u, v, d; };\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v; cin >> u >> v;\n        int dx = coord[u].first - coord[v].first;\n        int dy = coord[u].second - coord[v].second;\n        double dist = sqrt(dx*dx + dy*dy);\n        int d = round(dist);\n        edges[i] = {u, v, d};\n    }\n\n    // ---------- precompute MST based on d ----------\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return edges[a].d < edges[b].d;\n    });\n\n    DSU dsu_mst(N);\n    vector<bool> in_mst(M, false);\n    vector<int> tree_edges; // edge ids of MST\n    for (int idx : order) {\n        auto& e = edges[idx];\n        if (dsu_mst.unite(e.u, e.v)) {\n            in_mst[idx] = true;\n            tree_edges.push_back(idx);\n            if ((int)tree_edges.size() == N-1) break;\n        }\n    }\n\n    // ---------- build tree adjacency and LCA ----------\n    vector<vector<pair<int,int>>> adj(N);\n    for (int idx : tree_edges) {\n        auto& e = edges[idx];\n        adj[e.u].push_back({e.v, idx});\n        adj[e.v].push_back({e.u, idx});\n    }\n\n    vector<int> parent(N, -1), depth(N, 0), parent_edge(N, -1);\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0;\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [v, eid] : adj[u]) {\n            if (v == parent[u]) continue;\n            parent[v] = u;\n            depth[v] = depth[u] + 1;\n            parent_edge[v] = eid;\n            q.push(v);\n        }\n    }\n\n    auto get_path_edges = [&](int u, int v) -> vector<int> {\n        vector<int> path;\n        while (depth[u] > depth[v]) {\n            path.push_back(parent_edge[u]);\n            u = parent[u];\n        }\n        while (depth[v] > depth[u]) {\n            path.push_back(parent_edge[v]);\n            v = parent[v];\n        }\n        while (u != v) {\n            path.push_back(parent_edge[u]);\n            path.push_back(parent_edge[v]);\n            u = parent[u];\n            v = parent[v];\n        }\n        return path;\n    };\n\n    // for each non-tree edge, store the tree edge with maximum d on its path\n    vector<int> max_tree_edge(M, -1);\n    vector<int> max_tree_d(M, 0);\n    for (int i = 0; i < M; ++i) {\n        if (in_mst[i]) continue;\n        auto path = get_path_edges(edges[i].u, edges[i].v);\n        int mx = 0, best_id = -1;\n        for (int tid : path) {\n            if (edges[tid].d > mx) {\n                mx = edges[tid].d;\n                best_id = tid;\n            }\n        }\n        max_tree_edge[i] = best_id;\n        max_tree_d[i] = mx;\n    }\n\n    // ---------- online decision ----------\n    DSU dsu(N);\n    vector<bool> tree_skippable(M, false); // set true when tree edge no longer needed\n    int components = N;\n\n    for (int i = 0; i < M; ++i) {\n        long long l; cin >> l;\n        auto& e = edges[i];\n        int u = e.u, v = e.v, d = e.d;\n\n        if (components == 1) {\n            cout << 0 << '\\n' << flush;\n            continue;\n        }\n\n        // already connected?\n        if (dsu.find(u) == dsu.find(v)) {\n            cout << 0 << '\\n' << flush;\n            continue;\n        }\n\n        bool adopt = false;\n\n        if (in_mst[i]) {\n            // tree edge: adopt only if its endpoints not yet connected (we already checked)\n            // Also ensure we haven't already replaced it by a non-tree edge\n            if (!tree_skippable[i]) {\n                adopt = true;\n            }\n        } else {\n            // non-tree edge\n            int target = max_tree_edge[i];\n            if (target != -1 && !tree_skippable[target] && dsu.find(edges[target].u) != dsu.find(edges[target].v)) {\n                // This non-tree edge can replace an unconnected tree edge\n                double thr = 1.3 * max_tree_d[i]; // must be cheaper than the tree edge's d\n                if (l <= thr) {\n                    adopt = true;\n                    tree_skippable[target] = true; // mark the tree edge as replaceable\n                }\n            }\n        }\n\n        if (adopt) {\n            cout << 1 << '\\n' << flush;\n            dsu.unite(u, v);\n            --components;\n        } else {\n            cout << 0 << '\\n' << flush;\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int MAXT = 300;\nconst int MAXN = 20;\nconst int MAXM = 10;\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char move_ch[4] = {'U', 'D', 'L', 'R'};\nconst char block_ch[4] = {'u', 'd', 'l', 'r'};\n\nint N, M;\nint pet_x[MAXN], pet_y[MAXN], pet_type[MAXN];\nint human_x[MAXM], human_y[MAXM];\nbool impassable[GRID + 2][GRID + 2];\ndouble pow2[21];\nint threat[GRID + 2][GRID + 2]; // number of pets within Manhattan distance 2\n\ninline bool inside(int x, int y) {\n    return 1 <= x && x <= GRID && 1 <= y && y <= GRID;\n}\n\nstruct BFSRes {\n    int area;\n    int pets;\n    int frontier;\n    int exposed; // number of region cells adjacent to a pet\n};\n\nBFSRes bfs(int sx, int sy,\n           const bool tmp_imp[GRID + 2][GRID + 2],\n           const int spx[], const int spy[]) {\n    static int vis[GRID + 2][GRID + 2];\n    static int qx[GRID * GRID], qy[GRID * GRID];\n    static int vis_id = 0;\n    ++vis_id;\n\n    int front = 0, back = 0;\n    qx[back] = sx; qy[back] = sy; ++back;\n    vis[sx][sy] = vis_id;\n    int area = 1;\n\n    while (front < back) {\n        int x = qx[front], y = qy[front]; ++front;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (tmp_imp[nx][ny]) continue;\n            if (vis[nx][ny] == vis_id) continue;\n            vis[nx][ny] = vis_id;\n            qx[back] = nx; qy[back] = ny; ++back;\n            ++area;\n        }\n    }\n\n    int frontier = 0;\n    int exposed = 0;\n    for (int i = 0; i < back; ++i) {\n        int x = qx[i], y = qy[i];\n        bool is_boundary = false;\n        bool has_pet_adj = false;\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny) || tmp_imp[nx][ny]) {\n                is_boundary = true;\n            } else {\n                // check if this neighbor is a pet (start positions)\n                for (int p = 0; p < N; ++p) {\n                    if (spx[p] == nx && spy[p] == ny) {\n                        has_pet_adj = true;\n                        break;\n                    }\n                }\n            }\n        }\n        if (is_boundary) ++frontier;\n        if (has_pet_adj) ++exposed;\n    }\n\n    int pets = 0;\n    for (int i = 0; i < N; ++i)\n        if (vis[spx[i]][spy[i]] == vis_id) ++pets;\n    return {area, pets, frontier, exposed};\n}\n\nvoid computeThreat(const int spx[], const int spy[]) {\n    memset(threat, 0, sizeof(threat));\n    for (int i = 0; i < N; ++i) {\n        int px = spx[i], py = spy[i];\n        for (int x = max(1, px - 2); x <= min(GRID, px + 2); ++x)\n            for (int y = max(1, py - 2); y <= min(GRID, py + 2); ++y)\n                if (abs(x - px) + abs(y - py) <= 2)\n                    threat[x][y]++;\n    }\n}\n\ninline bool blockLegal(int nx, int ny,\n                       const int start_hx[], const int start_hy[],\n                       const int start_px[], const int start_py[]) {\n    if (!inside(nx, ny)) return false;\n    if (impassable[nx][ny]) return false;\n    for (int i = 0; i < M; ++i)\n        if (start_hx[i] == nx && start_hy[i] == ny) return false;\n    for (int i = 0; i < N; ++i)\n        if (start_px[i] == nx && start_py[i] == ny) return false;\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < 4; ++k)\n            if (nx + dx[k] == start_px[i] && ny + dy[k] == start_py[i])\n                return false;\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    pow2[0] = 1.0;\n    for (int i = 1; i <= 20; ++i) pow2[i] = pow2[i-1] * 0.5;\n\n    cin >> N;\n    for (int i = 0; i < N; ++i)\n        cin >> pet_x[i] >> pet_y[i] >> pet_type[i];\n    cin >> M;\n    for (int i = 0; i < M; ++i)\n        cin >> human_x[i] >> human_y[i];\n\n    memset(impassable, 0, sizeof(impassable));\n    mt19937 rng(12345);\n\n    // Heuristic weights\n    const double FRONTIER_BONUS = 0.2;\n    const double THREAT_PENALTY = 0.4;\n    const double EXPOSED_PENALTY = 0.6;\n    const double BLOCK_THREAT_BONUS = 0.5;\n\n    for (int turn = 0; turn < MAXT; ++turn) {\n        int start_hx[MAXM], start_hy[MAXM];\n        int start_px[MAXN], start_py[MAXN];\n        for (int i = 0; i < M; ++i) {\n            start_hx[i] = human_x[i];\n            start_hy[i] = human_y[i];\n        }\n        for (int i = 0; i < N; ++i) {\n            start_px[i] = pet_x[i];\n            start_py[i] = pet_y[i];\n        }\n\n        computeThreat(start_px, start_py);\n\n        bool cur_imp[GRID + 2][GRID + 2];\n        memcpy(cur_imp, impassable, sizeof(impassable));\n        int cur_hx[MAXM], cur_hy[MAXM];\n        memcpy(cur_hx, start_hx, sizeof(int) * M);\n        memcpy(cur_hy, start_hy, sizeof(int) * M);\n\n        char actions[MAXM];\n\n        // 4 passes with random order for better coordination\n        for (int pass = 0; pass < 4; ++pass) {\n            vector<int> order(M);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), rng);\n\n            for (int idx : order) {\n                int sx = cur_hx[idx], sy = cur_hy[idx];\n\n                double best_val = -1e18;\n                int best_action = 0; // 0 = '.'\n\n                // evaluate do-nothing\n                {\n                    BFSRes r = bfs(sx, sy, cur_imp, start_px, start_py);\n                    double base = r.area * pow2[r.pets];\n                    double val = base + FRONTIER_BONUS * r.frontier\n                                 - THREAT_PENALTY * threat[sx][sy]\n                                 - EXPOSED_PENALTY * r.exposed;\n                    if (val > best_val) { best_val = val; best_action = 0; }\n                }\n\n                // evaluate moves\n                for (int d = 0; d < 4; ++d) {\n                    int nx = sx + dx[d], ny = sy + dy[d];\n                    if (!inside(nx, ny)) continue;\n                    if (cur_imp[nx][ny]) continue;\n                    int save_x = cur_hx[idx], save_y = cur_hy[idx];\n                    cur_hx[idx] = nx; cur_hy[idx] = ny;\n                    BFSRes r = bfs(nx, ny, cur_imp, start_px, start_py);\n                    double base = r.area * pow2[r.pets];\n                    double val = base + FRONTIER_BONUS * r.frontier\n                                 - THREAT_PENALTY * threat[nx][ny]\n                                 - EXPOSED_PENALTY * r.exposed;\n                    if (val > best_val) { best_val = val; best_action = 1 + d; }\n                    cur_hx[idx] = save_x; cur_hy[idx] = save_y;\n                }\n\n                // evaluate blocks (only if legal)\n                for (int d = 0; d < 4; ++d) {\n                    int nx = sx + dx[d], ny = sy + dy[d];\n                    if (!inside(nx, ny)) continue;\n                    if (!blockLegal(nx, ny, start_hx, start_hy, start_px, start_py))\n                        continue;\n                    bool saved = cur_imp[nx][ny];\n                    cur_imp[nx][ny] = true;\n                    BFSRes r = bfs(sx, sy, cur_imp, start_px, start_py);\n                    double base = r.area * pow2[r.pets];\n                    double val = base + FRONTIER_BONUS * r.frontier\n                                 - THREAT_PENALTY * threat[sx][sy]\n                                 - EXPOSED_PENALTY * r.exposed\n                                 + BLOCK_THREAT_BONUS * threat[nx][ny];\n                    if (val > best_val) { best_val = val; best_action = 5 + d; }\n                    cur_imp[nx][ny] = saved;\n                }\n\n                // Apply best action\n                if (best_action >= 5) {\n                    int d = best_action - 5;\n                    int nx = sx + dx[d], ny = sy + dy[d];\n                    if (!blockLegal(nx, ny, start_hx, start_hy, start_px, start_py)) {\n                        best_action = 0;\n                    }\n                }\n\n                if (best_action == 0) {\n                    // stay\n                } else if (best_action <= 4) {\n                    int d = best_action - 1;\n                    cur_hx[idx] = sx + dx[d];\n                    cur_hy[idx] = sy + dy[d];\n                } else {\n                    int d = best_action - 5;\n                    int nx = sx + dx[d], ny = sy + dy[d];\n                    cur_imp[nx][ny] = true;\n                }\n\n                if (best_action == 0) actions[idx] = '.';\n                else if (best_action <= 4) actions[idx] = move_ch[best_action - 1];\n                else actions[idx] = block_ch[best_action - 5];\n            }\n        }\n\n        // Final validation for moves and blocks\n        for (int i = 0; i < M; ++i) {\n            char a = actions[i];\n            if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                int d;\n                if (a == 'U') d = 0;\n                else if (a == 'D') d = 1;\n                else if (a == 'L') d = 2;\n                else d = 3;\n                int nx = start_hx[i] + dx[d];\n                int ny = start_hy[i] + dy[d];\n                if (cur_imp[nx][ny]) {\n                    actions[i] = '.';\n                }\n            } else if (a == 'u' || a == 'd' || a == 'l' || a == 'r') {\n                int d;\n                if (a == 'u') d = 0;\n                else if (a == 'd') d = 1;\n                else if (a == 'l') d = 2;\n                else d = 3;\n                int nx = start_hx[i] + dx[d];\n                int ny = start_hy[i] + dy[d];\n                if (!blockLegal(nx, ny, start_hx, start_hy, start_px, start_py)) {\n                    actions[i] = '.';\n                }\n            }\n        }\n\n        // Output\n        for (int i = 0; i < M; ++i) cout << actions[i];\n        cout << endl;\n        cout.flush();\n\n        // Read pet moves\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            if (s == \".\") continue;\n            int x = pet_x[i], y = pet_y[i];\n            for (char c : s) {\n                if (c == 'U') x--;\n                else if (c == 'D') x++;\n                else if (c == 'L') y--;\n                else if (c == 'R') y++;\n            }\n            pet_x[i] = x;\n            pet_y[i] = y;\n        }\n\n        // Update human positions\n        for (int i = 0; i < M; ++i) {\n            char a = actions[i];\n            if (a == 'U') human_x[i]--;\n            else if (a == 'D') human_x[i]++;\n            else if (a == 'L') human_y[i]--;\n            else if (a == 'R') human_y[i]++;\n        }\n\n        memcpy(impassable, cur_imp, sizeof(impassable));\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nint si, sj, ti, tj;\ndouble p;\nvector<string> h(20), v(19);\nint dr[4] = {1, 0, -1, 0};\nint dc[4] = {0, 1, 0, -1};\nchar dir_chars[4] = {'D', 'R', 'U', 'L'};\nint next_state[400][4];\n\nvoid precompute_next() {\n    for (int i = 0; i < 20; ++i) {\n        for (int j = 0; j < 20; ++j) {\n            int id = i * 20 + j;\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dr[d], nj = j + dc[d];\n                if (ni < 0 || ni >= 20 || nj < 0 || nj >= 20) {\n                    next_state[id][d] = id;\n                } else {\n                    bool can_move = false;\n                    if (d == 0) can_move = (v[i][j] == '0');\n                    else if (d == 1) can_move = (h[i][j] == '0');\n                    else if (d == 2) can_move = (v[i-1][j] == '0');\n                    else can_move = (h[i][j-1] == '0');\n                    if (can_move) next_state[id][d] = ni * 20 + nj;\n                    else next_state[id][d] = id;\n                }\n            }\n        }\n    }\n}\n\ndouble evaluate(const string &s) {\n    int L = (int)s.size();\n    static array<double, 400> dp, ndp;\n    fill(dp.begin(), dp.end(), 0.0);\n    for (int i = 0; i < 20; ++i) for (int j = 0; j < 20; ++j) {\n        int id = i*20 + j;\n        if (i == ti && j == tj) dp[id] = 401.0 - L;\n    }\n    for (int t = L-1; t >= 0; --t) {\n        int d;\n        char c = s[t];\n        if (c == 'D') d = 0;\n        else if (c == 'R') d = 1;\n        else if (c == 'U') d = 2;\n        else d = 3;\n        for (int i = 0; i < 20; ++i) {\n            for (int j = 0; j < 20; ++j) {\n                int id = i*20 + j;\n                if (i == ti && j == tj) {\n                    ndp[id] = 401.0 - t;\n                } else {\n                    int nid = next_state[id][d];\n                    ndp[id] = p * dp[id] + (1.0 - p) * dp[nid];\n                }\n            }\n        }\n        swap(dp, ndp);\n    }\n    return dp[si*20 + sj];\n}\n\nstring generate_greedy(bool random_tie, mt19937 &rng) {\n    const int MAX_STEPS = 200;\n    const int N = 400;\n    static vector<vector<double>> V(MAX_STEPS+1, vector<double>(N, 0.0));\n    static bool computed = false;\n    if (!computed) {\n        for (int i = 0; i < 20; ++i) for (int j = 0; j < 20; ++j) {\n            int id = i*20 + j;\n            if (i == ti && j == tj) V[0][id] = 201.0;\n        }\n        for (int k = 1; k <= MAX_STEPS; ++k) {\n            for (int i = 0; i < 20; ++i)\n                for (int j = 0; j < 20; ++j) {\n                    int id = i*20 + j;\n                    if (i == ti && j == tj) {\n                        V[k][id] = 201.0 + k;\n                        continue;\n                    }\n                    double best = 0.0;\n                    for (int d = 0; d < 4; ++d) {\n                        double val;\n                        int nid = next_state[id][d];\n                        if (nid == id) {\n                            val = V[k-1][id];\n                        } else {\n                            val = p * V[k-1][id] + (1.0 - p) * V[k-1][nid];\n                        }\n                        if (val > best) best = val;\n                    }\n                    V[k][id] = best;\n                }\n        }\n        computed = true;\n    }\n\n    string ans;\n    vector<double> dist(N, 0.0);\n    dist[si*20 + sj] = 1.0;\n\n    for (int step = 0; step < MAX_STEPS; ++step) {\n        int remaining = MAX_STEPS - step - 1;\n        double best_val = -1e100;\n        vector<int> candidates;\n        for (int d = 0; d < 4; ++d) {\n            double total = 0.0;\n            for (int id = 0; id < N; ++id) {\n                if (dist[id] == 0.0) continue;\n                int i = id/20, j = id%20;\n                double base;\n                int nid = next_state[id][d];\n                if (nid == id) {\n                    base = V[remaining][id];\n                } else {\n                    base = p * V[remaining][id] + (1.0 - p) * V[remaining][nid];\n                }\n                total += dist[id] * base;\n            }\n            if (total > best_val + 1e-12) {\n                best_val = total;\n                candidates.clear();\n                candidates.push_back(d);\n            } else if (fabs(total - best_val) < 1e-12) {\n                candidates.push_back(d);\n            }\n        }\n        int best_d;\n        if (random_tie && !candidates.empty())\n            best_d = candidates[uniform_int_distribution<int>(0, (int)candidates.size()-1)(rng)];\n        else\n            best_d = candidates[0];\n        ans.push_back(dir_chars[best_d]);\n\n        vector<double> new_dist(N, 0.0);\n        for (int id = 0; id < N; ++id) {\n            if (dist[id] == 0.0) continue;\n            int i = id/20, j = id%20;\n            new_dist[id] += p * dist[id];\n            int nid = next_state[id][best_d];\n            if (nid != id) {\n                new_dist[nid] += (1.0 - p) * dist[id];\n            } else {\n                new_dist[id] += (1.0 - p) * dist[id];\n            }\n        }\n        dist.swap(new_dist);\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj >> ti >> tj >> p;\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i];\n    precompute_next();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    const int RESTARTS = 12;\n    string best_string;\n    double best_score = -1e100;\n    for (int r = 0; r < RESTARTS; ++r) {\n        bool use_random = (r > 0);\n        string cand = generate_greedy(use_random, rng);\n        double score = evaluate(cand);\n        // quick hill climb (1 pass)\n        for (int pos = 0; pos < (int)cand.size(); ++pos) {\n            char orig = cand[pos];\n            double best_local = score;\n            int best_d = -1;\n            for (int d = 0; d < 4; ++d) {\n                char nc = dir_chars[d];\n                if (nc == orig) continue;\n                cand[pos] = nc;\n                double new_score = evaluate(cand);\n                if (new_score > best_local + 1e-12) {\n                    best_local = new_score;\n                    best_d = d;\n                }\n                cand[pos] = orig;\n            }\n            if (best_d != -1) {\n                cand[pos] = dir_chars[best_d];\n                score = best_local;\n            }\n        }\n        if (score > best_score) {\n            best_score = score;\n            best_string = cand;\n        }\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.2) break;\n    }\n\n    // Hill climb on best (3 passes)\n    for (int pass = 0; pass < 3; ++pass) {\n        bool improved = false;\n        for (int pos = 0; pos < (int)best_string.size(); ++pos) {\n            char orig = best_string[pos];\n            double best_local = best_score;\n            int best_d = -1;\n            for (int d = 0; d < 4; ++d) {\n                char nc = dir_chars[d];\n                if (nc == orig) continue;\n                best_string[pos] = nc;\n                double new_score = evaluate(best_string);\n                if (new_score > best_local + 1e-12) {\n                    best_local = new_score;\n                    best_d = d;\n                }\n                best_string[pos] = orig;\n            }\n            if (best_d != -1) {\n                best_string[pos] = dir_chars[best_d];\n                best_score = best_local;\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Simulated Annealing with multiple move types\n    double T = best_score * 0.001;\n    const double COOL = 0.9975;\n    const int TOTAL_ITERS = 10000;\n    for (int iter = 0; iter < TOTAL_ITERS; ++iter) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.85) break;\n\n        int L = (int)best_string.size();\n        if (L < 1) break;\n\n        int move_type = uniform_int_distribution<int>(0, 4)(rng);\n        double new_score;\n        string orig = best_string;\n        if (move_type == 0) {\n            int pos = uniform_int_distribution<int>(0, L-1)(rng);\n            char orig_c = best_string[pos];\n            int d = uniform_int_distribution<int>(0, 3)(rng);\n            char nc = dir_chars[d];\n            if (nc == orig_c) continue;\n            best_string[pos] = nc;\n            new_score = evaluate(best_string);\n        } else if (move_type == 1) {\n            if (L < 2) continue;\n            int a = uniform_int_distribution<int>(0, L-1)(rng);\n            int b = uniform_int_distribution<int>(0, L-1)(rng);\n            if (a == b) continue;\n            swap(best_string[a], best_string[b]);\n            new_score = evaluate(best_string);\n        } else if (move_type == 2) {\n            if (L < 2) continue;\n            int max_len = min(20, L-1);\n            if (max_len < 1) continue;\n            int len = uniform_int_distribution<int>(1, max_len)(rng);\n            int start = uniform_int_distribution<int>(0, L - len)(rng);\n            int target = uniform_int_distribution<int>(0, L - len)(rng);\n            if (start == target) continue;\n            if ((target > start && target < start + len) || (start > target && start < target + len)) continue;\n            string sub = best_string.substr(start, len);\n            best_string.erase(start, len);\n            if (target > start) target -= len;\n            best_string.insert(target, sub);\n            new_score = evaluate(best_string);\n        } else if (move_type == 3) {\n            if (L < 4) continue;\n            int max_len = min(15, L/2);\n            if (max_len < 1) continue;\n            int len = uniform_int_distribution<int>(1, max_len)(rng);\n            int start1 = uniform_int_distribution<int>(0, L - 2*len)(rng);\n            int start2 = uniform_int_distribution<int>(start1 + len, L - len)(rng);\n            if (start2 < start1 + len) continue;\n            string sub1 = best_string.substr(start1, len);\n            string sub2 = best_string.substr(start2, len);\n            string new_s = best_string.substr(0, start1) + sub2 +\n                           best_string.substr(start1+len, start2 - (start1+len)) + sub1 +\n                           best_string.substr(start2+len);\n            best_string = new_s;\n            new_score = evaluate(best_string);\n        } else {\n            if (uniform_int_distribution<int>(0,1)(rng) == 0 && L > 1) {\n                int pos = uniform_int_distribution<int>(0, L-1)(rng);\n                best_string.erase(best_string.begin() + pos);\n                new_score = evaluate(best_string);\n            } else if (L < 200) {\n                int pos = uniform_int_distribution<int>(0, L)(rng);\n                int d = uniform_int_distribution<int>(0, 3)(rng);\n                best_string.insert(best_string.begin() + pos, dir_chars[d]);\n                new_score = evaluate(best_string);\n            } else {\n                continue;\n            }\n        }\n\n        double delta = new_score - best_score;\n        if (delta > 0) {\n            best_score = new_score;\n        } else {\n            double prob = exp(delta / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                best_score = new_score;\n            } else {\n                best_string = orig;\n            }\n        }\n        T *= COOL;\n    }\n\n    // Length optimization\n    string best_len_str = best_string;\n    double best_len_score = best_score;\n    for (int len = 1; len <= 200; ++len) {\n        if (len > (int)best_string.size()) continue;\n        string cand = best_string.substr(0, len);\n        double sc = evaluate(cand);\n        if (sc > best_len_score) {\n            best_len_score = sc;\n            best_len_str = cand;\n        }\n        if (len < (int)best_string.size()) {\n            cand = best_string.substr(best_string.size() - len);\n            sc = evaluate(cand);\n            if (sc > best_len_score) {\n                best_len_score = sc;\n                best_len_str = cand;\n            }\n        }\n    }\n    best_string = best_len_str;\n    best_score = best_len_score;\n\n    // Final hill climb (2 passes)\n    for (int pass = 0; pass < 2; ++pass) {\n        bool improved = false;\n        for (int pos = 0; pos < (int)best_string.size(); ++pos) {\n            char orig = best_string[pos];\n            double best_local = best_score;\n            int best_d = -1;\n            for (int d = 0; d < 4; ++d) {\n                char nc = dir_chars[d];\n                if (nc == orig) continue;\n                best_string[pos] = nc;\n                double new_score = evaluate(best_string);\n                if (new_score > best_local + 1e-12) {\n                    best_local = new_score;\n                    best_d = d;\n                }\n                best_string[pos] = orig;\n            }\n            if (best_d != -1) {\n                best_string[pos] = dir_chars[best_d];\n                best_score = best_local;\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n\n    cout << best_string << '\\n';\n    return 0;\n}","ahc010":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n\nusing namespace std;\n\nconst int N = 30;\nconst int M = N * N;  // 900\nconst int H = M * 4;  // number of half-edges\n\n// direction arrays: 0:left, 1:up, 2:right, 3:down\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\n// to[t][d] = exit direction when entering tile t from direction d, -1 if invalid\nconst int to[8][4] = {\n    {1, 0, -1, -1},  // 0\n    {3, -1, -1, 0},  // 1\n    {-1, -1, 3, 2},  // 2\n    {-1, 2, 1, -1},  // 3\n    {1, 0, 3, 2},    // 4\n    {3, 2, 1, 0},    // 5\n    {2, -1, 0, -1},  // 6\n    {-1, 3, -1, 1}   // 7\n};\n\n// precomputed rotated tile types\nint rot_type[8][4];\n\nint evaluate(const int* state) {\n    static int visited[H];\n    static int gen = 0;\n    ++gen;  // new generation\n    int best = 0, second = 0;\n\n    for (int idx = 0; idx < M; ++idx) {\n        int t = state[idx];\n        int i = idx / N, j = idx % N;\n        for (int d = 0; d < 4; ++d) {\n            if (to[t][d] == -1) continue;\n            int he = (idx << 2) | d;\n            if (visited[he] == gen) continue;\n\n            // trace this path\n            int ci = i, cj = j, cd = d;\n            int len = 0;\n            bool is_cycle = false;\n            while (true) {\n                int cur_he = (ci * N + cj) * 4 + cd;\n                visited[cur_he] = gen;\n                int d2 = to[state[ci * N + cj]][cd];\n                if (d2 == -1) break;\n                int ni = ci + di[d2];\n                int nj = cj + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) break;\n                cd = (d2 + 2) & 3;\n                ci = ni;\n                cj = nj;\n                ++len;\n                if (ci == i && cj == j && cd == d) {\n                    is_cycle = true;\n                    break;\n                }\n            }\n            if (is_cycle) {\n                if (len > best) {\n                    second = best;\n                    best = len;\n                } else if (len > second) {\n                    second = len;\n                }\n            }\n        }\n    }\n    return best * second;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // precompute rotated tile types\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            if (t < 4) rot_type[t][r] = (t + r) % 4;\n            else if (t < 6) rot_type[t][r] = 4 + ((t - 4 + r) % 2);\n            else rot_type[t][r] = 6 + ((t - 6 + r) % 2);\n        }\n    }\n\n    // read original tile types\n    vector<int> orig(M);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            orig[i * N + j] = s[j] - '0';\n        }\n    }\n\n    // random generator\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist4(0, 3);\n    uniform_int_distribution<int> dist900(0, M - 1);\n\n    // current and best state\n    vector<int> state(M), rot(M);\n    vector<int> best_rot(M);\n    int best_score = 0;\n\n    // Phase 1: many random trials (reduced number, using fast evaluate with timestamp)\n    const int TRIALS = 20000;\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // early time check every 2000 trials\n        if (trial % 2000 == 0) {\n            static auto start = chrono::steady_clock::now();\n            auto now = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start).count();\n            if (elapsed > 1200) break; // leave time for phase 2\n        }\n        for (int i = 0; i < M; ++i) {\n            int r = dist4(rng);\n            rot[i] = r;\n            state[i] = rot_type[orig[i]][r];\n        }\n        int score = evaluate(state.data());\n        if (score > best_score) {\n            best_score = score;\n            best_rot = rot;\n        }\n    }\n\n    // Phase 2: greedy hill climbing on best found\n    // restore best state\n    for (int i = 0; i < M; ++i) {\n        rot[i] = best_rot[i];\n        state[i] = rot_type[orig[i]][rot[i]];\n    }\n    int cur_score = best_score;\n\n    // greedy passes: try all rotations for each tile, keep if improves\n    bool improved = true;\n    int pass = 0;\n    while (improved && pass < 30) { // limit passes\n        improved = false;\n        ++pass;\n        // random order to avoid bias\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int idx : order) {\n            int r_old = rot[idx];\n            int best_val = cur_score;\n            int best_r = r_old;\n            for (int r = 0; r < 4; ++r) {\n                if (r == r_old) continue;\n                int new_s = rot_type[orig[idx]][r];\n                state[idx] = new_s;\n                int val = evaluate(state.data());\n                if (val > best_val) {\n                    best_val = val;\n                    best_r = r;\n                }\n            }\n            if (best_val > cur_score) {\n                cur_score = best_val;\n                rot[idx] = best_r;\n                state[idx] = rot_type[orig[idx]][best_r];\n                improved = true;\n                if (best_val > best_score) {\n                    best_score = best_val;\n                    best_rot = rot;\n                }\n            } else {\n                // restore\n                state[idx] = rot_type[orig[idx]][r_old];\n            }\n        }\n        // quick time check after each pass\n        static auto start2 = chrono::steady_clock::now();\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start2).count();\n        if (elapsed > 1900) break;\n    }\n\n    // output best rotation string\n    for (int i = 0; i < M; ++i) cout << best_rot[i];\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\n\n// ---------- DSU ----------\nstruct DSU {\n    int parent[100], sz[100], edges[100];\n    int V;\n    void init(int n) {\n        V = n;\n        for (int i = 0; i < n; ++i) parent[i] = i, sz[i] = 1, edges[i] = 0;\n    }\n    int find(int x) {\n        while (x != parent[x]) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) { edges[a]++; return; }\n        if (sz[a] < sz[b]) swap(a, b);\n        parent[b] = a;\n        sz[a] += sz[b];\n        edges[a] += edges[b] + 1;\n    }\n    void build(const vector<int>& board, int N) {\n        init(N * N);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j) {\n                int id = i * N + j, t = board[id];\n                if (t == 0) continue;\n                if (j + 1 < N && board[id + 1] && (t & 4) && (board[id + 1] & 1))\n                    unite(id, id + 1);\n                if (i + 1 < N && board[id + N] && (t & 8) && (board[id + N] & 2))\n                    unite(id, id + N);\n            }\n    }\n} g_dsu;\n\ninline int compute_score(const vector<int>& board, int N) {\n    g_dsu.build(board, N);\n    int best = 0;\n    for (int i = 0; i < g_dsu.V; ++i) {\n        if (board[i] == 0) continue;\n        if (g_dsu.find(i) == i && g_dsu.edges[i] == g_dsu.sz[i] - 1)\n            best = max(best, g_dsu.sz[i]);\n    }\n    return best;\n}\n\ninline int count_edges(const vector<int>& board, int N) {\n    int cnt = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j, t = board[id];\n            if (t == 0) continue;\n            if (j + 1 < N && board[id + 1] && (t & 4) && (board[id + 1] & 1)) cnt++;\n            if (i + 1 < N && board[id + N] && (t & 8) && (board[id + N] & 2)) cnt++;\n        }\n    return cnt;\n}\n\nstruct State {\n    vector<int> board;\n    int empty;\n    string moves;\n    int score;      // best score reachable in <=2 moves\n    int edges;      // edges after first move\n    int steps;\n    int last_dir;   // index of last move (-1 if none)\n    bool operator<(const State& o) const {\n        if (score != o.score) return score > o.score;\n        if (edges != o.edges) return edges > o.edges;\n        return steps < o.steps;\n    }\n};\n\nsize_t hash_board(const vector<int>& board) {\n    size_t h = 0;\n    for (int v : board) h = h * 1000000007 + v;\n    return h;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    int N, T;\n    cin >> N >> T;\n    int V = N * N;\n    int full = V - 1;\n\n    vector<int> init_board(V);\n    int ei, ej;\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            char c = s[j];\n            int val = isdigit(c) ? c - '0' : 10 + (c - 'a');\n            init_board[i * N + j] = val;\n            if (val == 0) { ei = i; ej = j; }\n        }\n    }\n\n    int init_score = compute_score(init_board, N);\n    if (init_score == full) {\n        cout << \"\" << endl;\n        return 0;\n    }\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dir_ch[4] = {'U', 'D', 'L', 'R'};\n    const int rev_dir[4] = {1, 0, 3, 2};\n\n    const double TIME_LIMIT = 2.85;\n    const int MAX_BEAM = 1500;\n    const int MIN_BEAM = 300;\n\n    vector<State> cur;\n    cur.push_back({init_board, ei * N + ej, \"\", init_score, count_edges(init_board, N), 0, -1});\n\n    State best_complete;\n    best_complete.score = 0;\n    State best_partial = cur[0];\n\n    auto start = chrono::steady_clock::now();\n    unordered_set<size_t> global_visited;\n\n    int steps_no_improve = 0;\n\n    for (int step = 0; step < T; ++step) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > TIME_LIMIT) break;\n        if (best_complete.score == full) break;\n\n        int beam = max(MIN_BEAM, MAX_BEAM - step * 3);\n\n        vector<State> candidates;\n        unordered_set<size_t> local_seen;\n\n        for (const auto& s : cur) {\n            int eidx = s.empty;\n            int ci = eidx / N, cj = eidx % N;\n            for (int d = 0; d < 4; ++d) {\n                if (s.last_dir != -1 && d == rev_dir[s.last_dir]) continue;\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int new_empty = ni * N + nj;\n\n                vector<int> nb1 = s.board;\n                swap(nb1[eidx], nb1[new_empty]);\n\n                size_t h1 = hash_board(nb1);\n                if (global_visited.count(h1) || local_seen.count(h1)) continue;\n                local_seen.insert(h1);\n\n                int score1 = compute_score(nb1, N);\n                int edges1 = count_edges(nb1, N);\n                string moves1 = s.moves + dir_ch[d];\n                int steps1 = step + 1;\n                if (steps1 > T) continue;\n\n                // lookahead second move\n                int best2 = score1;\n                string best_moves2 = moves1;\n                for (int d2 = 0; d2 < 4; ++d2) {\n                    if (d2 == rev_dir[d]) continue;\n                    int ni2 = ni + di[d2], nj2 = nj + dj[d2];\n                    if (ni2 < 0 || ni2 >= N || nj2 < 0 || nj2 >= N) continue;\n                    vector<int> nb2 = nb1;\n                    swap(nb2[new_empty], nb2[ni2 * N + nj2]);\n                    int sc2 = compute_score(nb2, N);\n                    if (sc2 > best2) {\n                        best2 = sc2;\n                        best_moves2 = moves1 + dir_ch[d2];\n                    }\n                }\n\n                State ns = {move(nb1), new_empty, move(moves1), best2, edges1, steps1, d};\n\n                // update best partial\n                if (best2 > best_partial.score) {\n                    best_partial = ns;\n                    steps_no_improve = 0;\n                } else if (best2 == best_partial.score && edges1 > best_partial.edges) {\n                    best_partial = ns;\n                }\n\n                // check complete\n                if (best2 == full) {\n                    if (best_complete.score == 0 || best_moves2.size() < best_complete.moves.size()) {\n                        best_complete.moves = best_moves2;\n                        best_complete.score = full;\n                    }\n                }\n\n                candidates.push_back(move(ns));\n            }\n        }\n\n        // add current states to global visited\n        for (const auto& s : cur)\n            global_visited.insert(hash_board(s.board));\n\n        // random restart if stuck\n        steps_no_improve++;\n        if (steps_no_improve > 120) {\n            State restart = best_partial;\n            int restart_len = min(10, T - restart.steps);\n            for (int r = 0; r < restart_len; ++r) {\n                vector<int> valid;\n                for (int d = 0; d < 4; ++d) {\n                    if (restart.last_dir != -1 && d == rev_dir[restart.last_dir]) continue;\n                    int ni = restart.empty / N + di[d];\n                    int nj = restart.empty % N + dj[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) valid.push_back(d);\n                }\n                if (valid.empty()) break;\n                int d = valid[rng() % valid.size()];\n                int ni = restart.empty / N + di[d];\n                int nj = restart.empty % N + dj[d];\n                int new_empty = ni * N + nj;\n                swap(restart.board[restart.empty], restart.board[new_empty]);\n                restart.empty = new_empty;\n                restart.moves += dir_ch[d];\n                restart.steps += 1;\n                restart.last_dir = d;\n            }\n            restart.score = compute_score(restart.board, N);\n            restart.edges = count_edges(restart.board, N);\n            cur.clear();\n            cur.push_back(restart);\n            steps_no_improve = 0;\n            continue;\n        }\n\n        if (best_complete.score == full) break;\n        if (candidates.empty()) break;\n\n        // keep top beam\n        if ((int)candidates.size() > beam) {\n            partial_sort(candidates.begin(), candidates.begin() + beam, candidates.end());\n            candidates.resize(beam);\n        } else {\n            sort(candidates.begin(), candidates.end());\n        }\n        cur.swap(candidates);\n    }\n\n    if (best_complete.score == full)\n        cout << best_complete.moves << endl;\n    else\n        cout << best_partial.moves << endl;\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\n\nusing ll = long long;\nusing i128 = __int128_t;\n\nconst ll R = 10000;\nconst double PI = acos(-1.0);\nconst ll TWO_PI_R = ll(2 * PI * R) + 1; // approx 62832\n\n// Custom hash for __int128\nstruct hash_i128 {\n    size_t operator()(i128 x) const {\n        return hash<uint64_t>()(uint64_t(x)) ^ (hash<uint64_t>()(uint64_t(x >> 64)) << 1);\n    }\n};\n\n// Generate random point on circle boundary (integer coordinates)\npair<ll, ll> random_boundary_point(mt19937& rng) {\n    static uniform_int_distribution<ll> dist(0, TWO_PI_R - 1);\n    ll angle = dist(rng);\n    double rad = 2.0 * PI * angle / TWO_PI_R;\n    ll x = ll(R * cos(rad));\n    ll y = ll(R * sin(rad));\n    return {x, y};\n}\n\n// Generate a random line that cuts the circle (both points on boundary)\npair< pair<ll,ll>, pair<ll,ll> > random_line(mt19937& rng) {\n    auto p1 = random_boundary_point(rng);\n    auto p2 = random_boundary_point(rng);\n    while (p1 == p2) p2 = random_boundary_point(rng);\n    return {p1, p2};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    int a[11] = {0};\n    int sum_ad = 0;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> a[d];\n        sum_ad += a[d];\n    }\n    vector<ll> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Current masks (bits for each line added so far)\n    vector<i128> cur_mask(N, 0);\n    // Store the lines we selected\n    vector< pair<ll,ll> > line_ends[2]; // endpoints of each line (p and q)\n    line_ends[0].reserve(K);\n    line_ends[1].reserve(K);\n\n    // Candidate evaluation: compute score for a new line\n    auto evaluate_line = [&](ll p1x, ll p1y, ll qx, ll qy) -> int {\n        ll dx = qx - p1x;\n        ll dy = qy - p1y;\n        if (dx == 0 && dy == 0) return -1;\n        // Check if any point lies exactly on the line\n        bool any_on_line = false;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (ys[i] - p1y) - dy * (xs[i] - p1x);\n            if (cross == 0) { any_on_line = true; break; }\n        }\n        if (any_on_line) return -1;\n\n        // Compute new masks and count frequencies\n        unordered_map<i128, int, hash_i128> freq;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (ys[i] - p1y) - dy * (xs[i] - p1x);\n            int side = (cross > 0) ? 1 : 0;\n            i128 new_mask = (cur_mask[i] << 1) | side;\n            freq[new_mask]++;\n        }\n\n        // Compute b_d\n        int b[11] = {0};\n        for (auto& p : freq) {\n            int cnt = p.second;\n            if (cnt >= 1 && cnt <= 10) b[cnt]++;\n        }\n        int score = 0;\n        for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n        return score;\n    };\n\n    // Current score\n    auto compute_cur_score = [&]() {\n        unordered_map<i128, int, hash_i128> freq;\n        for (int i = 0; i < N; ++i) freq[cur_mask[i]]++;\n        int b[11] = {0};\n        for (auto& p : freq) {\n            int cnt = p.second;\n            if (cnt >= 1 && cnt <= 10) b[cnt]++;\n        }\n        int score = 0;\n        for (int d = 1; d <= 10; ++d) score += min(a[d], b[d]);\n        return score;\n    };\n\n    int cur_score = compute_cur_score();\n    const int CANDIDATES = 200;\n    const int MAX_STEPS = K;\n\n    for (int step = 0; step < MAX_STEPS; ++step) {\n        if (cur_score == sum_ad) break; // already optimal\n\n        ll best_px, best_py, best_qx, best_qy;\n        int best_score = cur_score;\n        bool found = false;\n\n        for (int t = 0; t < CANDIDATES; ++t) {\n            auto [p1, p2] = random_line(rng);\n            ll px = p1.first, py = p1.second;\n            ll qx = p2.first, qy = p2.second;\n            int score = evaluate_line(px, py, qx, qy);\n            if (score > best_score) {\n                best_score = score;\n                best_px = px; best_py = py;\n                best_qx = qx; best_qy = qy;\n                found = true;\n            }\n        }\n\n        if (!found || best_score <= cur_score) break;\n\n        // Apply the best line\n        line_ends[0].push_back({best_px, best_py});\n        line_ends[1].push_back({best_qx, best_qy});\n\n        // Update masks\n        ll dx = best_qx - best_px;\n        ll dy = best_qy - best_py;\n        for (int i = 0; i < N; ++i) {\n            ll cross = dx * (ys[i] - best_py) - dy * (xs[i] - best_px);\n            int side = (cross > 0) ? 1 : 0;\n            cur_mask[i] = (cur_mask[i] << 1) | side;\n        }\n        cur_score = best_score;\n    }\n\n    // Output k and lines\n    int k = (int)line_ends[0].size();\n    cout << k << \"\\n\";\n    for (int i = 0; i < k; ++i) {\n        cout << line_ends[0][i].first << \" \" << line_ends[0][i].second << \" \"\n             << line_ends[1][i].first << \" \" << line_ends[1][i].second << \"\\n\";\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 61;\nint N, M;\nbool dot[MAXN][MAXN];\nvector<int> rowDots[MAXN];      // by y, sorted x\nvector<int> colDots[MAXN];      // by x, sorted y\nvector<int> diag1Dots[2*MAXN];  // index = y - x + N-1, sorted x\nvector<int> diag2Dots[2*MAXN];  // index = y + x, sorted x\n\nint64_t weight[MAXN][MAXN];\nvector<pair<int,int>> sortedPoints; // by weight descending\n\n// ---------- Unit edge management (set of keys) ----------\nusing u64 = uint64_t;\nunordered_set<u64> usedEdges;\n\nenum EdgeType { H=0, V=1, D1=2, D2=3 };\n\ninline u64 makeKey(int type, int x, int y) {\n    return ((u64)type << 20) | ((u64)x << 10) | (u64)y;\n}\n\nvoid genH(int x1, int y, int x2, vector<u64>& out) {\n    int step = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += step) {\n        int ux = min(x, x+step);\n        out.push_back(makeKey(H, ux, y));\n    }\n}\nvoid genV(int x, int y1, int y2, vector<u64>& out) {\n    int step = (y2 > y1) ? 1 : -1;\n    for (int y = y1; y != y2; y += step) {\n        int uy = min(y, y+step);\n        out.push_back(makeKey(V, x, uy));\n    }\n}\nvoid genD1(int x1, int y1, int x2, int /*y2*/, vector<u64>& out) {\n    int dx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += dx) {\n        int y = y1 + (x - x1);\n        int ux = min(x, x+dx);\n        int uy = min(y, y+dx);\n        out.push_back(makeKey(D1, ux, uy));\n    }\n}\nvoid genD2(int x1, int y1, int x2, int /*y2*/, vector<u64>& out) {\n    int dx = (x2 > x1) ? 1 : -1;\n    for (int x = x1; x != x2; x += dx) {\n        int y = y1 - (x - x1);\n        int ux = min(x, x+dx);\n        int uy = min(y, y-dx);\n        out.push_back(makeKey(D2, ux, uy));\n    }\n}\n\nbool checkEdges(const vector<u64>& edges) {\n    for (auto e : edges) if (usedEdges.count(e)) return false;\n    return true;\n}\nvoid insertEdges(const vector<u64>& edges) {\n    for (auto e : edges) usedEdges.insert(e);\n}\n\n// ---------- Checks for dots on line segments ----------\ninline bool hasDotRow(int y, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = rowDots[y];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotCol(int x, int l, int r) {\n    if (l+1 >= r) return false;\n    const auto& vec = colDots[x];\n    auto it = lower_bound(vec.begin(), vec.end(), l+1);\n    return (it != vec.end() && *it < r);\n}\ninline bool hasDotDiag1(int c, int lx, int rx) {\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag1Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\ninline bool hasDotDiag2(int c, int lx, int rx) {\n    if (lx+1 >= rx) return false;\n    const auto& vec = diag2Dots[c];\n    auto it = lower_bound(vec.begin(), vec.end(), lx+1);\n    return (it != vec.end() && *it < rx);\n}\n\n// ---------- Try to place a dot at (x,y) ----------\nbool tryPlace(int x, int y, int rect[4][2], vector<u64>& outEdges) {\n    outEdges.clear();\n\n    // ----- Axis\u2011aligned rectangles -----\n    {\n        const auto& row = rowDots[y];\n        const auto& col = colDots[x];\n        for (int x2 : row) {\n            if (x2 == x) continue;\n            int xmin = min(x,x2), xmax = max(x,x2);\n            for (int y4 : col) {\n                if (y4 == y) continue;\n                if (!dot[x2][y4]) continue;\n                int ymin = min(y,y4), ymax = max(y,y4);\n\n                // check dots on perimeter\n                if (hasDotRow(y, xmin, xmax)) continue;\n                if (hasDotRow(y4, xmin, xmax)) continue;\n                if (hasDotCol(x, ymin, ymax)) continue;\n                if (hasDotCol(x2, ymin, ymax)) continue;\n\n                // check unit edges\n                vector<u64> edges;\n                genH(x, y, x2, edges);\n                genV(x2, y, y4, edges);\n                genH(x, y4, x2, edges); // p4 -> p3 (x,y4) to (x2,y4)\n                genV(x, y, y4, edges); // p4->p1? Actually p4->p1: same x, from y4 to y\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y;\n                rect[2][0]=x2; rect[2][1]=y4;\n                rect[3][0]=x; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    // ----- Diagonal type1: p1->p2 slope=1, p2->p3 slope=-1 -----\n    {\n        int c1 = y - x + N-1;  // diag1 constant\n        int c2 = y + x;        // diag2 constant\n        for (int x2 : diag1Dots[c1]) {\n            if (x2 == x) continue;\n            int y2 = x2 + (y - x); // on diag1\n            for (int x4 : diag2Dots[c2]) {\n                if (x4 == x) continue;\n                int y4 = c2 - x4; // on diag2\n                int x3 = x2 + (x4 - x);\n                int y3 = y2 - (x4 - x);\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n\n                // check dots on perimeter\n                int lx12 = min(x,x2), rx12 = max(x,x2);\n                if (hasDotDiag1(c1, lx12, rx12)) continue;\n                int c23 = y2 + x2;\n                int lx23 = min(x2,x3), rx23 = max(x2,x3);\n                if (hasDotDiag2(c23, lx23, rx23)) continue;\n                int c34 = y3 - x3 + N-1;\n                int lx34 = min(x3,x4), rx34 = max(x3,x4);\n                if (hasDotDiag1(c34, lx34, rx34)) continue;\n                int c41 = y4 + x4;\n                int lx41 = min(x4,x), rx41 = max(x4,x);\n                if (hasDotDiag2(c41, lx41, rx41)) continue;\n\n                // check unit edges\n                vector<u64> edges;\n                genD1(x,y,x2,y2, edges);\n                genD2(x2,y2,x3,y3, edges);\n                genD1(x3,y3,x4,y4, edges);\n                genD2(x4,y4,x,y, edges);\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y2;\n                rect[2][0]=x3; rect[2][1]=y3;\n                rect[3][0]=x4; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    // ----- Diagonal type2: p1->p2 slope=-1, p2->p3 slope=1 -----\n    {\n        int c1 = y - x + N-1;\n        int c2 = y + x;\n        for (int x2 : diag2Dots[c2]) {\n            if (x2 == x) continue;\n            int y2 = c2 - x2; // on diag2\n            for (int x4 : diag1Dots[c1]) {\n                if (x4 == x) continue;\n                int y4 = x4 + (y - x); // on diag1\n                int x3 = x2 + (x4 - x);\n                int y3 = y2 + (x4 - x);\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n\n                int lx12 = min(x,x2), rx12 = max(x,x2);\n                if (hasDotDiag2(c2, lx12, rx12)) continue;\n                int c23 = y2 - x2 + N-1;\n                int lx23 = min(x2,x3), rx23 = max(x2,x3);\n                if (hasDotDiag1(c23, lx23, rx23)) continue;\n                int c34 = y3 + x3;\n                int lx34 = min(x3,x4), rx34 = max(x3,x4);\n                if (hasDotDiag2(c34, lx34, rx34)) continue;\n                int c41 = y4 - x4 + N-1;\n                int lx41 = min(x4,x), rx41 = max(x4,x);\n                if (hasDotDiag1(c41, lx41, rx41)) continue;\n\n                vector<u64> edges;\n                genD2(x,y,x2,y2, edges);\n                genD1(x2,y2,x3,y3, edges);\n                genD2(x3,y3,x4,y4, edges);\n                genD1(x4,y4,x,y, edges);\n                if (!checkEdges(edges)) continue;\n\n                rect[0][0]=x; rect[0][1]=y;\n                rect[1][0]=x2; rect[1][1]=y2;\n                rect[2][0]=x3; rect[2][1]=y3;\n                rect[3][0]=x4; rect[3][1]=y4;\n                outEdges = edges;\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n\nvoid placeDot(int x, int y) {\n    dot[x][y] = true;\n    auto ins = [](vector<int>& v, int val) {\n        v.insert(lower_bound(v.begin(), v.end(), val), val);\n    };\n    ins(rowDots[y], x);\n    ins(colDots[x], y);\n    ins(diag1Dots[y - x + N-1], x);\n    ins(diag2Dots[y + x], x);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    for (int i=0; i<N; ++i)\n        for (int j=0; j<N; ++j)\n            dot[i][j] = false;\n    for (int i=0; i<M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        placeDot(x, y);\n    }\n    int c = (N-1)/2;\n    for (int y=0; y<N; ++y) {\n        for (int x=0; x<N; ++x) {\n            weight[x][y] = (x-c)*(x-c) + (y-c)*(y-c) + 1;\n            sortedPoints.emplace_back(x, y);\n        }\n    }\n    sort(sortedPoints.begin(), sortedPoints.end(),\n         [](const pair<int,int>& a, const pair<int,int>& b) {\n             return weight[a.first][a.second] > weight[b.first][b.second];\n         });\n\n    vector<array<int,8>> operations;\n    vector<u64> edgeBuffer;\n    while (true) {\n        bool placed = false;\n        int rect[4][2];\n        for (const auto& p : sortedPoints) {\n            int x = p.first, y = p.second;\n            if (dot[x][y]) continue;\n            if (tryPlace(x, y, rect, edgeBuffer)) {\n                // perform operation\n                placeDot(rect[0][0], rect[0][1]);\n                insertEdges(edgeBuffer);\n                operations.push_back({rect[0][0], rect[0][1],\n                                      rect[1][0], rect[1][1],\n                                      rect[2][0], rect[2][1],\n                                      rect[3][0], rect[3][1]});\n                placed = true;\n                break;\n            }\n        }\n        if (!placed) break;\n    }\n    cout << operations.size() << \"\\n\";\n    for (const auto& op : operations) {\n        for (int i=0; i<8; ++i) {\n            if (i) cout << \" \";\n            cout << op[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\nconst int SIZE = N * N;\n\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\n\nusing Grid = array<int, SIZE>;\n\n// tilt the box in one of the four directions\nGrid tilt(const Grid& g, char dir) {\n    Grid ng = {0};\n    if (dir == 'F') {\n        for (int j = 0; j < N; ++j) {\n            int r = 0;\n            for (int i = 0; i < N; ++i)\n                if (g[i * N + j]) ng[(r++) * N + j] = g[i * N + j];\n        }\n    } else if (dir == 'B') {\n        for (int j = 0; j < N; ++j) {\n            int r = N - 1;\n            for (int i = N - 1; i >= 0; --i)\n                if (g[i * N + j]) ng[(r--) * N + j] = g[i * N + j];\n        }\n    } else if (dir == 'L') {\n        for (int i = 0; i < N; ++i) {\n            int c = 0;\n            for (int j = 0; j < N; ++j)\n                if (g[i * N + j]) ng[i * N + (c++)] = g[i * N + j];\n        }\n    } else { // 'R'\n        for (int i = 0; i < N; ++i) {\n            int c = N - 1;\n            for (int j = N - 1; j >= 0; --j)\n                if (g[i * N + j]) ng[i * N + (c--)] = g[i * N + j];\n        }\n    }\n    return ng;\n}\n\n// compute sum of squares of connected component sizes\nint score(const Grid& g) {\n    bool vis[SIZE] = {false};\n    int total = 0;\n    vector<int> stk;\n    stk.reserve(SIZE);\n    for (int idx = 0; idx < SIZE; ++idx) {\n        if (g[idx] && !vis[idx]) {\n            int flavor = g[idx];\n            int cnt = 0;\n            stk.push_back(idx);\n            vis[idx] = true;\n            while (!stk.empty()) {\n                int cur = stk.back();\n                stk.pop_back();\n                ++cnt;\n                int x = cur / N, y = cur % N;\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        int nidx = nx * N + ny;\n                        if (!vis[nidx] && g[nidx] == flavor) {\n                            vis[nidx] = true;\n                            stk.push_back(nidx);\n                        }\n                    }\n                }\n            }\n            total += cnt * cnt;\n        }\n    }\n    return total;\n}\n\n// global for flavors and random generator\nvector<int> flavors(100);\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// evaluate expected final score from state g at step, with given lookahead depth\n// depth = number of future steps to simulate with lookahead (max 2)\n// samples = number of random placements to consider at each future step\ndouble evaluate(const Grid& g, int step, int depth, int samples) {\n    if (step >= 100) return score(g);\n    // collect empty cells\n    vector<int> empties;\n    empties.reserve(SIZE);\n    for (int i = 0; i < SIZE; ++i)\n        if (g[i] == 0) empties.push_back(i);\n    int M = empties.size();\n    if (M == 0) return score(g); // should not happen before step 100\n\n    if (depth == 0) return score(g);\n\n    // sample placements for the next candy\n    int S = min(samples, M);\n    double total = 0.0;\n    for (int s = 0; s < S; ++s) {\n        // random placement\n        int pos = empties[rng() % M];\n        Grid g2 = g;\n        g2[pos] = flavors[step];\n\n        // try all tilts at this step (the decision)\n        double best_val = -1e18;\n        const char dirs[4] = {'F','B','L','R'};\n        for (char d : dirs) {\n            Grid g3 = tilt(g2, d);\n            double val = evaluate(g3, step + 1, depth - 1, samples);\n            if (val > best_val) best_val = val;\n        }\n        total += best_val;\n    }\n    return total / S;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; ++i) cin >> flavors[i];\n\n    Grid grid = {0};\n    const char dirs[4] = {'F','B','L','R'};\n\n    // time management: get start time\n    auto start = chrono::steady_clock::now();\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n\n        // place the t-th candy at the p-th empty cell\n        int zero_cnt = 0;\n        for (int i = 0; i < SIZE; ++i) {\n            if (grid[i] == 0) {\n                ++zero_cnt;\n                if (zero_cnt == p) {\n                    grid[i] = flavors[t];\n                    break;\n                }\n            }\n        }\n\n        // last tilt does nothing, just output something\n        if (t == 99) {\n            cout << \"F\\n\" << flush;\n            break;\n        }\n\n        // decide lookahead depth and samples based on remaining time and step\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        int depth;\n        int samples;\n        if (elapsed < 0.5) {\n            // early steps: two-step lookahead with moderate samples\n            depth = 2;\n            samples = 5;\n        } else if (elapsed < 1.2) {\n            // mid steps: one-step with many samples\n            depth = 1;\n            samples = 10;\n        } else {\n            // late steps: one-step with fewer samples to avoid TLE\n            depth = 1;\n            samples = 5;\n        }\n\n        // evaluate each candidate tilt\n        char best_dir = 'F';\n        double best_val = -1e18;\n\n        for (char d : dirs) {\n            Grid g1 = tilt(grid, d);\n            double val = evaluate(g1, t + 1, depth, samples);\n            if (val > best_val) {\n                best_val = val;\n                best_dir = d;\n            }\n        }\n\n        // apply the chosen tilt\n        grid = tilt(grid, best_dir);\n        cout << best_dir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n#include <Eigen/Dense>\nusing namespace std;\nusing Eigen::MatrixXd;\nusing Eigen::SelfAdjointEigenSolver;\n\n// ------------------------------------------------------------\n// epsilon == 0 : exact small N (N=4,5,6) - same as before\n// ------------------------------------------------------------\nvoid solve_eps_zero(int M) {\n    int N;\n    if (M <= 11) N = 4;\n    else if (M <= 34) N = 5;\n    else N = 6;\n    int L = N * (N - 1) / 2;\n    int total = 1 << L;\n\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    vector<vector<uint8_t>> perms_bit;\n    do {\n        vector<uint8_t> bit_perm(L);\n        int ptr = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                int u = perm[i], v = perm[j];\n                if (u > v) swap(u, v);\n                int idx = u * (2 * N - u - 1) / 2 + (v - u - 1);\n                bit_perm[ptr] = (uint8_t)idx;\n                ++ptr;\n            }\n        }\n        perms_bit.push_back(bit_perm);\n    } while (next_permutation(perm.begin(), perm.end()));\n\n    vector<uint64_t> can_mask(total);\n    for (int mask = 0; mask < total; ++mask) {\n        uint64_t best = UINT64_MAX;\n        for (const auto& bp : perms_bit) {\n            uint64_t new_mask = 0;\n            for (int b = 0; b < L; ++b)\n                if ((mask >> b) & 1) new_mask |= (1ULL << bp[b]);\n            if (new_mask < best) best = new_mask;\n        }\n        can_mask[mask] = best;\n    }\n\n    unordered_map<uint64_t, int> uniq_idx;\n    vector<uint64_t> uniq_masks;\n    for (int m = 0; m < total; ++m) {\n        uint64_t cm = can_mask[m];\n        if (uniq_idx.find(cm) == uniq_idx.end()) {\n            uniq_idx[cm] = (int)uniq_masks.size();\n            uniq_masks.push_back(cm);\n        }\n    }\n    int K = (int)uniq_masks.size();\n\n    vector<vector<int>> dist(K, vector<int>(K, 0));\n    for (int i = 0; i < K; ++i)\n        for (int j = i + 1; j < K; ++j)\n            dist[i][j] = dist[j][i] = __builtin_popcountll(uniq_masks[i] ^ uniq_masks[j]);\n\n    vector<int> selected;\n    vector<bool> used(K, false);\n    selected.push_back(0);\n    used[0] = true;\n    while ((int)selected.size() < M) {\n        int best_idx = -1, best_min = -1;\n        for (int i = 0; i < K; ++i) if (!used[i]) {\n            int cur_min = L + 1;\n            for (int j : selected) if (dist[i][j] < cur_min) cur_min = dist[i][j];\n            if (cur_min > best_min) { best_min = cur_min; best_idx = i; }\n        }\n        used[best_idx] = true;\n        selected.push_back(best_idx);\n    }\n\n    vector<int> lookup(total);\n    for (int m = 0; m < total; ++m) {\n        uint64_t cm = can_mask[m];\n        int best_d = L + 1, best_idx = 0;\n        for (int i = 0; i < M; ++i) {\n            int d = __builtin_popcountll(cm ^ uniq_masks[selected[i]]);\n            if (d < best_d) { best_d = d; best_idx = i; }\n        }\n        lookup[m] = best_idx;\n    }\n\n    cout << N << '\\n';\n    for (int idx : selected) {\n        uint64_t mask = uniq_masks[idx];\n        string s(L, '0');\n        for (int b = 0; b < L; ++b) if ((mask >> b) & 1) s[b] = '1';\n        cout << s << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; ++q) {\n        string H; cin >> H;\n        int mask = 0;\n        for (int b = 0; b < L; ++b) if (H[b] == '1') mask |= (1 << b);\n        cout << lookup[can_mask[mask]] << '\\n';\n        cout.flush();\n    }\n}\n\n// ------------------------------------------------------------\n// epsilon > 0 : N = 20, disjoint cliques, expected features\n// ------------------------------------------------------------\nvoid solve_eps_positive(int M, double eps) {\n    const int N = 20;\n    const int L = N * (N - 1) / 2;\n\n    // generate candidates: 1 or 2 cliques (sizes >= 2, sum <= N)\n    struct Candidate {\n        vector<int> sizes;          // cliques sizes (sorted descending)\n        vector<double> degrees;     // sorted expected degrees (N)\n        vector<double> eigenvalues; // sorted expected eigenvalues (N)\n    };\n    vector<Candidate> candidates;\n\n    // one clique\n    for (int s = 2; s <= N; ++s) {\n        candidates.push_back({{s}});\n    }\n    // two cliques (a >= b >= 2, a+b <= N)\n    for (int a = 2; a <= N - 2; ++a) {\n        for (int b = 2; b <= a && a + b <= N; ++b) {\n            candidates.push_back({{a, b}});\n        }\n    }\n\n    int K = (int)candidates.size(); // >= M (max ~100)\n\n    // noise parameters\n    const double p1 = 1.0 - eps;   // probability edge stays if present\n    const double p0 = eps;         // probability edge appears if absent\n\n    // Precompute expected degree and expected eigenvalues for each candidate\n    for (auto& cand : candidates) {\n        const auto& sizes = cand.sizes;\n        vector<double> degs, evals;\n        // Build expected adjacency matrix (as dense, but N=20 small)\n        MatrixXd exp_adj = MatrixXd::Zero(N, N);\n        int offset = 0;\n        for (int sz : sizes) {\n            for (int i = offset; i < offset + sz; ++i) {\n                for (int j = i + 1; j < offset + sz; ++j) {\n                    exp_adj(i, j) = p1;\n                    exp_adj(j, i) = p1;\n                }\n            }\n            offset += sz;\n        }\n        // Add off-diagonal entries for missing edges (including between different cliques and isolated vertices)\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (exp_adj(i, j) == 0.0) {\n                    exp_adj(i, j) = p0;\n                    exp_adj(j, i) = p0;\n                }\n            }\n        }\n\n        // Compute degrees (sum over row)\n        for (int i = 0; i < N; ++i) {\n            double d = 0;\n            for (int j = 0; j < N; ++j) d += exp_adj(i, j);\n            degs.push_back(d);\n        }\n        sort(degs.begin(), degs.end());\n        cand.degrees = move(degs);\n\n        // Compute eigenvalues\n        SelfAdjointEigenSolver<MatrixXd> solver(exp_adj);\n        vector<double> eig(N);\n        for (int i = 0; i < N; ++i) eig[i] = solver.eigenvalues()[i];\n        sort(eig.rbegin(), eig.rend());\n        cand.eigenvalues = move(eig);\n    }\n\n    // Greedy selection: start with candidate having largest degree variance\n    vector<int> selected;\n    vector<bool> used(K, false);\n    double best_var = -1;\n    int start_idx = 0;\n    for (int i = 0; i < K; ++i) {\n        double mean = accumulate(candidates[i].degrees.begin(), candidates[i].degrees.end(), 0.0) / N;\n        double var = 0;\n        for (double d : candidates[i].degrees) var += (d - mean) * (d - mean);\n        if (var > best_var) { best_var = var; start_idx = i; }\n    }\n    selected.push_back(start_idx);\n    used[start_idx] = true;\n\n    while ((int)selected.size() < M) {\n        double best_min = -1e100;\n        int best_i = -1;\n        for (int i = 0; i < K; ++i) if (!used[i]) {\n            double cur_min = 1e100;\n            for (int j : selected) {\n                double d_deg = 0, d_eig = 0;\n                for (int p = 0; p < N; ++p) {\n                    double diff = candidates[i].degrees[p] - candidates[j].degrees[p];\n                    d_deg += diff * diff;\n                    double diff2 = candidates[i].eigenvalues[p] - candidates[j].eigenvalues[p];\n                    d_eig += diff2 * diff2;\n                }\n                double d = d_deg + d_eig;\n                if (d < cur_min) cur_min = d;\n            }\n            if (cur_min > best_min) { best_min = cur_min; best_i = i; }\n        }\n        used[best_i] = true;\n        selected.push_back(best_i);\n    }\n\n    // Output graphs (only edges inside cliques)\n    cout << N << '\\n';\n    for (int idx : selected) {\n        const auto& sizes = candidates[idx].sizes;\n        string graph_str(L, '0');\n        int offset = 0;\n        for (int sz : sizes) {\n            for (int i = offset; i < offset + sz; ++i)\n                for (int j = i + 1; j < offset + sz; ++j) {\n                    int e = i * (2*N - i - 1) / 2 + (j - i - 1);\n                    graph_str[e] = '1';\n                }\n            offset += sz;\n        }\n        cout << graph_str << '\\n';\n    }\n    cout.flush();\n\n    // Store reference feature vectors for selected graphs\n    vector<vector<double>> ref_deg(M), ref_eig(M);\n    for (int i = 0; i < M; ++i) {\n        int idx = selected[i];\n        ref_deg[i] = candidates[idx].degrees;\n        ref_eig[i] = candidates[idx].eigenvalues;\n    }\n\n    // Answer queries\n    for (int q = 0; q < 100; ++q) {\n        string H; cin >> H;\n\n        // Build observed adjacency matrix\n        MatrixXd adj = MatrixXd::Zero(N, N);\n        int pos = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (H[pos] == '1') {\n                    adj(i, j) = 1.0;\n                    adj(j, i) = 1.0;\n                }\n                ++pos;\n            }\n        }\n\n        // Degree vector\n        vector<double> degs(N);\n        for (int i = 0; i < N; ++i) {\n            double d = 0;\n            for (int j = 0; j < N; ++j) d += adj(i, j);\n            degs[i] = d;\n        }\n        sort(degs.begin(), degs.end());\n\n        // Eigenvalues\n        SelfAdjointEigenSolver<MatrixXd> solver(adj);\n        vector<double> evals(N);\n        for (int i = 0; i < N; ++i) evals[i] = solver.eigenvalues()[i];\n        sort(evals.rbegin(), evals.rend());\n\n        // Find nearest candidate\n        int best_idx = 0;\n        double best_dist = 1e100;\n        for (int i = 0; i < M; ++i) {\n            double d_deg = 0, d_eig = 0;\n            for (int p = 0; p < N; ++p) {\n                double diff = degs[p] - ref_deg[i][p];\n                d_deg += diff * diff;\n                double diff2 = evals[p] - ref_eig[i][p];\n                d_eig += diff2 * diff2;\n            }\n            double d = d_deg + d_eig;\n            if (d < best_dist) { best_dist = d; best_idx = i; }\n        }\n        cout << best_idx << '\\n';\n        cout.flush();\n    }\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    if (eps == 0.0) {\n        solve_eps_zero(M);\n    } else {\n        solve_eps_positive(M, eps);\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ld = long double;\n\nconst ll INF = 1e18;\nconst double SCALE = 1e-12;\n\nstruct Edge {\n    int u, v, w, idx;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> g(N);\n    vector<vector<int>> edge_idx(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u, v, w, i};\n        g[u].emplace_back(v, w);\n        edge_idx[u].push_back(i);\n        g[v].emplace_back(u, w);\n        edge_idx[v].push_back(i);\n    }\n\n    // skip coordinates\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. all-pair shortest paths (for betweenness) ----------\n    vector<vector<ll>> dist_all(N, vector<ll>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        dist_all[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist_all[s][u]) continue;\n            for (int j = 0; j < (int)g[u].size(); ++j) {\n                int v = g[u][j].first;\n                int w = g[u][j].second;\n                ll nd = d + w;\n                if (nd < dist_all[s][v]) {\n                    dist_all[s][v] = nd;\n                    pq.emplace(nd, v);\n                }\n            }\n        }\n    }\n\n    // ---------- 2. betweenness centrality (Brandes) ----------\n    vector<ld> betweenness(M, 0.0);\n    for (int s = 0; s < N; ++s) {\n        const vector<ll>& dist = dist_all[s];\n        vector<ld> cnt(N, 0.0);\n        vector<vector<pair<int,int>>> pred(N);\n        cnt[s] = 1.0;\n        // order by distance\n        vector<int> order;\n        for (int i = 0; i < N; ++i)\n            if (dist[i] < INF) order.push_back(i);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] < dist[b]; });\n        for (int u : order) {\n            if (dist[u] >= INF) continue;\n            for (int j = 0; j < (int)g[u].size(); ++j) {\n                int v = g[u][j].first;\n                int w = g[u][j].second;\n                if (dist[v] == dist[u] + w) {\n                    cnt[v] += cnt[u];\n                    pred[v].emplace_back(u, edge_idx[u][j]);\n                }\n            }\n        }\n        vector<ld> dep(N, 0.0);\n        for (int i = (int)order.size()-1; i >= 0; --i) {\n            int v = order[i];\n            if (v == s) continue;\n            if (pred[v].empty()) continue;\n            ld sigma_v = cnt[v];\n            for (auto [p, eidx] : pred[v]) {\n                ld contrib = (cnt[p] / sigma_v) * (1.0 + dep[v]);\n                dep[p] += contrib;\n                betweenness[eidx] += contrib;\n            }\n        }\n    }\n\n    // ---------- 3. alternative path cost ----------\n    vector<ll> alt_cost(M, INF);\n    for (int e = 0; e < M; ++e) {\n        auto [u, v, w, idx] = edges[e];\n        vector<ll> dist(N, INF);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        dist[u] = 0;\n        pq.emplace(0, u);\n        while (!pq.empty()) {\n            auto [d, x] = pq.top(); pq.pop();\n            if (d != dist[x]) continue;\n            if (x == v) break;\n            for (int j = 0; j < (int)g[x].size(); ++j) {\n                int y = g[x][j].first;\n                int ww = g[x][j].second;\n                int eidx = edge_idx[x][j];\n                if (eidx == e) continue;\n                ll nd = d + ww;\n                if (nd < dist[y]) {\n                    dist[y] = nd;\n                    pq.emplace(nd, y);\n                }\n            }\n        }\n        alt_cost[e] = dist[v];\n    }\n\n    // ---------- 4. impact score ----------\n    vector<ld> impact(M);\n    for (int e = 0; e < M; ++e) {\n        if (alt_cost[e] >= INF/2) {\n            impact[e] = betweenness[e] * 1e12;\n        } else {\n            impact[e] = betweenness[e] * (alt_cost[e] - edges[e].w);\n        }\n    }\n\n    // ---------- 5. initial greedy assignment ----------\n    vector<pair<ld,int>> sorted(M);\n    for (int i = 0; i < M; ++i) sorted[i] = {impact[i], i};\n    sort(sorted.rbegin(), sorted.rend());\n\n    vector<int> day_of_edge(M, -1);\n    vector<ld> day_load(D, 0.0);\n    vector<int> day_cnt(D, 0);\n    vector<vector<int>> day_edges(D);\n\n    for (auto [imp, eid] : sorted) {\n        int best_day = -1;\n        ld best_load = INF;\n        for (int d = 0; d < D; ++d) {\n            if (day_cnt[d] < K && day_load[d] < best_load) {\n                best_load = day_load[d];\n                best_day = d;\n            }\n        }\n        assert(best_day != -1);\n        day_of_edge[eid] = best_day;\n        day_load[best_day] += imp;\n        day_cnt[best_day]++;\n        day_edges[best_day].push_back(eid);\n    }\n\n    // ---------- 6. simple load balancing local search ----------\n    const int MAX_ITER = 5000;\n    for (int iter = 0; iter < MAX_ITER; ++iter) {\n        int max_day = -1, min_day = -1;\n        ld max_load = -INF, min_load = INF;\n        for (int d = 0; d < D; ++d) {\n            if (day_load[d] > max_load) { max_load = day_load[d]; max_day = d; }\n            if (day_load[d] < min_load) { min_load = day_load[d]; min_day = d; }\n        }\n        if (max_day == min_day || day_cnt[min_day] >= K) break;\n        int best_eid = -1;\n        ld best_imp = -INF;\n        for (int eid : day_edges[max_day]) {\n            if (impact[eid] > best_imp) {\n                best_imp = impact[eid];\n                best_eid = eid;\n            }\n        }\n        if (best_eid == -1) break;\n        // move\n        auto& vec = day_edges[max_day];\n        for (auto it = vec.begin(); it != vec.end(); ++it) {\n            if (*it == best_eid) { vec.erase(it); break; }\n        }\n        day_edges[min_day].push_back(best_eid);\n        day_load[max_day] -= impact[best_eid];\n        day_load[min_day] += impact[best_eid];\n        day_cnt[max_day]--;\n        day_cnt[min_day]++;\n        day_of_edge[best_eid] = min_day;\n    }\n\n    // ---------- 7. refinement using random vertex pairs ----------\n    mt19937 rng(12345);\n    const int NUM_PAIRS = 10;\n    vector<pair<int,int>> pairs;\n    {\n        uniform_int_distribution<int> dist_v(0, N-1);\n        for (int i = 0; i < NUM_PAIRS; ++i) {\n            int a, b;\n            do {\n                a = dist_v(rng);\n                b = dist_v(rng);\n            } while (a == b || dist_all[a][b] >= INF/2);\n            pairs.emplace_back(a, b);\n        }\n    }\n\n    // get unique source vertices from pairs\n    vector<int> src_vertices;\n    for (auto [a,b] : pairs) {\n        src_vertices.push_back(a);\n        src_vertices.push_back(b);\n    }\n    sort(src_vertices.begin(), src_vertices.end());\n    src_vertices.erase(unique(src_vertices.begin(), src_vertices.end()), src_vertices.end());\n    int S = src_vertices.size();\n\n    // precompute original distances for each pair\n    vector<ll> pair_orig(NUM_PAIRS);\n    for (int i = 0; i < NUM_PAIRS; ++i) {\n        auto [a,b] = pairs[i];\n        pair_orig[i] = dist_all[a][b];\n    }\n\n    // function to compute frustration sum for a day given removed edges\n    auto compute_day_frustration = [&](int day, const vector<vector<bool>>& removed) -> ld {\n        // run Dijkstra from each source vertex\n        vector<vector<ll>> dists(S);\n        for (int si = 0; si < S; ++si) {\n            int s = src_vertices[si];\n            vector<ll> dist(N, INF);\n            priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n            dist[s] = 0;\n            pq.emplace(0, s);\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (int j = 0; j < (int)g[u].size(); ++j) {\n                    int v = g[u][j].first;\n                    int w = g[u][j].second;\n                    int eidx = edge_idx[u][j];\n                    if (removed[day][eidx]) continue;\n                    ll nd = d + w;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        pq.emplace(nd, v);\n                    }\n                }\n            }\n            dists[si] = move(dist);\n        }\n        // compute sum over pairs\n        ld total = 0.0;\n        for (int i = 0; i < NUM_PAIRS; ++i) {\n            auto [a,b] = pairs[i];\n            // find index of source in src_vertices\n            int si = lower_bound(src_vertices.begin(), src_vertices.end(), a) - src_vertices.begin();\n            ll cur = dists[si][b];\n            if (cur >= INF/2) cur = 1e9; // unreachable penalty\n            total += (ld)(cur - pair_orig[i]);\n        }\n        return total;\n    };\n\n    // build removed matrix\n    vector<vector<bool>> removed(D, vector<bool>(M, false));\n    for (int e = 0; e < M; ++e) removed[day_of_edge[e]][e] = true;\n\n    // initial frustration per day\n    vector<ld> day_frust(D);\n    ld total_frust = 0.0;\n    for (int d = 0; d < D; ++d) {\n        day_frust[d] = compute_day_frustration(d, removed);\n        total_frust += day_frust[d];\n    }\n\n    const int MAX_REFINE = 100;\n    for (int r = 0; r < MAX_REFINE; ++r) {\n        int worst_day = max_element(day_frust.begin(), day_frust.end()) - day_frust.begin();\n        int best_day = min_element(day_frust.begin(), day_frust.end()) - day_frust.begin();\n        if (worst_day == best_day || day_cnt[best_day] >= K) break;\n\n        // try to move the edge with highest impact on worst_day\n        int best_eid = -1;\n        ld best_improvement = 0.0;\n        // if there are many edges, sample a few\n        int sample_size = min((int)day_edges[worst_day].size(), 5);\n        vector<int> candidates;\n        if ((int)day_edges[worst_day].size() <= 5) {\n            candidates = day_edges[worst_day];\n        } else {\n            shuffle(day_edges[worst_day].begin(), day_edges[worst_day].end(), rng);\n            candidates.assign(day_edges[worst_day].begin(), day_edges[worst_day].begin() + 5);\n        }\n        for (int eid : candidates) {\n            // evaluate move\n            removed[worst_day][eid] = false;\n            removed[best_day][eid] = true;\n            ld new_worst = compute_day_frustration(worst_day, removed);\n            ld new_best = compute_day_frustration(best_day, removed);\n            removed[worst_day][eid] = true;\n            removed[best_day][eid] = false;\n\n            ld old_sum = day_frust[worst_day] + day_frust[best_day];\n            ld new_sum = new_worst + new_best;\n            if (new_sum < old_sum - 1e-12) {\n                ld improvement = old_sum - new_sum;\n                if (improvement > best_improvement) {\n                    best_improvement = improvement;\n                    best_eid = eid;\n                }\n            }\n        }\n        if (best_eid == -1) break;\n\n        // execute move\n        int eid = best_eid;\n        removed[worst_day][eid] = false;\n        removed[best_day][eid] = true;\n        // update data structures\n        auto& vec_w = day_edges[worst_day];\n        for (auto it = vec_w.begin(); it != vec_w.end(); ++it) {\n            if (*it == eid) { vec_w.erase(it); break; }\n        }\n        day_edges[best_day].push_back(eid);\n        day_cnt[worst_day]--;\n        day_cnt[best_day]++;\n        day_of_edge[eid] = best_day;\n        // recompute frustration for updated days\n        day_frust[worst_day] = compute_day_frustration(worst_day, removed);\n        day_frust[best_day] = compute_day_frustration(best_day, removed);\n    }\n\n    // ---------- 8. output ----------\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << day_of_edge[i] + 1;\n    }\n    cout << endl;\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\n// 24 proper 3D rotations (determinant = 1)\nvector<array<array<int,3>,3>> init_rotations() {\n    vector<array<array<int,3>,3>> rots;\n    int perm[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};\n    int parity[6] = {1,-1,-1,1,1,-1};\n    int signs[8][3] = {{1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},\n                       {-1,1,1},{-1,1,-1},{-1,-1,1},{-1,-1,-1}};\n    for (int p=0;p<6;p++) {\n        for (auto s : signs) {\n            int det = s[0]*s[1]*s[2] * parity[p];\n            if (det != 1) continue;\n            array<array<int,3>,3> mat;\n            for (int i=0;i<3;i++)\n                for (int j=0;j<3;j++)\n                    mat[i][j] = (j == perm[p][i]) ? s[i] : 0;\n            rots.push_back(mat);\n        }\n    }\n    return rots;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int D; cin >> D;\n    int N = D*D*D;\n    vector<string> f[2], r[2];\n    for (int t=0;t<2;t++) {\n        f[t].resize(D); for (int i=0;i<D;i++) cin >> f[t][i];\n        r[t].resize(D); for (int i=0;i<D;i++) cin >> r[t][i];\n    }\n\n    // occupancy arrays\n    vector<char> occ[2];\n    for (int t=0;t<2;t++) occ[t].resize(N,0);\n    for (int t=0;t<2;t++) {\n        for (int z=0;z<D;z++) {\n            for (int x=0;x<D;x++) {\n                if (f[t][z][x]=='0') continue;\n                for (int y=0;y<D;y++) {\n                    if (r[t][z][y]=='1') {\n                        int idx = x*D*D + y*D + z;\n                        occ[t][idx] = 1;\n                    }\n                }\n            }\n        }\n    }\n\n    auto rotations = init_rotations();\n\n    // connected components for each object\n    vector<vector<tuple<int,int,int>>> comps[2];\n    vector<int> compSize[2];\n    for (int t=0;t<2;t++) {\n        vector<char> vis(N,0);\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || vis[start]) continue;\n            queue<int> q; q.push(start);\n            vis[start]=1;\n            vector<tuple<int,int,int>> pts;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                pts.emplace_back(x,y,z);\n                static int dx[]={1,-1,0,0,0,0};\n                static int dy[]={0,0,1,-1,0,0};\n                static int dz[]={0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx=x+dx[d], ny=y+dy[d], nz=z+dz[d];\n                    if (nx<0||nx>=D||ny<0||ny>=D||nz<0||nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !vis[nid]) {\n                        vis[nid]=1;\n                        q.push(nid);\n                    }\n                }\n            }\n            comps[t].push_back(pts);\n            compSize[t].push_back(pts.size());\n        }\n    }\n\n    // used flags\n    vector<char> used[2];\n    for (int t=0;t<2;t++) used[t].resize(N,0);\n    vector<int> b1(N,0), b2(N,0);\n    int blockId = 1;\n\n    // helper: try to place a shape from srcObj into otherObj\n    auto tryPlaceShape = [&](int srcObj, const vector<tuple<int,int,int>>& shape) -> bool {\n        int other = 1 - srcObj;\n        for (const auto& rot : rotations) {\n            int mnx=1e9,mny=1e9,mnz=1e9, mxx=-1e9,mxy=-1e9,mxz=-1e9;\n            vector<tuple<int,int,int>> rotated;\n            for (auto [x,y,z] : shape) {\n                int nx = rot[0][0]*x + rot[0][1]*y + rot[0][2]*z;\n                int ny = rot[1][0]*x + rot[1][1]*y + rot[1][2]*z;\n                int nz = rot[2][0]*x + rot[2][1]*y + rot[2][2]*z;\n                rotated.emplace_back(nx,ny,nz);\n                mnx = min(mnx,nx); mxx = max(mxx,nx);\n                mny = min(mny,ny); mxy = max(mxy,ny);\n                mnz = min(mnz,nz); mxz = max(mxz,nz);\n            }\n            int sx = mxx - mnx, sy = mxy - mny, sz = mxz - mnz;\n            for (int tx=0; tx+sx < D; tx++) {\n                for (int ty=0; ty+sy < D; ty++) {\n                    for (int tz=0; tz+sz < D; tz++) {\n                        bool ok = true;\n                        for (auto [nx,ny,nz] : rotated) {\n                            int gx = nx - mnx + tx;\n                            int gy = ny - mny + ty;\n                            int gz = nz - mnz + tz;\n                            int idx = gx*D*D + gy*D + gz;\n                            if (!occ[other][idx] || used[other][idx]) {\n                                ok = false;\n                                break;\n                            }\n                        }\n                        if (ok) {\n                            for (auto [nx,ny,nz] : rotated) {\n                                int gx = nx - mnx + tx;\n                                int gy = ny - mny + ty;\n                                int gz = nz - mnz + tz;\n                                int idx = gx*D*D + gy*D + gz;\n                                used[other][idx] = 1;\n                                if (other == 0) b1[idx] = blockId;\n                                else            b2[idx] = blockId;\n                            }\n                            for (auto [x,y,z] : shape) {\n                                int idx = x*D*D + y*D + z;\n                                used[srcObj][idx] = 1;\n                                if (srcObj == 0) b1[idx] = blockId;\n                                else             b2[idx] = blockId;\n                            }\n                            blockId++;\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n        return false;\n    };\n\n    // Phase 1: Match components (largest first) with leaf removal\n    auto processComponents = [&](int obj) {\n        vector<int> idx(comps[obj].size());\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int a, int b) { return compSize[obj][a] > compSize[obj][b]; });\n        for (int i : idx) {\n            const auto& pts = comps[obj][i];\n            bool anyUsed = false;\n            for (auto [x,y,z] : pts) {\n                int idx = x*D*D + y*D + z;\n                if (used[obj][idx]) { anyUsed = true; break; }\n            }\n            if (anyUsed) continue;\n            if (tryPlaceShape(obj, pts)) continue;\n            // try removing leaves (up to 5)\n            unordered_map<int, vector<int>> adj;\n            for (auto [x,y,z] : pts) {\n                int u = x*D*D + y*D + z;\n                adj[u] = {};\n            }\n            for (auto [x,y,z] : pts) {\n                int u = x*D*D + y*D + z;\n                static int dx[]={1,-1,0,0,0,0};\n                static int dy[]={0,0,1,-1,0,0};\n                static int dz[]={0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx=x+dx[d], ny=y+dy[d], nz=z+dz[d];\n                    if (nx<0||nx>=D||ny<0||ny>=D||nz<0||nz>=D) continue;\n                    int v = nx*D*D + ny*D + nz;\n                    if (adj.count(v)) {\n                        adj[u].push_back(v);\n                        adj[v].push_back(u);\n                    }\n                }\n            }\n            vector<tuple<int,int,int>> curPts = pts;\n            vector<int> deg(curPts.size());\n            for (size_t j=0;j<curPts.size();j++) {\n                auto [x,y,z] = curPts[j];\n                int u = x*D*D + y*D + z;\n                deg[j] = adj[u].size();\n            }\n            for (int rem=0; rem<5 && curPts.size()>1; rem++) {\n                int leafIdx = -1;\n                for (size_t j=0;j<curPts.size();j++) {\n                    if (deg[j] <= 1) { leafIdx = j; break; }\n                }\n                if (leafIdx == -1) break;\n                auto [x,y,z] = curPts[leafIdx];\n                int u = x*D*D + y*D + z;\n                for (int v : adj[u]) {\n                    auto it = find_if(curPts.begin(), curPts.end(), [&](const auto& pt) {\n                        auto [a,b,c] = pt;\n                        return a*D*D + b*D + c == v;\n                    });\n                    if (it != curPts.end()) {\n                        int j = it - curPts.begin();\n                        deg[j]--;\n                    }\n                }\n                curPts[leafIdx] = curPts.back();\n                deg[leafIdx] = deg.back();\n                curPts.pop_back();\n                deg.pop_back();\n                if (tryPlaceShape(obj, curPts)) break;\n                // rebuild deg\n                for (size_t j=0;j<curPts.size();j++) {\n                    auto [x2,y2,z2] = curPts[j];\n                    int u2 = x2*D*D + y2*D + z2;\n                    deg[j] = adj[u2].size();\n                }\n            }\n        }\n    };\n\n    processComponents(0);\n    processComponents(1);\n\n    // Phase 2: Match remaining unit voxels (pair unused)\n    vector<int> rem1, rem2;\n    for (int i=0;i<N;i++) {\n        if (occ[0][i] && !used[0][i]) rem1.push_back(i);\n        if (occ[1][i] && !used[1][i]) rem2.push_back(i);\n    }\n    int k = min(rem1.size(), rem2.size());\n    for (int i=0;i<k;i++) {\n        int idx1 = rem1[i], idx2 = rem2[i];\n        used[0][idx1] = used[1][idx2] = 1;\n        b1[idx1] = blockId;\n        b2[idx2] = blockId;\n        blockId++;\n    }\n\n    // Remaining voxels become single-use blocks (connected components)\n    for (int t=0;t<2;t++) {\n        vector<char> seen(N,0);\n        for (int start=0;start<N;start++) {\n            if (!occ[t][start] || used[t][start] || seen[start]) continue;\n            queue<int> q; q.push(start);\n            seen[start]=1;\n            vector<int> comp;\n            while (!q.empty()) {\n                int cur = q.front(); q.pop();\n                comp.push_back(cur);\n                int x = cur/(D*D);\n                int y = (cur/D)%D;\n                int z = cur%D;\n                static int dx[]={1,-1,0,0,0,0};\n                static int dy[]={0,0,1,-1,0,0};\n                static int dz[]={0,0,0,0,1,-1};\n                for (int d=0;d<6;d++) {\n                    int nx=x+dx[d], ny=y+dy[d], nz=z+dz[d];\n                    if (nx<0||nx>=D||ny<0||ny>=D||nz<0||nz>=D) continue;\n                    int nid = nx*D*D + ny*D + nz;\n                    if (occ[t][nid] && !used[t][nid] && !seen[nid]) {\n                        seen[nid]=1;\n                        q.push(nid);\n                    }\n                }\n            }\n            for (int idx : comp) {\n                if (t==0) b1[idx]=blockId;\n                else      b2[idx]=blockId;\n            }\n            blockId++;\n        }\n    }\n\n    // Ensure all block IDs are exactly 1..n (no gaps due to removals)\n    unordered_set<int> allIds;\n    for (int i=0;i<N;i++) {\n        if (b1[i]) allIds.insert(b1[i]);\n        if (b2[i]) allIds.insert(b2[i]);\n    }\n    vector<int> oldToNew(blockId, 0);\n    int nxt = 1;\n    for (int id : allIds) oldToNew[id] = nxt++;\n    for (int i=0;i<N;i++) {\n        if (b1[i]) b1[i] = oldToNew[b1[i]];\n        if (b2[i]) b2[i] = oldToNew[b2[i]];\n    }\n    int n = nxt - 1;\n\n    cout << n << '\\n';\n    for (int i=0;i<N;i++) cout << b1[i] << \" \\n\"[i==N-1];\n    for (int i=0;i<N;i++) cout << b2[i] << \" \\n\"[i==N-1];\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing ll = long long;\nconst ll INF = 1LL << 60;\n\nstruct UnionFind {\n    vector<int> parent, rank;\n    UnionFind(int n) : parent(n), rank(n, 0) {\n        iota(parent.begin(), parent.end(), 0);\n    }\n    int find(int x) {\n        while (parent[x] != x) {\n            parent[x] = parent[parent[x]];\n            x = parent[x];\n        }\n        return x;\n    }\n    bool unite(int x, int y) {\n        x = find(x), y = find(y);\n        if (x == y) return false;\n        if (rank[x] < rank[y]) parent[x] = y;\n        else if (rank[x] > rank[y]) parent[y] = x;\n        else { parent[y] = x; rank[x]++; }\n        return true;\n    }\n};\n\nint ceil_sqrt(ll sq) {\n    if (sq <= 0) return 0;\n    double d = sqrt((double)sq);\n    int r = (int)ceil(d);\n    if ((ll)r * r < sq) ++r;\n    return min(r, 5000);\n}\n\nll compute_cable_cost(const vector<vector<ll>>& dist_sh, const vector<bool>& active, int N) {\n    vector<int> terms;\n    for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n    int T = terms.size();\n    if (T <= 1) return 0;\n    vector<ll> minDist(T, LLONG_MAX);\n    vector<bool> used(T, false);\n    minDist[0] = 0;\n    ll cable = 0;\n    for (int i = 0; i < T; ++i) {\n        int u = -1;\n        ll best = LLONG_MAX;\n        for (int j = 0; j < T; ++j) {\n            if (!used[j] && minDist[j] < best) {\n                best = minDist[j];\n                u = j;\n            }\n        }\n        used[u] = true;\n        cable += best;\n        for (int v = 0; v < T; ++v) {\n            if (!used[v]) {\n                ll d = dist_sh[terms[u]][terms[v]];\n                if (d < minDist[v]) minDist[v] = d;\n            }\n        }\n    }\n    return cable;\n}\n\nvoid recompute_power(vector<bool>& active, vector<int>& assign, vector<vector<int>>& residents,\n                     vector<ll>& maxDist, ll& powerCost, const vector<vector<ll>>& dist2,\n                     const vector<vector<int>>& cover, int N, int K) {\n    // Rebuild assignments from scratch (closest active station)\n    for (int i = 0; i < N; ++i) residents[i].clear();\n    fill(maxDist.begin(), maxDist.end(), 0);\n    powerCost = 0;\n    for (int k = 0; k < K; ++k) {\n        int best = -1;\n        for (int i : cover[k]) {\n            if (active[i]) {\n                best = i;\n                break;\n            }\n        }\n        // best must exist (coverage guaranteed)\n        assign[k] = best;\n        residents[best].push_back(k);\n        ll d = dist2[k][best];\n        if (d > maxDist[best]) maxDist[best] = d;\n    }\n    for (int i = 0; i < N; ++i) {\n        if (active[i] && maxDist[i] > 0) {\n            int r = ceil_sqrt(maxDist[i]);\n            powerCost += (ll)r * r;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    int N, M, K;\n    cin >> N >> M >> K;\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    vector<tuple<int,int,ll>> edges(M);\n    vector<vector<pair<int,ll>>> adj(N);\n    for (int j = 0; j < M; ++j) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].emplace_back(v, w);\n        adj[v].emplace_back(u, w);\n    }\n\n    vector<int> ax(K), ay(K);\n    for (int k = 0; k < K; ++k) cin >> ax[k] >> ay[k];\n\n    // squared distances\n    vector<vector<ll>> dist2(K, vector<ll>(N));\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            ll dx = ax[k] - x[i], dy = ay[k] - y[i];\n            dist2[k][i] = dx*dx + dy*dy;\n        }\n    }\n\n    // for each resident, stations within 5000 sorted by distance\n    vector<vector<int>> cover(K);\n    for (int k = 0; k < K; ++k) {\n        for (int i = 0; i < N; ++i) {\n            if (dist2[k][i] <= 5000LL * 5000LL) cover[k].push_back(i);\n        }\n        sort(cover[k].begin(), cover[k].end(), [&](int a, int b) {\n            return dist2[k][a] < dist2[k][b];\n        });\n    }\n\n    // all-pairs shortest paths\n    vector<vector<ll>> dist_sh(N, vector<ll>(N, INF));\n    vector<vector<int>> prev(N, vector<int>(N, -1));\n    for (int s = 0; s < N; ++s) {\n        dist_sh[s][s] = 0;\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<>> pq;\n        pq.emplace(0, s);\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist_sh[s][u]) continue;\n            for (auto [v, w] : adj[u]) {\n                if (dist_sh[s][v] > d + w) {\n                    dist_sh[s][v] = d + w;\n                    prev[s][v] = u;\n                    pq.emplace(d + w, v);\n                }\n            }\n        }\n    }\n\n    // edge index\n    vector<vector<int>> edge_idx(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        auto [u, v, w] = edges[j];\n        edge_idx[u][v] = edge_idx[v][u] = j;\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // ---------- Build initial active set ----------\n    vector<bool> active(N, false);\n    // include all stations that cover at least one resident\n    for (int k = 0; k < K; ++k) {\n        for (int i : cover[k]) active[i] = true;\n    }\n    active[0] = true; // station 1 always active\n\n    // Greedy removal: try to remove stations while coverage preserved (no cost considered)\n    {\n        vector<int> order(N-1);\n        iota(order.begin(), order.end(), 1);\n        shuffle(order.begin(), order.end(), rng);\n        for (int st : order) {\n            if (!active[st]) continue;\n            active[st] = false;\n            // check coverage\n            bool ok = true;\n            for (int k = 0; k < K; ++k) {\n                bool covered = false;\n                for (int i : cover[k]) {\n                    if (active[i]) { covered = true; break; }\n                }\n                if (!covered) { ok = false; break; }\n            }\n            if (!ok) active[st] = true; // restore\n        }\n    }\n\n    // Initialize incremental data structures\n    vector<int> assign(K, -1);\n    vector<vector<int>> residents(N);\n    vector<ll> maxDist(N, 0);\n    ll powerCost = 0;\n    recompute_power(active, assign, residents, maxDist, powerCost, dist2, cover, N, K);\n    ll cableCost = compute_cable_cost(dist_sh, active, N);\n    ll curCost = powerCost + cableCost;\n    vector<bool> bestActive = active;\n    ll bestCost = curCost;\n\n    // ---------- Simulated Annealing with incremental updates ----------\n    double T = 5e6;\n    double cooling = 0.99995;\n    int iters = 0;\n    const int MAX_ITERS = 5000;\n    while (iters < MAX_ITERS) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start).count() > 1900) break;\n\n        int flip = uniform_int_distribution<int>(1, N-1)(rng);\n        // Save state for potential rollback\n        auto old_active = active;\n        auto old_assign = assign;\n        auto old_residents = residents;\n        auto old_maxDist = maxDist;\n        ll old_power = powerCost;\n        ll old_cable = cableCost;\n        ll old_total = curCost;\n\n        if (active[flip]) {\n            // deactivate flip\n            // check if its residents can be moved elsewhere\n            bool canDeactivate = true;\n            for (int k : residents[flip]) {\n                bool found = false;\n                for (int i : cover[k]) {\n                    if (active[i] && i != flip) { found = true; break; }\n                }\n                if (!found) { canDeactivate = false; break; }\n            }\n            if (!canDeactivate) continue; // cannot deactivate\n\n            // perform deactivation\n            active[flip] = false;\n            vector<int> reassigned;\n            for (int k : residents[flip]) {\n                int newSt = -1;\n                for (int i : cover[k]) {\n                    if (active[i]) { newSt = i; break; }\n                }\n                // newSt must exist\n                reassigned.push_back(k);\n                // move resident from flip to newSt\n                assign[k] = newSt;\n                residents[newSt].push_back(k);\n                ll d = dist2[k][newSt];\n                if (d > maxDist[newSt]) maxDist[newSt] = d;\n            }\n            // clear flip's resident list and maxDist\n            residents[flip].clear();\n            maxDist[flip] = 0;\n\n            // recompute power cost (maxDist for some stations may have changed, but we only updated maxDist for new stations increased; we need to recompute maxDist for stations that lost residents (flip) and also for stations that might have had maxDist decrease? Actually, for stations that received new residents, maxDist may increase, but they might have lost residents? No, they only gained. For flip, maxDist becomes 0. For other stations, nothing changed. So powerCost can be recomputed by summing over all active stations.\n            // We'll just recompute powerCost from scratch quickly (O(N))\n            powerCost = 0;\n            for (int i = 0; i < N; ++i) {\n                if (active[i] && maxDist[i] > 0) {\n                    int r = ceil_sqrt(maxDist[i]);\n                    powerCost += (ll)r * r;\n                }\n            }\n            // cable cost recompute\n            cableCost = compute_cable_cost(dist_sh, active, N);\n            curCost = powerCost + cableCost;\n        } else {\n            // activate flip\n            active[flip] = true;\n            // For each resident, if flip is closer than current station, reassign\n            // We need to check only residents that have flip in their cover list.\n            // Since N is small, we can scan all residents.\n            for (int k = 0; k < K; ++k) {\n                // check if flip is in cover[k] (i.e., within 5000)\n                // We can check dist2[k][flip] <= 5000^2\n                if (dist2[k][flip] > 5000LL * 5000LL) continue;\n                int cur = assign[k];\n                if (cur == -1) continue;\n                if (dist2[k][flip] < dist2[k][cur]) {\n                    // move resident from cur to flip\n                    // remove from cur's list\n                    auto &vec_cur = residents[cur];\n                    for (auto it = vec_cur.begin(); it != vec_cur.end(); ++it) {\n                        if (*it == k) { vec_cur.erase(it); break; }\n                    }\n                    // add to flip\n                    residents[flip].push_back(k);\n                    assign[k] = flip;\n                }\n            }\n            // Now we need to update maxDist for all stations that changed: flip and any station that lost residents.\n            // For simplicity, recompute maxDist for all active stations by scanning their residents.\n            // This is O(K) per activation, which is okay.\n            for (int i = 0; i < N; ++i) {\n                if (!active[i]) continue;\n                ll mx = 0;\n                for (int k : residents[i]) {\n                    if (dist2[k][i] > mx) mx = dist2[k][i];\n                }\n                maxDist[i] = mx;\n            }\n            // power cost\n            powerCost = 0;\n            for (int i = 0; i < N; ++i) {\n                if (active[i] && maxDist[i] > 0) {\n                    int r = ceil_sqrt(maxDist[i]);\n                    powerCost += (ll)r * r;\n                }\n            }\n            cableCost = compute_cable_cost(dist_sh, active, N);\n            curCost = powerCost + cableCost;\n        }\n\n        if (curCost < bestCost) {\n            bestCost = curCost;\n            bestActive = active;\n        }\n\n        double delta = (double)(curCost - bestCost);\n        if (curCost < old_total) {\n            // accept\n            // already updated\n        } else {\n            double prob = exp(-delta / T);\n            if (uniform_real_distribution<double>(0,1)(rng) < prob) {\n                // accept\n            } else {\n                // rollback\n                active = old_active;\n                assign = old_assign;\n                residents = old_residents;\n                maxDist = old_maxDist;\n                powerCost = old_power;\n                cableCost = old_cable;\n                curCost = old_total;\n            }\n        }\n        T *= cooling;\n        iters++;\n    }\n\n    // Use best solution\n    active = bestActive;\n    recompute_power(active, assign, residents, maxDist, powerCost, dist2, cover, N, K);\n\n    // ---------- Local search on assignment ----------\n    bool changed = true;\n    int pass = 0;\n    while (changed && pass < 15) {\n        changed = false;\n        pass++;\n        for (int k = 0; k < K; ++k) {\n            int cur = assign[k];\n            ll d_cur = dist2[k][cur];\n            if (d_cur == 0) continue; // already at minimum distance? Not needed.\n            for (int j : cover[k]) {\n                if (!active[j] || j == cur) continue;\n                ll d_j = dist2[k][j];\n                // compute old cost contribution from cur and j\n                ll old_r_cur = ceil_sqrt(maxDist[cur]);\n                ll old_r_j = ceil_sqrt(maxDist[j]);\n                ll old_cost = old_r_cur * old_r_cur + old_r_j * old_r_j;\n\n                // new max for cur after removing k\n                ll new_d_cur = 0;\n                if (d_cur == maxDist[cur]) {\n                    // need second largest\n                    for (int other : residents[cur]) {\n                        if (other == k) continue;\n                        if (dist2[other][cur] > new_d_cur) new_d_cur = dist2[other][cur];\n                    }\n                } else {\n                    new_d_cur = maxDist[cur];\n                }\n                ll new_d_j = max(maxDist[j], d_j);\n\n                ll new_r_cur = ceil_sqrt(new_d_cur);\n                ll new_r_j = ceil_sqrt(new_d_j);\n                ll new_cost = new_r_cur * new_r_cur + new_r_j * new_r_j;\n\n                if (new_cost < old_cost) {\n                    // perform move\n                    auto &vec_cur = residents[cur];\n                    for (auto it = vec_cur.begin(); it != vec_cur.end(); ++it) {\n                        if (*it == k) { vec_cur.erase(it); break; }\n                    }\n                    residents[j].push_back(k);\n                    assign[k] = j;\n                    maxDist[cur] = new_d_cur;\n                    maxDist[j] = new_d_j;\n                    changed = true;\n                    break; // move to next resident\n                }\n            }\n        }\n    }\n\n    // Compute final powers\n    vector<int> P(N, 0);\n    for (int i = 0; i < N; ++i) {\n        if (active[i] && maxDist[i] > 0) {\n            P[i] = ceil_sqrt(maxDist[i]);\n        }\n    }\n\n    // ---------- Build Steiner tree ----------\n    vector<int> terms;\n    for (int i = 0; i < N; ++i) if (active[i]) terms.push_back(i);\n    vector<bool> edge_on(M, false);\n\n    if (terms.size() >= 2) {\n        int T = terms.size();\n        vector<int> parent_prim(T, -1);\n        vector<ll> minDist(T, LLONG_MAX);\n        vector<bool> used(T, false);\n        minDist[0] = 0;\n        vector<pair<int,int>> mst_pairs;\n        for (int i = 0; i < T; ++i) {\n            int u = -1;\n            ll best = LLONG_MAX;\n            for (int j = 0; j < T; ++j) {\n                if (!used[j] && minDist[j] < best) {\n                    best = minDist[j];\n                    u = j;\n                }\n            }\n            used[u] = true;\n            if (parent_prim[u] != -1) {\n                mst_pairs.emplace_back(terms[parent_prim[u]], terms[u]);\n            }\n            for (int v = 0; v < T; ++v) {\n                if (!used[v]) {\n                    ll d = dist_sh[terms[u]][terms[v]];\n                    if (d < minDist[v]) {\n                        minDist[v] = d;\n                        parent_prim[v] = u;\n                    }\n                }\n            }\n        }\n\n        for (auto &[u, v] : mst_pairs) {\n            int cur = v;\n            while (cur != u) {\n                int par = prev[u][cur];\n                int idx = edge_idx[par][cur];\n                if (idx != -1) edge_on[idx] = true;\n                cur = par;\n            }\n        }\n\n        vector<int> cand_edges;\n        for (int j = 0; j < M; ++j) if (edge_on[j]) cand_edges.push_back(j);\n        sort(cand_edges.begin(), cand_edges.end(), [&](int a, int b) {\n            return get<2>(edges[a]) < get<2>(edges[b]);\n        });\n        UnionFind uf(N);\n        fill(edge_on.begin(), edge_on.end(), false);\n        for (int idx : cand_edges) {\n            auto [u, v, w] = edges[idx];\n            if (uf.unite(u, v)) edge_on[idx] = true;\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (edge_on[j] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <tuple>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; ++i) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    vector<tuple<int, int, int, int>> ops;\n\n    // bottom-up heapify\n    for (int x = N - 2; x >= 0; --x) {\n        for (int y = 0; y <= x; ++y) {\n            int cx = x, cy = y;\n            while (cx < N - 1) {\n                int left_val  = a[cx + 1][cy];\n                int right_val = a[cx + 1][cy + 1];\n                int cur_val   = a[cx][cy];\n\n                if (cur_val > left_val || cur_val > right_val) {\n                    // swap with the smaller child\n                    int child_y = (left_val < right_val) ? cy : cy + 1;\n                    swap(a[cx][cy], a[cx + 1][child_y]);\n                    ops.emplace_back(cx, cy, cx + 1, child_y);\n                    cx = cx + 1;\n                    cy = child_y;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // output\n    cout << ops.size() << \"\\n\";\n    for (const auto& [x1, y1, x2, y2] : ops) {\n        cout << x1 << \" \" << y1 << \" \" << x2 << \" \" << y2 << \"\\n\";\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    const int entrance_r = 0, entrance_c = (D - 1) / 2; // (0,4)\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    const int total = D * D - 1 - N; // number of containers\n    const int dr[4] = {1, -1, 0, 0};\n    const int dc[4] = {0, 0, 1, -1};\n\n    // ------------------------------------------------------------\n    // 1. Build BFS tree rooted at entrance (parent, children)\n    // ------------------------------------------------------------\n    vector<vector<int>> parent(D, vector<int>(D, -1));\n    vector<vector<int>> child_cnt(D, vector<int>(D, 0));\n    vector<vector<int>> bfs_order(D, vector<int>(D, -1));\n    {\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        queue<pair<int, int>> q;\n        visited[entrance_r][entrance_c] = true;\n        q.emplace(entrance_r, entrance_c);\n        int idx = 0;\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            if (!(r == entrance_r && c == entrance_c)) {\n                bfs_order[r][c] = idx++;\n            }\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (obstacle[nr][nc] || visited[nr][nc]) continue;\n                visited[nr][nc] = true;\n                parent[nr][nc] = r * D + c; // encode as integer\n                child_cnt[r][c]++;\n                q.emplace(nr, nc);\n            }\n        }\n    }\n\n    // rem_child[i][j] = number of children (in tree) that are still empty\n    vector<vector<int>> rem_child = child_cnt;\n\n    // state\n    vector<vector<bool>> occupied(D, vector<bool>(D, false));\n    vector<vector<int>> container(D, vector<int>(D, -1));\n\n    // ------------------------------------------------------------\n    // 2. Placement phase\n    // ------------------------------------------------------------\n    for (int d = 0; d < total; ++d) {\n        int t;\n        cin >> t;\n\n        // BFS to find reachable empty cells\n        vector<vector<bool>> reachable(D, vector<bool>(D, false));\n        queue<pair<int, int>> q;\n        reachable[entrance_r][entrance_c] = true;\n        q.emplace(entrance_r, entrance_c);\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (obstacle[nr][nc] || occupied[nr][nc]) continue;\n                if (!reachable[nr][nc]) {\n                    reachable[nr][nc] = true;\n                    q.emplace(nr, nc);\n                }\n            }\n        }\n\n        // Among reachable empty cells that are leaves in tree (rem_child == 0)\n        // pick the one with BFS order closest to t.\n        vector<tuple<int, int, int>> candidates; // (diff, r, c)\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (obstacle[i][j] || occupied[i][j]) continue;\n                if (i == entrance_r && j == entrance_c) continue;\n                if (!reachable[i][j]) continue;\n                if (rem_child[i][j] == 0) {  // leaf in the remaining tree\n                    int diff = abs(bfs_order[i][j] - t);\n                    candidates.emplace_back(diff, i, j);\n                }\n            }\n        }\n\n        // Fallback: if no leaf, use any reachable cell (should not happen)\n        if (candidates.empty()) {\n            for (int i = 0; i < D; ++i) {\n                for (int j = 0; j < D; ++j) {\n                    if (obstacle[i][j] || occupied[i][j]) continue;\n                    if (i == entrance_r && j == entrance_c) continue;\n                    if (reachable[i][j]) {\n                        int diff = abs(bfs_order[i][j] - t);\n                        candidates.emplace_back(diff, i, j);\n                    }\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        auto [df, r_place, c_place] = candidates[0];\n\n        // Place container\n        occupied[r_place][c_place] = true;\n        container[r_place][c_place] = t;\n\n        // Update rem_child of parent\n        int par = parent[r_place][c_place];\n        if (par != -1) {\n            int pr = par / D, pc = par % D;\n            rem_child[pr][pc]--;\n        }\n\n        cout << r_place << \" \" << c_place << endl;\n    }\n\n    // ------------------------------------------------------------\n    // 3. Retrieval phase\n    // ------------------------------------------------------------\n    for (int step = 0; step < total; ++step) {\n        // BFS from entrance, collect reachable containers\n        vector<vector<bool>> visited(D, vector<bool>(D, false));\n        vector<vector<bool>> container_seen(D, vector<bool>(D, false));\n        queue<pair<int, int>> q;\n        visited[entrance_r][entrance_c] = true;\n        q.emplace(entrance_r, entrance_c);\n        int best_num = INT_MAX, best_r = -1, best_c = -1;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n\n            // Check four neighbours: if neighbour is a container, it's reachable\n            for (int k = 0; k < 4; ++k) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (nr < 0 || nr >= D || nc < 0 || nc >= D) continue;\n                if (obstacle[nr][nc]) continue;\n                if (container[nr][nc] != -1 && !container_seen[nr][nc]) {\n                    container_seen[nr][nc] = true;\n                    if (container[nr][nc] < best_num) {\n                        best_num = container[nr][nc];\n                        best_r = nr;\n                        best_c = nc;\n                    }\n                }\n                // If neighbour is empty and not visited, explore it\n                if (container[nr][nc] == -1 && !occupied[nr][nc] && !visited[nr][nc]) {\n                    visited[nr][nc] = true;\n                    q.emplace(nr, nc);\n                }\n            }\n        }\n\n        // Remove the selected container\n        occupied[best_r][best_c] = false;\n        container[best_r][best_c] = -1;\n        cout << best_r << \" \" << best_c << \"\\n\";\n    }\n    cout << flush;\n\n    return 0;\n}","ahc024":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <map>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int dx[4] = {1, -1, 0, 0};\nconst int dy[4] = {0, 0, 1, -1};\n\nint n, m;\nvector<vector<int>> grid_best;\nint best_score = 0;\n\n// Global data for a run\nvector<vector<int>> grid;\nvector<vector<int>> adjCnt;            // adjacency counts between colors (1..m)\nvector<vector<bool>> origAdj;          // original adjacency matrix (including color 0)\nvector<int> tot;                       // total cells per color\nvector<int> zeroCnt;                   // cells of color currently adjacent to zero (including boundary)\nvector<vector<bool>> adjZero;          // whether cell adjacent to zero\n\nbool can_remove(int i, int j, int c) {\n    if (c == 0) return false;\n    if (tot[c] <= 1) return false;\n    if (!adjZero[i][j]) return false;   // must be adjacent to zero to keep zero connectivity\n\n    int neigh[4];\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) {\n            neigh[d] = 0;\n        } else {\n            int col = grid[ni][nj];\n            neigh[d] = (col == 0) ? 0 : col;\n        }\n    }\n\n    // Check for new unoriginal adjacencies through the removed cell\n    if (neigh[0] != neigh[1] && !origAdj[neigh[0]][neigh[1]]) return false;\n    if (neigh[2] != neigh[3] && !origAdj[neigh[2]][neigh[3]]) return false;\n\n    map<int, int> neighCount;\n    for (int d = 0; d < 4; ++d) {\n        if (neigh[d] == c) continue;\n        if (neigh[d] != 0) neighCount[neigh[d]]++;\n    }\n\n    // Preserve inter-color adjacencies\n    for (auto &p : neighCount) {\n        int col = p.first;\n        int cnt = p.second;\n        int a = min(c, col);\n        int b = max(c, col);\n        if (adjCnt[a][b] - cnt < 1) return false;\n    }\n\n    // Zero adjacency checks for neighbor colors\n    for (auto &p : neighCount) {\n        int col = p.first;\n        if (!origAdj[0][col]) return false;\n    }\n\n    // For color c itself\n    int newZeroC = zeroCnt[c] - (adjZero[i][j] ? 1 : 0);\n    for (int d = 0; d < 4; ++d) {\n        if (neigh[d] == c) {\n            int ni = i + dx[d], nj = j + dy[d];\n            if (!adjZero[ni][nj]) newZeroC++;\n        }\n    }\n    if (origAdj[0][c]) {\n        if (newZeroC == 0) return false;\n    } else {\n        if (newZeroC > 0) return false;\n    }\n\n    // Connectivity check for color c after removal\n    vector<vector<bool>> visited(n, vector<bool>(n, false));\n    queue<pair<int,int>> q;\n    bool found = false;\n    for (int d = 0; d < 4; ++d) {\n        if (neigh[d] == c) {\n            int ni = i + dx[d], nj = j + dy[d];\n            q.push({ni, nj});\n            visited[ni][nj] = true;\n            found = true;\n            break;\n        }\n    }\n    if (!found) {\n        for (int x = 0; x < n; ++x) {\n            for (int y = 0; y < n; ++y) {\n                if ((x != i || y != j) && grid[x][y] == c) {\n                    q.push({x, y});\n                    visited[x][y] = true;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n    }\n    if (!found) return false;\n    int cnt = 1;\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;\n            if (nx == i && ny == j) continue;\n            if (!visited[nx][ny] && grid[nx][ny] == c) {\n                visited[nx][ny] = true;\n                cnt++;\n                q.push({nx, ny});\n            }\n        }\n    }\n    if (cnt != tot[c] - 1) return false;\n\n    return true;\n}\n\nvoid remove_cell(int i, int j, int c) {\n    if (adjZero[i][j]) zeroCnt[c]--;\n    tot[c]--;\n    for (int d = 0; d < 4; ++d) {\n        int ni = i + dx[d];\n        int nj = j + dy[d];\n        if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n        int col = grid[ni][nj];\n        if (col == 0) continue;\n        if (col != c) {\n            int a = min(c, col);\n            int b = max(c, col);\n            adjCnt[a][b]--;\n        }\n        if (!adjZero[ni][nj]) {\n            adjZero[ni][nj] = true;\n            zeroCnt[col]++;\n        }\n    }\n    grid[i][j] = 0;\n}\n\nvoid run(int seed) {\n    grid = grid_best; // start from original input\n    const int MAXC = m + 2;\n    adjCnt.assign(MAXC, vector<int>(MAXC, 0));\n    tot.assign(MAXC, 0);\n    zeroCnt.assign(MAXC, 0);\n    adjZero.assign(n, vector<bool>(n, false));\n    origAdj.assign(MAXC, vector<bool>(MAXC, false));\n\n    // Initialize from original map\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = grid[i][j];\n            tot[c]++;\n            bool onBoundary = (i == 0 || i == n-1 || j == 0 || j == n-1);\n            if (onBoundary) {\n                zeroCnt[c]++;\n                adjZero[i][j] = true;\n                origAdj[0][c] = origAdj[c][0] = true;\n            }\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) {\n                    origAdj[0][c] = origAdj[c][0] = true;\n                    continue;\n                }\n                int col = grid[ni][nj];\n                if (c != col) {\n                    if (c < col) adjCnt[c][col]++;\n                    origAdj[c][col] = origAdj[col][c] = true;\n                }\n            }\n        }\n    }\n\n    mt19937 rng(seed);\n    uniform_real_distribution<double> skip(0.0, 1.0);\n\n    // Priority queue: prefer cells with more zero neighbors and fewer same-color neighbors\n    auto cmp = [&](const pair<int,int>& a, const pair<int,int>& b) -> bool {\n        auto count = [&](int i, int j, int& zeroN, int& sameN) {\n            zeroN = 0; sameN = 0;\n            int col = grid[i][j];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + dx[d];\n                int nj = j + dy[d];\n                if (ni < 0 || ni >= n || nj < 0 || nj >= n) {\n                    zeroN++;\n                    continue;\n                }\n                int nb = grid[ni][nj];\n                if (nb == 0) zeroN++;\n                else if (nb == col) sameN++;\n            }\n        };\n        int za, sa, zb, sb;\n        count(a.first, a.second, za, sa);\n        count(b.first, b.second, zb, sb);\n        if (za != zb) return za < zb;   // larger zero neighbors first\n        return sa > sb;                 // smaller same-color neighbors first\n    };\n    priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(cmp)> pq(cmp);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (adjZero[i][j] && grid[i][j] != 0) {\n                pq.push({i, j});\n            }\n        }\n    }\n\n    // Phase 1: priority queue based removal with random skip\n    while (!pq.empty()) {\n        auto [i, j] = pq.top(); pq.pop();\n        int c = grid[i][j];\n        if (c == 0) continue;\n        if (!can_remove(i, j, c)) continue;\n        // With probability 0.1, skip and push back to try different order\n        if (skip(rng) < 0.1) {\n            pq.push({i, j});\n            continue;\n        }\n        remove_cell(i, j, c);\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + dx[d];\n            int nj = j + dy[d];\n            if (ni < 0 || ni >= n || nj < 0 || nj >= n) continue;\n            if (grid[ni][nj] != 0) {\n                pq.push({ni, nj});\n            }\n        }\n    }\n\n    // Phase 2: multiple random-scan passes (max 10 passes)\n    bool changed = true;\n    int passes = 0;\n    while (changed && passes < 10) {\n        changed = false;\n        passes++;\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (grid[i][j] != 0) cells.push_back({i, j});\n            }\n        }\n        shuffle(cells.begin(), cells.end(), rng);\n        for (auto &[i, j] : cells) {\n            int c = grid[i][j];\n            if (c == 0) continue;\n            if (!can_remove(i, j, c)) continue;\n            remove_cell(i, j, c);\n            changed = true;\n        }\n    }\n\n    // Score\n    int score = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (grid[i][j] == 0) score++;\n        }\n    }\n    if (score > best_score) {\n        best_score = score;\n        grid_best = grid;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    grid_best.assign(n, vector<int>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cin >> grid_best[i][j];\n        }\n    }\n\n    best_score = 0;\n    // Run with many random seeds to increase chance of better solutions\n    for (int seed = 0; seed < 200; ++seed) {\n        run(seed);\n    }\n\n    // Output best solution\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            cout << grid_best[i][j];\n            if (j < n-1) cout << ' ';\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\n#include <cmath>\n\nusing namespace std;\n\nint queries_left;\nint N, D, Q;\n\nvoid query(const vector<int>& L, const vector<int>& R, string& res) {\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    cin >> res;\n    --queries_left;\n}\n\nbool lighter(int a, int b) {\n    if (a == b) return false;\n    vector<int> L = {a}, R = {b};\n    string res;\n    query(L, R, res);\n    return res == \"<\";\n}\n\n// Full binary insertion sort, returns sorted order (lightest first)\nvector<int> full_sort() {\n    vector<int> sorted;\n    sorted.push_back(0);\n    for (int i = 1; i < N; ++i) {\n        auto pos = lower_bound(sorted.begin(), sorted.end(), i,\n                               [&](int a, int b) { return lighter(a, b); });\n        sorted.insert(pos, i);\n    }\n    return sorted;\n}\n\n// Quick heuristic ordering using reference items, returns order (heaviest first)\n// Also fills weight[] with estimated \"score\" (larger = heavier)\nvector<int> quick_order(vector<long long>& weight) {\n    int ref_cnt = min(10, max(2, Q / (3 * N)));\n    if (ref_cnt > N) ref_cnt = N;\n    vector<int> refs;\n    for (int i = 0; i < ref_cnt; ++i) refs.push_back(i);\n    vector<int> win(N, 0);\n    for (int i = 0; i < N && queries_left > 0; ++i) {\n        for (int r : refs) {\n            if (i == r) continue;\n            if (queries_left <= 0) break;\n            if (!lighter(i, r)) win[i]++;\n        }\n    }\n    for (int i = 0; i < N; ++i) weight[i] = win[i];\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n    sort(idx.begin(), idx.end(), [&](int a, int b) {\n        if (win[a] != win[b]) return win[a] > win[b];\n        return a < b;\n    });\n    return idx; // heaviest first\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cout.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    queries_left = Q;\n\n    vector<int> order;          // items in descending weight (heaviest first)\n    vector<long long> weight(N, 0); // estimated weight (larger = heavier)\n\n    int sort_cost = N * (int)ceil(log2(N)) + N; // approximate comparisons needed for full sort\n    if (Q >= sort_cost) {\n        // Full binary insertion sort\n        vector<int> sorted = full_sort(); // lightest first\n        for (int i = 0; i < N; ++i) {\n            int item = sorted[i];\n            weight[item] = i; // lightest gets 0, heaviest gets N-1\n        }\n        // order = heaviest first\n        order = sorted;\n        reverse(order.begin(), order.end());\n    } else {\n        // Quick heuristic ordering\n        order = quick_order(weight); // weight is filled inside, heaviest first\n    }\n\n    // ---------- Greedy partition ----------\n    vector<int> assign(N, -1);\n    vector<long long> group_sum(D, 0);\n    for (int item : order) {\n        int best = 0;\n        for (int g = 1; g < D; ++g) {\n            if (group_sum[g] < group_sum[best]) best = g;\n        }\n        assign[item] = best;\n        group_sum[best] += weight[item];\n    }\n\n    // ---------- Build group item lists ----------\n    vector<vector<int>> groups(D);\n    for (int i = 0; i < N; ++i) groups[assign[i]].push_back(i);\n\n    // ---------- Refinement using actual balance comparisons ----------\n    // Keep a copy of estimated sums from initial weight\n    vector<long long> est_sum = group_sum; // already computed\n    while (queries_left > 0) {\n        // Find groups with max and min estimated sum\n        int heavy = 0, light = 0;\n        for (int g = 1; g < D; ++g) {\n            if (est_sum[g] > est_sum[heavy]) heavy = g;\n            if (est_sum[g] < est_sum[light]) light = g;\n        }\n        if (heavy == light) break; // all equal, done\n        if (groups[heavy].empty() || groups[light].empty()) break; // should not happen\n        // Compare actual total weights of heavy and light groups\n        string res;\n        query(groups[heavy], groups[light], res);\n        int actual_heavy, actual_light;\n        if (res == \">\") {\n            actual_heavy = heavy;\n            actual_light = light;\n        } else if (res == \"<\") {\n            actual_heavy = light;\n            actual_light = heavy;\n        } else { // equal weights\n            // No need to move, try other pair? But we break to avoid infinite loop\n            break;\n        }\n        // Ensure actual_heavy has at least 2 items before moving (to avoid empty group)\n        if (groups[actual_heavy].size() <= 1) break;\n        // Pick item with smallest estimated weight from actual_heavy\n        int move_item = -1;\n        long long min_w = LLONG_MAX;\n        for (int item : groups[actual_heavy]) {\n            if (weight[item] < min_w) {\n                min_w = weight[item];\n                move_item = item;\n            }\n        }\n        if (move_item == -1) break;\n        // Perform move\n        auto it = find(groups[actual_heavy].begin(), groups[actual_heavy].end(), move_item);\n        if (it != groups[actual_heavy].end()) groups[actual_heavy].erase(it);\n        groups[actual_light].push_back(move_item);\n        assign[move_item] = actual_light;\n        est_sum[actual_heavy] -= weight[move_item];\n        est_sum[actual_light] += weight[move_item];\n    }\n\n    // ---------- Consume remaining queries ----------\n    while (queries_left > 0) {\n        cout << \"1 1 0 1\" << endl;\n        string res;\n        cin >> res;\n        --queries_left;\n    }\n\n    // ---------- Output final assignment ----------\n    for (int i = 0; i < N; ++i) {\n        cout << assign[i] << (i == N - 1 ? '\\n' : ' ');\n    }\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\n// length of strictly decreasing prefix (from bottom)\nint pref_len(const vector<int>& st) {\n    int sz = (int)st.size();\n    if (sz == 0) return 0;\n    int len = 1;\n    for (int i = 1; i < sz; ++i) {\n        if (st[i-1] > st[i]) ++len;\n        else break;\n    }\n    return len;\n}\n\n// score: number of boxes not in the decreasing prefix\nint stack_score(const vector<int>& st) {\n    return (int)st.size() - pref_len(st);\n}\n\n// total score over all stacks\nint total_score(const vector<vector<int>>& stacks) {\n    int s = 0;\n    for (const auto& st : stacks) s += stack_score(st);\n    return s;\n}\n\nstruct State {\n    vector<vector<int>> stacks;\n    int cost;                   // energy used so far\n    vector<pair<int,int>> ops;  // performed operations\n\n    State(const vector<vector<int>>& st, int c) : stacks(st), cost(c) {}\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int per_stack = n / m;\n    vector<vector<int>> init_stacks(m);\n    for (int i = 0; i < m; ++i) {\n        init_stacks[i].resize(per_stack);\n        for (int j = 0; j < per_stack; ++j) {\n            cin >> init_stacks[i][j];\n        }\n    }\n\n    // beam search parameters\n    const int BEAM = 150;\n    const double WEIGHT = 3.0;\n\n    vector<State> beam;\n    beam.emplace_back(init_stacks, 0);\n\n    for (int target = 1; target <= n; ++target) {\n        vector<State> candidates;\n\n        for (const State& state : beam) {\n            // locate target\n            int s = -1, idx = -1;\n            for (int i = 0; i < m; ++i) {\n                const auto& st = state.stacks[i];\n                for (int j = 0; j < (int)st.size(); ++j) {\n                    if (st[j] == target) {\n                        s = i;\n                        idx = j;\n                        break;\n                    }\n                }\n                if (s != -1) break;\n            }\n\n            int top_idx = (int)state.stacks[s].size() - 1;\n            if (idx == top_idx) {\n                // target already on top: carry out directly\n                State ns = state;\n                ns.stacks[s].pop_back();\n                ns.ops.emplace_back(target, 0);\n                candidates.push_back(move(ns));\n                continue;\n            }\n\n            // Only valid move: move the block starting at the box directly above target\n            int v_idx = idx + 1;\n            int block_size = top_idx - idx;   // number of boxes moved\n            int v = state.stacks[s][v_idx];   // bottom box of the moved block\n\n            for (int d = 0; d < m; ++d) {\n                if (d == s) continue;\n                State ns = state;  // deep copy\n                auto& src = ns.stacks[s];\n                auto& dst = ns.stacks[d];\n\n                // move block [v_idx, top_idx] to destination\n                for (int k = v_idx; k < (int)src.size(); ++k) {\n                    dst.push_back(src[k]);\n                }\n                src.resize(v_idx);\n\n                // now target is on top (src.size() == v_idx and idx == v_idx-1)\n                src.pop_back();   // carry out target\n\n                ns.cost += block_size + 1;\n                ns.ops.emplace_back(v, d + 1);   // move operation (1\u2011based stack)\n                ns.ops.emplace_back(target, 0);  // carry out\n                candidates.push_back(move(ns));\n            }\n        }\n\n        // keep the best BEAM candidates according to cost + WEIGHT * total_score\n        int keep = min(BEAM, (int)candidates.size());\n        partial_sort(candidates.begin(),\n                     candidates.begin() + keep,\n                     candidates.end(),\n                     [WEIGHT](const State& a, const State& b) {\n                         int va = a.cost + (int)(WEIGHT * total_score(a.stacks));\n                         int vb = b.cost + (int)(WEIGHT * total_score(b.stacks));\n                         if (va != vb) return va < vb;\n                         return a.cost < b.cost;  // tie\u2011break by actual cost\n                     });\n\n        beam.clear();\n        for (int i = 0; i < keep; ++i) {\n            beam.push_back(move(candidates[i]));\n        }\n    }\n\n    // output the operation sequence of the best state\n    const State& best = beam[0];\n    for (const auto& op : best.ops) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\n#include <cmath>\n#include <stack>\n#include <string>\n#include <vector>\nusing namespace std;\n\nint N;\nvector<vector<int>> graph;\nvector<double> sqrt_d;\nvector<int> parent;\nvector<vector<int>> children;\nvector<char> dir_to_child;  // direction from parent to node\n\nint idx(int i, int j) { return i * N + j; }\nint ix(int id) { return id / N; }\nint jy(int id) { return id % N; }\n\nchar dir_char(int di, int dj) {\n    if (di == -1 && dj == 0) return 'U';\n    if (di == 1 && dj == 0) return 'D';\n    if (di == 0 && dj == -1) return 'L';\n    if (di == 0 && dj == 1) return 'R';\n    return '?';\n}\nchar opposite(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return '?';\n}\n\n// compute f values for a given K, return total_moves = 2 * sum_{v>0} f[v]\npair<vector<int>, int> compute_f(double K) {\n    int M = N * N;\n    vector<int> f(M, 0);\n    // post-order DFS using stack (iterative to avoid recursion depth)\n    // We'll use explicit stack with state: (node, visited flag)\n    // Since tree is small, recursion is fine, but for safety we use iterative.\n    stack<pair<int, bool>> st;  // (node, processed)\n    st.push({0, false});\n    while (!st.empty()) {\n        auto [v, processed] = st.top(); st.pop();\n        if (!processed) {\n            st.push({v, true});\n            for (int c : children[v]) {\n                st.push({c, false});\n            }\n        } else {\n            // post-order\n            if (v == 0) continue;\n            double sq = sqrt_d[v];\n            int target = max(1, (int)round(K * sq));\n            int sum_child = 0;\n            for (int c : children[v]) sum_child += f[c];\n            f[v] = max(1, target - sum_child);\n        }\n    }\n    int total_moves = 0;\n    for (int v = 1; v < M; ++v) total_moves += f[v];\n    total_moves *= 2;\n    return {f, total_moves};\n}\n\nstring build_route(const vector<int>& f) {\n    int M = N * N;\n    vector<int> rem = f;  // rem[0] is unused\n    // stack of nodes (current path)\n    stack<int> st;\n    st.push(0);\n    vector<char> moves;\n    moves.reserve(100000);\n    while (true) {\n        int v = st.top();\n        // find child with maximum remaining visits\n        int best_child = -1;\n        int best_rem = 0;\n        for (int c : children[v]) {\n            if (rem[c] > best_rem) {\n                best_rem = rem[c];\n                best_child = c;\n            }\n        }\n        if (best_child != -1) {\n            // go down to child\n            moves.push_back(dir_to_child[best_child]);\n            rem[best_child]--;\n            st.push(best_child);\n        } else {\n            // no child remaining\n            if (v == 0) break;  // back at root, finish\n            st.pop();\n            char up_dir = opposite(dir_to_child[v]);\n            moves.push_back(up_dir);\n        }\n    }\n    return string(moves.begin(), moves.end());\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> d[i][j];\n\n    // build graph\n    int M = N * N;\n    graph.assign(M, {});\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = idx(i, j);\n            if (i < N - 1 && h[i][j] == '0') {\n                int id2 = idx(i + 1, j);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n            if (j < N - 1 && v[i][j] == '0') {\n                int id2 = idx(i, j + 1);\n                graph[id].push_back(id2);\n                graph[id2].push_back(id);\n            }\n        }\n    }\n\n    // BFS tree from (0,0)\n    parent.assign(M, -1);\n    children.assign(M, {});\n    dir_to_child.assign(M, ' ');\n    queue<int> q;\n    q.push(0);\n    parent[0] = 0; // mark root (self)\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) {\n            if (parent[u] == -1) {\n                parent[u] = v;\n                children[v].push_back(u);\n                int di = ix(u) - ix(v);\n                int dj = jy(u) - jy(v);\n                dir_to_child[u] = dir_char(di, dj);\n                q.push(u);\n            }\n        }\n    }\n    // compute sqrt_d\n    sqrt_d.assign(M, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sqrt_d[idx(i, j)] = sqrt((double)d[i][j]);\n\n    // binary search for maximum K such that total_moves <= 100000\n    double low = 0.0, high = 200.0; // sufficient range\n    vector<int> best_f;\n    for (int iter = 0; iter < 60; ++iter) {\n        double mid = (low + high) / 2.0;\n        auto [f, moves] = compute_f(mid);\n        if (moves <= 100000) {\n            best_f = f;\n            low = mid;\n        } else {\n            high = mid;\n        }\n    }\n    // final route from best_f (guaranteed moves <= 100000)\n    string route = build_route(best_f);\n    cout << route << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\nusing LL = long long;\nconst LL INF = 1e18;\nconst int N = 15;\nconst int SZ = N * N;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummyN, M;\n    cin >> dummyN >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    vector<string> pat(M);\n    for (int i = 0; i < M; ++i) cin >> pat[i];\n\n    // positions for each letter\n    vector<vector<int>> pos(26);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            pos[grid[i][j] - 'A'].push_back(i * N + j);\n\n    // Manhattan distance\n    array<array<int, SZ>, SZ> dist;\n    for (int i = 0; i < SZ; ++i) {\n        int x1 = i / N, y1 = i % N;\n        for (int j = 0; j < SZ; ++j) {\n            int x2 = j / N, y2 = j % N;\n            dist[i][j] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    // Precompute cost and end cell (flattened)\n    LL* cost_flat = new LL[M * 6 * SZ];\n    int* endCell_flat = new int[M * 6 * SZ];\n    #define COST(j,ov,st) cost_flat[((j)*6 + ov)*SZ + st]\n    #define END(j,ov,st) endCell_flat[((j)*6 + ov)*SZ + st]\n\n    for (int j = 0; j < M; ++j) {\n        const string& s = pat[j];\n        for (int ov = 0; ov <= 5; ++ov) {\n            int len = 5 - ov;\n            if (len == 0) {\n                for (int st = 0; st < SZ; ++st) {\n                    COST(j, ov, st) = 0;\n                    END(j, ov, st) = st;\n                }\n                continue;\n            }\n            for (int st = 0; st < SZ; ++st) {\n                vector<LL> dp(SZ, INF);\n                int fc = s[ov] - 'A';\n                for (int p : pos[fc]) dp[p] = dist[st][p] + 1;\n                for (int step = 1; step < len; ++step) {\n                    vector<LL> ndp(SZ, INF);\n                    int cc = s[ov + step] - 'A';\n                    int pc = s[ov + step - 1] - 'A';\n                    for (int p : pos[cc]) {\n                        LL best = INF;\n                        for (int q : pos[pc])\n                            if (dp[q] != INF) best = min(best, dp[q] + dist[q][p] + 1);\n                        ndp[p] = best;\n                    }\n                    dp.swap(ndp);\n                }\n                int lc = s[4] - 'A';\n                LL bestCost = INF;\n                int bestEnd = -1;\n                for (int p : pos[lc])\n                    if (dp[p] < bestCost) { bestCost = dp[p]; bestEnd = p; }\n                COST(j, ov, st) = bestCost;\n                END(j, ov, st) = bestEnd;\n            }\n        }\n    }\n    #undef COST\n    #undef END\n\n    // Overlap matrix (suffix i vs prefix j)\n    vector<vector<short>> ovPref(M, vector<short>(M, 0));\n    for (int i = 0; i < M; ++i)\n        for (int j = 0; j < M; ++j)\n            for (int l = 5; l >= 1; --l)\n                if (pat[i].substr(5 - l) == pat[j].substr(0, l)) {\n                    ovPref[i][j] = l;\n                    break;\n                }\n\n    int start = si * N + sj;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    auto eval_fast = [&](const vector<int>& order) -> LL {\n        int cur = start, last = -1;\n        LL total = 0;\n        for (int idx : order) {\n            int ol = (last == -1) ? 0 : ovPref[last][idx];\n            total += cost_flat[((idx)*6 + ol) * SZ + cur];\n            cur = endCell_flat[((idx)*6 + ol) * SZ + cur];\n            last = idx;\n        }\n        return total;\n    };\n\n    auto reconstruct = [&](const vector<int>& order, vector<int>& moves) {\n        int cur = start;\n        string built;\n        moves.clear();\n        for (int idx : order) {\n            const string& t = pat[idx];\n            int real_ol = 0;\n            for (int l = min(5, (int)built.size()); l >= 1; --l)\n                if (built.compare(built.size()-l, l, t, 0, l) == 0) { real_ol = l; break; }\n            if (real_ol == 5) continue;\n            int len = 5 - real_ol;\n            vector<vector<LL>> dp(len, vector<LL>(SZ, INF));\n            vector<vector<int>> prev(len, vector<int>(SZ, -1));\n            int fc = t[real_ol] - 'A';\n            for (int p : pos[fc]) dp[0][p] = dist[cur][p] + 1;\n            for (int step = 1; step < len; ++step) {\n                int cc = t[real_ol + step] - 'A';\n                int pc = t[real_ol + step - 1] - 'A';\n                for (int p : pos[cc]) {\n                    LL best = INF;\n                    int bestPrev = -1;\n                    for (int q : pos[pc]) {\n                        if (dp[step-1][q] == INF) continue;\n                        LL cand = dp[step-1][q] + dist[q][p] + 1;\n                        if (cand < best) { best = cand; bestPrev = q; }\n                    }\n                    dp[step][p] = best;\n                    prev[step][p] = bestPrev;\n                }\n            }\n            int lc = t[4] - 'A';\n            LL bestCost = INF;\n            int bestEnd = -1;\n            for (int p : pos[lc]) if (dp[len-1][p] < bestCost) { bestCost = dp[len-1][p]; bestEnd = p; }\n            vector<int> path(len);\n            int p = bestEnd;\n            for (int step = len-1; step >= 0; --step) {\n                path[step] = p;\n                if (step > 0) p = prev[step][p];\n            }\n            for (int x : path) moves.push_back(x);\n            cur = bestEnd;\n            built += t.substr(real_ol);\n        }\n    };\n\n    vector<int> best_order;\n    LL best_total = INF;\n    vector<int> best_moves;\n\n    // Phase 1: random permutations\n    const int NUM_RANDOM = 30000;\n    for (int trial = 0; trial < NUM_RANDOM; ++trial) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > 0.6) break;\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        LL total = eval_fast(order);\n        if (total < best_total) { best_total = total; best_order = order; }\n    }\n\n    // Phase 2: greedy with randomness (with stronger overlap bias)\n    const int GREEDY_TRIALS = 50;\n    for (int trial = 0; trial < GREEDY_TRIALS; ++trial) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > 1.0) break;\n        vector<bool> covered(M, false);\n        vector<int> order;\n        int cur = start;\n        string built;\n        LL total = 0;\n        int remaining = M;\n        while (remaining > 0) {\n            for (int j = 0; j < M; ++j)\n                if (!covered[j] && built.find(pat[j]) != string::npos) { covered[j] = true; remaining--; }\n            if (remaining == 0) break;\n            vector<pair<LL, int>> cand;\n            for (int j = 0; j < M; ++j) {\n                if (covered[j]) continue;\n                int real_ol = 0;\n                for (int l = min(5, (int)built.size()); l >= 1; --l)\n                    if (built.compare(built.size()-l, l, pat[j], 0, l) == 0) { real_ol = l; break; }\n                if (real_ol == 5) { covered[j] = true; remaining--; continue; }\n                LL c = cost_flat[((j)*6 + real_ol)*SZ + cur];\n                cand.emplace_back(c - 2.5 * real_ol, j);\n            }\n            if (cand.empty()) break;\n            sort(cand.begin(), cand.end());\n            int chosen;\n            if (trial == 0) chosen = cand[0].second;\n            else {\n                int topk = min(3, (int)cand.size());\n                uniform_int_distribution<int> uid(0, topk-1);\n                chosen = cand[uid(rng)].second;\n            }\n            int real_ol = 0;\n            for (int l = min(5, (int)built.size()); l >= 1; --l)\n                if (built.compare(built.size()-l, l, pat[chosen], 0, l) == 0) { real_ol = l; break; }\n            total += cost_flat[((chosen)*6 + real_ol)*SZ + cur];\n            cur = endCell_flat[((chosen)*6 + real_ol)*SZ + cur];\n            built += pat[chosen].substr(real_ol);\n            order.push_back(chosen);\n            covered[chosen] = true;\n            remaining--;\n        }\n        if (total < best_total) { best_total = total; best_order = order; }\n    }\n\n    // Phase 3: Simulated annealing with swap and 2-opt\n    if (!best_order.empty()) {\n        vector<int> cur_order = best_order;\n        LL cur_cost = best_total;\n        double T = 300.0, cooling = 0.9992;\n        int max_iter = 40000;\n        for (int it = 0; it < max_iter; ++it) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > 1.7) break;\n            int type = uniform_int_distribution<int>(0,1)(rng);\n            LL new_total;\n            if (type == 0) {\n                int i = uniform_int_distribution<int>(0, M-2)(rng);\n                int j = uniform_int_distribution<int>(i+1, M-1)(rng);\n                swap(cur_order[i], cur_order[j]);\n                new_total = eval_fast(cur_order);\n                LL delta = new_total - cur_cost;\n                if (delta < 0 || (double)rng()/rng.max() < exp(-delta/T)) {\n                    cur_cost = new_total;\n                    if (new_total < best_total) { best_total = new_total; best_order = cur_order; }\n                } else swap(cur_order[i], cur_order[j]);\n            } else {\n                int l = uniform_int_distribution<int>(0, M-2)(rng);\n                int r = uniform_int_distribution<int>(l+1, M-1)(rng);\n                reverse(cur_order.begin()+l, cur_order.begin()+r+1);\n                new_total = eval_fast(cur_order);\n                LL delta = new_total - cur_cost;\n                if (delta < 0 || (double)rng()/rng.max() < exp(-delta/T)) {\n                    cur_cost = new_total;\n                    if (new_total < best_total) { best_total = new_total; best_order = cur_order; }\n                } else reverse(cur_order.begin()+l, cur_order.begin()+r+1);\n            }\n            T *= cooling;\n        }\n    }\n\n    // Phase 4: Local search via best insertion (greedy)\n    if (!best_order.empty()) {\n        vector<int> order = best_order;\n        LL cur_cost = best_total;\n        bool improved = true;\n        int iter = 0;\n        while (improved && iter < 5) {\n            improved = false;\n            iter++;\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > 1.95) break;\n            for (int i = 0; i < M; ++i) {\n                int idx = order[i];\n                // try to move idx to every other position\n                int best_pos = i;\n                LL best_val = cur_cost;\n                // compute current contribution of idx (use eval_fast on full order? easier: compute cost without idx and try insertion)\n                // We'll compute total cost without idx, then try inserting at each position.\n                // Build order without idx\n                vector<int> without;\n                for (int k = 0; k < M; ++k) if (k != i) without.push_back(order[k]);\n                // compute cost of without? Not straightforward due to overlap changes. Use approximate: evaluate full order with idx removed? but overlaps depend on neighbors.\n                // We'll use eval_fast for each candidate insertion.\n                for (int pos = 0; pos <= M-1; ++pos) {\n                    // insert idx at position pos in without\n                    vector<int> candidate = without;\n                    candidate.insert(candidate.begin() + pos, idx);\n                    LL val = eval_fast(candidate);\n                    if (val < best_val) {\n                        best_val = val;\n                        best_pos = pos;\n                    }\n                }\n                if (best_pos != i) {\n                    // apply best insertion\n                    vector<int> without2;\n                    for (int k = 0; k < M; ++k) if (k != i) without2.push_back(order[k]);\n                    order = without2;\n                    order.insert(order.begin() + best_pos, idx);\n                    cur_cost = best_val;\n                    improved = true;\n                }\n            }\n        }\n        if (cur_cost < best_total) {\n            best_total = cur_cost;\n            best_order = order;\n        }\n    }\n\n    // Final reconstruction\n    if (!best_order.empty()) reconstruct(best_order, best_moves);\n    for (int p : best_moves) cout << p / N << ' ' << p % N << '\\n';\n\n    delete[] cost_flat;\n    delete[] endCell_flat;\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 20;\nconst int MAX_CELLS = MAX_N * MAX_N;\n\nint N, M;\ndouble eps;\n\n// Pre-define structures\nstruct Placement {\n    vector<int> cells; // indices of covered cells (i*N+j)\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    vector<Placement> placements;\n    vector<bool> active; // true if placement still possible\n    int active_cnt;\n};\n\nvector<Field> fields;\nint drilled_v[MAX_CELLS]; // -1 unknown, else exact value\nint cover_count[MAX_CELLS]; // number of active placements covering this cell\nint ops = 0;\nconst int MAX_OPS = 2 * MAX_N * MAX_N;\n\n// For each cell, list of (field_index, placement_index)\nvector<pair<int,int>> cell_placements[MAX_CELLS];\n\n// For backtracking\nint cur_sum[MAX_CELLS];\nint found_solutions;\nvector<int> cur_assign; // placement index for each field\nvector<int> best_assign;\n\nvoid flush_output() {\n    cout.flush();\n}\n\nvoid read_input() {\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        vector<pair<int,int>> shape(d);\n        for (int l = 0; l < d; ++l) {\n            cin >> shape[l].first >> shape[l].second;\n        }\n        fields[k].shape = shape;\n    }\n}\n\nvoid generate_placements() {\n    for (int f = 0; f < M; ++f) {\n        const auto& shape = fields[f].shape;\n        int max_i = 0, max_j = 0;\n        for (const auto& p : shape) {\n            max_i = max(max_i, p.first);\n            max_j = max(max_j, p.second);\n        }\n        int h = max_i + 1, w = max_j + 1;\n        for (int di = 0; di <= N - h; ++di) {\n            for (int dj = 0; dj <= N - w; ++dj) {\n                Placement pl;\n                for (const auto& p : shape) {\n                    int i = di + p.first;\n                    int j = dj + p.second;\n                    pl.cells.push_back(i * N + j);\n                }\n                fields[f].placements.push_back(move(pl));\n            }\n        }\n        fields[f].active.assign(fields[f].placements.size(), true);\n        fields[f].active_cnt = fields[f].placements.size();\n    }\n}\n\nvoid build_cell_cover() {\n    for (int cell = 0; cell < N * N; ++cell) {\n        cell_placements[cell].clear();\n    }\n    for (int f = 0; f < M; ++f) {\n        int pid = 0;\n        for (const auto& pl : fields[f].placements) {\n            for (int cell : pl.cells) {\n                cell_placements[cell].push_back({f, pid});\n            }\n            ++pid;\n        }\n    }\n    // initial cover counts\n    memset(cover_count, 0, sizeof(cover_count));\n    for (int cell = 0; cell < N * N; ++cell) {\n        cover_count[cell] = cell_placements[cell].size();\n    }\n}\n\nint find_best_cell() {\n    int best_cell = -1, best_cnt = -1;\n    for (int cell = 0; cell < N * N; ++cell) {\n        if (drilled_v[cell] != -1) continue;\n        if (cover_count[cell] > best_cnt) {\n            best_cnt = cover_count[cell];\n            best_cell = cell;\n        }\n    }\n    return best_cell;\n}\n\nvoid eliminate_placement(int f, int pid) {\n    if (!fields[f].active[pid]) return;\n    fields[f].active[pid] = false;\n    fields[f].active_cnt--;\n    for (int cell : fields[f].placements[pid].cells) {\n        cover_count[cell]--;\n    }\n}\n\nvoid drill_cell(int cell) {\n    int i = cell / N, j = cell % N;\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    drilled_v[cell] = resp;\n    ops++;\n    if (resp == 0) {\n        // eliminate all placements covering this cell\n        for (auto [f, pid] : cell_placements[cell]) {\n            eliminate_placement(f, pid);\n        }\n    }\n}\n\n// ---- Backtracking ----\nbool can_place(int f, int pid) {\n    for (int cell : fields[f].placements[pid].cells) {\n        if (drilled_v[cell] != -1 && cur_sum[cell] + 1 > drilled_v[cell]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nvoid dfs(int step, const vector<int>& order) {\n    if (found_solutions >= 2) return;\n    if (step == (int)order.size()) {\n        // check all drilled cells exactly\n        for (int cell = 0; cell < N * N; ++cell) {\n            if (drilled_v[cell] != -1 && cur_sum[cell] != drilled_v[cell]) {\n                return;\n            }\n        }\n        found_solutions++;\n        if (found_solutions == 1) {\n            best_assign = cur_assign;\n        }\n        return;\n    }\n    int f = order[step];\n    const auto& placements = fields[f].placements;\n    const auto& active = fields[f].active;\n    for (int pid = 0; pid < (int)placements.size(); ++pid) {\n        if (!active[pid]) continue;\n        if (!can_place(f, pid)) continue;\n        // place\n        cur_assign[f] = pid;\n        for (int cell : placements[pid].cells) {\n            cur_sum[cell]++;\n        }\n        dfs(step + 1, order);\n        // undo\n        for (int cell : placements[pid].cells) {\n            cur_sum[cell]--;\n        }\n        cur_assign[f] = -1;\n        if (found_solutions >= 2) return;\n    }\n}\n\nbool find_unique() {\n    found_solutions = 0;\n    // order fields by number of active placements (ascending)\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return fields[a].active_cnt < fields[b].active_cnt;\n    });\n    memset(cur_sum, 0, sizeof(cur_sum));\n    cur_assign.assign(M, -1);\n    best_assign.assign(M, -1);\n    dfs(0, order);\n    return (found_solutions == 1);\n}\n\nbool estimate_small() {\n    long long prod = 1;\n    for (int f = 0; f < M; ++f) {\n        int cnt = fields[f].active_cnt;\n        if (cnt == 0) return false;\n        prod *= cnt;\n        if (prod > 100000) return false;\n    }\n    return true;\n}\n\nvoid guess_and_check() {\n    // compute set of positive cells from best_assign\n    vector<int> pos_cells;\n    for (int f = 0; f < M; ++f) {\n        int pid = best_assign[f];\n        if (pid == -1) continue;\n        for (int cell : fields[f].placements[pid].cells) {\n            pos_cells.push_back(cell);\n        }\n    }\n    sort(pos_cells.begin(), pos_cells.end());\n    pos_cells.erase(unique(pos_cells.begin(), pos_cells.end()), pos_cells.end());\n    cout << \"a \" << pos_cells.size();\n    for (int cell : pos_cells) {\n        cout << \" \" << cell / N << \" \" << cell % N;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp;\n    ops++;\n    if (resp == 1) {\n        exit(0); // success, terminate\n    }\n    // else: wrong guess, continue\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    read_input();\n    generate_placements();\n    build_cell_cover();\n    memset(drilled_v, -1, sizeof(drilled_v));\n    ops = 0;\n\n    // Optional: perform row/col divine queries to gather information (can be used for pruning, but we will just ignore the answers)\n    // These are cheap (cost 2*N queries), but they may help later. We'll keep them.\n    // Note: The results are not used in the current pruning, but we can record them if needed.\n    // For now, we skip to avoid complexity. (They might add extra info but also cost extra operations.)\n    // Since we are in the early stage of drilling, we can skip them to reduce branching.\n\n    while (ops < MAX_OPS) {\n        // Try to guess if product of active placements is small\n        if (ops >= 10 && estimate_small()) {\n            if (find_unique()) {\n                guess_and_check();\n                // if guess fails, we continue drilling\n            }\n        }\n        int cell = find_best_cell();\n        if (cell == -1) break; // all cells drilled\n        drill_cell(cell);\n    }\n\n    // Fallback: drill any remaining cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int cell = i * N + j;\n            if (drilled_v[cell] == -1) {\n                drill_cell(cell);\n                if (ops >= MAX_OPS) break;\n            }\n        }\n        if (ops >= MAX_OPS) break;\n    }\n\n    // Now we have exact v for every cell, output answer\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (drilled_v[i * N + j] > 0) {\n                ans.emplace_back(i, j);\n            }\n        }\n    }\n    cout << \"a \" << ans.size();\n    for (auto [i,j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    flush_output();\n    int resp;\n    cin >> resp; // should be 1\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <climits>\n#include <random>\n#include <chrono>\n\nusing namespace std;\nusing ll = long long;\n\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nint sym_diff_size(const vector<int>& a, const vector<int>& b) {\n    int i = 0, j = 0, cnt = 0;\n    int na = (int)a.size(), nb = (int)b.size();\n    while (i < na || j < nb) {\n        if (i < na && j < nb) {\n            if (a[i] == b[j]) { ++i; ++j; }\n            else if (a[i] < b[j]) { ++cnt; ++i; }\n            else { ++cnt; ++j; }\n        } else if (i < na) { ++cnt; ++i; }\n        else { ++cnt; ++j; }\n    }\n    return cnt;\n}\n\nvector<int> widths_from_cuts(const vector<int>& cuts, int W, int N) {\n    vector<int> w(N);\n    int prev = 0;\n    for (int i = 0; i < N - 1; ++i) {\n        w[i] = cuts[i] - prev;\n        prev = cuts[i];\n    }\n    w[N-1] = W - prev;\n    return w;\n}\n\nll deficit_cost(const vector<int>& dem, const vector<int>& wid) {\n    ll c = 0;\n    for (size_t i = 0; i < dem.size(); ++i) {\n        ll area = 1LL * wid[i] * 1000;\n        if (dem[i] > area) c += 100LL * (dem[i] - area);\n    }\n    return c;\n}\n\nll total_cost(const vector<int>& cuts, const vector<int>& prev_cuts,\n              const vector<int>& dem_desc, int W, int N) {\n    vector<int> w = widths_from_cuts(cuts, W, N);\n    vector<int> w_desc = w;\n    sort(w_desc.begin(), w_desc.end(), greater<int>());\n    ll def = deficit_cost(dem_desc, w_desc);\n    ll change = 1LL * W * sym_diff_size(cuts, prev_cuts);\n    return def + change;\n}\n\n// Local search: single-cut moves (delta = -2,-1,1,2) repeatedly\nvector<int> local_search_single(const vector<int>& start_cuts, const vector<int>& prev_cuts,\n                                const vector<int>& dem_desc, int W, int N, int max_iter=200) {\n    vector<int> cur = start_cuts;\n    bool improved = true;\n    for (int iter = 0; iter < max_iter && improved; ++iter) {\n        improved = false;\n        ll cur_cost = total_cost(cur, prev_cuts, dem_desc, W, N);\n        for (int ci = 0; ci < N - 1; ++ci) {\n            int orig = cur[ci];\n            int left_limit = (ci == 0) ? 1 : cur[ci-1] + 1;\n            int right_limit = (ci == N-2) ? W-1 : cur[ci+1] - 1;\n            for (int delta : {-2, -1, 1, 2}) {\n                int new_val = orig + delta;\n                if (new_val < left_limit || new_val > right_limit) continue;\n                cur[ci] = new_val;\n                ll new_cost = total_cost(cur, prev_cuts, dem_desc, W, N);\n                if (new_cost < cur_cost) {\n                    improved = true;\n                    cur_cost = new_cost;\n                    break; // restart loop after improvement\n                } else {\n                    cur[ci] = orig; // revert\n                }\n            }\n            if (improved) break;\n        }\n    }\n    return cur;\n}\n\n// Two-cut move: randomly try a few pairs and adjust both by small amounts\nvector<int> local_search_two(const vector<int>& start_cuts, const vector<int>& prev_cuts,\n                             const vector<int>& dem_desc, int W, int N, int trials=30) {\n    vector<int> cur = start_cuts;\n    ll best_cost = total_cost(cur, prev_cuts, dem_desc, W, N);\n    for (int t = 0; t < trials; ++t) {\n        int i = uniform_int_distribution<int>(0, N-2)(rng);\n        int j = uniform_int_distribution<int>(0, N-2)(rng);\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n        // try shifts for i and j within bounds\n        int shift_i = uniform_int_distribution<int>(-2, 2)(rng);\n        int shift_j = uniform_int_distribution<int>(-2, 2)(rng);\n        int new_i = cur[i] + shift_i;\n        int new_j = cur[j] + shift_j;\n        // enforce order and bounds\n        int min_i = (i == 0) ? 1 : cur[i-1] + 1;\n        int max_i = (i == N-2) ? W-1 : cur[i+1] - 1;\n        if (new_i < min_i || new_i > max_i) continue;\n        int min_j = (j == 0) ? 1 : cur[j-1] + 1;\n        int max_j = (j == N-2) ? W-1 : cur[j+1] - 1;\n        if (new_j < min_j || new_j > max_j) continue;\n        // after changes, ensure i and j are still ordered\n        if (i+1 == j && new_i >= new_j) continue;\n        vector<int> new_cuts = cur;\n        new_cuts[i] = new_i;\n        new_cuts[j] = new_j;\n        // also need to ensure all cuts are sorted and within bounds (due to possible overlapping after change)\n        // easy: just sort and then enforce bounds\n        sort(new_cuts.begin(), new_cuts.end());\n        bool valid = true;\n        for (int idx = 0; idx < N-1; ++idx) {\n            int left = (idx == 0) ? 1 : new_cuts[idx-1] + 1;\n            int right = (idx == N-2) ? W-1 : new_cuts[idx+1] - 1;\n            if (new_cuts[idx] < left || new_cuts[idx] > right) { valid = false; break; }\n        }\n        if (!valid) continue;\n        // also ensure all cuts distinct (should be enforced by sorting)\n        ll new_cost = total_cost(new_cuts, prev_cuts, dem_desc, W, N);\n        if (new_cost < best_cost) {\n            best_cost = new_cost;\n            cur = new_cuts;\n        }\n    }\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    vector<int> prev_cuts;\n\n    for (int d = 0; d < D; ++d) {\n        vector<pair<int,int>> items(N);\n        for (int k = 0; k < N; ++k) items[k] = {a[d][k], k};\n        sort(items.begin(), items.end(), [](auto& p, auto& q) { return p.first > q.first; });\n        vector<int> dem_desc(N), idx_desc(N);\n        for (int i = 0; i < N; ++i) {\n            dem_desc[i] = items[i].first;\n            idx_desc[i] = items[i].second;\n        }\n\n        // Greedy ideal widths\n        vector<int> ideal_w(N, 1);\n        vector<ll> deficit(N);\n        for (int i = 0; i < N; ++i) deficit[i] = dem_desc[i] - 1000;\n        int total = N;\n        while (total < W) {\n            int best = -1;\n            ll best_def = LLONG_MIN;\n            for (int i = 0; i < N; ++i) if (deficit[i] > best_def) { best_def = deficit[i]; best = i; }\n            if (best == -1 || best_def <= 0) break;\n            ideal_w[best]++; total++;\n            deficit[best] = dem_desc[best] - 1LL * ideal_w[best] * 1000;\n        }\n        while (total < W) {\n            for (int i = 0; i < N && total < W; ++i) { ideal_w[i]++; total++; }\n        }\n        vector<int> ideal_cuts(N-1);\n        int cum = 0;\n        for (int i = 0; i < N-1; ++i) { cum += ideal_w[i]; ideal_cuts[i] = cum; }\n\n        // Candidate generation\n        vector<vector<int>> candidates;\n        candidates.push_back(ideal_cuts);\n        if (d > 0) {\n            candidates.push_back(prev_cuts);\n            // multiple random perturbations\n            for (int r = 0; r < 10; ++r) {\n                vector<int> cand = prev_cuts;\n                for (int &v : cand) {\n                    int shift = uniform_int_distribution<int>(-5, 5)(rng);\n                    v += shift;\n                }\n                sort(cand.begin(), cand.end());\n                for (int i = 0; i < N-1; ++i) {\n                    int left_min = (i == 0) ? 1 : cand[i-1] + 1;\n                    int right_max = (i == N-2) ? W-1 : cand[i+1] - 1;\n                    if (cand[i] < left_min) cand[i] = left_min;\n                    if (cand[i] > right_max) cand[i] = right_max;\n                }\n                // ensure increasing\n                for (int i = 0; i < N-2; ++i) if (cand[i] >= cand[i+1]) cand[i+1] = cand[i] + 1;\n                candidates.push_back(cand);\n            }\n        }\n\n        // Evaluate each candidate with local search\n        vector<int> best_cuts = candidates[0];\n        ll best_cost = total_cost(best_cuts, prev_cuts, dem_desc, W, N);\n        for (const auto& cand : candidates) {\n            vector<int> improved = local_search_single(cand, prev_cuts, dem_desc, W, N, 200);\n            improved = local_search_two(improved, prev_cuts, dem_desc, W, N, 30);\n            ll cost = total_cost(improved, prev_cuts, dem_desc, W, N);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_cuts = improved;\n            }\n        }\n\n        // Final assignment\n        vector<int> w = widths_from_cuts(best_cuts, W, N);\n        vector<int> order(N);\n        for (int i = 0; i < N; ++i) order[i] = i;\n        sort(order.begin(), order.end(), [&](int a, int b) { return w[a] > w[b]; });\n\n        vector<int> x0(N), x1(N);\n        for (int i = 0; i < N; ++i) {\n            int si = order[i];\n            int l = (si == 0) ? 0 : best_cuts[si-1];\n            int r = (si == N-1) ? W : best_cuts[si];\n            int orig = idx_desc[i];\n            x0[orig] = l;\n            x1[orig] = r;\n        }\n\n        for (int k = 0; k < N; ++k) {\n            cout << x0[k] << \" 0 \" << x1[k] << \" \" << W << '\\n';\n        }\n\n        prev_cuts = best_cuts;\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing ull = unsigned long long;\n\nconst ll MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\n\nstruct Operation {\n    int m, p, q;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k;\n    cin >> n >> m >> k;\n    // n=9, m=20, k=81 always\n\n    vector<vector<ll>> board(N, vector<ll>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> board[i][j];\n\n    vector<vector<vector<ll>>> stamps(M, vector<vector<ll>>(3, vector<ll>(3)));\n    for (int id = 0; id < M; ++id)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamps[id][i][j];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n\n    // initial score (sum of remainders)\n    ll initial_score = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            initial_score += board[i][j] % MOD;\n\n    pair<ll, vector<Operation>> best = {0, {}};\n    const int TRIALS = 15; // enough time\n\n    // helper lambda: compute gain of applying a stamp (without changing board)\n    auto compute_gain = [&](const vector<vector<ll>>& cur, int m, int p, int q) -> ll {\n        ll gain = 0;\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j) {\n                ll x = cur[p + i][q + j];\n                gain += ((x + stamps[m][i][j]) % MOD) - (x % MOD);\n            }\n        return gain;\n    };\n\n    for (int trial = 0; trial < TRIALS; ++trial) {\n        // check time limit\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count() > 1900)\n            break;\n\n        vector<vector<ll>> cur = board;\n        vector<Operation> ops;\n        ll cur_score = initial_score;\n\n        // ---------- greedy construction ----------\n        while ((int)ops.size() < K) {\n            vector<pair<ll, Operation>> candidates;\n            ll best_gain = -1e18;\n            for (int mm = 0; mm < M; ++mm) {\n                for (int p = 0; p + 2 < N; ++p) {\n                    for (int q = 0; q + 2 < N; ++q) {\n                        ll gain = compute_gain(cur, mm, p, q);\n                        if (gain > best_gain) {\n                            best_gain = gain;\n                            candidates.clear();\n                            candidates.push_back({gain, {mm, p, q}});\n                        } else if (gain == best_gain && gain > 0) {\n                            candidates.push_back({gain, {mm, p, q}});\n                        }\n                    }\n                }\n            }\n            if (candidates.empty()) break;\n            uniform_int_distribution<int> dist(0, (int)candidates.size() - 1);\n            auto op = candidates[dist(rng)].second;\n            // apply stamp\n            for (int i = 0; i < 3; ++i)\n                for (int j = 0; j < 3; ++j)\n                    cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n            cur_score += best_gain;\n            ops.push_back(op);\n        }\n\n        // ---------- local search ----------\n        bool improved = true;\n        int max_passes = 20;\n        while (improved && max_passes-- > 0) {\n            improved = false;\n\n            // ---- A: replace each operation with the best possible ----\n            vector<int> indices(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                Operation old_op = ops[idx];\n                // remove old_op (subtract stamp)\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[old_op.p + i][old_op.q + j] -= stamps[old_op.m][i][j];\n                // recompute score delta for this 3x3 area\n                // we can recompute whole score quickly but we just recompute the area effect\n                ll old_area_sum = 0, new_area_sum = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        // old before removal = (cur after removal) + stamp value\n                        ll after = cur[old_op.p + i][old_op.q + j];\n                        old_area_sum += (after + stamps[old_op.m][i][j]) % MOD;\n                        new_area_sum += after % MOD;\n                    }\n                ll delta = new_area_sum - old_area_sum; // negative if removal is good\n                cur_score += delta;\n\n                // find best stamp to add now\n                ll best_gain = -1e18;\n                Operation best_op;\n                for (int mm = 0; mm < M; ++mm) {\n                    for (int p = 0; p + 2 < N; ++p) {\n                        for (int q = 0; q + 2 < N; ++q) {\n                            ll gain = compute_gain(cur, mm, p, q);\n                            if (gain > best_gain) {\n                                best_gain = gain;\n                                best_op = {mm, p, q};\n                            }\n                        }\n                    }\n                }\n                if (best_gain > 0 && best_gain > -delta) {\n                    // apply best_op\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[best_op.p + i][best_op.q + j] += stamps[best_op.m][i][j];\n                    cur_score += best_gain;\n                    ops[idx] = best_op;\n                    improved = true;\n                } else {\n                    // restore old_op\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[old_op.p + i][old_op.q + j] += stamps[old_op.m][i][j];\n                    cur_score -= delta; // revert the score change\n                }\n            }\n\n            // ---- B: remove operations that have negative contribution ----\n            indices.resize(ops.size());\n            iota(indices.begin(), indices.end(), 0);\n            shuffle(indices.begin(), indices.end(), rng);\n            for (int idx : indices) {\n                if (ops.empty()) break;\n                Operation op = ops[idx];\n                // remove\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[op.p + i][op.q + j] -= stamps[op.m][i][j];\n                ll old_area = 0, new_area = 0;\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j) {\n                        ll after = cur[op.p + i][op.q + j];\n                        old_area += (after + stamps[op.m][i][j]) % MOD;\n                        new_area += after % MOD;\n                    }\n                ll delta = new_area - old_area;\n                cur_score += delta;\n                if (delta > 0) { // removal increased total score\n                    ops.erase(ops.begin() + idx);\n                    improved = true;\n                } else {\n                    // restore\n                    for (int i = 0; i < 3; ++i)\n                        for (int j = 0; j < 3; ++j)\n                            cur[op.p + i][op.q + j] += stamps[op.m][i][j];\n                    cur_score -= delta;\n                }\n            }\n\n            // ---- C: fill empty slots (if any) with greedy addition ----\n            while ((int)ops.size() < K) {\n                ll best_gain = -1e18;\n                Operation best_op;\n                for (int mm = 0; mm < M; ++mm) {\n                    for (int p = 0; p + 2 < N; ++p) {\n                        for (int q = 0; q + 2 < N; ++q) {\n                            ll gain = compute_gain(cur, mm, p, q);\n                            if (gain > best_gain) {\n                                best_gain = gain;\n                                best_op = {mm, p, q};\n                            }\n                        }\n                    }\n                }\n                if (best_gain <= 0) break;\n                // apply best\n                for (int i = 0; i < 3; ++i)\n                    for (int j = 0; j < 3; ++j)\n                        cur[best_op.p + i][best_op.q + j] += stamps[best_op.m][i][j];\n                cur_score += best_gain;\n                ops.push_back(best_op);\n                improved = true;\n            }\n        }\n\n        // keep best solution\n        if (cur_score > best.first) {\n            best = {cur_score, ops};\n        }\n    }\n\n    // output answer\n    cout << best.second.size() << \"\\n\";\n    for (const auto& op : best.second) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nint A[N][N];\nint targetRow[25];   // targetRow[num] = num / 5\n\nint craneR = 0, craneC = 0;\nbool holding = false;\nint heldContainer = -1;\n\nint grid[N][N];          // -1 = empty, otherwise container number\nint gateNextIdx[N];       // next index in A[i] to appear\nint gateContainer[N];     // current container at the gate (row,0), -1 if none\n\nvoid placeContainer(int num, int r, int c) {\n    grid[r][c] = num;\n}\n\nvoid removeContainer(int r, int c) {\n    grid[r][c] = -1;\n}\n\n// Manhattan distance (ignoring obstacles)\nint dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n// Decide direction (U/D/L/R) to move from (cr,cc) towards (tr,tc),\n// preferring to avoid standing on a gate cell if we are not going to pick immediately.\nchar direction(int cr, int cc, int tr, int tc) {\n    // Prefer vertical movement if far, else horizontal\n    if (cr < tr) return 'D';\n    if (cr > tr) return 'U';\n    if (cc < tc) return 'R';\n    if (cc > tc) return 'L';\n    return '.'; // already at target\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int dummyN;\n    cin >> dummyN;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> A[i][j];\n        }\n    }\n\n    // Precompute targetRow\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int num = A[i][j];\n            targetRow[num] = num / N;\n        }\n    }\n\n    // Initialize grid, gates\n    memset(grid, -1, sizeof(grid));\n    memset(gateNextIdx, 0, sizeof(gateNextIdx));\n    memset(gateContainer, -1, sizeof(gateContainer));\n\n    vector<string> out(N);  // output strings for each crane\n\n    // Turn 1: free the (0,0) gate and bomb all small cranes\n    out[0] += 'R';          // large crane moves to (0,1)\n    craneC = 1;\n    for (int i = 1; i < N; ++i) {\n        out[i] += 'B';      // small cranes bombed\n    }\n\n    // Main loop (turn = 2 ... )\n    for (int turn = 2; turn <= 10000; ++turn) {\n        // Step 1: place new containers at receiving gates\n        for (int i = 0; i < N; ++i) {\n            if (gateContainer[i] == -1 && gateNextIdx[i] < N) {\n                int num = A[i][gateNextIdx[i]++];\n                gateContainer[i] = num;\n                placeContainer(num, i, 0);\n            }\n        }\n\n        // Step 2: decide action for the large crane\n        char action = '.';\n        if (!holding) {\n            // Find the nearest gate that has a container\n            int bestDist = 1e9, bestRow = -1;\n            for (int r = 0; r < N; ++r) {\n                if (gateContainer[r] != -1) {\n                    int d = dist(craneR, craneC, r, 0);\n                    if (d < bestDist) {\n                        bestDist = d;\n                        bestRow = r;\n                    }\n                }\n            }\n            if (bestRow != -1) {\n                // Move towards that gate, or pick if already there\n                if (craneR == bestRow && craneC == 0) {\n                    // pick the container\n                    action = 'P';\n                } else {\n                    action = direction(craneR, craneC, bestRow, 0);\n                }\n            } else {\n                // No gate has a container: wait at current position (or move to center)\n                // Move towards (2,2) to stay out of way\n                if (craneR != 2 || craneC != 2) {\n                    action = direction(craneR, craneC, 2, 2);\n                }\n            }\n        } else {\n            // Holding a container: go to (targetRow[heldContainer], 4)\n            int tgtR = targetRow[heldContainer];\n            int tgtC = 4;\n            if (craneR == tgtR && craneC == tgtC) {\n                action = 'Q';\n            } else {\n                action = direction(craneR, craneC, tgtR, tgtC);\n            }\n        }\n\n        // Execute action\n        if (action == 'P') {\n            int num = grid[craneR][craneC];\n            if (num != -1) {\n                holding = true;\n                heldContainer = num;\n                int row = craneR;   // which gate we picked from\n                removeContainer(craneR, craneC);\n                gateContainer[row] = -1;  // gate becomes empty\n            } else {\n                action = '.'; // safety\n            }\n        } else if (action == 'Q') {\n            if (holding) {\n                int num = heldContainer;\n                grid[craneR][craneC] = num;\n                holding = false;\n                heldContainer = -1;\n            } else {\n                action = '.';\n            }\n        } else if (action == 'U' && craneR > 0) {\n            craneR--;\n        } else if (action == 'D' && craneR < N-1) {\n            craneR++;\n        } else if (action == 'L' && craneC > 0) {\n            craneC--;\n        } else if (action == 'R' && craneC < N-1) {\n            craneC++;\n        }\n\n        // Record the action (large crane)\n        out[0] += action;\n        // The bombed small cranes do nothing\n        for (int i = 1; i < N; ++i) {\n            out[i] += '.';\n        }\n\n        // Step 3: dispatch containers at right edge\n        for (int i = 0; i < N; ++i) {\n            if (grid[i][4] != -1) {\n                // Container is dispatched, remove from grid\n                grid[i][4] = -1;\n                // We don't track dispatch order, so just ignore.\n            }\n        }\n\n        // Check if all containers have been dispatched (i.e., grid empty and no holding and no gate containers)\n        bool allDone = true;\n        if (holding) allDone = false;\n        else {\n            for (int r = 0; r < N; ++r) {\n                if (gateNextIdx[r] < N || gateContainer[r] != -1) {\n                    allDone = false;\n                    break;\n                }\n                for (int c = 0; c < N; ++c) {\n                    if (grid[r][c] != -1) {\n                        allDone = false;\n                        break;\n                    }\n                }\n            }\n        }\n        if (allDone) break;\n    }\n\n    // Pad all strings to the same length\n    size_t maxLen = 0;\n    for (int i = 0; i < N; ++i) {\n        maxLen = max(maxLen, out[i].size());\n    }\n    for (int i = 0; i < N; ++i) {\n        while (out[i].size() < maxLen) out[i] += '.';\n        cout << out[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\nusing namespace std;\nusing ll = long long;\n\nstruct Node {\n    int x, y, delta;\n};\n\nint N;\nvector<Node> nodes;\nvector<vector<int>> dist;\nvector<int> distStart;\nint M;\n\nll computeCost(const vector<int>& order) {\n    ll cost = 0;\n    ll load = 0;\n    cost += (100LL + load) * distStart[order[0]];\n    load += nodes[order[0]].delta;\n    for (size_t i = 1; i < order.size(); ++i) {\n        int p = order[i-1], c = order[i];\n        cost += (100LL + load) * dist[p][c];\n        load += nodes[c].delta;\n    }\n    return cost;\n}\n\nbool feasible(const vector<int>& order) {\n    int load = 0;\n    for (int idx : order) {\n        load += nodes[idx].delta;\n        if (load < 0) return false;\n    }\n    return true;\n}\n\nvector<int> randomFeasible(mt19937& rng) {\n    vector<int> order; order.reserve(M);\n    vector<bool> used(M, false);\n    int load = 0;\n    for (int step = 0; step < M; ++step) {\n        vector<int> cand;\n        for (int i = 0; i < M; ++i)\n            if (!used[i] && (nodes[i].delta >= 0 || load >= -nodes[i].delta))\n                cand.push_back(i);\n        if (cand.empty())\n            for (int i = 0; i < M; ++i) if (!used[i]) cand.push_back(i);\n        int pick = cand[uniform_int_distribution<int>(0, (int)cand.size()-1)(rng)];\n        order.push_back(pick);\n        used[pick] = true;\n        load += nodes[pick].delta;\n    }\n    return order;\n}\n\nvector<int> greedyInitial() {\n    vector<int> order; order.reserve(M);\n    vector<bool> used(M, false);\n    ll load = 0;\n    for (int step = 0; step < M; ++step) {\n        int best = -1;\n        ll bestCost = 1e18;\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            if (nodes[i].delta < 0 && load < -nodes[i].delta) continue;\n            int d = (step == 0) ? distStart[i] : dist[order.back()][i];\n            ll c = (100LL + load) * d;\n            if (c < bestCost) { bestCost = c; best = i; }\n        }\n        if (best == -1) {\n            for (int i = 0; i < M; ++i) if (!used[i]) { best = i; break; }\n        }\n        order.push_back(best);\n        used[best] = true;\n        load += nodes[best].delta;\n    }\n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Input\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    ll base = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n            base += abs(h[i][j]);\n            if (h[i][j] != 0) nodes.push_back({i, j, h[i][j]});\n        }\n    }\n    M = nodes.size();\n    if (M == 0) return 0;\n\n    // Precompute distances\n    dist.assign(M, vector<int>(M));\n    distStart.assign(M, 0);\n    for (int i = 0; i < M; ++i) {\n        distStart[i] = nodes[i].x + nodes[i].y;\n        for (int j = 0; j < M; ++j) {\n            if (i == j) continue;\n            dist[i][j] = abs(nodes[i].x - nodes[j].x) + abs(nodes[i].y - nodes[j].y);\n        }\n    }\n\n    // Initial solutions\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    vector<int> bestOrder = greedyInitial();\n    ll bestCost = computeCost(bestOrder);\n    for (int t = 0; t < 50; ++t) {\n        vector<int> ord = randomFeasible(rng);\n        ll c = computeCost(ord);\n        if (c < bestCost) { bestCost = c; bestOrder = ord; }\n    }\n\n    // Simulated Annealing\n    vector<int> curOrder = bestOrder;\n    ll curCost = bestCost;\n    const double T_start = 1e6, T_end = 0.1;\n    const int iterations = 5000000;\n    double T = T_start;\n    auto startTime = chrono::steady_clock::now();\n    int noImprove = 0;\n    const int restartGap = 20000;\n\n    for (int it = 0; it < iterations; ++it) {\n        if (it % 1000 == 0) {\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n                chrono::steady_clock::now() - startTime).count();\n            if (elapsed > 1950) break;\n        }\n\n        vector<int> newOrder = curOrder;\n        int type = rng() % 3;\n        if (type == 0) {\n            int i = uniform_int_distribution<int>(0, M-1)(rng);\n            int j = uniform_int_distribution<int>(0, M-1)(rng);\n            if (i == j) continue;\n            swap(newOrder[i], newOrder[j]);\n        } else if (type == 1) {\n            int l = uniform_int_distribution<int>(0, M-1)(rng);\n            int r = uniform_int_distribution<int>(0, M-1)(rng);\n            if (l > r) swap(l, r);\n            reverse(newOrder.begin() + l, newOrder.begin() + r + 1);\n        } else {\n            int i = uniform_int_distribution<int>(0, M-1)(rng);\n            int val = newOrder[i];\n            newOrder.erase(newOrder.begin() + i);\n            int pos = uniform_int_distribution<int>(0, M-2)(rng);\n            newOrder.insert(newOrder.begin() + pos, val);\n        }\n\n        if (!feasible(newOrder)) continue;\n\n        ll newCost = computeCost(newOrder);\n        double delta = newCost - curCost;\n        if (delta < 0 ||\n            exp(-delta / T) > uniform_real_distribution<double>(0.0, 1.0)(rng)) {\n            curOrder = move(newOrder);\n            curCost = newCost;\n            if (newCost < bestCost) {\n                bestCost = newCost;\n                bestOrder = curOrder;\n                noImprove = 0;\n            } else noImprove++;\n        } else noImprove++;\n\n        if (noImprove > restartGap) {\n            curOrder = bestOrder;\n            curCost = bestCost;\n            noImprove = 0;\n            T = T_start;\n        }\n\n        double progress = (double)it / iterations;\n        T = T_start * pow(T_end / T_start, progress);\n    }\n\n    // Local search: 2-opt + Or-opt (block length up to 4)\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        if (chrono::duration_cast<chrono::milliseconds>(\n                chrono::steady_clock::now() - startTime).count() > 1950) break;\n\n        // 2-opt\n        for (int i = 0; i < M - 2; ++i) {\n            for (int j = i + 2; j < M; ++j) {\n                vector<int> test = bestOrder;\n                reverse(test.begin() + i + 1, test.begin() + j + 1);\n                if (!feasible(test)) continue;\n                ll c = computeCost(test);\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestOrder = test;\n                    improved = true;\n                }\n            }\n            if (chrono::duration_cast<chrono::milliseconds>(\n                    chrono::steady_clock::now() - startTime).count() > 1950) break;\n        }\n\n        // Or-opt: block length 1 to 4\n        for (int len = 1; len <= 4; ++len) {\n            for (int start = 0; start <= M - len; ++start) {\n                for (int pos = 0; pos <= M - len; ++pos) {\n                    if (pos == start) continue;\n                    // avoid overlapping\n                    if (pos >= start && pos < start + len) continue;\n                    vector<int> test = bestOrder;\n                    vector<int> block(test.begin() + start, test.begin() + start + len);\n                    test.erase(test.begin() + start, test.begin() + start + len);\n                    if (pos < start)\n                        test.insert(test.begin() + pos, block.begin(), block.end());\n                    else\n                        test.insert(test.begin() + pos - len + 1, block.begin(), block.end());\n                    if (!feasible(test)) continue;\n                    ll c = computeCost(test);\n                    if (c < bestCost) {\n                        bestCost = c;\n                        bestOrder = test;\n                        improved = true;\n                    }\n                }\n                if (chrono::duration_cast<chrono::milliseconds>(\n                        chrono::steady_clock::now() - startTime).count() > 1950) break;\n            }\n            if (chrono::duration_cast<chrono::milliseconds>(\n                    chrono::steady_clock::now() - startTime).count() > 1950) break;\n        }\n    }\n\n    // Output\n    vector<string> ops;\n    int cx = 0, cy = 0;\n    for (int idx : bestOrder) {\n        int nx = nodes[idx].x, ny = nodes[idx].y;\n        while (cx < nx) { ops.push_back(\"D\"); cx++; }\n        while (cx > nx) { ops.push_back(\"U\"); cx--; }\n        while (cy < ny) { ops.push_back(\"R\"); cy++; }\n        while (cy > ny) { ops.push_back(\"L\"); cy--; }\n        int d = nodes[idx].delta;\n        if (d > 0) ops.push_back(\"+\" + to_string(d));\n        else if (d < 0) ops.push_back(\"-\" + to_string(-d));\n    }\n    for (const string& s : ops) cout << s << \"\\n\";\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <unordered_set>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n    const int SEED_COUNT = 2 * N * (N - 1); // 60\n    const int GRID_SIZE = N * N;           // 36\n\n    vector<vector<int>> X(SEED_COUNT, vector<int>(M));\n    for (int i = 0; i < SEED_COUNT; ++i) {\n        for (int j = 0; j < M; ++j) {\n            cin >> X[i][j];\n        }\n    }\n\n    for (int turn = 0; turn < T; ++turn) {\n        // 1. Evaluate current seeds\n        vector<int> sumX(SEED_COUNT, 0);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            sumX[i] = accumulate(X[i].begin(), X[i].end(), 0);\n        }\n\n        // best overall seed (max sum)\n        int bestIdx = max_element(sumX.begin(), sumX.end()) - sumX.begin();\n\n        // per\u2011dimension best seeds\n        vector<int> dimMax(M, -1), dimIdx(M, -1);\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int l = 0; l < M; ++l) {\n                if (X[i][l] > dimMax[l]) {\n                    dimMax[l] = X[i][l];\n                    dimIdx[l] = i;\n                }\n            }\n        }\n\n        // 2. Build the set of elite seeds (best overall + per\u2011dimension best)\n        unordered_set<int> eliteSet;\n        eliteSet.insert(bestIdx);\n        for (int l = 0; l < M; ++l) {\n            eliteSet.insert(dimIdx[l]);\n        }\n        vector<int> elite(eliteSet.begin(), eliteSet.end());\n\n        // 3. Select 36 seeds: all elites + top sum among the rest\n        vector<bool> used(SEED_COUNT, false);\n        for (int idx : elite) used[idx] = true;\n        vector<int> additional;\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            if (!used[i]) additional.push_back(i);\n        }\n        sort(additional.begin(), additional.end(), [&](int a, int b) {\n            return sumX[a] > sumX[b];\n        });\n        int needFromAdd = GRID_SIZE - (int)elite.size();\n        // selected = elite + first needFromAdd of additional\n        vector<int> selected = elite;\n        selected.insert(selected.end(), additional.begin(), additional.begin() + needFromAdd);\n\n        // 4. Partition into interior (16) and border (20) seeds\n        int interiorSize = (N - 2) * (N - 2); // 16\n        int eliteSize = (int)elite.size();\n        int takeFromAdd = min(interiorSize - eliteSize, needFromAdd);\n        vector<int> interiorSeeds(elite.begin(), elite.end());\n        interiorSeeds.insert(interiorSeeds.end(), additional.begin(), additional.begin() + takeFromAdd);\n        // borderSeeds: the rest of selected\n        vector<int> borderSeeds(additional.begin() + takeFromAdd, additional.begin() + needFromAdd);\n        // sanity: (int)selected.size() == GRID_SIZE\n        // (int)interiorSeeds.size() == interiorSize\n        // borderSeeds.size() == GRID_SIZE - interiorSize\n\n        // 5. Build the placement grid\n        vector<vector<int>> A(N, vector<int>(N, -1));\n\n        // 5a. Define interior positions (1,\u2026,N-2)\n        vector<pair<int,int>> interiorPos;\n        for (int i = 1; i <= N-2; ++i)\n            for (int j = 1; j <= N-2; ++j)\n                interiorPos.push_back({i, j});\n\n        // 5b. Place the best overall at the centre (2,2)\n        int centre_i = 2, centre_j = 2; // 0\u2011based, inside interior\n        A[centre_i][centre_j] = bestIdx;\n\n        // Remove bestIdx from interiorSeeds (it's the first one)\n        auto it = find(interiorSeeds.begin(), interiorSeeds.end(), bestIdx);\n        if (it != interiorSeeds.end()) interiorSeeds.erase(it);\n        // Now interiorSeeds has size = interiorSize - 1 = 15\n\n        // Compute complement scores with bestIdx\n        vector<pair<int,int>> compScores; // (score, seedIdx)\n        for (int idx : interiorSeeds) {\n            int score = 0;\n            for (int l = 0; l < M; ++l) {\n                score += max(X[bestIdx][l], X[idx][l]);\n            }\n            compScores.push_back({-score, idx}); // negative for descending sort\n        }\n        sort(compScores.begin(), compScores.end());\n        // Top 4 become neighbours\n        vector<pair<int,int>> neighPos = {{centre_i-1, centre_j},\n                                          {centre_i+1, centre_j},\n                                          {centre_i, centre_j-1},\n                                          {centre_i, centre_j+1}};\n        unordered_set<int> usedInterior;\n        usedInterior.insert(bestIdx);\n        for (int k = 0; k < 4; ++k) {\n            int idx = compScores[k].second;\n            int ni = neighPos[k].first, nj = neighPos[k].second;\n            A[ni][nj] = idx;\n            usedInterior.insert(idx);\n        }\n\n        // 5d. Assign remaining interior seeds to remaining interior positions\n        // Remaining interior positions (exclude centre and neighbours)\n        vector<pair<int,int>> restInteriorPos;\n        for (auto [i,j] : interiorPos) {\n            if (i == centre_i && j == centre_j) continue;\n            bool isNeigh = false;\n            for (auto [ni,nj] : neighPos) if (ni==i && nj==j) { isNeigh = true; break; }\n            if (!isNeigh) restInteriorPos.push_back({i,j});\n        }\n        // Get the remaining seeds (not used)\n        vector<int> restSeeds;\n        for (int idx : interiorSeeds) {\n            if (!usedInterior.count(idx)) restSeeds.push_back(idx);\n        }\n        // restSeeds.size() should be 11\n        for (size_t k = 0; k < restInteriorPos.size(); ++k) {\n            A[restInteriorPos[k].first][restInteriorPos[k].second] = restSeeds[k];\n        }\n\n        // 5e. Fill border cells with borderSeeds\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (A[i][j] == -1) {\n                    A[i][j] = borderSeeds.back();\n                    borderSeeds.pop_back();\n                }\n            }\n        }\n\n        // 6. Output the grid\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                cout << A[i][j];\n                if (j < N-1) cout << ' ';\n            }\n            cout << '\\n';\n        }\n        cout << flush;\n\n        // 7. Read the new generation of seeds\n        for (int i = 0; i < SEED_COUNT; ++i) {\n            for (int j = 0; j < M; ++j) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<string> s_str, t_str;\nvector<vector<bool>> source, target;\n\nint root_x = 0, root_y = 0;\nint V_used;\nvector<int> parent, length;\nvector<int> dir;        // 0:right, 1:down, 2:left, 3:up\nvector<bool> holding;\n\nvector<string> commands;\n\nconst vector<pair<int,int>> offset_dir = {{0,1}, {1,0}, {0,-1}, {-1,0}};\n\nvoid rotate_leaf(int i, char c) {\n    if (c == 'R') dir[i] = (dir[i] + 1) % 4;\n    else if (c == 'L') dir[i] = (dir[i] + 3) % 4;\n}\n\n// get all four possible positions for a leaf of length L from (rx,ry)\nvector<pair<int,int>> get_positions(int rx, int ry, int L) {\n    vector<pair<int,int>> res;\n    for (int d = 0; d < 4; ++d) {\n        int nx = rx + offset_dir[d].first * L;\n        int ny = ry + offset_dir[d].second * L;\n        if (0 <= nx && nx < N && 0 <= ny && ny < N) {\n            res.emplace_back(nx, ny);\n        }\n    }\n    return res;\n}\n\n// Kuhn DFS for bipartite matching\nbool dfs(int u, const vector<vector<int>>& adj, vector<int>& matchR, vector<bool>& visited) {\n    for (int v : adj[u]) {\n        if (!visited[v]) {\n            visited[v] = true;\n            if (matchR[v] == -1 || dfs(matchR[v], adj, matchR, visited)) {\n                matchR[v] = u;\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n    s_str.resize(N);\n    t_str.resize(N);\n    for (int i = 0; i < N; ++i) cin >> s_str[i];\n    for (int i = 0; i < N; ++i) cin >> t_str[i];\n\n    source.assign(N, vector<bool>(N, false));\n    target.assign(N, vector<bool>(N, false));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s_str[i][j] == '1') source[i][j] = true;\n            if (t_str[i][j] == '1') target[i][j] = true;\n        }\n    }\n\n    // ---- design tree (star with lengths 1..V-1) ----\n    V_used = V;\n    parent.assign(V_used, 0);\n    length.assign(V_used, 0);\n    for (int i = 1; i < V_used; ++i) {\n        parent[i] = 0;\n        length[i] = i;\n    }\n\n    cout << V_used << '\\n';\n    for (int i = 1; i < V_used; ++i) {\n        cout << parent[i] << ' ' << length[i] << '\\n';\n    }\n    root_x = 0; root_y = 0;\n    cout << root_x << ' ' << root_y << '\\n';\n\n    dir.assign(V_used, 0);\n    holding.assign(V_used, false);\n\n    int total_source = M;\n    int total_target = M;\n    int turn_count = 0;\n    const int MAX_TURNS = 100000;\n\n    while ((total_source > 0 || total_target > 0) && turn_count < MAX_TURNS) {\n        // find best root position (max immediate actions, then min distance)\n        int best_cnt = -1;\n        int best_rx = -1, best_ry = -1;\n        for (int rx = 0; rx < N; ++rx) {\n            for (int ry = 0; ry < N; ++ry) {\n                int cnt = 0;\n                for (int i = 1; i < V_used; ++i) {\n                    int L = length[i];\n                    auto pos = get_positions(rx, ry, L);\n                    for (auto [cx, cy] : pos) {\n                        if (!holding[i] && source[cx][cy] && !target[cx][cy]) { cnt++; break; }\n                        if ( holding[i] && target[cx][cy] && !source[cx][cy]) { cnt++; break; }\n                    }\n                }\n                if (cnt > best_cnt) {\n                    best_cnt = cnt;\n                    best_rx = rx;\n                    best_ry = ry;\n                } else if (cnt == best_cnt) {\n                    int dist = abs(rx - root_x) + abs(ry - root_y);\n                    int best_dist = abs(best_rx - root_x) + abs(best_ry - root_y);\n                    if (dist < best_dist) {\n                        best_rx = rx; best_ry = ry;\n                    }\n                }\n            }\n        }\n        if (best_cnt == 0) break; // no valid actions left (should not happen)\n\n        // move root to best position\n        while ((root_x != best_rx || root_y != best_ry) && turn_count < MAX_TURNS) {\n            char move_char = '.';\n            int dx = best_rx - root_x, dy = best_ry - root_y;\n            if (dx > 0) { move_char = 'D'; root_x++; }\n            else if (dx < 0) { move_char = 'U'; root_x--; }\n            else if (dy > 0) { move_char = 'R'; root_y++; }\n            else if (dy < 0) { move_char = 'L'; root_y--; }\n\n            string rot(V_used - 1, '.');\n            string action(V_used, '.');\n            commands.push_back(move_char + rot + action);\n            turn_count++;\n        }\n        if (turn_count >= MAX_TURNS) break;\n\n        // perform actions at current root until no more matches\n        while (turn_count < MAX_TURNS) {\n            // build bipartite graph: leaves -> cells\n            map<pair<int,int>, int> cell_id;\n            vector<pair<int,int>> id_cell;\n            vector<vector<int>> adj(V_used);\n\n            for (int i = 1; i < V_used; ++i) {\n                int L = length[i];\n                auto pos = get_positions(best_rx, best_ry, L);\n                for (auto [cx, cy] : pos) {\n                    bool ok = false;\n                    if (!holding[i] && source[cx][cy] && !target[cx][cy]) ok = true;\n                    if ( holding[i] && target[cx][cy] && !source[cx][cy]) ok = true;\n                    if (ok) {\n                        auto key = make_pair(cx, cy);\n                        if (cell_id.find(key) == cell_id.end()) {\n                            cell_id[key] = id_cell.size();\n                            id_cell.push_back(key);\n                        }\n                        adj[i].push_back(cell_id[key]);\n                    }\n                }\n            }\n\n            int item_cnt = id_cell.size();\n            vector<int> matchR(item_cnt, -1);\n            int matching = 0;\n            for (int i = 1; i < V_used; ++i) {\n                vector<bool> visited(item_cnt, false);\n                if (dfs(i, adj, matchR, visited)) matching++;\n            }\n            if (matching == 0) break;\n\n            // assign cells to leaves\n            vector<pair<int,int>> leaf_target(V_used, {-1, -1});\n            for (int v = 0; v < item_cnt; ++v) {\n                if (matchR[v] != -1) {\n                    leaf_target[matchR[v]] = id_cell[v];\n                }\n            }\n\n            // compute target directions for matched leaves\n            vector<int> target_dir(V_used, -1);\n            for (int i = 1; i < V_used; ++i) {\n                auto [cx, cy] = leaf_target[i];\n                if (cx == -1) continue;\n                int L = length[i];\n                int dx = cx - best_rx, dy = cy - best_ry;\n                if (dx == 0 && dy == L) target_dir[i] = 0;\n                else if (dx == L && dy == 0) target_dir[i] = 1;\n                else if (dx == 0 && dy == -L) target_dir[i] = 2;\n                else if (dx == -L && dy == 0) target_dir[i] = 3;\n            }\n\n            // rotate leaves to target directions\n            while (true) {\n                if (turn_count >= MAX_TURNS) break;\n                bool all_aligned = true;\n                string rot = \"\";\n                for (int i = 1; i < V_used; ++i) {\n                    if (target_dir[i] == -1) { rot += '.'; continue; }\n                    int cur = dir[i];\n                    int tgt = target_dir[i];\n                    int diff = (tgt - cur + 4) % 4;\n                    char c = '.';\n                    if (diff == 1) c = 'R';\n                    else if (diff == 2) { c = 'R'; } // two rotations: can do R twice, but one turn only one rotation? Actually we can rotate by 180? The operation allows rotating by 90 degrees either direction. Two rotations would require two turns. So we need to do one rotation per turn. So we can only rotate 90 or -90 each turn. For diff==2, we need two turns. But our loop will continue. However, the direction change is done in the loop by repeatedly applying rotations. So we need to handle diff==2 as requiring two separate turns. Our code currently sets c='R' for diff==2, which rotates 90 clockwise, but we need to rotate 180. Better to choose any single rotation; the loop will then check again. So it's fine.\n                    else if (diff == 3) c = 'L';\n                    rot += c;\n                    if (c != '.') all_aligned = false;\n                    rotate_leaf(i, c);\n                }\n                if (all_aligned) break;\n                string action(V_used, '.');\n                commands.push_back('.' + rot + action);\n                turn_count++;\n            }\n            if (turn_count >= MAX_TURNS) break;\n\n            // action turn: pick or place\n            string rot(V_used - 1, '.');\n            string action = \".\";\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) action += 'P';\n                else action += '.';\n            }\n            commands.push_back('.' + rot + action);\n            turn_count++;\n\n            // update state\n            for (int i = 1; i < V_used; ++i) {\n                if (leaf_target[i].first != -1) {\n                    auto [cx, cy] = leaf_target[i];\n                    if (!holding[i]) {\n                        source[cx][cy] = false;\n                        holding[i] = true;\n                        total_source--;\n                    } else {\n                        target[cx][cy] = false;\n                        holding[i] = false;\n                        total_target--;\n                    }\n                }\n            }\n            if (total_source == 0 && total_target == 0) break;\n        }\n    }\n\n    // output all commands\n    for (const string& cmd : commands) {\n        cout << cmd << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing pii = pair<int, int>;\n\nconst int COORD_MAX = 100000;\nconst int PERIMETER_LIMIT = 400000;\n\n// count points inside rectangle [x1,x2]\u00d7[y1,y2]\ninline int countInRect(const vector<pii>& pts, int x1, int x2, int y1, int y2) {\n    int cnt = 0;\n    for (auto [x, y] : pts)\n        if (x1 <= x && x <= x2 && y1 <= y && y <= y2)\n            ++cnt;\n    return cnt;\n}\n\nint evaluateRect(int x1, int x2, int y1, int y2,\n                 const vector<pii>& mol, const vector<pii>& sol) {\n    if (x1 > x2 || y1 > y2) return -1;\n    int perim = 2 * (x2 - x1 + y2 - y1);\n    if (perim > PERIMETER_LIMIT) return -1;\n    int a = countInRect(mol, x1, x2, y1, y2);\n    int b = countInRect(sol, x1, x2, y1, y2);\n    return max(0, a - b + 1);\n}\n\n// find best tile rectangle for a given tile size S (0 <= coordinates <= COORD_MAX)\npair<int, pii> bestTileRect(const vector<pii>& mol,\n                             const vector<pii>& sol,\n                             int S) {\n    int T = COORD_MAX / S + 1;   // number of tiles per dimension\n    vector<vector<int>> w(T, vector<int>(T, 0));\n    for (auto [x, y] : mol) w[x / S][y / S]++;\n    for (auto [x, y] : sol) w[x / S][y / S]--;\n\n    // prefix sum (unused directly, only for verification)\n    // we compute rolling column sums for each pair of rows\n    int best_sum = -1e9, r1 = -1, r2 = -1, c1 = -1, c2 = -1;\n\n    for (int i = 0; i < T; ++i) {\n        vector<int> colSum(T, 0);\n        for (int j = i; j < T; ++j) {\n            // add current row\n            for (int k = 0; k < T; ++k)\n                colSum[k] += w[j][k];\n\n            int dy = j - i + 1;               // number of tile rows\n            int max_dx = PERIMETER_LIMIT / (2 * S) - dy;\n            if (max_dx <= 0) continue;\n            max_dx = min(max_dx, T);\n\n            // maximum subarray sum with length <= max_dx\n            vector<int> pref(T + 1, 0);\n            for (int k = 0; k < T; ++k)\n                pref[k + 1] = pref[k] + colSum[k];\n\n            deque<int> dq;\n            int local_best = -1e9;\n            int lc1 = -1, lc2 = -1;\n            for (int k = 0; k <= T; ++k) {\n                while (!dq.empty() && dq.front() < k - max_dx)\n                    dq.pop_front();\n                if (!dq.empty()) {\n                    int cur = pref[k] - pref[dq.front()];\n                    if (cur > local_best) {\n                        local_best = cur;\n                        lc1 = dq.front();\n                        lc2 = k - 1;\n                    }\n                }\n                while (!dq.empty() && pref[dq.back()] >= pref[k])\n                    dq.pop_back();\n                dq.push_back(k);\n            }\n\n            if (local_best > best_sum) {\n                best_sum = local_best;\n                r1 = i; r2 = j;\n                c1 = lc1; c2 = lc2;\n            }\n        }\n    }\n    return {best_sum, {r1, r2 * 10000 + c1 * 100 + c2}};\n}\n\n// tighten tile rectangle to the bounding box of mackerels inside it\nvoid tighten(const vector<pii>& mol,\n             int tile_x1, int tile_x2, int tile_y1, int tile_y2,\n             int &x1, int &x2, int &y1, int &y2) {\n    int minx = COORD_MAX + 1, maxx = -1;\n    int miny = COORD_MAX + 1, maxy = -1;\n    bool found = false;\n    for (auto [x, y] : mol) {\n        if (x >= tile_x1 && x <= tile_x2 && y >= tile_y1 && y <= tile_y2) {\n            minx = min(minx, x); maxx = max(maxx, x);\n            miny = min(miny, y); maxy = max(maxy, y);\n            found = true;\n        }\n    }\n    if (found) {\n        x1 = minx; x2 = maxx;\n        y1 = miny; y2 = maxy;\n        if (x1 == x2) x2 = min(COORD_MAX, x2 + 1);\n        if (y1 == y2) y2 = min(COORD_MAX, y2 + 1);\n    } else {\n        // fallback: first mackerel (should not happen if tile rectangle has positive sum)\n        auto [mx, my] = mol[0];\n        x1 = mx; x2 = min(COORD_MAX, mx + 1);\n        y1 = my; y2 = min(COORD_MAX, my + 1);\n    }\n}\n\n// local search on rectangle boundaries using fish coordinates\nvoid localSearch(const vector<pii>& mol, const vector<pii>& sol,\n                 int &x1, int &x2, int &y1, int &y2) {\n    // collect all distinct fish coordinates + borders\n    set<int> xs_set, ys_set;\n    xs_set.insert(0); xs_set.insert(COORD_MAX);\n    ys_set.insert(0); ys_set.insert(COORD_MAX);\n    for (auto [x, y] : mol) { xs_set.insert(x); ys_set.insert(y); }\n    for (auto [x, y] : sol) { xs_set.insert(x); ys_set.insert(y); }\n    vector<int> xs(xs_set.begin(), xs_set.end());\n    vector<int> ys(ys_set.begin(), ys_set.end());\n\n    auto prev_val = [](const vector<int>& v, int cur) {\n        auto it = lower_bound(v.begin(), v.end(), cur);\n        return it == v.begin() ? -1 : *prev(it);\n    };\n    auto next_val = [](const vector<int>& v, int cur) {\n        auto it = upper_bound(v.begin(), v.end(), cur);\n        return it == v.end() ? -1 : *it;\n    };\n\n    for (int iter = 0; iter < 100; ++iter) {\n        int cur = evaluateRect(x1, x2, y1, y2, mol, sol);\n        if (cur <= 0) break;\n        // expansions\n        int cand = prev_val(xs, x1);\n        if (cand >= 0 && evaluateRect(cand, x2, y1, y2, mol, sol) > cur) { x1 = cand; continue; }\n        cand = next_val(xs, x2);\n        if (cand >= 0 && evaluateRect(x1, cand, y1, y2, mol, sol) > cur) { x2 = cand; continue; }\n        cand = prev_val(ys, y1);\n        if (cand >= 0 && evaluateRect(x1, x2, cand, y2, mol, sol) > cur) { y1 = cand; continue; }\n        cand = next_val(ys, y2);\n        if (cand >= 0 && evaluateRect(x1, x2, y1, cand, mol, sol) > cur) { y2 = cand; continue; }\n        // shrinkages\n        cand = next_val(xs, x1);\n        if (cand >= 0 && cand <= x2 && evaluateRect(cand, x2, y1, y2, mol, sol) > cur) { x1 = cand; continue; }\n        cand = prev_val(xs, x2);\n        if (cand >= 0 && cand >= x1 && evaluateRect(x1, cand, y1, y2, mol, sol) > cur) { x2 = cand; continue; }\n        cand = next_val(ys, y1);\n        if (cand >= 0 && cand <= y2 && evaluateRect(x1, x2, cand, y2, mol, sol) > cur) { y1 = cand; continue; }\n        cand = prev_val(ys, y2);\n        if (cand >= 0 && cand >= y1 && evaluateRect(x1, x2, y1, cand, mol, sol) > cur) { y2 = cand; continue; }\n        break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<pii> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i)\n        cin >> mackerels[i].first >> mackerels[i].second;\n    for (int i = 0; i < N; ++i)\n        cin >> sardines[i].first >> sardines[i].second;\n\n    int bestScore = -1e9;\n    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;\n\n    // Try two tile sizes: 500 (fast) and 1000 (coarser but cheap)\n    for (int S : {500, 1000}) {\n        auto [sum, enc] = bestTileRect(mackerels, sardines, S);\n        if (sum <= 0) continue;\n        int r1 = enc.first;\n        int r2 = enc.second / 10000;\n        int c1 = (enc.second % 10000) / 100;\n        int c2 = enc.second % 100;\n        if (r1 < 0 || c1 < 0) continue;\n\n        // tile rectangle in pixel coordinates\n        int tile_x1 = c1 * S;\n        int tile_x2 = min(COORD_MAX, (c2 + 1) * S);\n        int tile_y1 = r1 * S;\n        int tile_y2 = min(COORD_MAX, (r2 + 1) * S);\n\n        int tx1, tx2, ty1, ty2;\n        tighten(mackerels, tile_x1, tile_x2, tile_y1, tile_y2,\n                tx1, tx2, ty1, ty2);\n        localSearch(mackerels, sardines, tx1, tx2, ty1, ty2);\n\n        // clamp to valid range\n        tx1 = max(0, min(tx1, COORD_MAX));\n        tx2 = max(0, min(tx2, COORD_MAX));\n        ty1 = max(0, min(ty1, COORD_MAX));\n        ty2 = max(0, min(ty2, COORD_MAX));\n        if (tx1 > tx2) swap(tx1, tx2);\n        if (ty1 > ty2) swap(ty1, ty2);\n\n        int sc = evaluateRect(tx1, tx2, ty1, ty2, mackerels, sardines);\n        if (sc > bestScore) {\n            bestScore = sc;\n            x1 = tx1; x2 = tx2; y1 = ty1; y2 = ty2;\n        }\n    }\n\n    // Also try bounding box of all mackerels (if perimeter allows)\n    {\n        int minx = COORD_MAX+1, maxx = -1, miny = COORD_MAX+1, maxy = -1;\n        for (auto [x, y] : mackerels) {\n            minx = min(minx, x); maxx = max(maxx, x);\n            miny = min(miny, y); maxy = max(maxy, y);\n        }\n        int sc = evaluateRect(minx, maxx, miny, maxy, mackerels, sardines);\n        if (sc > bestScore) {\n            bestScore = sc;\n            x1 = minx; x2 = maxx; y1 = miny; y2 = maxy;\n        }\n    }\n\n    // Fallback: smallest rectangle containing a mackerel without sardines\n    if (bestScore <= 0) {\n        for (auto [mx, my] : mackerels) {\n            int cntS = countInRect(sardines, mx, mx+1, my, my+1);\n            if (cntS == 0) {\n                x1 = mx; x2 = min(COORD_MAX, mx+1);\n                y1 = my; y2 = min(COORD_MAX, my+1);\n                bestScore = 1;\n                break;\n            }\n        }\n        if (bestScore <= 0) {\n            auto [mx, my] = mackerels[0];\n            x1 = mx; x2 = min(COORD_MAX, mx+1);\n            y1 = my; y2 = min(COORD_MAX, my+1);\n        }\n    }\n\n    // final clamp\n    x1 = max(0, min(x1, COORD_MAX));\n    x2 = max(0, min(x2, COORD_MAX));\n    y1 = max(0, min(y1, COORD_MAX));\n    y2 = max(0, min(y2, COORD_MAX));\n    if (x1 == x2) x2 = min(COORD_MAX, x2 + 1);\n    if (y1 == y2) y2 = min(COORD_MAX, y2 + 1);\n\n    // output rectangle\n    cout << 4 << '\\n';\n    cout << x1 << ' ' << y1 << '\\n';\n    cout << x2 << ' ' << y1 << '\\n';\n    cout << x2 << ' ' << y2 << '\\n';\n    cout << x1 << ' ' << y2 << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\n#include <chrono>\n#include <random>\n#include <cmath>\nusing namespace std;\nusing ll = long long;\n\nstruct Rect {\n    ll x, y, w, h;\n    int orig;\n};\n\nstruct PlacementInfo {\n    int orig, rot;\n    char dir;\n    int ref_orig;\n};\n\nstruct State {\n    vector<Rect> placed;\n    vector<PlacementInfo> ops;\n    vector<int> skipped;\n    ll W, H, skipped_sum;\n    ll score() const { return W + H + skipped_sum; }\n};\n\n// Rebuild state from ops and skipped, return false if invalid\nbool rebuild_state(const vector<PlacementInfo>& ops, const vector<int>& skipped,\n                   const vector<ll>& est_w, const vector<ll>& est_h,\n                   vector<Rect>& placed, ll& W, ll& H, ll& skipped_sum) {\n    placed.clear();\n    W = 0; H = 0; skipped_sum = 0;\n    for (auto& op : ops) {\n        int i = op.orig;\n        ll w = (op.rot == 0) ? est_w[i] : est_h[i];\n        ll h = (op.rot == 0) ? est_h[i] : est_w[i];\n        int ref_idx = -1;\n        if (op.ref_orig != -1) {\n            bool found = false;\n            for (int j = 0; j < (int)placed.size(); ++j) {\n                if (placed[j].orig == op.ref_orig) { ref_idx = j; found = true; break; }\n            }\n            if (!found) return false;\n        }\n        ll x, y;\n        if (op.dir == 'U') {\n            x = (ref_idx == -1) ? 0 : placed[ref_idx].x + placed[ref_idx].w;\n            y = 0;\n            for (auto& p : placed)\n                if (x < p.x + p.w && x + w > p.x) y = max(y, p.y + p.h);\n        } else { // 'L'\n            y = (ref_idx == -1) ? 0 : placed[ref_idx].y + placed[ref_idx].h;\n            x = 0;\n            for (auto& p : placed)\n                if (y < p.y + p.h && y + h > p.y) x = max(x, p.x + p.w);\n        }\n        placed.push_back({x, y, w, h, i});\n        W = max(W, x + w);\n        H = max(H, y + h);\n    }\n    for (int sk : skipped) skipped_sum += est_w[sk] + est_h[sk];\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T, sigma;\n    cin >> N >> T >> sigma;\n    vector<ll> w_obs(N), h_obs(N);\n    for (int i = 0; i < N; ++i) cin >> w_obs[i] >> h_obs[i];\n\n    vector<ll> sum_w(N, 0), sum_h(N, 0);\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < N; ++i) {\n        sum_w[i] = w_obs[i];\n        sum_h[i] = h_obs[i];\n        cnt[i] = 1;\n    }\n\n    auto get_est = [&](int i) -> pair<ll, ll> {\n        long double aw = (long double)sum_w[i] / cnt[i];\n        long double ah = (long double)sum_h[i] / cnt[i];\n        ll ew = (ll)llround(aw);\n        ll eh = (ll)llround(ah);\n        if (ew < 1) ew = 1;\n        if (eh < 1) eh = 1;\n        return {ew, eh};\n    };\n\n    int meas_turns = T - 1;\n    // first N measurements\n    for (int t = 0; t < min(N, meas_turns); ++t) {\n        cout << \"1\\n\" << t << \" 0 U -1\" << endl;\n        ll Wp, Hp;\n        cin >> Wp >> Hp;\n        sum_w[t] += Wp;\n        sum_h[t] += Hp;\n        cnt[t]++;\n    }\n    // remaining measurements: pick rectangle with fewest measurements\n    for (int t = N; t < meas_turns; ++t) {\n        int min_cnt = cnt[0];\n        int best_idx = 0;\n        for (int i = 1; i < N; ++i) {\n            if (cnt[i] < min_cnt) {\n                min_cnt = cnt[i];\n                best_idx = i;\n            }\n        }\n        cout << \"1\\n\" << best_idx << \" 0 U -1\" << endl;\n        ll Wp, Hp;\n        cin >> Wp >> Hp;\n        sum_w[best_idx] += Wp;\n        sum_h[best_idx] += Hp;\n        cnt[best_idx]++;\n    }\n\n    vector<ll> est_w(N), est_h(N);\n    for (int i = 0; i < N; ++i) tie(est_w[i], est_h[i]) = get_est(i);\n\n    // Beam search\n    const int BEAM_WIDTH = 250; // increased\n    vector<State> beam = {{{}, {}, {}, 0, 0, 0}};\n\n    for (int i = 0; i < N; ++i) {\n        vector<State> candidates;\n        for (const State& st : beam) {\n            // skip\n            State skip_st = st;\n            skip_st.skipped.push_back(i);\n            skip_st.skipped_sum += est_w[i] + est_h[i];\n            candidates.push_back(move(skip_st));\n\n            // place with all rot/dir and best ref\n            for (int rot = 0; rot <= 1; ++rot) {\n                ll w = (rot == 0) ? est_w[i] : est_h[i];\n                ll h = (rot == 0) ? est_h[i] : est_w[i];\n                for (int dir = 0; dir < 2; ++dir) {\n                    int best_ref = -1;\n                    ll best_score_val = LLONG_MAX;\n                    ll best_x = 0, best_y = 0, best_newW = 0, best_newH = 0;\n                    int placed_cnt = (int)st.placed.size();\n                    for (int ref_idx = -1; ref_idx < placed_cnt; ++ref_idx) {\n                        ll x, y;\n                        if (dir == 0) { // U\n                            x = (ref_idx == -1) ? 0 : st.placed[ref_idx].x + st.placed[ref_idx].w;\n                            y = 0;\n                            for (auto& p : st.placed)\n                                if (x < p.x + p.w && x + w > p.x) y = max(y, p.y + p.h);\n                        } else { // L\n                            y = (ref_idx == -1) ? 0 : st.placed[ref_idx].y + st.placed[ref_idx].h;\n                            x = 0;\n                            for (auto& p : st.placed)\n                                if (y < p.y + p.h && y + h > p.y) x = max(x, p.x + p.w);\n                        }\n                        ll newW = max(st.W, x + w);\n                        ll newH = max(st.H, y + h);\n                        ll cand_score = newW + newH + st.skipped_sum;\n                        if (cand_score < best_score_val) {\n                            best_score_val = cand_score;\n                            best_ref = ref_idx;\n                            best_x = x; best_y = y;\n                            best_newW = newW; best_newH = newH;\n                        }\n                    }\n                    State new_st = st;\n                    new_st.W = best_newW;\n                    new_st.H = best_newH;\n                    int ref_orig = (best_ref == -1) ? -1 : st.placed[best_ref].orig;\n                    new_st.ops.push_back({i, rot, (dir == 0 ? 'U' : 'L'), ref_orig});\n                    new_st.placed.push_back({best_x, best_y, w, h, i});\n                    candidates.push_back(move(new_st));\n                }\n            }\n        }\n\n        // prune\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.score() < b.score(); });\n        if (candidates.size() > BEAM_WIDTH)\n            candidates.resize(BEAM_WIDTH);\n        beam.swap(candidates);\n    }\n\n    // Take the best beam state\n    auto best_beam = *min_element(beam.begin(), beam.end(),\n        [](const State& a, const State& b) { return a.score() < b.score(); });\n\n    // Simulated annealing on multiple starting points\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    State global_best = best_beam;\n    int chains = 3;\n    int steps_per_chain = 1500;\n    double initial_temp = best_beam.score() * 0.1;\n    double cooling = 0.992;\n\n    for (int ch = 0; ch < chains; ++ch) {\n        // start from a random beam state or best\n        State current = (ch == 0) ? best_beam : beam[rng() % min((size_t)10, beam.size())];\n        double T = initial_temp;\n\n        for (int step = 0; step < steps_per_chain; ++step) {\n            if (current.ops.empty()) break;\n            uniform_int_distribution<int> idx_dist(0, (int)current.ops.size() - 1);\n            int pos = idx_dist(rng);\n            PlacementInfo old_op = current.ops[pos];\n            int new_rot = rng() % 2;\n            int new_dir = rng() % 2;\n            vector<int> valid_refs = {-1};\n            for (int j = 0; j < pos; ++j) {\n                if (current.ops[j].orig < old_op.orig)\n                    valid_refs.push_back(j);\n            }\n            uniform_int_distribution<int> ref_dist(0, (int)valid_refs.size() - 1);\n            int ref_idx = valid_refs[ref_dist(rng)];\n            int new_ref_orig = (ref_idx == -1) ? -1 : current.placed[ref_idx].orig;\n\n            vector<PlacementInfo> new_ops = current.ops;\n            new_ops[pos] = {old_op.orig, new_rot, (new_dir == 0 ? 'U' : 'L'), new_ref_orig};\n            vector<int> new_skipped = current.skipped;\n\n            vector<Rect> new_placed;\n            ll nW, nH, nSkipSum;\n            if (!rebuild_state(new_ops, new_skipped, est_w, est_h, new_placed, nW, nH, nSkipSum))\n                continue;\n            State new_state;\n            new_state.placed = new_placed;\n            new_state.ops = new_ops;\n            new_state.skipped = new_skipped;\n            new_state.W = nW; new_state.H = nH;\n            new_state.skipped_sum = nSkipSum;\n\n            ll delta = new_state.score() - current.score();\n            if (delta < 0 || prob(rng) < exp(-delta / max(T, 1e-9))) {\n                current = new_state;\n                if (current.score() < global_best.score()) {\n                    global_best = current;\n                }\n            }\n            T *= cooling;\n        }\n    }\n\n    // Output final packing\n    int placed_cnt = (int)global_best.ops.size();\n    cout << placed_cnt << \"\\n\";\n    for (auto& op : global_best.ops) {\n        cout << op.orig << \" \" << op.rot << \" \" << op.dir << \" \" << op.ref_orig << \"\\n\";\n    }\n    cout.flush();\n\n    // final measurement (ignored)\n    ll dummyW, dummyH;\n    cin >> dummyW >> dummyH;\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\n#include <chrono>\nusing namespace std;\nusing namespace std::chrono;\nusing ll = long long;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<vector<int>> graph(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        graph[u].push_back(v);\n        graph[v].push_back(u);\n    }\n    // read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // ---------- 1. All-pairs shortest distances ----------\n    const int INF = 1e9;\n    vector<vector<int>> dist(N, vector<int>(N, INF));\n    for (int s = 0; s < N; ++s) {\n        queue<int> q;\n        dist[s][s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int u : graph[v]) if (dist[s][u] == INF) {\n                dist[s][u] = dist[s][v] + 1;\n                q.push(u);\n            }\n        }\n    }\n\n    // ---------- 2. For each vertex, list of all vertices sorted by distance ----------\n    vector<vector<int>> order(N, vector<int>(N));\n    vector<vector<int>> pos(N, vector<int>(N)); // pos[v][u] = index in order[v]\n    for (int v = 0; v < N; ++v) {\n        iota(order[v].begin(), order[v].end(), 0);\n        sort(order[v].begin(), order[v].end(), [&](int a, int b) {\n            return dist[v][a] < dist[v][b];\n        });\n        for (int i = 0; i < N; ++i) pos[v][order[v][i]] = i;\n    }\n\n    // ---------- 3. Greedy removal of roots ----------\n    vector<bool> active(N, true);\n    vector<int> best_root(N), best_dist(N), best_idx(N);\n    vector<vector<int>> children(N);\n    for (int v = 0; v < N; ++v) {\n        best_root[v] = v;\n        best_dist[v] = 0;\n        best_idx[v] = 0;\n        children[v].push_back(v);\n    }\n\n    while (true) {\n        // compute gain and feasibility for each root\n        vector<ll> gain(N, 0);\n        vector<bool> feasible(N, true);\n        for (int r = 0; r < N; ++r) if (active[r]) {\n            for (int v : children[r]) {\n                int idx = best_idx[v] + 1;\n                while (idx < N && !active[order[v][idx]]) ++idx;\n                if (idx == N || dist[v][order[v][idx]] > H) {\n                    feasible[r] = false;\n                    break;\n                }\n                int new_root = order[v][idx];\n                int new_dist = dist[v][new_root];\n                gain[r] += (ll)(new_dist - best_dist[v]) * A[v];\n            }\n        }\n\n        // choose root with maximum gain (prefer positive, accept zero)\n        int best = -1;\n        ll best_gain = -1;\n        for (int r = 0; r < N; ++r) if (active[r] && feasible[r] && gain[r] >= 0) {\n            if (gain[r] > best_gain) {\n                best_gain = gain[r];\n                best = r;\n            }\n        }\n        if (best == -1) break; // no improvement\n\n        // remove root best\n        active[best] = false;\n        for (int v : children[best]) {\n            int idx = best_idx[v] + 1;\n            while (!active[order[v][idx]]) ++idx;\n            int new_root = order[v][idx];\n            int new_dist = dist[v][new_root];\n            best_idx[v] = idx;\n            best_dist[v] = new_dist;\n            best_root[v] = new_root;\n            children[new_root].push_back(v);\n        }\n        children[best].clear();\n    }\n\n    // ---------- 4. Build BFS forest from final roots ----------\n    vector<int> parent(N, -1), depth(N, -1);\n    queue<int> q;\n    for (int r = 0; r < N; ++r) if (active[r]) {\n        depth[r] = 0;\n        q.push(r);\n    }\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        for (int u : graph[v]) if (depth[u] == -1) {\n            depth[u] = depth[v] + 1;\n            parent[u] = v;\n            q.push(u);\n        }\n    }\n\n    // ---------- 5. Post-processing: increase depth of leaves ----------\n    // compute child counts\n    vector<int> child_cnt(N, 0);\n    for (int v = 0; v < N; ++v) if (parent[v] != -1) child_cnt[parent[v]]++;\n\n    // sort vertices by beauty descending\n    vector<int> vorder(N);\n    iota(vorder.begin(), vorder.end(), 0);\n    sort(vorder.begin(), vorder.end(), [&](int i, int j) { return A[i] > A[j]; });\n\n    // repeat several passes\n    for (int pass = 0; pass < 20; ++pass) {\n        bool changed = false;\n        for (int v : vorder) {\n            if (depth[v] == H || child_cnt[v] > 0) continue; // only leaves with depth < H\n            int best_u = -1, best_d = depth[v];\n            for (int u : graph[v]) {\n                if (depth[u] >= depth[v] && depth[u] < H && depth[u] + 1 > best_d) {\n                    best_u = u;\n                    best_d = depth[u] + 1;\n                }\n            }\n            if (best_u != -1) {\n                // update parent and depth\n                if (parent[v] != -1) child_cnt[parent[v]]--;\n                parent[v] = best_u;\n                child_cnt[best_u]++;\n                depth[v] = best_d;\n                changed = true;\n            }\n        }\n        if (!changed) break;\n    }\n\n    // ---------- 6. Output ----------\n    for (int i = 0; i < N; ++i) {\n        cout << parent[i] << (i+1 == N ? \"\\n\" : \" \");\n    }\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <climits>\n#include <chrono>\n#include <cstdlib>\n\nusing namespace std;\n\nint N;\nvector<string> grid;\nvector<pair<char, int>> ops;\n\n// ---------- move helpers (on real grid) ----------\nvoid shift_left(int r) {\n    for (int j = 0; j < N - 1; ++j) grid[r][j] = grid[r][j + 1];\n    grid[r][N - 1] = '.';\n    ops.emplace_back('L', r);\n}\nvoid shift_right(int r) {\n    for (int j = N - 1; j > 0; --j) grid[r][j] = grid[r][j - 1];\n    grid[r][0] = '.';\n    ops.emplace_back('R', r);\n}\nvoid shift_up(int c) {\n    for (int i = 0; i < N - 1; ++i) grid[i][c] = grid[i + 1][c];\n    grid[N - 1][c] = '.';\n    ops.emplace_back('U', c);\n}\nvoid shift_down(int c) {\n    for (int i = N - 1; i > 0; --i) grid[i][c] = grid[i - 1][c];\n    grid[0][c] = '.';\n    ops.emplace_back('D', c);\n}\n\n// ---------- simulation on a copy ----------\nvector<string> apply_batch(const vector<string>& g, char dir, int idx, int shifts) {\n    vector<string> h = g;\n    for (int k = 0; k < shifts; ++k) {\n        if (dir == 'L') {\n            for (int j = 0; j < N - 1; ++j) h[idx][j] = h[idx][j + 1];\n            h[idx][N - 1] = '.';\n        } else if (dir == 'R') {\n            for (int j = N - 1; j > 0; --j) h[idx][j] = h[idx][j - 1];\n            h[idx][0] = '.';\n        } else if (dir == 'U') {\n            for (int i = 0; i < N - 1; ++i) h[i][idx] = h[i + 1][idx];\n            h[N - 1][idx] = '.';\n        } else {\n            for (int i = N - 1; i > 0; --i) h[i][idx] = h[i - 1][idx];\n            h[0][idx] = '.';\n        }\n    }\n    return h;\n}\n\n// ---------- utilities ----------\nint count_oni(const vector<string>& g) {\n    int cnt = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (g[i][j] == 'x') ++cnt;\n    return cnt;\n}\n\nbool all_oni_safe(const vector<string>& g) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (g[i][j] != 'x') continue;\n            bool ok = false;\n            // up\n            bool safe = true;\n            for (int r = i - 1; r >= 0; --r)\n                if (g[r][j] == 'o') { safe = false; break; }\n            if (safe) ok = true;\n            // down\n            if (!ok) {\n                safe = true;\n                for (int r = i + 1; r < N; ++r)\n                    if (g[r][j] == 'o') { safe = false; break; }\n                if (safe) ok = true;\n            }\n            // left\n            if (!ok) {\n                safe = true;\n                for (int c = j - 1; c >= 0; --c)\n                    if (g[i][c] == 'o') { safe = false; break; }\n                if (safe) ok = true;\n            }\n            // right\n            if (!ok) {\n                safe = true;\n                for (int c = j + 1; c < N; ++c)\n                    if (g[i][c] == 'o') { safe = false; break; }\n                if (safe) ok = true;\n            }\n            if (!ok) return false;\n        }\n    }\n    return true;\n}\n\n// lower bound for remaining cost (sum of 2*min_safe_distance for each oni)\nint heuristic_lower_bnd(const vector<string>& g) {\n    int total = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (g[i][j] != 'x') continue;\n            int best = N + 1;\n            // up\n            bool safe = true;\n            for (int r = i - 1; r >= 0; --r)\n                if (g[r][j] == 'o') { safe = false; break; }\n            if (safe) best = min(best, i + 1);\n            // down\n            safe = true;\n            for (int r = i + 1; r < N; ++r)\n                if (g[r][j] == 'o') { safe = false; break; }\n            if (safe) best = min(best, N - i);\n            // left\n            safe = true;\n            for (int c = j - 1; c >= 0; --c)\n                if (g[i][c] == 'o') { safe = false; break; }\n            if (safe) best = min(best, j + 1);\n            // right\n            safe = true;\n            for (int c = j + 1; c < N; ++c)\n                if (g[i][c] == 'o') { safe = false; break; }\n            if (safe) best = min(best, N - j);\n            total += 2 * best;\n        }\n    }\n    return total;\n}\n\nstruct Candidate {\n    int removals;\n    int shifts;\n    char dir;\n    int idx;\n};\n\nvector<Candidate> get_candidates(const vector<string>& g) {\n    vector<Candidate> cands;\n    // rows\n    for (int i = 0; i < N; ++i) {\n        int left_god = N, right_god = -1;\n        for (int j = 0; j < N; ++j)\n            if (g[i][j] == 'o') {\n                left_god = min(left_god, j);\n                right_god = max(right_god, j);\n            }\n        if (left_god == N) continue;\n        if (left_god > 0) {\n            int cnt = 0;\n            for (int j = 0; j < left_god; ++j)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, left_god, 'L', i});\n        }\n        if (right_god < N - 1) {\n            int cnt = 0;\n            for (int j = right_god + 1; j < N; ++j)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, N - 1 - right_god, 'R', i});\n        }\n    }\n    // columns\n    for (int j = 0; j < N; ++j) {\n        int top_god = N, bottom_god = -1;\n        for (int i = 0; i < N; ++i)\n            if (g[i][j] == 'o') {\n                top_god = min(top_god, i);\n                bottom_god = max(bottom_god, i);\n            }\n        if (top_god == N) continue;\n        if (top_god > 0) {\n            int cnt = 0;\n            for (int i = 0; i < top_god; ++i)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, top_god, 'U', j});\n        }\n        if (bottom_god < N - 1) {\n            int cnt = 0;\n            for (int i = bottom_god + 1; i < N; ++i)\n                if (g[i][j] == 'x') ++cnt;\n            if (cnt > 0) cands.push_back({cnt, N - 1 - bottom_god, 'D', j});\n        }\n    }\n    return cands;\n}\n\n// ---------- improved rollout using one-step lookahead ----------\nint rollout_cost(vector<string> g) {\n    int total = 0;\n    const int MAX_STEPS = 150; // reduced to avoid timeouts\n    for (int step = 0; step < MAX_STEPS; ++step) {\n        // clear godless rows/cols repeatedly\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            // rows\n            for (int i = 0; i < N; ++i) {\n                bool has_god = false;\n                for (int j = 0; j < N; ++j)\n                    if (g[i][j] == 'o') { has_god = true; break; }\n                if (has_god) continue;\n                int leftmost = N, rightmost = -1;\n                for (int j = 0; j < N; ++j)\n                    if (g[i][j] == 'x') {\n                        leftmost = min(leftmost, j);\n                        rightmost = max(rightmost, j);\n                    }\n                if (rightmost == -1) continue;\n                changed = true;\n                int left_cost = rightmost + 1;\n                int right_cost = N - leftmost;\n                if (left_cost <= right_cost) {\n                    total += left_cost;\n                    g = apply_batch(g, 'L', i, left_cost);\n                } else {\n                    total += right_cost;\n                    g = apply_batch(g, 'R', i, right_cost);\n                }\n            }\n            // columns\n            for (int j = 0; j < N; ++j) {\n                bool has_god = false;\n                for (int i = 0; i < N; ++i)\n                    if (g[i][j] == 'o') { has_god = true; break; }\n                if (has_god) continue;\n                int topmost = N, bottommost = -1;\n                for (int i = 0; i < N; ++i)\n                    if (g[i][j] == 'x') {\n                        topmost = min(topmost, i);\n                        bottommost = max(bottommost, i);\n                    }\n                if (bottommost == -1) continue;\n                changed = true;\n                int up_cost = bottommost + 1;\n                int down_cost = N - topmost;\n                if (up_cost <= down_cost) {\n                    total += up_cost;\n                    g = apply_batch(g, 'U', j, up_cost);\n                } else {\n                    total += down_cost;\n                    g = apply_batch(g, 'D', j, down_cost);\n                }\n            }\n        }\n        if (count_oni(g) == 0) break;\n\n        // generate candidates\n        vector<Candidate> cands = get_candidates(g);\n        if (cands.empty()) {\n            total += heuristic_lower_bnd(g);\n            break;\n        }\n\n        // choose best candidate using one-step lookahead with heuristic lower bound\n        int best_total = INT_MAX;\n        int best_idx = 0;\n        for (size_t i = 0; i < cands.size(); ++i) {\n            const auto& cand = cands[i];\n            vector<string> g2 = apply_batch(g, cand.dir, cand.idx, cand.shifts);\n            if (!all_oni_safe(g2)) continue;\n            int future = heuristic_lower_bnd(g2);\n            int cur = cand.shifts + future;\n            if (cur < best_total) {\n                best_total = cur;\n                best_idx = i;\n            }\n        }\n        if (best_total == INT_MAX) {\n            // fallback: just use heuristic lower bound\n            total += heuristic_lower_bnd(g);\n            break;\n        }\n\n        // apply best candidate\n        const auto& best = cands[best_idx];\n        g = apply_batch(g, best.dir, best.idx, best.shifts);\n        total += best.shifts;\n    }\n    return total;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    grid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    // main loop (real moves)\n    while (true) {\n        int total_oni = count_oni(grid);\n        if (total_oni == 0) break;\n\n        // clear godless rows/cols on real board\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = 0; i < N; ++i) {\n                bool has_god = false;\n                for (int j = 0; j < N; ++j)\n                    if (grid[i][j] == 'o') { has_god = true; break; }\n                if (has_god) continue;\n                int leftmost = N, rightmost = -1;\n                for (int j = 0; j < N; ++j)\n                    if (grid[i][j] == 'x') {\n                        leftmost = min(leftmost, j);\n                        rightmost = max(rightmost, j);\n                    }\n                if (rightmost == -1) continue;\n                changed = true;\n                int left_cost = rightmost + 1;\n                int right_cost = N - leftmost;\n                if (left_cost <= right_cost) {\n                    for (int k = 0; k < left_cost; ++k) shift_left(i);\n                } else {\n                    for (int k = 0; k < right_cost; ++k) shift_right(i);\n                }\n            }\n            for (int j = 0; j < N; ++j) {\n                bool has_god = false;\n                for (int i = 0; i < N; ++i)\n                    if (grid[i][j] == 'o') { has_god = true; break; }\n                if (has_god) continue;\n                int topmost = N, bottommost = -1;\n                for (int i = 0; i < N; ++i)\n                    if (grid[i][j] == 'x') {\n                        topmost = min(topmost, i);\n                        bottommost = max(bottommost, i);\n                    }\n                if (bottommost == -1) continue;\n                changed = true;\n                int up_cost = bottommost + 1;\n                int down_cost = N - topmost;\n                if (up_cost <= down_cost) {\n                    for (int k = 0; k < up_cost; ++k) shift_up(j);\n                } else {\n                    for (int k = 0; k < down_cost; ++k) shift_down(j);\n                }\n            }\n        }\n\n        if (count_oni(grid) == 0) break;\n\n        // batch candidates\n        vector<Candidate> cands = get_candidates(grid);\n        if (cands.empty()) {\n            // individual round-trip\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (grid[i][j] != 'x') continue;\n                    int best_dir = -1, best_dist = N + 1;\n                    // up\n                    bool safe = true;\n                    for (int r = i - 1; r >= 0; --r)\n                        if (grid[r][j] == 'o') { safe = false; break; }\n                    if (safe && i + 1 < best_dist) { best_dir = 0; best_dist = i + 1; }\n                    // down\n                    safe = true;\n                    for (int r = i + 1; r < N; ++r)\n                        if (grid[r][j] == 'o') { safe = false; break; }\n                    if (safe && N - i < best_dist) { best_dir = 1; best_dist = N - i; }\n                    // left\n                    safe = true;\n                    for (int c = j - 1; c >= 0; --c)\n                        if (grid[i][c] == 'o') { safe = false; break; }\n                    if (safe && j + 1 < best_dist) { best_dir = 2; best_dist = j + 1; }\n                    // right\n                    safe = true;\n                    for (int c = j + 1; c < N; ++c)\n                        if (grid[i][c] == 'o') { safe = false; break; }\n                    if (safe && N - j < best_dist) { best_dir = 3; best_dist = N - j; }\n\n                    if (best_dir == -1) continue; // should not happen\n\n                    if (best_dir == 0) {\n                        for (int k = 0; k < best_dist; ++k) shift_up(j);\n                        for (int k = 0; k < best_dist; ++k) shift_down(j);\n                    } else if (best_dir == 1) {\n                        for (int k = 0; k < best_dist; ++k) shift_down(j);\n                        for (int k = 0; k < best_dist; ++k) shift_up(j);\n                    } else if (best_dir == 2) {\n                        for (int k = 0; k < best_dist; ++k) shift_left(i);\n                        for (int k = 0; k < best_dist; ++k) shift_right(i);\n                    } else {\n                        for (int k = 0; k < best_dist; ++k) shift_right(i);\n                        for (int k = 0; k < best_dist; ++k) shift_left(i);\n                    }\n                }\n            }\n            continue;\n        }\n\n        // Evaluate each candidate using improved rollout\n        int best_total = INT_MAX;\n        Candidate* best_cand = nullptr;\n\n        for (auto& cand : cands) {\n            vector<string> g1 = apply_batch(grid, cand.dir, cand.idx, cand.shifts);\n            if (!all_oni_safe(g1)) continue;\n            int future = rollout_cost(g1);\n            int total = cand.shifts + future;\n            if (total < best_total) {\n                best_total = total;\n                best_cand = &cand;\n            }\n        }\n\n        // fallback if no safe candidate (should be rare)\n        if (best_cand == nullptr) {\n            for (auto& cand : cands) {\n                vector<string> g1 = apply_batch(grid, cand.dir, cand.idx, cand.shifts);\n                if (all_oni_safe(g1)) {\n                    best_cand = &cand;\n                    break;\n                }\n            }\n            if (best_cand == nullptr) break;\n        }\n\n        // apply chosen candidate to real grid\n        for (int k = 0; k < best_cand->shifts; ++k) {\n            if (best_cand->dir == 'L') shift_left(best_cand->idx);\n            else if (best_cand->dir == 'R') shift_right(best_cand->idx);\n            else if (best_cand->dir == 'U') shift_up(best_cand->idx);\n            else shift_down(best_cand->idx);\n        }\n    }\n\n    // output\n    for (const auto& op : ops)\n        cout << op.first << ' ' << op.second << '\\n';\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\n#include <chrono>\n#include <cmath>\nusing namespace std;\n\nconst int N = 100;\nconst int L = 500000;\n\nint target[N];\ndouble pi_target[N];\n\nstruct Solution {\n    int a[N], b[N];\n};\n\n// Xorshift\nstatic uint32_t x = 123456789, y = 362436069, z = 521288629, w = 88675123;\ninline uint32_t xorshift() {\n    uint32_t t = x ^ (x << 11);\n    x = y; y = z; z = w;\n    w = w ^ (w >> 19) ^ (t ^ (t >> 8));\n    return w;\n}\ninline int rand_int(int mod) {\n    return xorshift() % mod;\n}\ninline double rand_double() {\n    return (double)xorshift() / 4294967296.0;\n}\n\n// Solve linear system for stationary distribution of the random walk\ndouble exact_stationary_error(const Solution &sol, double pi_out[]) {\n    // Build transition matrix P (row-stochastic)\n    double P[N][N] = {0.0};\n    for (int i = 0; i < N; ++i) {\n        P[i][sol.a[i]] += 0.5;\n        P[i][sol.b[i]] += 0.5;\n    }\n\n    // Set up linear system (I - P^T) pi = 0, with sum pi = 1\n    double A[N][N];\n    double b[N];\n    for (int i = 0; i < N-1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            A[i][j] = (i == j ? 1.0 : 0.0) - P[j][i]; // column j, row i\n        }\n        b[i] = 0.0;\n    }\n    // Last equation: sum pi = 1\n    for (int j = 0; j < N; ++j) {\n        A[N-1][j] = 1.0;\n    }\n    b[N-1] = 1.0;\n\n    // Gaussian elimination with partial pivoting\n    for (int col = 0; col < N; ++col) {\n        // Find pivot\n        int pivot = col;\n        double max_val = fabs(A[col][col]);\n        for (int row = col+1; row < N; ++row) {\n            if (fabs(A[row][col]) > max_val) {\n                max_val = fabs(A[row][col]);\n                pivot = row;\n            }\n        }\n        // Swap rows\n        if (pivot != col) {\n            for (int j = col; j < N; ++j) swap(A[col][j], A[pivot][j]);\n            swap(b[col], b[pivot]);\n        }\n        // Eliminate\n        double piv = A[col][col];\n        if (fabs(piv) < 1e-15) continue; // singular, but unlikely\n        for (int row = col+1; row < N; ++row) {\n            double factor = A[row][col] / piv;\n            if (fabs(factor) < 1e-15) continue;\n            for (int j = col; j < N; ++j) {\n                A[row][j] -= factor * A[col][j];\n            }\n            b[row] -= factor * b[col];\n        }\n    }\n\n    // Back substitution\n    for (int row = N-1; row >= 0; --row) {\n        double sum = b[row];\n        for (int j = row+1; j < N; ++j) {\n            sum -= A[row][j] * pi_out[j];\n        }\n        if (fabs(A[row][row]) > 1e-15)\n            pi_out[row] = sum / A[row][row];\n        else\n            pi_out[row] = 0.0;\n    }\n\n    // Normalize due to numerical errors\n    double sum_pi = 0.0;\n    for (int i = 0; i < N; ++i) sum_pi += pi_out[i];\n    for (int i = 0; i < N; ++i) pi_out[i] /= sum_pi;\n\n    // Compute L1 error\n    double err = 0.0;\n    for (int i = 0; i < N; ++i) err += fabs(pi_out[i] - pi_target[i]);\n    return err;\n}\n\n// Full simulation (expensive)\nint simulate(const Solution &sol, int cnt[]) {\n    const int *a = sol.a;\n    const int *b = sol.b;\n    fill(cnt, cnt + N, 0);\n    int cur = 0;\n    cnt[0] = 1;\n    for (int w = 2; w <= L; ++w) {\n        int t = cnt[cur];\n        int nxt = (t & 1) ? a[cur] : b[cur];\n        ++cnt[nxt];\n        cur = nxt;\n    }\n    int err = 0;\n    for (int i = 0; i < N; ++i) err += abs(cnt[i] - target[i]);\n    return err;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) {\n        cin >> target[i];\n        pi_target[i] = (double)target[i] / L;\n    }\n\n    // Initial solution: each node points to the two most frequent employees\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [](int i, int j) {\n        return pi_target[i] > pi_target[j];\n    });\n    int top1 = order[0];\n    int top2 = order[1];\n    Solution best_sol;\n    for (int i = 0; i < N; ++i) {\n        best_sol.a[i] = top1;\n        best_sol.b[i] = top2;\n    }\n\n    int cnt[N];\n    int best_err = simulate(best_sol, cnt);\n    double best_stat_err = 0.0;\n    double pi_best[N];\n    best_stat_err = exact_stationary_error(best_sol, pi_best);\n\n    Solution cur_sol = best_sol;\n    double cur_stat_err = best_stat_err;\n    double pi_cur[N];\n    for (int i = 0; i < N; ++i) pi_cur[i] = pi_best[i];\n\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.95;\n\n    // Phase 1: Simulated annealing on stationary error (many iterations)\n    const int STAT_ITERS = 30000;\n    const double init_temp_stat = 0.1;\n    const double final_temp_stat = 1e-6;\n    const double cooling_stat = pow(final_temp_stat / init_temp_stat, 1.0 / STAT_ITERS);\n    double temperature = init_temp_stat;\n\n    for (int iter = 0; iter < STAT_ITERS; ++iter) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit * 0.7) break; // reserve time for actual simulation\n\n        Solution new_sol = cur_sol;\n        int i = rand_int(N);\n        if (rand_int(2) == 0)\n            new_sol.a[i] = rand_int(N);\n        else\n            new_sol.b[i] = rand_int(N);\n\n        double pi_new[N];\n        double new_stat_err = exact_stationary_error(new_sol, pi_new);\n        double delta = new_stat_err - cur_stat_err;\n\n        if (delta < 0) {\n            cur_sol = new_sol;\n            cur_stat_err = new_stat_err;\n            for (int j = 0; j < N; ++j) pi_cur[j] = pi_new[j];\n            if (new_stat_err < best_stat_err) {\n                best_stat_err = new_stat_err;\n                best_sol = new_sol;\n                for (int j = 0; j < N; ++j) pi_best[j] = pi_new[j];\n            }\n        } else {\n            double prob = exp(-delta / temperature);\n            if (rand_double() < prob) {\n                cur_sol = new_sol;\n                cur_stat_err = new_stat_err;\n                for (int j = 0; j < N; ++j) pi_cur[j] = pi_new[j];\n            }\n        }\n\n        temperature *= cooling_stat;\n    }\n\n    // Evaluate actual error of best from stationary phase\n    best_err = simulate(best_sol, cnt);\n\n    // Phase 2: Greedy hill-climbing on actual error (limited attempts)\n    cur_sol = best_sol;\n    int cur_err = best_err;\n    const int GREEDY_ATTEMPTS = 1000;\n    for (int attempt = 0; attempt < GREEDY_ATTEMPTS; ++attempt) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        if (elapsed > time_limit) break;\n\n        Solution new_sol = cur_sol;\n        int i = rand_int(N);\n        int r = rand_int(2);\n        if (r == 0)\n            new_sol.a[i] = rand_int(N);\n        else\n            new_sol.b[i] = rand_int(N);\n\n        int new_err = simulate(new_sol, cnt);\n        if (new_err < cur_err) {\n            cur_sol = new_sol;\n            cur_err = new_err;\n            if (new_err < best_err) {\n                best_err = new_err;\n                best_sol = new_sol;\n            }\n        }\n    }\n\n    // Output best solution\n    for (int i = 0; i < N; ++i)\n        cout << best_sol.a[i] << \" \" << best_sol.b[i] << \"\\n\";\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\n// ---------- DSU ----------\nstruct DSU {\n    vector<int> parent, rank_;\n    DSU(int n) : parent(n), rank_(n, 0) { iota(parent.begin(), parent.end(), 0); }\n    int find(int x) {\n        while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rank_[a] < rank_[b]) swap(a, b);\n        parent[b] = a;\n        if (rank_[a] == rank_[b]) rank_[a]++;\n        return true;\n    }\n};\n\n// ---------- query helper ----------\nvector<pair<int,int>> do_query(const vector<int>& subset) {\n    int l = subset.size();\n    cout << \"? \" << l;\n    for (int v : subset) cout << ' ' << v;\n    cout << endl;\n    vector<pair<int,int>> res;\n    for (int i = 0; i < l-1; ++i) {\n        int a, b; cin >> a >> b;\n        if (a > b) swap(a, b);\n        res.emplace_back(a, b);\n    }\n    return res;\n}\n\n// ---------- Hilbert index (14 bits) ----------\nuint64_t hilbertIndex(uint32_t x, uint32_t y, int bits = 14) {\n    uint32_t n = 1u << bits;\n    uint64_t d = 0;\n    uint32_t s, rx, ry;\n    for (s = n >> 1; s; s >>= 1) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d = (d << 2) | ((rx * 3) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = (n - 1) - x;\n                y = (n - 1) - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n\n    vector<ll> lx(N), rx(N), ly(N), ry(N);\n    vector<ll> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // ---- order cities by Hilbert index (using center) ----\n    auto scale = [](ll v) -> uint32_t { return (uint32_t)clamp(v, 0LL, 16383LL); };\n    vector<uint64_t> hi(N);\n    for (int i = 0; i < N; ++i) hi[i] = hilbertIndex(scale(cx[i]), scale(cy[i]));\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) { return hi[a] < hi[b]; });\n\n    // ---- assign groups by consecutive blocks ----\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int k = 0; k < M; ++k) {\n        groups[k].reserve(G[k]);\n        for (int j = 0; j < G[k]; ++j) groups[k].push_back(order[idx++]);\n    }\n\n    // ---- plan queries: small groups first, then proportional for large ----\n    vector<int> q_per_group(M, 0);\n    int used_q = 0;\n\n    // small groups (size <= L)\n    for (int k = 0; k < M; ++k) {\n        int sz = groups[k].size();\n        if (sz <= L && used_q < Q) {\n            q_per_group[k] = 1;\n            ++used_q;\n        }\n    }\n\n    // large groups \u2013 allocate remaining queries proportionally to (sz - L + 1)\n    int remaining = Q - used_q;\n    if (remaining > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) {\n            if (groups[k].size() > L) large.push_back(k);\n        }\n        ll total_needed = 0;\n        for (int k : large) total_needed += max(1, (int)groups[k].size() - L + 1);\n        for (int k : large) {\n            int need = max(1, (int)groups[k].size() - L + 1);\n            int alloc = (int)((ll)remaining * need / total_needed);\n            if (alloc == 0) alloc = 1;\n            q_per_group[k] = alloc;\n        }\n        // adjust to not exceed remaining\n        int sum = 0;\n        for (int k : large) sum += q_per_group[k];\n        while (sum > remaining) {\n            for (int k : large) {\n                if (sum <= remaining) break;\n                if (q_per_group[k] > 1) {\n                    --q_per_group[k];\n                    --sum;\n                }\n            }\n        }\n    }\n\n    // ---- execute queries and build MST per group ----\n    vector<vector<pair<int,int>>> answer_edges(M);\n    for (int k = 0; k < M; ++k) {\n        const auto& cities = groups[k];\n        int sz = cities.size();\n        if (sz <= 1) continue;\n\n        // collect query edges\n        vector<pair<int,int>> query_edges;\n        int nq = q_per_group[k];\n        if (nq > 0) {\n            if (sz <= L) {\n                // whole group query\n                auto edges = do_query(cities);\n                for (auto e : edges) query_edges.push_back(e);\n            } else {\n                // sliding windows with step to achieve nq queries\n                int step = max(1, (sz - L + 1 + nq - 1) / nq);\n                for (int start = 0; start + L <= sz && nq > 0; start += step, --nq) {\n                    vector<int> subset(cities.begin() + start, cities.begin() + start + L);\n                    auto edges = do_query(subset);\n                    for (auto e : edges) query_edges.push_back(e);\n                }\n            }\n        }\n\n        // ---- build MST ----\n        // use query edges first, then complete graph for missing connections\n        struct Edge { int u, v; ll w; };\n        auto estimated_weight = [&](int a, int b) -> ll {\n            ll dx = cx[a] - cx[b];\n            ll dy = cy[a] - cy[b];\n            return (ll)sqrt(dx*dx + dy*dy);\n        };\n\n        DSU dsu(N);\n        vector<pair<int,int>> mst;\n\n        // 1) process query edges (sorted by estimated weight)\n        vector<Edge> cand;\n        for (auto& p : query_edges) {\n            ll w = estimated_weight(p.first, p.second);\n            cand.push_back({p.first, p.second, w});\n        }\n        sort(cand.begin(), cand.end(), [](const Edge& a, const Edge& b) { return a.w < b.w; });\n        for (auto& e : cand) {\n            if (dsu.unite(e.u, e.v)) mst.emplace_back(e.u, e.v);\n            if ((int)mst.size() == sz - 1) break;\n        }\n\n        // 2) if still not connected, add edges from complete graph (estimated)\n        if ((int)mst.size() < sz - 1) {\n            cand.clear();\n            for (int i = 0; i < sz; ++i) {\n                for (int j = i+1; j < sz; ++j) {\n                    int u = cities[i], v = cities[j];\n                    if (dsu.find(u) == dsu.find(v)) continue;\n                    ll w = estimated_weight(u, v);\n                    cand.push_back({u, v, w});\n                }\n            }\n            sort(cand.begin(), cand.end(), [](const Edge& a, const Edge& b) { return a.w < b.w; });\n            for (auto& e : cand) {\n                if (dsu.unite(e.u, e.v)) mst.emplace_back(e.u, e.v);\n                if ((int)mst.size() == sz - 1) break;\n            }\n        }\n\n        for (auto& e : mst) answer_edges[k].push_back(e);\n    }\n\n    // ---- output answer ----\n    cout << \"!\" << endl;\n    for (int k = 0; k < M; ++k) {\n        for (int v : groups[k]) cout << v << ' ';\n        cout << endl;\n        for (auto& e : answer_edges[k]) cout << e.first << ' ' << e.second << endl;\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nconst int dy[4] = {-1, 1, 0, 0}; // U, D, L, R\nconst int dx[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\n// BFS to find shortest path from (si,sj) to (ti,tj) using only Move and Slide.\n// Returns vector of (action, direction) pairs.\nvector<pair<char, char>> get_path(int si, int sj, int ti, int tj) {\n    int start = si * N + sj, goal = ti * N + tj;\n    vector<int> dist(N * N, -1), prev(N * N, -1), act(N * N, -1), dir(N * N, -1);\n    queue<int> q;\n    dist[start] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        if (u == goal) break;\n        int i = u / N, j = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move one step\n            int ni = i + dy[d], nj = j + dx[d];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int v = ni * N + nj;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 0; // Move\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n\n            // Slide to the edge in direction d\n            // Only valid if the first square in that direction is inside (otherwise slide does nothing)\n            if (d == 0 && i > 0) { // up\n                int v = 0 * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1; // Slide\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 1 && i < N - 1) { // down\n                int v = (N - 1) * N + j;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 2 && j > 0) { // left\n                int v = i * N + 0;\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            } else if (d == 3 && j < N - 1) { // right\n                int v = i * N + (N - 1);\n                if (dist[v] == -1) {\n                    dist[v] = dist[u] + 1;\n                    prev[v] = u;\n                    act[v] = 1;\n                    dir[v] = d;\n                    q.push(v);\n                }\n            }\n        }\n    }\n\n    // Reconstruct path from goal to start\n    vector<pair<char, char>> rev;\n    int cur = goal;\n    while (cur != start) {\n        int a = act[cur];\n        int d = dir[cur];\n        rev.push_back({(a == 0 ? 'M' : 'S'), dir_char[d]});\n        cur = prev[cur];\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int, int>> points(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> points[i].first >> points[i].second;\n    }\n\n    int cur_i = points[0].first, cur_j = points[0].second;\n\n    for (int t = 1; t < M; ++t) {\n        int ti = points[t].first, tj = points[t].second;\n        auto path = get_path(cur_i, cur_j, ti, tj);\n        for (auto [act, dir] : path) {\n            cout << act << \" \" << dir << \"\\n\";\n        }\n        cur_i = ti;\n        cur_j = tj;\n    }\n\n    return 0;\n}"}}}