{"model_name":"deepseek-v4-pro-no-thinking","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y, r, id;\n};\n\nint n;\nvector<Point> pts;\nvector<Rect> ans;\n\n// Recursively assign rectangles\nvoid solve(int x1, int y1, int x2, int y2, vector<int> idxs) {\n    if (idxs.empty()) return;\n    if (idxs.size() == 1) {\n        int i = idxs[0];\n        // ensure point is inside\n        // make rectangle as given\n        ans[i] = {x1, y1, x2, y2};\n        // adjust if point not inside? but point is inside by construction.\n        return;\n    }\n    // total area of this box\n    long long totalArea = 1LL * (x2 - x1) * (y2 - y1);\n    long long sumR = 0;\n    for (int i : idxs) sumR += pts[i].r;\n\n    // try split by x\n    sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n    int bestSplit = -1;\n    double bestScore = -1e100;\n    // We'll decide to split between idxs[k] and idxs[k+1] at some x coordinate\n    for (int k = 0; k < (int)idxs.size() - 1; k++) {\n        int leftX = pts[idxs[k]].x; // max x of left\n        int rightX = pts[idxs[k+1]].x; // min x of right\n        // we can split anywhere between leftX+1 and rightX\n        // we choose split line = rightX (so left gets up to rightX)\n        int splitX = rightX;\n        if (splitX <= x1 || splitX >= x2) continue;\n        long long leftArea = 1LL * (splitX - x1) * (y2 - y1);\n        long long leftR = 0;\n        for (int i = 0; i <= k; i++) leftR += pts[idxs[i]].r;\n        double leftRatio = (double)leftArea / totalArea;\n        double rightRatio = 1.0 - leftRatio;\n        double targetRatio = (double)leftR / sumR;\n        double score = -fabs(leftRatio - targetRatio);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSplit = k;\n        }\n    }\n    // try split by y\n    sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n    int bestSplitY = -1;\n    double bestScoreY = -1e100;\n    for (int k = 0; k < (int)idxs.size() - 1; k++) {\n        int bottomY = pts[idxs[k]].y; // max y of bottom\n        int topY = pts[idxs[k+1]].y; // min y of top\n        int splitY = topY;\n        if (splitY <= y1 || splitY >= y2) continue;\n        long long bottomArea = 1LL * (x2 - x1) * (splitY - y1);\n        long long bottomR = 0;\n        for (int i = 0; i <= k; i++) bottomR += pts[idxs[i]].r;\n        double bottomRatio = (double)bottomArea / totalArea;\n        double targetRatio = (double)bottomR / sumR;\n        double score = -fabs(bottomRatio - targetRatio);\n        if (score > bestScoreY) {\n            bestScoreY = score;\n            bestSplitY = k;\n        }\n    }\n\n    if (bestScore > bestScoreY) {\n        // split by x at bestSplit\n        sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n        int splitX = pts[idxs[bestSplit+1]].x;\n        vector<int> left(idxs.begin(), idxs.begin() + bestSplit + 1);\n        vector<int> right(idxs.begin() + bestSplit + 1, idxs.end());\n        solve(x1, y1, splitX, y2, left);\n        solve(splitX, y1, x2, y2, right);\n    } else if (bestSplitY != -1) {\n        sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n        int splitY = pts[idxs[bestSplitY+1]].y;\n        vector<int> bottom(idxs.begin(), idxs.begin() + bestSplitY + 1);\n        vector<int> top(idxs.begin() + bestSplitY + 1, idxs.end());\n        solve(x1, y1, x2, splitY, bottom);\n        solve(x1, splitY, x2, y2, top);\n    } else {\n        // fallback: just assign whole to first? shouldn't happen\n        int i = idxs[0];\n        ans[i] = {x1, y1, x2, y2};\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n;\n    pts.resize(n);\n    ans.resize(n);\n    for (int i = 0; i < n; i++) {\n        cin >> pts[i].x >> pts[i].y >> pts[i].r;\n        pts[i].id = i;\n    }\n    vector<int> all(n);\n    iota(all.begin(), all.end(), 0);\n    solve(0, 0, 10000, 10000, all);\n    for (int i = 0; i < n; i++) {\n        cout << ans[i].a << \" \" << ans[i].b << \" \" << ans[i].c << \" \" << ans[i].d << \"\\n\";\n    }\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <bitset>\n#include <queue>\n#include <cstring>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_TILES = 2500;\nconst int BEAM_WIDTH = 150;\nconst int MAX_DEPTH = 2000;\n\nstruct State {\n    int score;\n    int est_score;\n    short i, j;         // current position\n    short pi, pj;       // previous position (to avoid immediate backtrack)\n    bitset<MAX_TILES> visited;\n    int prev_idx;       // index in the previous beam\n    char move_char;     // move that led to this state\n};\n\nint si, sj;\nint tile_id[N][N];\nint p[N][N];\nint M; // number of tiles\nvector<pair<short, short>> tile_squares[MAX_TILES];\nint tile_value[MAX_TILES];\nvector<int> tile_adj[MAX_TILES];\nint bfs_tag[MAX_TILES];\nint current_bfs_tag = 0;\n\n// Heuristic: sum of values of all unvisited tiles reachable from the current tile\nint compute_potential(const State& st) {\n    current_bfs_tag++;\n    int start_tile = tile_id[st.i][st.j];\n    queue<int> q;\n    int pot = 0;\n    // Start BFS from unvisited neighbors of the current tile\n    for (int v : tile_adj[start_tile]) {\n        if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n            bfs_tag[v] = current_bfs_tag;\n            q.push(v);\n            pot += tile_value[v];\n        }\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : tile_adj[u]) {\n            if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n                bfs_tag[v] = current_bfs_tag;\n                q.push(v);\n                pot += tile_value[v];\n            }\n        }\n    }\n    return pot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(1950);\n\n    cin >> si >> sj;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    // Determine the number of tiles\n    M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (tile_id[i][j] >= M) M = tile_id[i][j] + 1;\n\n    // Collect tile squares and values\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            tile_squares[tile_id[i][j]].emplace_back(i, j);\n    for (int t = 0; t < M; ++t) {\n        int val = 0;\n        for (auto& sq : tile_squares[t])\n            val += p[sq.first][sq.second];\n        tile_value[t] = val;\n    }\n\n    // Build inter-tile adjacency\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int nt = tile_id[ni][nj];\n                    if (nt != t)\n                        tile_adj[t].push_back(nt);\n                }\n            }\n        }\n    }\n    for (int t = 0; t < M; ++t) {\n        sort(tile_adj[t].begin(), tile_adj[t].end());\n        tile_adj[t].erase(unique(tile_adj[t].begin(), tile_adj[t].end()), tile_adj[t].end());\n    }\n\n    // Initial state\n    State init;\n    init.score = p[si][sj];\n    init.i = si; init.j = sj;\n    init.pi = -1; init.pj = -1;\n    init.visited.reset();\n    init.visited[tile_id[si][sj]] = 1;\n    init.prev_idx = -1;\n    init.est_score = init.score + compute_potential(init);\n\n    vector<State> beam;\n    beam.push_back(init);\n    vector<vector<State>> beam_history;\n    beam_history.push_back(beam);\n\n    int best_score = init.score;\n    int best_depth = 0;\n    int best_state_idx = 0;\n\n    // Beam search\n    for (int depth = 1; depth <= MAX_DEPTH; ++depth) {\n        if (chrono::steady_clock::now() - start_time > time_limit) break;\n\n        vector<State> next_beam;\n        for (int s_idx = 0; s_idx < (int)beam.size(); ++s_idx) {\n            const State& st = beam[s_idx];\n            short i = st.i, j = st.j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (ni == st.pi && nj == st.pj) continue;   // immediate backtrack\n\n                int nt = tile_id[ni][nj];\n                bool same_tile = (nt == tile_id[i][j]);\n\n                if (!same_tile && st.visited[nt]) continue; // tile already used\n\n                State nxt = st;\n                nxt.i = ni; nxt.j = nj;\n                nxt.pi = i; nxt.pj = j;\n                nxt.score += p[ni][nj];\n                if (!same_tile) nxt.visited[nt] = 1;\n                nxt.prev_idx = s_idx;\n                nxt.move_char = (k == 0 ? 'U' : (k == 1 ? 'D' : (k == 2 ? 'L' : 'R')));\n                nxt.est_score = nxt.score + compute_potential(nxt);\n                next_beam.push_back(move(nxt));\n            }\n        }\n        if (next_beam.empty()) break;\n\n        sort(next_beam.begin(), next_beam.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)next_beam.size() > BEAM_WIDTH)\n            next_beam.resize(BEAM_WIDTH);\n\n        if (next_beam[0].score > best_score) {\n            best_score = next_beam[0].score;\n            best_depth = depth;\n            best_state_idx = 0;\n        }\n\n        beam = move(next_beam);\n        beam_history.push_back(beam);\n    }\n\n    // Retrieve the absolute best state from the whole history\n    for (int d = 0; d < (int)beam_history.size(); ++d) {\n        for (int idx = 0; idx < (int)beam_history[d].size(); ++idx) {\n            if (beam_history[d][idx].score > best_score) {\n                best_score = beam_history[d][idx].score;\n                best_depth = d;\n                best_state_idx = idx;\n            }\n        }\n    }\n\n    // Reconstruct the path\n    string path;\n    int cur_depth = best_depth;\n    int cur_idx = best_state_idx;\n    while (cur_depth > 0) {\n        const State& st = beam_history[cur_depth][cur_idx];\n        path.push_back(st.move_char);\n        cur_idx = st.prev_idx;\n        --cur_depth;\n    }\n    reverse(path.begin(), path.end());\n    cout << path << '\\n';\n\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace std::chrono;\n\nconstexpr int N = 30;\nconstexpr int INF = 1e9;\n\n// Edge estimates\ndouble est_H[N][N-1];\ndouble est_V[N-1][N];\nint cnt_H[N][N-1];\nint cnt_V[N-1][N];\n\nint di[] = {-1, 1, 0, 0};\nint dj[] = {0, 0, -1, 1};\nchar dir[] = {'U', 'D', 'L', 'R'};\n\n// Dijkstra\npair<vector<pair<int,int>>, double> dijkstra(int si, int sj, int ti, int tj, double explore_bonus) {\n    vector dist(N, vector<double>(N, INF));\n    vector prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    dist[si][sj] = 0;\n    using State = tuple<double,int,int>;\n    priority_queue<State, vector<State>, greater<State>> pq;\n    pq.push({0, si, sj});\n    while(!pq.empty()) {\n        auto [d,i,j] = pq.top(); pq.pop();\n        if(d != dist[i][j]) continue;\n        if(i==ti && j==tj) break;\n        for(int k=0;k<4;k++){\n            int ni = i+di[k], nj = j+dj[k];\n            if(ni<0||ni>=N||nj<0||nj>=N) continue;\n            double w = 0;\n            if(k==0) w = est_V[ni][nj] + explore_bonus/(cnt_V[ni][nj]+1);\n            else if(k==1) w = est_V[i][j] + explore_bonus/(cnt_V[i][j]+1);\n            else if(k==2) w = est_H[ni][nj] + explore_bonus/(cnt_H[ni][nj]+1);\n            else w = est_H[i][j] + explore_bonus/(cnt_H[i][j]+1);\n            if(dist[ni][nj] > dist[i][j] + w){\n                dist[ni][nj] = dist[i][j] + w;\n                prev[ni][nj] = {i,j};\n                pq.push({dist[ni][nj], ni, nj});\n            }\n        }\n    }\n    vector<pair<int,int>> path;\n    int ci=ti, cj=tj;\n    double est_len = 0;\n    while(!(ci==si && cj==sj)){\n        path.push_back({ci,cj});\n        auto [pi,pj] = prev[ci][cj];\n        if(pi==ci-1) est_len += est_V[pi][pj];\n        else if(pi==ci+1) est_len += est_V[ci][pj];\n        else if(pj==cj-1) est_len += est_H[pi][pj];\n        else est_len += est_H[ci][pj];\n        ci=pi; cj=pj;\n    }\n    path.push_back({si,sj});\n    reverse(path.begin(), path.end());\n    return {path, est_len};\n}\n\nstring path_to_string(const vector<pair<int,int>>& path){\n    string s;\n    for(size_t i=1;i<path.size();i++){\n        auto [a,b] = path[i-1];\n        auto [c,d] = path[i];\n        if(c==a-1) s+='U';\n        else if(c==a+1) s+='D';\n        else if(d==b-1) s+='L';\n        else s+='R';\n    }\n    return s;\n}\n\nint main(){\n    ios::sync_with_stdio(false); cin.tie(nullptr);\n    // Initialize estimates\n    for(int i=0;i<N;i++) for(int j=0;j<N-1;j++) est_H[i][j] = 5000;\n    for(int i=0;i<N-1;i++) for(int j=0;j<N;j++) est_V[i][j] = 5000;\n    memset(cnt_H,0,sizeof(cnt_H));\n    memset(cnt_V,0,sizeof(cnt_V));\n\n    double explore_bonus = 3000;\n\n    for(int k=0;k<1000;k++){\n        int si,sj,ti,tj;\n        cin >> si >> sj >> ti >> tj;\n\n        // Path with exploration\n        auto [path, est_len] = dijkstra(si,sj,ti,tj, explore_bonus);\n        cout << path_to_string(path) << endl;\n\n        int observed; cin >> observed;\n        // Update counts and estimates\n        for(size_t i=1;i<path.size();i++){\n            auto [a,b] = path[i-1];\n            auto [c,d] = path[i];\n            if(c==a-1){ // U\n                cnt_V[c][d]++; \n            } else if(c==a+1){ // D\n                cnt_V[a][b]++; \n            } else if(d==b-1){ // L\n                cnt_H[c][d]++; \n            } else { // R\n                cnt_H[a][b]++; \n            }\n        }\n        if(est_len > 0){\n            double ratio = observed / est_len;\n            for(size_t i=1;i<path.size();i++){\n                auto [a,b] = path[i-1];\n                auto [c,d] = path[i];\n                double &e = (c==a-1) ? est_V[c][d] : (c==a+1) ? est_V[a][b] : (d==b-1) ? est_H[c][d] : est_H[a][b];\n                e = e * 0.9 + e * ratio * 0.1; // moving avg update\n            }\n        }\n        explore_bonus *= 0.995; // decay exploration\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nconst int N = 20;\nint M;\nvector<string> strings;\nvector<int> string_lens;\n\n// directions: 0 horizontal, 1 vertical\nstruct MatchPos {\n    int r, c, dir, idx;\n};\n\nvector<vector<MatchPos>> candidates_per_string;\n\n// current grid\nchar grid[N][N];\n\n// precomputed: which strings are currently matched? For speed, we keep a count of matched and bool array\nbitset<800> matched;\nint matched_count = 0;\nint empty_count = 0;\n\n// For each cell, list of matches that use it (so we can quickly recompute on change)\nstruct CellDep {\n    int string_idx;\n    int pos_idx; // which candidate for that string\n};\nvector<CellDep> cell_deps[N][N];\n\n// Score with all matched: 10^8 * 2*N^2 / (2*N^2 - d)\n// Otherwise: 10^8 * c / M\ndouble calc_score() {\n    if (matched_count < M) {\n        return 1e8 * matched_count / M;\n    } else {\n        return 1e8 * (2.0 * N * N) / (2.0 * N * N - empty_count);\n    }\n}\n\n// Check if a specific candidate matches current grid\nbool check_candidate(const MatchPos &mp) {\n    const string &s = strings[mp.idx];\n    int len = s.size();\n    if (mp.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            char c = grid[mp.r][(mp.c + p) % N];\n            if (c != '.' && c != s[p]) return false;\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            char c = grid[(mp.r + p) % N][mp.c];\n            if (c != '.' && c != s[p]) return false;\n        }\n    }\n    return true;\n}\n\n// Update matched status for all strings that depend on a cell (r,c)\nvoid update_after_change(int r, int c) {\n    for (auto &dep : cell_deps[r][c]) {\n        int sidx = dep.string_idx;\n        bool was = matched[sidx];\n        const MatchPos &mp = candidates_per_string[sidx][dep.pos_idx];\n        bool now = check_candidate(mp);\n        if (was && !now) {\n            matched[sidx] = false;\n            --matched_count;\n        } else if (!was && now) {\n            matched[sidx] = true;\n            ++matched_count;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    strings.resize(M);\n    string_lens.resize(M);\n    candidates_per_string.resize(M);\n\n    // Generate candidates for each string\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n        int len = strings[i].size();\n        string_lens[i] = len;\n        // horizontal candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                candidates_per_string[i].push_back({r, c, 0, i});\n            }\n        }\n        // vertical candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                candidates_per_string[i].push_back({r, c, 1, i});\n            }\n        }\n    }\n\n    // Initialize grid with random letters\n    const char letters[] = {'A','B','C','D','E','F','G','H'};\n    mt19937 rng(42);\n    uniform_int_distribution<int> letter_dist(0,7);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = letters[letter_dist(rng)];\n\n    // Build dependencies\n    for (int i = 0; i < M; ++i) {\n        for (int p = 0; p < (int)candidates_per_string[i].size(); ++p) {\n            const auto &mp = candidates_per_string[i][p];\n            const string &s = strings[i];\n            int len = s.size();\n            if (mp.dir == 0) {\n                for (int k = 0; k < len; ++k) {\n                    int rr = mp.r;\n                    int cc = (mp.c + k) % N;\n                    cell_deps[rr][cc].push_back({i, p});\n                }\n            } else {\n                for (int k = 0; k < len; ++k) {\n                    int rr = (mp.r + k) % N;\n                    int cc = mp.c;\n                    cell_deps[rr][cc].push_back({i, p});\n                }\n            }\n        }\n    }\n\n    // Initial match count\n    for (int i = 0; i < M; ++i) {\n        for (auto &mp : candidates_per_string[i]) {\n            if (check_candidate(mp)) {\n                matched[i] = true;\n                ++matched_count;\n                break;\n            }\n        }\n    }\n    empty_count = 0;\n\n    // Simulated Annealing parameters\n    double temp_start = 2.0;\n    double temp_end = 0.01;\n    int max_iter = 200000;\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    uniform_int_distribution<int> cell_dist(0, N-1);\n    uniform_int_distribution<int> letter_dist2(0, 7);\n    auto start_time = high_resolution_clock::now();\n\n    double best_score = calc_score();\n    char best_grid[N][N];\n    memcpy(best_grid, grid, sizeof(grid));\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        double progress = (double)iter / max_iter;\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int r = cell_dist(rng);\n        int c = cell_dist(rng);\n        char old_char = grid[r][c];\n        char new_char;\n        if (prob_dist(rng) < 0.1) {\n            new_char = '.';\n        } else {\n            new_char = letters[letter_dist2(rng)];\n        }\n        if (new_char == old_char) continue;\n\n        int old_empty = empty_count;\n        if (old_char == '.') --empty_count;\n        if (new_char == '.') ++empty_count;\n\n        grid[r][c] = new_char;\n        update_after_change(r, c);\n\n        double new_score = calc_score();\n        double score_diff = new_score - best_score;\n        if (score_diff >= 0 || prob_dist(rng) < exp(score_diff / (best_score * temp + 1e-9))) {\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_grid, grid, sizeof(grid));\n            }\n        } else {\n            // revert\n            grid[r][c] = old_char;\n            empty_count = old_empty;\n            update_after_change(r, c);\n        }\n    }\n\n    // Output best found\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dir[4] = {'U', 'D', 'L', 'R'};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> cost;\nvector<vector<bool>> road;\n\nvector<vector<pair<int,int>>> visibility; // visibility sets as lists\nvector<bitset<5000>> visMask;\nint totalRoads = 0;\nvector<int> roadId; // map each cell to an ID or -1\n\nbool inside(int i, int j) {\n    return i>=0 && i<N && j>=0 && j<N;\n}\n\n// BFS/Dijkstra to compute shortest path between two cells\nvector<pair<int,int>> shortestPath(int si, int sj, int ti, int tj) {\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    priority_queue<pair<int,pair<int,int>>, vector<pair<int,pair<int,int>>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, {si, sj}});\n    while(!pq.empty()) {\n        auto [d, pos] = pq.top(); pq.pop();\n        auto [i, j] = pos;\n        if(d != dist[i][j]) continue;\n        if(i==ti && j==tj) break;\n        for(int k=0;k<4;k++) {\n            int ni = i+dx[k], nj = j+dy[k];\n            if(inside(ni,nj) && road[ni][nj]) {\n                int nd = d + cost[ni][nj];\n                if(nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i,j};\n                    pq.push({nd, {ni,nj}});\n                }\n            }\n        }\n    }\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; cj = p.second;\n    }\n    path.push_back({si,sj});\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// convert path to direction string\nstring pathToDir(const vector<pair<int,int>>& path) {\n    string res;\n    for(int i=0;i+1<(int)path.size();i++) {\n        int di = path[i+1].first - path[i].first;\n        int dj = path[i+1].second - path[i].second;\n        if(di == -1) res += 'U';\n        else if(di == 1) res += 'D';\n        else if(dj == -1) res += 'L';\n        else res += 'R';\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    cost.assign(N, vector<int>(N,0));\n    road.assign(N, vector<bool>(N,false));\n    roadId.assign(N, vector<int>(N,-1));\n    \n    for(int i=0;i<N;i++) {\n        cin >> grid[i];\n        for(int j=0;j<N;j++) {\n            if(grid[i][j] != '#') {\n                road[i][j] = true;\n                cost[i][j] = grid[i][j] - '0';\n                roadId[i][j] = totalRoads++;\n            }\n        }\n    }\n    \n    // compute visibility masks\n    visMask.resize(N, bitset<5000>());\n    for(int i=0;i<N;i++) {\n        for(int j=0;j<N;j++) {\n            if(!road[i][j]) continue;\n            // horizontal\n            for(int jj=j; jj<N && road[i][jj]; jj++) \n                visMask[i][j].set(roadId[i][jj]);\n            for(int jj=j-1; jj>=0 && road[i][jj]; jj--) \n                visMask[i][j].set(roadId[i][jj]);\n            // vertical\n            for(int ii=i; ii<N && road[ii][j]; ii++) \n                visMask[i][j].set(roadId[ii][j]);\n            for(int ii=i-1; ii>=0 && road[ii][j]; ii--) \n                visMask[i][j].set(roadId[ii][j]);\n        }\n    }\n    \n    // Greedy set cover to choose points\n    bitset<5000> covered;\n    vector<pair<int,int>> chosen;\n    covered.set(roadId[si][sj]);\n    chosen.push_back({si,sj});\n    \n    while(covered.count() < totalRoads) {\n        int best = -1, bi = -1, bj = -1;\n        for(int i=0;i<N;i++) {\n            for(int j=0;j<N;j++) {\n                if(!road[i][j]) continue;\n                auto newCov = (visMask[i][j] | covered);\n                int gain = (int)newCov.count() - (int)covered.count();\n                if(gain > best) {\n                    best = gain;\n                    bi = i; bj = j;\n                }\n            }\n        }\n        if(best<=0) break;\n        covered |= visMask[bi][bj];\n        chosen.push_back({bi,bj});\n    }\n    \n    // Build route in nearest-neighbor order (simple)\n    vector<pair<int,int>> order;\n    vector<bool> used(chosen.size(), false);\n    int cur = 0;\n    order.push_back(chosen[0]);\n    used[0] = true;\n    for(int step=1; step<(int)chosen.size(); step++) {\n        int bestIdx = -1;\n        int bestDist = 1e9;\n        for(int i=1;i<(int)chosen.size();i++) {\n            if(!used[i]) {\n                // approximate distance\n                int d = abs(chosen[cur].first - chosen[i].first) + abs(chosen[cur].second - chosen[i].second);\n                if(d < bestDist) {\n                    bestDist = d;\n                    bestIdx = i;\n                }\n            }\n        }\n        used[bestIdx] = true;\n        order.push_back(chosen[bestIdx]);\n        cur = bestIdx;\n    }\n    order.push_back(chosen[0]); // return to start\n    \n    // 2-opt improvement\n    auto distEst = [&](int a, int b) {\n        return abs(order[a].first - order[b].first) + abs(order[a].second - order[b].second);\n    };\n    bool improved = true;\n    int m = (int)order.size();\n    while(improved) {\n        improved = false;\n        for(int i=1;i<m-2;i++) {\n            for(int j=i+1;j<m-1;j++) {\n                int oldCost = distEst(i-1,i) + distEst(j,j+1);\n                int newCost = distEst(i-1,j) + distEst(i,j+1);\n                if(newCost < oldCost) {\n                    reverse(order.begin()+i, order.begin()+j+1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // Build full path\n    vector<pair<int,int>> fullPath;\n    for(int i=0;i+1<(int)order.size();i++) {\n        auto pp = shortestPath(order[i].first, order[i].second,\n                                order[i+1].first, order[i+1].second);\n        if(!fullPath.empty()) fullPath.pop_back(); // avoid duplicate junction\n        fullPath.insert(fullPath.end(), pp.begin(), pp.end());\n    }\n    \n    string ans = pathToDir(fullPath);\n    cout << ans << \"\\n\";\n    \n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N_MAX = 1000;\nconst int M_MAX = 20;\nconst int K_MAX = 20;\nconst int MAX_DAY = 2000;\n\nint N, M, K, R;\nvector<vector<int>> d; // task difficulties\nvector<vector<int>> dep; // dependencies: dep[i] = list of tasks that task i depends on\nvector<vector<int>> rev_dep; // reverse dependencies\nvector<int> in_degree;\n\nvector<vector<double>> s_est; // estimated skills [M][K]\nvector<vector<int>> observed_t; // observed times for each (task, member)\nvector<vector<pair<int,int>>> task_member_obs; // (task, member) -> list of (predicted_t, actual_t)\n\n// For each member, track which skills we've observed\nvector<vector<int>> skill_observations; // [M][K] count of observations\n\nenum TaskStatus { NOT_STARTED = 0, IN_PROGRESS = 1, COMPLETED = 2 };\nvector<TaskStatus> task_status;\nvector<int> task_assigned_to; // which member is doing task (-1 if none)\nvector<int> task_start_day; // when task was started\nvector<int> member_busy_until; // day until which member is busy\nvector<int> completed_tasks;\n\n// For estimation\nvector<vector<double>> skill_gaps_sum; // sum of observed gaps for each (member, skill)\nvector<vector<int>> skill_gaps_count; // count of observations for each (member, skill)\n\nvoid parse_input() {\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            cin >> d[i][k];\n        }\n    }\n    dep.resize(N);\n    rev_dep.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        dep[v].push_back(u);\n        rev_dep[u].push_back(v);\n        in_degree[v]++;\n    }\n}\n\nvoid init_estimation() {\n    s_est.assign(M, vector<double>(K, 0.0));\n    // Initialize with average expected skill (middle of range 20-60)\n    // We'll estimate as we observe\n    skill_observations.assign(M, vector<int>(K, 0));\n    observed_t.assign(N, vector<int>(M, -1));\n    task_member_obs.resize(N * M);\n    skill_gaps_sum.assign(M, vector<double>(K, 0.0));\n    skill_gaps_count.assign(M, vector<int>(K, 0));\n    \n    // Initialize s_est with moderate values\n    for (int j = 0; j < M; j++) {\n        for (int k = 0; k < K; k++) {\n            s_est[j][k] = 30.0; // prior estimate\n        }\n    }\n}\n\nvoid init_scheduling() {\n    task_status.assign(N, NOT_STARTED);\n    task_assigned_to.assign(N, -1);\n    task_start_day.assign(N, -1);\n    member_busy_until.assign(M, 0);\n    completed_tasks.clear();\n}\n\n// Estimate w_i,j based on current s_est\ndouble estimate_w(int i, int j) {\n    double w = 0;\n    for (int k = 0; k < K; k++) {\n        w += max(0.0, (double)d[i][k] - s_est[j][k]);\n    }\n    return w;\n}\n\n// Estimate t_i,j based on w\nint estimate_t(int i, int j) {\n    double w = estimate_w(i, j);\n    if (w < 0.5) return 1; // effectively zero\n    return max(1, (int)round(w));\n}\n\n// Update skill estimates based on observation\nvoid update_skill_estimate(int task, int member, int actual_t) {\n    // actual_t = 1 means w_i,j was likely 0 (or very small)\n    // actual_t > 1 means w_i,j was approximately actual_t (with noise -3 to +3)\n    \n    if (actual_t == 1) {\n        // All skills of member are at least d[task][k]\n        for (int k = 0; k < K; k++) {\n            if (d[task][k] > 0) {\n                // We know s[member][k] >= d[task][k]\n                s_est[member][k] = max(s_est[member][k], (double)d[task][k] + 0.5);\n            }\n        }\n    } else {\n        // w_i,j is roughly actual_t (with noise)\n        // We can't easily decompose which skills contributed\n        // Use gradient-like update\n        double current_w = estimate_w(task, member);\n        double target_w = actual_t;\n        \n        // Distribute the difference proportionally to skills where d > s_est\n        double diff = target_w - current_w;\n        if (abs(diff) > 0.01) {\n            double total_weight = 0;\n            vector<double> gaps(K, 0);\n            for (int k = 0; k < K; k++) {\n                gaps[k] = max(0.0, (double)d[task][k] - s_est[member][k]);\n                total_weight += gaps[k];\n            }\n            if (total_weight > 0.01) {\n                for (int k = 0; k < K; k++) {\n                    if (gaps[k] > 0.01) {\n                        double update = diff * gaps[k] / total_weight;\n                        s_est[member][k] -= update * 0.5; // learning rate\n                        s_est[member][k] = max(0.0, s_est[member][k]);\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate critical path length (longest path to completion)\nvector<int> compute_critical_path() {\n    vector<int> topo;\n    vector<int> indeg = in_degree;\n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (indeg[i] == 0 && task_status[i] != COMPLETED) {\n            q.push(i);\n        }\n    }\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) {\n                q.push(u);\n            }\n        }\n    }\n    \n    vector<int> est_time(N, 0);\n    // Process in reverse topological order\n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        if (task_status[v] == COMPLETED) {\n            est_time[v] = 0;\n        } else {\n            int best_t = 1000000;\n            for (int j = 0; j < M; j++) {\n                best_t = min(best_t, estimate_t(v, j));\n            }\n            est_time[v] = best_t;\n            int max_succ = 0;\n            for (int u : rev_dep[v]) {\n                max_succ = max(max_succ, est_time[u]);\n            }\n            est_time[v] += max_succ;\n        }\n    }\n    \n    return est_time;\n}\n\n// Check if task is ready (all dependencies completed)\nbool is_task_ready(int task, int current_day) {\n    if (task_status[task] != NOT_STARTED) return false;\n    for (int dep_task : dep[task]) {\n        if (task_status[dep_task] != COMPLETED) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    parse_input();\n    init_estimation();\n    init_scheduling();\n    \n    int current_day = 0;\n    vector<int> last_completed;\n    \n    while (true) {\n        current_day++;\n        \n        // Process completions from previous day\n        for (int member : last_completed) {\n            // Find which task this member was doing\n            for (int i = 0; i < N; i++) {\n                if (task_assigned_to[i] == member && task_status[i] == IN_PROGRESS) {\n                    task_status[i] = COMPLETED;\n                    completed_tasks.push_back(i);\n                    \n                    // Update skill estimates\n                    int actual_t = current_day - task_start_day[i];\n                    update_skill_estimate(i, member, actual_t);\n                    \n                    task_assigned_to[i] = -1;\n                    break;\n                }\n            }\n        }\n        \n        // Check if all tasks completed\n        if ((int)completed_tasks.size() == N) {\n            break;\n        }\n        if (current_day > MAX_DAY) {\n            break;\n        }\n        \n        // Compute task priorities\n        vector<int> crit_path = compute_critical_path();\n        \n        // Find available tasks\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (is_task_ready(i, current_day)) {\n                ready_tasks.push_back(i);\n            }\n        }\n        \n        // Sort ready tasks by critical path length (descending - more urgent first)\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            return crit_path[a] > crit_path[b];\n        });\n        \n        // Find available members\n        vector<int> available_members;\n        for (int j = 0; j < M; j++) {\n            if (member_busy_until[j] <= current_day) {\n                available_members.push_back(j);\n            }\n        }\n        \n        // Track which members we assign to ensure no double assignment\n        vector<bool> member_used(M, false);\n        \n        // Assignment strategy\n        vector<pair<int,int>> assignments;\n        \n        // First pass: assign tasks that can be done in 1 day by some member\n        for (int task : ready_tasks) {\n            if (assignments.size() >= available_members.size()) break;\n            \n            int best_member = -1;\n            int best_t = 1000000;\n            \n            for (int j : available_members) {\n                if (member_used[j]) continue;\n                int est_t = estimate_t(task, j);\n                if (est_t < best_t) {\n                    best_t = est_t;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1 && best_t == 1) {\n                assignments.push_back({best_member, task});\n                member_used[best_member] = true;\n            }\n        }\n        \n        // Second pass: assign remaining tasks to best available members\n        for (int task : ready_tasks) {\n            if (assignments.size() >= available_members.size()) break;\n            \n            // Skip if already assigned\n            bool already = false;\n            for (auto &p : assignments) {\n                if (p.second == task) { already = true; break; }\n            }\n            if (already) continue;\n            \n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int j : available_members) {\n                if (member_used[j]) continue;\n                int est_t = estimate_t(task, j);\n                // Prioritize lower time, but also consider exploration\n                double score = -est_t;\n                \n                // Add exploration bonus for tasks with few observations\n                int obs_count = 0;\n                for (int k = 0; k < K; k++) {\n                    if (d[task][k] > 0) obs_count += skill_gaps_count[j][k];\n                }\n                if (obs_count < 5) score += 10.0; // exploration bonus\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                assignments.push_back({best_member, task});\n                member_used[best_member] = true;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            int member = p.first;\n            int task = p.second;\n            cout << \" \" << (member + 1) << \" \" << (task + 1);\n            \n            // Update state\n            task_status[task] = IN_PROGRESS;\n            task_assigned_to[task] = member;\n            task_start_day[task] = current_day;\n            int duration = estimate_t(task, member);\n            member_busy_until[member] = current_day + duration;\n        }\n        cout << \"\\n\";\n        \n        // Output skill predictions as comments\n        for (int j = 0; j < M; j++) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << \" \" << (int)round(s_est[j][k]);\n            }\n            cout << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read input\n        string line;\n        getline(cin, line);\n        if (line.empty()) continue;\n        \n        istringstream iss(line);\n        vector<int> vals;\n        int x;\n        while (iss >> x) vals.push_back(x);\n        \n        if (vals.size() == 1 && vals[0] == -1) {\n            break;\n        }\n        \n        last_completed.clear();\n        if (vals.size() > 0) {\n            int n_comp = vals[0];\n            for (int i = 0; i < n_comp; i++) {\n                last_completed.push_back(vals[i + 1] - 1);\n            }\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <cassert>\n#include <climits>\n\nusing namespace std;\n\n// ------------------------------------------------------------\n// geometry / distance\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ------------------------------------------------------------\n// order structure\nstruct Order {\n    int id;\n    int ax, ay; // restaurant\n    int cx, cy; // destination\n};\n\n// ------------------------------------------------------------\n// route node kinds\nenum NodeType { PICKUP, DELIVERY, DEPOT };\n\nstruct Node {\n    NodeType type;\n    int order_id; // -1 for depot\n    int x, y;\n};\n\n// ------------------------------------------------------------\n// compute total Manhattan distance of a route\nint routeLength(const vector<Node>& route) {\n    int total = 0;\n    for (size_t i = 0; i + 1 < route.size(); ++i) {\n        total += manhattan(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// check if route satisfies pickup before delivery for all orders\nbool feasibleRoute(const vector<Node>& route) {\n    map<int, int> firstSeen;\n    for (size_t i = 0; i < route.size(); ++i) {\n        if (route[i].type == DEPOT) continue;\n        int oid = route[i].order_id;\n        if (route[i].type == PICKUP) {\n            if (firstSeen.find(oid) == firstSeen.end()) {\n                firstSeen[oid] = i;\n            }\n        } else { // DELIVERY\n            if (firstSeen.find(oid) == firstSeen.end()) return false;\n        }\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// insert one order (pickup then delivery) at best positions to minimize extra distance\npair<int,int> bestInsert(const vector<Node>& route, const Order& ord) {\n    int bestCost = INT_MAX;\n    int bestP = -1, bestD = -1;\n    // we cannot insert at pos 0 (depot) and pos N-1 (depot)\n    int n = (int)route.size();\n    // pickup can go after position i (0 <= i < n-1), delivery after position j (i+1 <= j < n-1)\n    for (int i = 0; i < n-1; ++i) {\n        // tentative pickup position after i\n        int pi = i+1;\n        int distPBefore = manhattan(route[i].x, route[i].y, ord.ax, ord.ay);\n        int distPAfter  = manhattan(ord.ax, ord.ay, route[pi].x, route[pi].y);\n        int extraP = distPBefore + distPAfter - manhattan(route[i].x, route[i].y, route[pi].x, route[pi].y);\n        for (int j = i; j < n-1; ++j) {\n            // delivery position after j, but after pickup inserted, indices shift\n            int dj = j+1;\n            int distDBefore = manhattan(route[j].x, route[j].y, ord.cx, ord.cy);\n            int distDAfter  = manhattan(ord.cx, ord.cy, route[dj].x, route[dj].y);\n            int extraD = distDBefore + distDAfter - manhattan(route[j].x, route[j].y, route[dj].x, route[dj].y);\n            int totalExtra = extraP + extraD;\n            if (totalExtra < bestCost) {\n                bestCost = totalExtra;\n                bestP = pi;\n                // delivery shift due to pickup inserted before j\n                bestD = (j >= i) ? dj + 1 : dj;\n            }\n        }\n    }\n    return {bestP, bestD};\n}\n\n// ------------------------------------------------------------\n// insert order at given positions (indices in the current route)\nvector<Node> insertOrder(const vector<Node>& route, const Order& ord, int posP, int posD) {\n    vector<Node> newRoute = route;\n    Node pNode = {PICKUP, ord.id, ord.ax, ord.ay};\n    Node dNode = {DELIVERY, ord.id, ord.cx, ord.cy};\n    if (posP < posD) {\n        newRoute.insert(newRoute.begin() + posD, dNode);\n        newRoute.insert(newRoute.begin() + posP, pNode);\n    } else {\n        newRoute.insert(newRoute.begin() + posP, pNode);\n        newRoute.insert(newRoute.begin() + posD, dNode);\n    }\n    return newRoute;\n}\n\n// ------------------------------------------------------------\n// build initial route with selected orders (simple greedy insertion)\nvector<Node> buildInitialRoute(const vector<Order>& orders, const vector<int>& selected) {\n    vector<Node> route;\n    route.push_back({DEPOT, -1, 400, 400});\n    route.push_back({DEPOT, -1, 400, 400});\n    \n    for (int id : selected) {\n        auto [p, d] = bestInsert(route, orders[id]);\n        route = insertOrder(route, orders[id], p, d);\n    }\n    return route;\n}\n\n// ------------------------------------------------------------\n// random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// main optimization\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    const int N = 1000;\n    const int K = 50;\n    const int DEPOT_X = 400, DEPOT_Y = 400;\n    \n    vector<Order> orders(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        orders[i].id = i;\n    }\n    \n    // initial selection: first 50\n    vector<int> selected(K);\n    iota(selected.begin(), selected.end(), 0);\n    \n    // build initial route\n    vector<Node> route = buildInitialRoute(orders, selected);\n    int bestLen = routeLength(route);\n    vector<Node> bestRoute = route;\n    vector<int> bestSelected = selected;\n    \n    // set of available orders (not selected)\n    set<int> available;\n    for (int i = K; i < N; ++i) available.insert(i);\n    \n    // hill climbing with random restarts limited by time\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.8; // seconds\n    int iterations = 0;\n    \n    uniform_int_distribution<int> selDist(0, K-1);\n    uniform_int_distribution<int> availIdx(0, N-K-1);\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        iterations++;\n        \n        // Try to replace one selected order with an unchosen one\n        int idxRemove = selDist(rng);\n        int oldOrderId = selected[idxRemove];\n        \n        // pick a random available order\n        int pick = availIdx(rng) % (int)available.size();\n        auto it = available.begin();\n        advance(it, pick);\n        int newOrderId = *it;\n        \n        // new selection\n        vector<int> newSel = selected;\n        newSel[idxRemove] = newOrderId;\n        \n        // build route with new selection using greedy insertion from scratch\n        vector<Node> candRoute;\n        candRoute.push_back({DEPOT, -1, DEPOT_X, DEPOT_Y});\n        candRoute.push_back({DEPOT, -1, DEPOT_X, DEPOT_Y});\n        \n        for (int oid : newSel) {\n            auto [p, d] = bestInsert(candRoute, orders[oid]);\n            candRoute = insertOrder(candRoute, orders[oid], p, d);\n        }\n        \n        int candLen = routeLength(candRoute);\n        if (candLen < bestLen) {\n            bestLen = candLen;\n            bestRoute = candRoute;\n            bestSelected = newSel;\n            \n            // update available set\n            available.erase(newOrderId);\n            available.insert(oldOrderId);\n            selected = newSel;\n        }\n        \n        // also try some local search moves on the current best route\n        // for simplicity just 2-opt like relocation of single node\n        if (iterations % 10 == 0) {\n            int n = (int)bestRoute.size();\n            // try moving a node to another position maintaining feasibility\n            for (int i = 1; i < n-1; ++i) {\n                for (int j = 1; j < n-1; ++j) {\n                    if (i == j) continue;\n                    vector<Node> newRoute = bestRoute;\n                    Node moved = newRoute[i];\n                    newRoute.erase(newRoute.begin() + i);\n                    if (j > i) j--;\n                    newRoute.insert(newRoute.begin() + j, moved);\n                    if (feasibleRoute(newRoute)) {\n                        int len = routeLength(newRoute);\n                        if (len < bestLen) {\n                            bestLen = len;\n                            bestRoute = newRoute;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Output final\n    cout << K;\n    for (int id : bestSelected) cout << \" \" << id+1;\n    cout << \"\\n\";\n    cout << bestRoute.size();\n    for (const auto& node : bestRoute) {\n        cout << \" \" << node.x << \" \" << node.y;\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <queue>\n#include <tuple>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    double d;  // Euclidean distance\n    int index;\n};\n\nclass UnionFind {\npublic:\n    vector<int> parent, rank;\n    \n    UnionFind(int n) {\n        parent.resize(n);\n        rank.resize(n, 0);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int x) {\n        if (parent[x] != x)\n            parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    \n    bool unite(int x, int y) {\n        int px = find(x), py = find(y);\n        if (px == py) return false;\n        if (rank[px] < rank[py])\n            parent[px] = py;\n        else if (rank[px] > rank[py])\n            parent[py] = px;\n        else {\n            parent[py] = px;\n            rank[px]++;\n        }\n        return true;\n    }\n    \n    bool connected(int x, int y) {\n        return find(x) == find(y);\n    }\n    \n    int countComponents() {\n        int cnt = 0;\n        for (int i = 0; i < parent.size(); i++)\n            if (find(i) == i) cnt++;\n        return cnt;\n    }\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>> coords(N);\n    for (int i = 0; i < N; i++) {\n        cin >> coords[i].first >> coords[i].second;\n    }\n    \n    // Read edges\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        edges[i].index = i;\n        int dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        int dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = round(sqrt(dx*dx + dy*dy));\n    }\n    \n    // Pre-compute offline MST using d_i to understand edge importance\n    vector<int> edgeImportance(M, 2);  // 0: MST edge, 1: 2nd round, etc.\n    \n    // We'll do 5 rounds of MST extraction to label edges\n    vector<bool> used(M, false);\n    for (int round = 0; round < 5; round++) {\n        vector<pair<double, int>> remaining;\n        for (int i = 0; i < M; i++) {\n            if (!used[i]) {\n                remaining.push_back({edges[i].d, i});\n            }\n        }\n        sort(remaining.begin(), remaining.end());\n        \n        UnionFind uf(N);\n        for (auto& [d, idx] : remaining) {\n            if (uf.unite(edges[idx].u, edges[idx].v)) {\n                used[idx] = true;\n                edgeImportance[idx] = round;\n            }\n        }\n    }\n    \n    // Now process edges online\n    UnionFind uf(N);\n    vector<int> accepted;\n    int remainingEdges = M;\n    int neededEdges = N - 1;\n    int acceptedCount = 0;\n    \n    // Track how many edges of each importance level we've seen\n    vector<int> seenByImportance(5, 0);\n    vector<int> acceptedByImportance(5, 0);\n    \n    for (int i = 0; i < M; i++) {\n        int li;\n        cin >> li;\n        \n        bool accept = false;\n        int importance = edgeImportance[i];\n        seenByImportance[importance]++;\n        \n        if (uf.connected(edges[i].u, edges[i].v)) {\n            // Edge creates a cycle, reject\n            accept = false;\n        } else {\n            // Edge connects two components\n            double ratio = (double)li / edges[i].d;\n            \n            // Dynamic threshold based on importance and progress\n            double threshold;\n            if (importance == 0) {\n                // MST edges: be more lenient\n                threshold = 2.5;\n            } else if (importance == 1) {\n                threshold = 2.0;\n            } else if (importance == 2) {\n                threshold = 1.5;\n            } else {\n                threshold = 1.2;\n            }\n            \n            // Adjust threshold based on how many edges we still need\n            int componentsRemaining = 0;\n            for (int j = 0; j < N; j++) {\n                if (uf.find(j) == j) componentsRemaining++;\n            }\n            \n            if (componentsRemaining <= 10) {\n                // Desperate: accept almost anything\n                threshold = 3.0;\n            }\n            \n            // Also consider how many edges remain\n            double progressRatio = (double)(M - i - 1) / (double)(componentsRemaining - 1);\n            if (progressRatio < 2.0) {\n                // Running out of edges, be more aggressive\n                threshold = max(threshold, 2.5);\n            }\n            \n            if (ratio <= threshold) {\n                accept = true;\n            } else {\n                // Even if expensive, accept if we're running out of options\n                if (progressRatio < 1.5) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept) {\n            uf.unite(edges[i].u, edges[i].v);\n            accepted.push_back(i);\n            acceptedCount++;\n            acceptedByImportance[importance]++;\n        }\n        \n        cout << (accept ? 1 : 0) << endl;\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int TURNS = 300;\n\n// Directions\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dir_char[] = {'u', 'd', 'l', 'r'};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n    Pos(int x=0, int y=0) : x(x), y(y) {}\n    bool operator==(const Pos& o) const { return x==o.x && y==o.y; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n    bool valid() const { return x>=0 && x<GRID && y>=0 && y<GRID; }\n    Pos operator+(int d) const { return Pos(x+dx[d], y+dy[d]); }\n};\n\nstruct Pet {\n    Pos pos;\n    int type;\n};\n\n// Global state\nint N, M;\nvector<Pet> pets;\nvector<Pos> humans;\nvector<vector<bool>> impassable;\nvector<Pos> human_start;\n\n// BFS for reachable area\nint bfs_area(Pos start) {\n    vector<vector<bool>> vis(GRID, vector<bool>(GRID, false));\n    queue<Pos> q;\n    q.push(start);\n    vis[start.x][start.y] = true;\n    int area = 0;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        area++;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur + d;\n            if(nxt.valid() && !impassable[nxt.x][nxt.y] && !vis[nxt.x][nxt.y]) {\n                vis[nxt.x][nxt.y] = true;\n                q.push(nxt);\n            }\n        }\n    }\n    return area;\n}\n\n// Check if pet is adjacent to a position\nbool pet_adjacent(Pos p) {\n    for(const auto& pet : pets) {\n        if(abs(pet.pos.x - p.x) + abs(pet.pos.y - p.y) <= 1) return true;\n    }\n    return false;\n}\n\n// Check if human is at a position\nbool human_at(Pos p) {\n    for(const auto& h : humans) {\n        if(h == p) return true;\n    }\n    return false;\n}\n\n// Check if pet is at a position\nbool pet_at(Pos p) {\n    for(const auto& pet : pets) {\n        if(pet.pos == p) return true;\n    }\n    return false;\n}\n\n// Can build wall at position\nbool can_build(Pos p, int human_idx) {\n    if(!p.valid()) return false;\n    if(impassable[p.x][p.y]) return true; // already impassable\n    if(pet_at(p)) return false;\n    if(human_at(p)) return false;\n    if(pet_adjacent(p)) return false;\n    return true;\n}\n\n// Manhattan distance\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\n// Direction from a to b\nint dir_to(Pos from, Pos to) {\n    if(to.x < from.x) return 0; // up\n    if(to.x > from.x) return 1; // down\n    if(to.y < from.y) return 2; // left\n    if(to.y > from.y) return 3; // right\n    return -1;\n}\n\n// BFS path\nvector<int> find_path(Pos from, Pos to) {\n    vector<vector<int>> prev(GRID, vector<int>(GRID, -1));\n    vector<vector<int>> prev_dir(GRID, vector<int>(GRID, -1));\n    queue<Pos> q;\n    q.push(from);\n    prev[from.x][from.y] = -2;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        if(cur == to) break;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur + d;\n            if(nxt.valid() && !impassable[nxt.x][nxt.y] && prev[nxt.x][nxt.y] == -1) {\n                prev[nxt.x][nxt.y] = d;\n                prev_dir[nxt.x][nxt.y] = d;\n                q.push(nxt);\n            }\n        }\n    }\n    \n    if(prev[to.x][to.y] == -1) return {};\n    \n    vector<int> path;\n    Pos cur = to;\n    while(cur != from) {\n        int d = prev[cur.x][cur.y];\n        path.push_back(d);\n        cur = Pos(cur.x - dx[d], cur.y - dy[d]);\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    \n    // Read input\n    cin >> N;\n    pets.resize(N);\n    for(int i=0; i<N; i++) {\n        cin >> pets[i].pos.x >> pets[i].pos.y >> pets[i].type;\n        pets[i].pos.x--; pets[i].pos.y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    human_start.resize(M);\n    for(int i=0; i<M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n        human_start[i] = humans[i];\n    }\n    \n    // Initialize grid\n    impassable.assign(GRID, vector<bool>(GRID, false));\n    \n    // Strategy state\n    enum State { MOVING, BUILDING };\n    vector<State> state(M, MOVING);\n    vector<Pos> target(M);\n    vector<vector<Pos>> wall_plan(M);\n    vector<int> wall_idx(M, 0);\n    \n    // Assign targets: spread humans to different corners\n    vector<Pos> corners = {\n        Pos(0, 0), Pos(0, GRID-1), \n        Pos(GRID-1, 0), Pos(GRID-1, GRID-1),\n        Pos(0, GRID/2), Pos(GRID/2, 0),\n        Pos(GRID-1, GRID/2), Pos(GRID/2, GRID-1)\n    };\n    \n    // Assign each human to nearest unassigned corner\n    vector<bool> corner_used(corners.size(), false);\n    for(int i=0; i<M; i++) {\n        int best_c = -1;\n        int best_dist = 1e9;\n        for(int c=0; c<(int)corners.size(); c++) {\n            if(!corner_used[c]) {\n                int dist = manhattan(humans[i], corners[c]);\n                if(dist < best_dist) {\n                    best_dist = dist;\n                    best_c = c;\n                }\n            }\n        }\n        if(best_c != -1) {\n            target[i] = corners[best_c];\n            corner_used[best_c] = true;\n        }\n    }\n    \n    // Wall building plan: each human builds walls to create their region\n    // Simple plan: build walls extending from their target corner\n    for(int i=0; i<M; i++) {\n        Pos tgt = target[i];\n        // Build walls to create a rectangular area around their starting position\n        // For simplicity, build a wall along two edges from the corner\n        \n        if(tgt.x == 0 && tgt.y == 0) {\n            // Top-left corner: build right and down\n            for(int y=tgt.y; y<GRID; y++) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x+1; x<GRID; x++) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == 0 && tgt.y == GRID-1) {\n            // Top-right corner\n            for(int y=tgt.y; y>=0; y--) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x+1; x<GRID; x++) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == GRID-1 && tgt.y == 0) {\n            // Bottom-left corner\n            for(int y=tgt.y; y<GRID; y++) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x-1; x>=0; x--) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == GRID-1 && tgt.y == GRID-1) {\n            // Bottom-right corner\n            for(int y=tgt.y; y>=0; y--) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x-1; x>=0; x--) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else {\n            // Other positions - build a small enclosure\n            wall_plan[i].push_back(tgt);\n        }\n    }\n    \n    // Main game loop\n    for(int turn = 0; turn < TURNS; turn++) {\n        string actions(M, '.');\n        \n        for(int i=0; i<M; i++) {\n            if(state[i] == MOVING) {\n                // Move toward target\n                if(humans[i] == target[i]) {\n                    state[i] = BUILDING;\n                    wall_idx[i] = 0;\n                } else {\n                    auto path = find_path(humans[i], target[i]);\n                    if(!path.empty()) {\n                        int d = path[0];\n                        Pos next_pos = humans[i] + d;\n                        bool blocked = false;\n                        // Check if any other human is building there\n                        // (simplified check)\n                        actions[i] = move_char[d];\n                    } else {\n                        // Path blocked, try to build walls\n                        state[i] = BUILDING;\n                        wall_idx[i] = 0;\n                    }\n                }\n            }\n            \n            if(state[i] == BUILDING) {\n                if(wall_idx[i] < (int)wall_plan[i].size()) {\n                    Pos build_pos = wall_plan[i][wall_idx[i]];\n                    // Check if we can build here\n                    if(can_build(build_pos, i)) {\n                        int d = dir_to(humans[i], build_pos);\n                        if(d != -1 && manhattan(humans[i], build_pos) == 1) {\n                            actions[i] = dir_char[d];\n                            wall_idx[i]++;\n                        } else {\n                            // Need to move closer\n                            auto path = find_path(humans[i], build_pos);\n                            if(!path.empty() && path.size() == 1) {\n                                actions[i] = dir_char[path[0]];\n                                wall_idx[i]++;\n                            } else if(!path.empty()) {\n                                actions[i] = move_char[path[0]];\n                            }\n                        }\n                    } else {\n                        // Can't build here, skip this wall segment\n                        wall_idx[i]++;\n                    }\n                } else {\n                    // Done building, stay\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        // Output actions\n        cout << actions << endl;\n        cout.flush();\n        \n        // Read pet movements\n        for(int i=0; i<N; i++) {\n            string movement;\n            cin >> movement;\n            if(movement != \".\") {\n                for(char m : movement) {\n                    if(m == 'U') pets[i].pos.x--;\n                    else if(m == 'D') pets[i].pos.x++;\n                    else if(m == 'L') pets[i].pos.y--;\n                    else if(m == 'R') pets[i].pos.y++;\n                }\n            }\n        }\n        \n        // Update human positions and grid\n        for(int i=0; i<M; i++) {\n            char act = actions[i];\n            if(act == 'U') humans[i].x--;\n            else if(act == 'D') humans[i].x++;\n            else if(act == 'L') humans[i].y--;\n            else if(act == 'R') humans[i].y++;\n            else if(act == 'u') impassable[humans[i].x-1][humans[i].y] = true;\n            else if(act == 'd') impassable[humans[i].x+1][humans[i].y] = true;\n            else if(act == 'l') impassable[humans[i].x][humans[i].y-1] = true;\n            else if(act == 'r') impassable[humans[i].x][humans[i].y+1] = true;\n        }\n        \n        // Emergency: if human is trapped with many pets nearby, try to escape\n        // (simplified: just continue with plan)\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), v(19);\n    for (int i = 0; i < 20; i++) cin >> h[i];\n    for (int i = 0; i < 19; i++) cin >> v[i];\n    \n    // BFS to find shortest path\n    vector<vector<int>> dist(20, vector<int>(20, -1));\n    vector<vector<pair<int,int>>> prev(20, vector<pair<int,int>>(20, {-1,-1}));\n    vector<vector<char>> moveTo(20, vector<char>(20, ' '));\n    \n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\n    \n    int di[] = {-1, 1, 0, 0};\n    int dj[] = {0, 0, -1, 1};\n    char dir[] = {'U', 'D', 'L', 'R'};\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 + di[d], nj = j + dj[d];\n            if (ni < 0 || ni >= 20 || nj < 0 || nj >= 20) continue;\n            if (d == 0 && i > 0 && v[i-1][j] == '1') continue; // U\n            if (d == 1 && i < 19 && v[i][j] == '1') continue;  // D\n            if (d == 2 && j > 0 && h[i][j-1] == '1') continue; // L\n            if (d == 3 && j < 19 && h[i][j] == '1') continue;  // R\n            if (dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                prev[ni][nj] = {i, j};\n                moveTo[ni][nj] = dir[d];\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    // Reconstruct path directions\n    string path;\n    int ci = ti, cj = tj;\n    while (ci != si || cj != sj) {\n        path.push_back(moveTo[ci][cj]);\n        auto [pi, pj] = prev[ci][cj];\n        ci = pi; cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    \n    // Determine repetition factor\n    int base_len = path.size();\n    int max_len = 200;\n    int repeat = max_len / base_len;\n    if (repeat < 1) repeat = 1;\n    if (repeat > 5) repeat = 5; // reasonable upper bound\n    \n    // Build output\n    string ans;\n    for (char c : path) {\n        for (int r = 0; r < repeat; r++) {\n            if ((int)ans.size() >= max_len) break;\n            ans.push_back(c);\n        }\n        if ((int)ans.size() >= max_len) break;\n    }\n    \n    // If still under 200, we can pad with safe moves that don't hurt\n    // Actually, padding might reduce score, so better to leave as is.\n    \n    cout << ans << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 30;\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\nconst int to[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1}\n};\n\nint tile_type[N][N];\nint rot[N][N]; // 0..3\n\nint get_exit(int type, int rot, int dir) {\n    if (to[type][dir] == -1) return -1;\n    return (to[type][dir] + rot) % 4;\n}\n\nint edge_id[N][N][4]; // node index for each edge of each tile\nint node_count = 0;\n\nvector<int> graph[3600]; // max N*N*4 = 3600\nint adj_edge[3600]; // each node has at most one neighbor (degree <= 2 in cycle graph)\n\nvoid build_graph() {\n    node_count = 0;\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                edge_id[i][j][d] = node_count++;\n    for (int i = 0; i < node_count; i++) graph[i].clear();\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 exit_dir = get_exit(tile_type[i][j], rot[i][j], d);\n                if (exit_dir == -1) continue;\n                int ni = i + di[exit_dir];\n                int nj = j + dj[exit_dir];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nd = (exit_dir + 2) % 4;\n                int exit2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                if (exit2 == d) {\n                    int u = edge_id[i][j][d];\n                    int v = edge_id[ni][nj][exit_dir];\n                    graph[u].push_back(v);\n                }\n            }\n        }\n    }\n}\n\nbool vis[3600];\nint comp[3600];\nint comp_len[3600];\nint comp_count = 0;\n\nvoid find_cycles() {\n    fill(vis, vis + node_count, false);\n    comp_count = 0;\n    for (int i = 0; i < node_count; i++) {\n        if (vis[i]) continue;\n        if (graph[i].empty()) { vis[i] = true; continue; }\n        // follow the cycle/path\n        vector<int> nodes;\n        int cur = i;\n        while (!vis[cur]) {\n            vis[cur] = true;\n            nodes.push_back(cur);\n            if (graph[cur].empty()) break;\n            int nxt = graph[cur][0];\n            if (vis[nxt]) break;\n            cur = nxt;\n        }\n        if (graph[nodes.back()].empty()) {\n            for (int x : nodes) comp[x] = -1; // path\n        } else if (graph[nodes.back()][0] == nodes[0]) {\n            // cycle\n            int len = nodes.size();\n            for (int x : nodes) comp[x] = comp_count;\n            comp_len[comp_count] = len;\n            comp_count++;\n        } else {\n            for (int x : nodes) comp[x] = -1; // dead end\n        }\n    }\n}\n\nint get_score() {\n    build_graph();\n    find_cycles();\n    vector<int> lengths;\n    for (int c = 0; c < comp_count; c++) lengths.push_back(comp_len[c]);\n    sort(lengths.rbegin(), lengths.rend());\n    if (lengths.size() < 2) return 0;\n    return lengths[0] * lengths[1];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = high_resolution_clock::now();\n\n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++) {\n            tile_type[i][j] = s[j] - '0';\n        }\n    }\n\n    // initial random rotations\n    mt19937 rng(42);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            rot[i][j] = rng() % 4;\n\n    int best_score = get_score();\n    int cur_score = best_score;\n    int best_rot[N][N];\n    memcpy(best_rot, rot, sizeof(rot));\n\n    double temp_start = 100.0, temp_end = 0.1;\n    int iterations = 0;\n    const int max_iter = 500000;\n\n    uniform_real_distribution<> prob(0, 1);\n    uniform_int_distribution<> pos(0, N-1);\n    uniform_int_distribution<> rrot(1, 3);\n\n    while (true) {\n        auto now = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(now - start_time).count() > 1900) break;\n        if (iterations >= max_iter) break;\n        iterations++;\n\n        int i = pos(rng);\n        int j = pos(rng);\n        int old_r = rot[i][j];\n        int new_r = (old_r + rrot(rng)) % 4;\n        rot[i][j] = new_r;\n        int new_score = get_score();\n\n        if (new_score > best_score) {\n            best_score = new_score;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n\n        if (new_score >= cur_score) {\n            cur_score = new_score;\n        } else {\n            double t = temp_start * pow(temp_end / temp_start, (double)iterations / max_iter);\n            double p = exp((new_score - cur_score) / t);\n            if (prob(rng) < p) {\n                cur_score = new_score;\n            } else {\n                rot[i][j] = old_r;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cout << best_rot[i][j];\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 10;\nint N, T;\nvector<string> board;\nint empty_r, empty_c;\n\n// Directions: L=0, U=1, R=2, D=3\nconst int dr[] = {0, -1, 0, 1};\nconst int dc[] = {-1, 0, 1, 0};\nconst char dir_char[] = {'L', 'U', 'R', 'D'};\nconst int opposite[] = {2, 3, 0, 1};\nconst int bit[] = {1, 2, 4, 8}; // L, U, R, D\n\nstring moves;\n\nbool in_board(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nvoid apply_move(int dir) {\n    int nr = empty_r + dr[dir];\n    int nc = empty_c + dc[dir];\n    if (!in_board(nr, nc)) return;\n    swap(board[empty_r][empty_c], board[nr][nc]);\n    empty_r = nr;\n    empty_c = nc;\n    moves += dir_char[dir];\n}\n\n// BFS to find path for empty square\nvector<int> find_path(int target_r, int target_c) {\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<int>> prev(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.push({empty_r, empty_c});\n    dist[empty_r][empty_c] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        if (r == target_r && c == target_c) break;\n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            if (in_board(nr, nc) && dist[nr][nc] == -1) {\n                dist[nr][nc] = dist[r][c] + 1;\n                prev[nr][nc] = d;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    vector<int> path;\n    int r = target_r, c = target_c;\n    while (r != empty_r || c != empty_c) {\n        int d = prev[r][c];\n        path.push_back(d);\n        r -= dr[d];\n        c -= dc[d];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Move empty to target position\nvoid move_empty_to(int tr, int tc) {\n    if (empty_r == tr && empty_c == tc) return;\n    vector<int> path = find_path(tr, tc);\n    for (int d : path) {\n        apply_move(d);\n    }\n}\n\n// Check if tile at (r,c) has a line in direction d\nbool has_line(char tile, int d) {\n    int val = (tile >= 'a' && tile <= 'f') ? (tile - 'a' + 10) : (tile - '0');\n    return (val & bit[d]) != 0;\n}\n\n// Set line in direction d on tile\nchar set_line(char tile, int d, bool on) {\n    int val = (tile >= 'a' && tile <= 'f') ? (tile - 'a' + 10) : (tile - '0');\n    if (on) val |= bit[d];\n    else val &= ~bit[d];\n    if (val < 10) return '0' + val;\n    return 'a' + (val - 10);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0') {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    // Target: snake spanning tree\n    // We'll create a target pattern where all tiles are connected in a snake pattern\n    vector<vector<char>> target(N, vector<char>(N, '0'));\n    vector<pair<int,int>> order;\n    \n    // Build snake pattern: go right, then down, then left, then down, etc.\n    for (int i = 0; i < N; i++) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; j++) {\n                if (i == N-1 && j == N-1) continue; // last cell is empty\n                order.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (i == N-1 && j == N-1) continue;\n                order.push_back({i, j});\n            }\n        }\n    }\n    \n    // Design target connections\n    for (int idx = 0; idx < (int)order.size() - 1; idx++) {\n        auto [r1, c1] = order[idx];\n        auto [r2, c2] = order[idx + 1];\n        \n        if (r1 == r2 && c1 + 1 == c2) {\n            // r1,c1 -> right to r2,c2\n            target[r1][c1] = set_line(target[r1][c1], 2, true); // right\n            target[r2][c2] = set_line(target[r2][c2], 0, true); // left\n        } else if (r1 == r2 && c1 - 1 == c2) {\n            target[r1][c1] = set_line(target[r1][c1], 0, true); // left\n            target[r2][c2] = set_line(target[r2][c2], 2, true); // right\n        } else if (r1 + 1 == r2 && c1 == c2) {\n            target[r1][c1] = set_line(target[r1][c1], 3, true); // down\n            target[r2][c2] = set_line(target[r2][c2], 1, true); // up\n        } else if (r1 - 1 == r2 && c1 == c2) {\n            target[r1][c1] = set_line(target[r1][c1], 1, true); // up\n            target[r2][c2] = set_line(target[r2][c2], 3, true); // down\n        }\n    }\n    \n    // Target empty at (N-1, N-1)\n    int target_empty_r = N-1, target_empty_c = N-1;\n    target[target_empty_r][target_empty_c] = '0';\n    \n    // Greedy assembly: work from top-left to bottom-right\n    // Fix tiles that are out of place\n    auto start_time = chrono::steady_clock::now();\n    \n    for (int i = 0; i < N && moves.length() < T; i++) {\n        for (int j = 0; j < N && moves.length() < T; j++) {\n            if (i == target_empty_r && j == target_empty_c) continue;\n            \n            if (board[i][j] != target[i][j]) {\n                // Find the target tile somewhere else\n                int found_r = -1, found_c = -1;\n                for (int r = 0; r < N; r++) {\n                    for (int c = 0; c < N; c++) {\n                        if (board[r][c] == target[i][j]) {\n                            found_r = r;\n                            found_c = c;\n                            goto found;\n                        }\n                    }\n                }\n                found:\n                \n                if (found_r == -1) continue; // tile not found (unlikely)\n                \n                // Move empty to the tile we want to move\n                move_empty_to(found_r, found_c);\n                if (moves.length() >= T) break;\n                \n                // Now find a path to bring the tile to (i,j)\n                // We'll do this by moving the tile step by step\n                int cr = found_r, cc = found_c;\n                \n                // Simple approach: move tile towards target\n                while ((cr != i || cc != j) && moves.length() < T) {\n                    // Check time\n                    auto now = chrono::steady_clock::now();\n                    auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n                    if (elapsed > 2500) {\n                        cout << moves << endl;\n                        return 0;\n                    }\n                    \n                    if (cr < i) {\n                        // Need to move down\n                        // Empty should be below the tile\n                        if (empty_r == cr && empty_c == cc) {\n                            apply_move(3); // move tile down\n                            cr++;\n                        } else if (in_board(cr+1, cc)) {\n                            move_empty_to(cr+1, cc);\n                            if (moves.length() >= T) break;\n                        } else {\n                            // Can't move down directly, move empty around\n                            break;\n                        }\n                    } else if (cr > i) {\n                        if (empty_r == cr && empty_c == cc) {\n                            apply_move(1); // move tile up\n                            cr--;\n                        } else if (in_board(cr-1, cc)) {\n                            move_empty_to(cr-1, cc);\n                            if (moves.length() >= T) break;\n                        } else {\n                            break;\n                        }\n                    } else if (cc < j) {\n                        if (empty_r == cr && empty_c == cc) {\n                            apply_move(2); // move tile right\n                            cc++;\n                        } else if (in_board(cr, cc+1)) {\n                            move_empty_to(cr, cc+1);\n                            if (moves.length() >= T) break;\n                        } else {\n                            break;\n                        }\n                    } else if (cc > j) {\n                        if (empty_r == cr && empty_c == cc) {\n                            apply_move(0); // move tile left\n                            cc--;\n                        } else if (in_board(cr, cc-1)) {\n                            move_empty_to(cr, cc-1);\n                            if (moves.length() >= T) break;\n                        } else {\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // If we have remaining moves, try to optimize\n    // Move empty to (N-1, N-1) if possible\n    if (moves.length() < T) {\n        move_empty_to(target_empty_r, target_empty_c);\n    }\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n    Point(long long x = 0, long long y = 0) : x(x), y(y) {}\n    \n    Point operator-(const Point& other) const {\n        return Point(x - other.x, y - other.y);\n    }\n    \n    long long dot(const Point& other) const {\n        return x * other.x + y * other.y;\n    }\n    \n    long long cross(const Point& other) const {\n        return x * other.y - y * other.x;\n    }\n    \n    long long dist2() const {\n        return x * x + y * y;\n    }\n    \n    double dist() const {\n        return sqrt(dist2());\n    }\n    \n    double angle() const {\n        return atan2(y, x);\n    }\n    \n    bool operator<(const Point& other) const {\n        return angle() < other.angle();\n    }\n};\n\nstruct Strawberry {\n    double x, y;\n    int id;\n    Strawberry(double x = 0, double y = 0, int id = 0) : x(x), y(y), id(id) {}\n};\n\n// Generate a line that separates two points\npair<pair<long long, long long>, pair<long long, long long>> \nseparatingLine(const Point& p1, const Point& p2) {\n    // Midpoint\n    double mx = (p1.x + p2.x) / 2.0;\n    double my = (p1.y + p2.y) / 2.0;\n    \n    // Direction perpendicular to the line connecting p1 and p2\n    double dx = p2.y - p1.y;\n    double dy = p1.x - p2.x;\n    \n    // Scale to get integer coordinates within range\n    double scale = 1e9 / max(abs(dx), abs(dy));\n    dx *= scale;\n    dy *= scale;\n    \n    long long px = (long long)(mx - dx);\n    long long py = (long long)(my - dy);\n    long long qx = (long long)(mx + dx);\n    long long qy = (long long)(my + dy);\n    \n    // Clamp to valid range\n    auto clamp = [](long long& v) {\n        v = max(-1000000000LL, min(1000000000LL, v));\n    };\n    clamp(px); clamp(py); clamp(qx); clamp(qy);\n    \n    return {{px, py}, {qx, qy}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(10);\n    for (int i = 0; i < 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Strategy: Use angular partitioning + some additional cuts\n    vector<pair<double, int>> angles;\n    for (int i = 0; i < N; i++) {\n        angles.push_back({atan2(strawberries[i].y, strawberries[i].x), i});\n    }\n    sort(angles.begin(), angles.end());\n    \n    vector<pair<pair<long long, long long>, pair<long long, long long>>> lines;\n    \n    // Create pie-slice cuts from center\n    int num_cuts = min(K, N);\n    \n    // Try to make cuts that separate groups of strawberries\n    // Use lines through origin at specific angles\n    for (int i = 0; i < num_cuts; i++) {\n        double angle1 = 2.0 * M_PI * i / num_cuts;\n        double angle2 = angle1 + M_PI;\n        \n        long long x1 = (long long)(1000000000.0 * cos(angle1));\n        long long y1 = (long long)(1000000000.0 * sin(angle1));\n        long long x2 = (long long)(1000000000.0 * cos(angle2));\n        long long y2 = (long long)(1000000000.0 * sin(angle2));\n        \n        // Ensure points are distinct\n        if (abs(x1 - x2) < 2 && abs(y1 - y2) < 2) {\n            x2 = -x1;\n            y2 = -y1;\n        }\n        \n        lines.push_back({{x1, y1}, {x2, y2}});\n    }\n    \n    // Add some grid-like cuts to better isolate strawberries\n    int remaining_cuts = K - num_cuts;\n    if (remaining_cuts > 0) {\n        // Add horizontal and vertical cuts\n        for (int i = 0; i < min(remaining_cuts / 2, 20); i++) {\n            long long offset = (long long)((i + 1) * 5000);\n            // Horizontal line\n            lines.push_back({{-1000000000, offset}, {1000000000, offset}});\n            if (lines.size() >= K) break;\n            // Vertical line\n            lines.push_back({{offset, -1000000000}, {offset, 1000000000}});\n            if (lines.size() >= K) break;\n        }\n    }\n    \n    // Also add some diagonal cuts for better separation\n    remaining_cuts = K - lines.size();\n    if (remaining_cuts > 0) {\n        for (int i = 0; i < min(remaining_cuts, 10); i++) {\n            long long offset = (long long)((i + 1) * 3000);\n            lines.push_back({{-1000000000, -1000000000 + offset * 2}, \n                           {1000000000 - offset * 2, 1000000000}});\n        }\n    }\n    \n    // Ensure we don't exceed K\n    if (lines.size() > K) {\n        lines.resize(K);\n    }\n    \n    // Output\n    cout << lines.size() << '\\n';\n    for (const auto& line : lines) {\n        cout << line.first.first << ' ' << line.first.second << ' '\n             << line.second.first << ' ' << line.second.second << '\\n';\n    }\n    \n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing P = pair<int, int>;\n\nconst int MAX_N = 65;\n\nint N, M;\nvector<P> initial_dots;\nset<P> dot_set;\nset<array<P, 4>> used_segments; // unordered set of segment endpoints pairs\nvector<array<P, 4>> operations;\nll weight_sum = 0;\nll total_weight_sum = 0;\n\nll weight(int x, int y) {\n    int c = (N - 1) / 2;\n    return (ll)(x - c) * (x - c) + (ll)(y - c) * (y - c) + 1;\n}\n\nbool in_grid(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\nvoid add_segment(P a, P b) {\n    if (a > b) swap(a, b);\n    used_segments.insert({a, b, {0,0}, {0,0}}); // dummy\n}\n\nbool has_segment(P a, P b) {\n    if (a > b) swap(a, b);\n    return used_segments.count({a, b, {0,0}, {0,0}});\n}\n\nbool dot_exists(int x, int y) {\n    return dot_set.count({x, y});\n}\n\n// Check if line from p to q has no dots except endpoints (and the 3 known dots)\nbool clear_path(P p, P q, const set<P> &allowed) {\n    int dx = q.first - p.first;\n    int dy = q.second - p.second;\n    int g = gcd(abs(dx), abs(dy));\n    int stepx = dx / g;\n    int stepy = dy / g;\n    for (int i = 1; i < g; ++i) {\n        int cx = p.first + i * stepx;\n        int cy = p.second + i * stepy;\n        if (dot_exists(cx, cy) && !allowed.count({cx, cy}))\n            return false;\n    }\n    return true;\n}\n\nbool rect_valid(P p1, P p2, P p3, P p4) {\n    // p1 is new dot (no dot), p2,p3,p4 have dots\n    if (dot_exists(p1.first, p1.second)) return false;\n    if (!dot_exists(p2.first, p2.second)) return false;\n    if (!dot_exists(p3.first, p3.second)) return false;\n    if (!dot_exists(p4.first, p4.second)) return false;\n\n    set<P> allowed = {p2, p3, p4};\n    // check all edges\n    vector<pair<P,P>> edges = {{p1,p2},{p2,p3},{p3,p4},{p4,p1}};\n    for (auto &e : edges) {\n        if (!clear_path(e.first, e.second, allowed)) return false;\n        if (has_segment(e.first, e.second)) 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    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        initial_dots.push_back({x, y});\n        dot_set.insert({x, y});\n        weight_sum += weight(x, y);\n    }\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y < N; ++y)\n            total_weight_sum += weight(x, y);\n\n    // Precompute all possible rectangles (axis-aligned and 45-degree)\n    vector<array<P,4>> candidates;\n    int c = (N - 1) / 2;\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            if (dot_exists(x, y)) continue;\n            // axis-aligned\n            for (int dx = 1; dx < N; ++dx) {\n                for (int dy = 1; dy < N; ++dy) {\n                    vector<array<P,4>> rects = {\n                        {{{x,y},{x+dx,y},{x+dx,y+dy},{x,y+dy}}},\n                        {{{x,y},{x,y+dy},{x+dx,y+dy},{x+dx,y}}},\n                        {{{x,y},{x-dx,y},{x-dx,y-dy},{x,y-dy}}},\n                        {{{x,y},{x,y-dy},{x-dx,y-dy},{x-dx,y}}}\n                    };\n                    for (auto &r : rects) {\n                        bool ok = true;\n                        for (auto &p : r) if (!in_grid(p.first, p.second)) ok = false;\n                        if (ok) candidates.push_back(r);\n                    }\n                }\n            }\n            // 45-degree rotated\n            for (int d = 1; d < N; ++d) {\n                vector<array<P,4>> diag = {\n                    {{{x,y},{x+d,y+d},{x+d+d, y},{x+d, y-d}}},\n                    {{{x,y},{x+d,y-d},{x,y-d-d},{x-d,y-d}}},\n                    {{{x,y},{x-d,y-d},{x-d-d,y},{x-d,y+d}}},\n                    {{{x,y},{x-d,y+d},{x,y+d+d},{x+d,y+d}}}\n                };\n                for (auto &r : diag) {\n                    bool ok = true;\n                    for (auto &p : r) if (!in_grid(p.first, p.second)) ok = false;\n                    if (ok) candidates.push_back(r);\n                }\n            }\n        }\n    }\n\n    // Greedy loop\n    while (true) {\n        array<P,4> best_move;\n        ll best_gain = -1;\n        for (auto &r : candidates) {\n            if (rect_valid(r[0], r[1], r[2], r[3])) {\n                ll gain = weight(r[0].first, r[0].second);\n                if (gain > best_gain) {\n                    best_gain = gain;\n                    best_move = r;\n                }\n            }\n        }\n        if (best_gain == -1) break;\n\n        // perform move\n        operations.push_back(best_move);\n        dot_set.insert(best_move[0]);\n        weight_sum += best_gain;\n        add_segment(best_move[0], best_move[1]);\n        add_segment(best_move[1], best_move[2]);\n        add_segment(best_move[2], best_move[3]);\n        add_segment(best_move[3], best_move[0]);\n    }\n\n    // output\n    cout << operations.size() << \"\\n\";\n    for (auto &op : operations) {\n        for (int i = 0; i < 4; ++i) {\n            cout << op[i].first << \" \" << op[i].second << (i == 3 ? \"\\n\" : \" \");\n        }\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\nint grid[N][N];\nint flavor[100];\n\nint dx[4] = {0, 0, -1, 1}; // L, R, F, B\nint dy[4] = {-1, 1, 0, 0};\nchar dirs[4] = {'L', 'R', 'F', 'B'};\n\nvoid tilt(int d) {\n    if (d == 0) { // L\n        for (int i = 0; i < N; i++) {\n            int pos = 0;\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0) {\n                    grid[i][pos++] = grid[i][j];\n                }\n            }\n            while (pos < N) grid[i][pos++] = 0;\n        }\n    } else if (d == 1) { // R\n        for (int i = 0; i < N; i++) {\n            int pos = N-1;\n            for (int j = N-1; j >= 0; j--) {\n                if (grid[i][j] != 0) {\n                    grid[i][pos--] = grid[i][j];\n                }\n            }\n            while (pos >= 0) grid[i][pos--] = 0;\n        }\n    } else if (d == 2) { // F (up)\n        for (int j = 0; j < N; j++) {\n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                if (grid[i][j] != 0) {\n                    grid[pos++][j] = grid[i][j];\n                }\n            }\n            while (pos < N) grid[pos++][j] = 0;\n        }\n    } else if (d == 3) { // B (down)\n        for (int j = 0; j < N; j++) {\n            int pos = N-1;\n            for (int i = N-1; i >= 0; i--) {\n                if (grid[i][j] != 0) {\n                    grid[pos--][j] = grid[i][j];\n                }\n            }\n            while (pos >= 0) grid[pos--][j] = 0;\n        }\n    }\n}\n\nint64_t eval() {\n    bool vis[N][N] = {false};\n    int64_t sum_sq = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != 0 && !vis[i][j]) {\n                int flav = 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 k = 0; k < 4; k++) {\n                        int nx = x + dx[k], ny = y + dy[k];\n                        if (nx >= 0 && nx < N && ny >= 0 && ny < N &&\n                            !vis[nx][ny] && grid[nx][ny] == flav) {\n                            vis[nx][ny] = true;\n                            q.push({nx,ny});\n                        }\n                    }\n                }\n                sum_sq += 1LL * cnt * cnt;\n            }\n        }\n    }\n    return sum_sq;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < 100; i++) {\n        cin >> flavor[i];\n    }\n    \n    memset(grid, 0, sizeof(grid));\n    \n    int empty_count = 100;\n    \n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        // find p-th empty cell\n        int placed = 0;\n        int r, c;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    placed++;\n                    if (placed == p) {\n                        r = i; c = j;\n                    }\n                }\n            }\n        }\n        grid[r][c] = flavor[t];\n        \n        // save grid\n        int old_grid[N][N];\n        memcpy(old_grid, grid, sizeof(grid));\n        \n        int64_t best_score = -1;\n        int best_dir = 0;\n        \n        for (int d = 0; d < 4; d++) {\n            memcpy(grid, old_grid, sizeof(grid));\n            tilt(d);\n            int64_t score = eval();\n            if (score > best_score) {\n                best_score = score;\n                best_dir = d;\n            }\n        }\n        \n        memcpy(grid, old_grid, sizeof(grid));\n        tilt(best_dir);\n        cout << dirs[best_dir] << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Compute degree sequence from graph string\nvector<int> get_degrees(const string& g, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute feature vector for a graph\nvector<double> compute_features(const string& g, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    int edges = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n                edges++;\n            }\n            idx++;\n        }\n    }\n    \n    // Feature 1: Number of edges (normalized)\n    double max_edges = N * (N - 1) / 2.0;\n    double edge_ratio = edges / max_edges;\n    \n    // Feature 2: Degree statistics\n    sort(deg.begin(), deg.end());\n    double mean_deg = 0, var_deg = 0;\n    for (int d : deg) mean_deg += d;\n    mean_deg /= N;\n    for (int d : deg) var_deg += (d - mean_deg) * (d - mean_deg);\n    var_deg /= N;\n    \n    // Feature 3: Degree distribution quantiles\n    vector<double> features;\n    features.push_back(edge_ratio);\n    features.push_back(mean_deg / (N - 1));\n    features.push_back(sqrt(var_deg) / (N - 1));\n    \n    // Quantiles of degree distribution\n    for (int p : {10, 25, 50, 75, 90}) {\n        features.push_back(deg[min(N-1, N * p / 100)] / (double)(N - 1));\n    }\n    \n    return features;\n}\n\n// Generate a graph with specified edge probability\nstring generate_random_graph(int N, double p) {\n    string g;\n    int m = N * (N - 1) / 2;\n    uniform_real_distribution<> dis(0.0, 1.0);\n    for (int i = 0; i < m; i++) {\n        g += (dis(rng) < p) ? '1' : '0';\n    }\n    return g;\n}\n\n// Generate M distinctive graphs\nvector<string> generate_graphs(int N, int M, double eps) {\n    vector<string> graphs;\n    set<string> used;\n    \n    // Strategy: Generate graphs with different edge densities\n    // Use multiple rounds to ensure diversity\n    double base_p = 0.1;\n    double step = 0.8 / max(1, M - 1);\n    \n    for (int k = 0; k < M; k++) {\n        double p = base_p + k * step;\n        p = min(0.9, max(0.05, p));\n        \n        string best_g;\n        double best_dist = -1;\n        \n        // Try multiple times to get well-separated features\n        for (int trial = 0; trial < 20; trial++) {\n            string g = generate_random_graph(N, p);\n            if (used.count(g)) continue;\n            \n            auto feat = compute_features(g, N);\n            \n            // Calculate minimum distance to existing graphs\n            double min_dist = 1e9;\n            for (const auto& existing : graphs) {\n                auto feat2 = compute_features(existing, N);\n                double dist = 0;\n                for (size_t i = 0; i < feat.size(); i++) {\n                    dist += (feat[i] - feat2[i]) * (feat[i] - feat2[i]);\n                }\n                min_dist = min(min_dist, sqrt(dist));\n            }\n            \n            if (graphs.empty() || min_dist > best_dist) {\n                best_dist = min_dist;\n                best_g = g;\n            }\n        }\n        \n        if (best_dist < 0) {\n            best_g = generate_random_graph(N, p);\n        }\n        \n        graphs.push_back(best_g);\n        used.insert(best_g);\n    }\n    \n    return graphs;\n}\n\n// Predict which original graph generated H\nint predict(const string& H, const vector<string>& graphs, int N, double eps) {\n    auto feat_H = compute_features(H, N);\n    \n    int best_idx = 0;\n    double best_score = -1e9;\n    \n    // Calculate expected noise variance\n    double noise_std = sqrt(eps * (1 - eps));\n    \n    for (int k = 0; k < (int)graphs.size(); k++) {\n        auto feat_G = compute_features(graphs[k], N);\n        \n        // Compute weighted distance\n        double score = 0;\n        for (size_t i = 0; i < feat_H.size(); i++) {\n            double diff = feat_H[i] - feat_G[i];\n            // Weight by feature importance and noise sensitivity\n            double weight = 1.0;\n            if (i == 0) weight = 5.0;  // Edge ratio is very informative\n            score -= weight * diff * diff / (noise_std * noise_std + 0.01);\n        }\n        \n        if (score > best_score) {\n            best_score = score;\n            best_idx = k;\n        }\n    }\n    \n    return best_idx;\n}\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 N based on M and eps\n    // Smaller N for easier cases, larger N for harder cases\n    int N;\n    if (eps <= 0.05 && M <= 30) {\n        N = max(10, min(20, M + 5));\n    } else if (eps <= 0.15 && M <= 50) {\n        N = max(15, min(40, M + 10));\n    } else if (eps <= 0.25) {\n        N = max(20, min(60, M * 2 / 3 + 20));\n    } else {\n        N = max(30, min(80, M + 20));\n    }\n    N = min(N, 100);\n    N = max(N, 4);\n    \n    // Generate graphs\n    auto graphs = generate_graphs(N, M, eps);\n    \n    // Output graphs\n    cout << N << endl;\n    for (const auto& g : graphs) {\n        cout << g << endl;\n    }\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n        \n        int t = predict(H, graphs, N, eps);\n        cout << t << endl;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Edge structure\nstruct Edge {\n    int u, v, w, id;\n};\n\n// Timer for time management\nchrono::steady_clock::time_point start_time;\n\nbool time_left() {\n    auto now = chrono::steady_clock::now();\n    auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n    return elapsed < 5500; // 5.5 seconds margin\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::steady_clock::now();\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>>> adj(N);\n    \n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        adj[edges[i].u].push_back({edges[i].v, i});\n        adj[edges[i].v].push_back({edges[i].u, i});\n    }\n    \n    // Read coordinates (we don't really need them)\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n    }\n    \n    // Compute all-pairs shortest paths in original graph\n    const long long INF = 1e18;\n    vector<vector<long long>> orig_dist(N, vector<long long>(N, INF));\n    \n    for (int src = 0; src < N; src++) {\n        orig_dist[src][src] = 0;\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != orig_dist[src][u]) continue;\n            \n            for (auto [v, eid] : adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < orig_dist[src][v]) {\n                    orig_dist[src][v] = nd;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n    \n    // Compute edge importance: for each edge, count how many shortest paths use it\n    // Approximation: sample pairs\n    vector<double> edge_importance(M, 0.0);\n    \n    // Use betweenness centrality approximation\n    int samples = min(200, N);\n    vector<int> sample_nodes;\n    for (int i = 0; i < samples; i++) {\n        sample_nodes.push_back((i * N) / samples);\n    }\n    \n    for (int src : sample_nodes) {\n        vector<long long> dist(N, INF);\n        vector<int> parent_count(N, 0);\n        vector<vector<int>> parents(N);\n        \n        dist[src] = 0;\n        parent_count[src] = 1;\n        \n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            \n            for (auto [v, eid] : adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent_count[v] = parent_count[u];\n                    parents[v] = {eid};\n                    pq.push({nd, v});\n                } else if (nd == dist[v]) {\n                    parent_count[v] += parent_count[u];\n                    parents[v].push_back(eid);\n                }\n            }\n        }\n        \n        // Backward propagation\n        vector<double> node_score(N, 1.0);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return dist[a] > dist[b];\n        });\n        \n        for (int u : order) {\n            if (dist[u] >= INF) continue;\n            for (int eid : parents[u]) {\n                int v = (edges[eid].u == u) ? edges[eid].v : edges[eid].u;\n                double contrib = node_score[u] * (double)parent_count[v] / parent_count[u];\n                edge_importance[eid] += contrib;\n                node_score[v] += contrib;\n            }\n        }\n    }\n    \n    // Normalize importance\n    double max_imp = 0;\n    for (double imp : edge_importance) max_imp = max(max_imp, imp);\n    if (max_imp > 0) {\n        for (auto& imp : edge_importance) imp /= max_imp;\n    }\n    \n    // Greedy assignment\n    vector<int> assignment(M, -1);\n    vector<int> day_count(D, 0);\n    vector<vector<bool>> day_removed(D, vector<bool>(M, false));\n    \n    // Sort edges by importance (most important first)\n    vector<pair<double,int>> edge_order;\n    for (int i = 0; i < M; i++) {\n        edge_order.push_back({edge_importance[i], i});\n    }\n    sort(edge_order.rbegin(), edge_order.rend());\n    \n    // Assign edges greedily\n    for (auto [imp, eid] : edge_order) {\n        // Find best day for this edge\n        int best_day = -1;\n        double best_score = -1e18;\n        \n        for (int d = 0; d < D; d++) {\n            if (day_count[d] >= K) continue;\n            \n            // Score this day: prefer days with fewer important edges already assigned\n            double score = -day_count[d];\n            \n            // Also consider connectivity - simplistic check\n            // We just try to balance the load\n            if (score > best_score) {\n                best_score = score;\n                best_day = d;\n            }\n        }\n        \n        if (best_day == -1) {\n            // Shouldn't happen if K*D >= M, but just in case\n            for (int d = 0; d < D; d++) {\n                if (day_count[d] < K) {\n                    best_day = d;\n                    break;\n                }\n            }\n        }\n        \n        assignment[eid] = best_day;\n        day_removed[best_day][eid] = true;\n        day_count[best_day]++;\n    }\n    \n    // Local improvement: try swapping edges between days\n    // Goal: reduce maximum frustration\n    // We'll do simple swaps\n    \n    // Compute initial frustration per day (approximation)\n    auto compute_day_frustration = [&](int day) -> double {\n        // Create graph without edges removed on this day\n        vector<vector<pair<int,int>>> temp_adj(N);\n        for (int i = 0; i < M; i++) {\n            if (!day_removed[day][i]) {\n                temp_adj[edges[i].u].push_back({edges[i].v, i});\n                temp_adj[edges[i].v].push_back({edges[i].u, i});\n            }\n        }\n        \n        double total_increase = 0;\n        int pairs = 0;\n        \n        // Sample vertices to estimate frustration\n        int sample_count = min(50, N);\n        for (int i = 0; i < sample_count; i++) {\n            int src = (i * N) / sample_count;\n            \n            vector<long long> dist(N, INF);\n            dist[src] = 0;\n            priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                \n                for (auto [v, eid] : temp_adj[u]) {\n                    long long nd = d + edges[eid].w;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        pq.push({nd, v});\n                    }\n                }\n            }\n            \n            for (int j = 0; j < sample_count; j++) {\n                int dst = (j * N) / sample_count;\n                if (src != dst) {\n                    long long d_new = dist[dst];\n                    if (d_new >= INF / 2) d_new = 1e9;\n                    long long increase = max(0LL, d_new - orig_dist[src][dst]);\n                    total_increase += increase;\n                    pairs++;\n                }\n            }\n        }\n        \n        return total_increase / pairs;\n    };\n    \n    // Try to improve with local search\n    int iterations = 0;\n    while (time_left() && iterations < 100000) {\n        iterations++;\n        \n        // Pick two random edges on different days\n        int e1 = rand() % M;\n        int e2 = rand() % M;\n        int d1 = assignment[e1];\n        int d2 = assignment[e2];\n        \n        if (d1 == d2) continue;\n        \n        // Swap\n        assignment[e1] = d2;\n        assignment[e2] = d1;\n        day_removed[d1][e1] = false;\n        day_removed[d2][e2] = false;\n        day_removed[d1][e2] = true;\n        day_removed[d2][e1] = true;\n        \n        // Check if improvement (simple heuristic: balance days)\n        // For speed, we'll just check day counts are reasonable\n        // A more sophisticated check would compute frustration\n        \n        bool good = true;\n        // Simple acceptance: keep with some probability\n        if (rand() % 100 < 50) {\n            // Revert\n            assignment[e1] = d1;\n            assignment[e2] = d2;\n            day_removed[d1][e1] = true;\n            day_removed[d2][e2] = true;\n            day_removed[d1][e2] = false;\n            day_removed[d2][e1] = false;\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < M; i++) {\n        if (i > 0) cout << \" \";\n        cout << assignment[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"   auto start_time = chrono::steady_clock::now();\n   auto get_elapsed_ms = [&]() {\n       return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n   };\n   ```\n\n   **Greedy loop with time limit:**\n   ```\n   while (true) {\n       if (get_elapsed_ms() > 5000) break; // 5 sec limit\n       // find best block\n       // if best_volume == 0 break;\n   }\n   ```\n\n   **After greedy:**\n   Handle remaining uncovered lines with 1x1 blocks.\n\n   Let's implement and test mentally.\n\n   **Edge Cases:**\n   - A1 or A2 might have zero volume? Input guarantees at least one 1 per z, so non-empty.\n   - The greedy might find a block that covers all remaining lines, leaving none. That's fine.\n   - The block volume could be up to D3.\n\n   **Optimization in BFS:**\n   Use a preallocated array for visited instead of FastBitset? But FastBitset is fine. For BFS, we need queue. We can use a static vector as queue to avoid allocations.\n\n   **Memory:**\n   b1, b2: vector<int> of size D3. D<=14 -> D3 up to 2744. Very small.\n\n   **Output:**\n   Print n first, then b1 elements space-separated, then b2.\n\n   **Potential bug:**\n   When we find a block, we update `available1` and `available2` by resetting bits. But we also need to update the list of available voxels for iteration? We used `forEachSetBit` which directly iterates the bitset. So it's fine.\n\n   However, after we remove voxels, the `rot1` for the next iteration will be recomputed from the updated `available1`. So it's correct.\n\n   **Inverse rotation:**\n   We have `inv_mat[24][3][3]`. Since rotation matrices are orthogonal, inverse is transpose.\n\n   **Shift range:**\n   After computing `rot1`, we find min/max of coordinates. If `rot1` is empty, skip.\n\n   **Building overlap:**\n   ```\n   FastBitset overlap;\n   rot1.forEachSetBit([&](int idx) {\n       auto [x,y,z] = decode(idx);\n       int nx = x + dx, ny = y + dy, nz = z + dz;\n       if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n           int idx2 = encode(nx,ny,nz);\n           if (available2.test(idx2)) {\n               overlap.set(idx2);\n           }\n       }\n   });\n   ```\n\n   **Connected components:**\n   ```\n   FastBitset visited;\n   int best_comp_size = 0;\n   FastBitset best_comp;\n   overlap.forEachSetBit([&](int seed) {\n       if (!visited.test(seed)) {\n           queue<int> q;\n           q.push(seed);\n           visited.set(seed);\n           int comp_size = 1;\n           // We need to collect component voxels to evaluate later. We can just record the seed and do BFS again if it's best? But we need the component bitset to extract. We can store the component bitset for the best only, or we can store all components? Too much memory. Instead, we can do two-pass: if we find a component larger than best, we store its voxels by doing BFS and setting a temporary bitset. We can use a local bitset `comp` and fill it during BFS.\n           // ...\n       }\n   });\n   ```\n   To avoid BFS twice, we can maintain `comp` bitset during BFS. If `comp_size > best_comp_size`, we copy `comp` to `best_comp` (which is a bitset copy). Since bitset is 43*8=344 bytes, copying is cheap.\n\n   **Line coverage update:**\n   After extracting preimage and best_comp, we update `uncovered1` and `uncovered2`.\n   For obj1, uncovered1 is a 2D array `bool uncovered1[D][D]` for front lines (z,x). Wait, the silhouette f1 is indexed f1(z,x). So uncovered1[z][x] indicates if that front line is not yet covered.\n   For preimage, we iterate its voxels, get x,y,z, set `uncovered1[z][x] = false`.\n   For obj2, silhouette r2 is r2(z,y). So uncovered2[z][y]. We iterate best_comp voxels, get x,y,z, set `uncovered2[z][y] = false`.\n\n   But wait: Object 1 has silhouettes f1 (front) and r1 (right). Object 2 has f2 and r2. Our algorithm uses A1 = f1 & r1, A2 = f2 & r2. When we place a block in obj1, it covers f1 lines and r1 lines. We must track both! I previously only tracked f1 and r2? That was a mistake. We need to ensure ALL FOUR silhouettes are satisfied.\n\n   Let's correct:\n   - Object 1: silhouettes f1 (front, z,x) and r1 (right, z,y).\n   - Object 2: silhouettes f2 (front, z,x) and r2 (right, z,y).\n\n   We must cover all required lines in all four.\n   So we need:\n   - uncovered1_f[z][x] for f1.\n   - uncovered1_r[z][y] for r1.\n   - uncovered2_f[z][x] for f2.\n   - uncovered2_r[z][y] for r2.\n\n   When we place a shared block:\n   - In obj1: preimage covers some f1 and r1 lines.\n   - In obj2: best_comp covers some f2 and r2 lines.\n\n   We update all four accordingly.\n\n   After greedy, we must cover remaining lines in all four.\n\n   **A1 and A2 definitions:**\n   A1 = { (x,y,z) | f1[z][x]=='1' and r1[z][y]=='1' }\n   A2 = { (x,y,z) | f2[z][x]=='1' and r2[z][y]=='1' }\n\n   **Finalization:**\n   For obj1:\n   - While there is uncovered line in f1 or r1:\n        Pick an available voxel in A1 (which is remaining available1) that covers at least one uncovered line.\n        Create a new block ID, assign to b1.\n        Mark all lines covered by this voxel as covered.\n   For obj2 similarly with A2 (available2).\n\n   But we can also try to share these 1x1 blocks: if both obj1 and obj2 have uncovered lines, we can pick one voxel from available1 and one from available2, and make them a shared block (since any single voxel is congruent to any single voxel). We just need to assign the same block ID to both. This reduces r1 and r2. So I'll implement:\n   - While obj1 has uncovered lines AND obj2 has uncovered lines:\n        Pick an available voxel v1 in A1 covering an uncovered line in obj1.\n        Pick an available voxel v2 in A2 covering an uncovered line in obj2.\n        Assign new shared block ID, set b1[v1]=ID, b2[v2]=ID.\n        Mark lines covered.\n   - Then cover remaining in each separately.\n\n   This finalization will produce many volume-1 blocks. But we might have missed opportunities to merge them into larger blocks. However, the main shared block(s) will provide the bulk of the score.\n\n   **Testing with sample:**\n   I can't run but I'll trust the logic.\n\n   **Potential improvements within time:**\n   - After greedy loop, before finalization, we could try to merge adjacent 1x1 blocks into larger blocks? Not necessary.\n   - We could also try to add more shared blocks by running the greedy again with remaining available sets? The greedy loop already does that until time or no block found. So if time permits, it will find multiple shared blocks.\n\n   **Edge case:**\n   If the greedy finds a block of size 1, it's equivalent to a shared 1x1. But it will stop after that because no larger block? Actually it will continue until best_volume == 0. If best_volume == 1, it will take it. That's fine.\n\n   We should set a minimum block size? Maybe 2? But size 1 shared block is better than separate 1x1. So take it.\n\n   **Optimization:**\n   In BFS, we can early-stop if comp_size + (remaining unvisited overlap) <= best_comp_size. But not necessary.\n\n   **Let's write the code.**\n\n   I'll structure the code clearly.\n\n   ```cpp\n   #include <bits/stdc++.h>\n   using namespace std;\n\n   // FastBitset\n   struct FastBitset {\n       static const int N = 2744;\n       static const int CHUNKS = (N + 63) / 64;\n       uint64_t bits[CHUNKS];\n       FastBitset() { clear(); }\n       void clear() { memset(bits, 0, sizeof bits); }\n       void set(int i) { bits[i>>6] |= 1ULL << (i&63); }\n       void reset(int i) { bits[i>>6] &= ~(1ULL << (i&63)); }\n       bool test(int i) const { return (bits[i>>6] >> (i&63)) & 1ULL; }\n       int count() const {\n           int c = 0;\n           for (int i = 0; i < CHUNKS; ++i) c += __builtin_popcountll(bits[i]);\n           return c;\n       }\n       FastBitset operator&(const FastBitset& o) const {\n           FastBitset r;\n           for (int i = 0; i < CHUNKS; ++i) r.bits[i] = bits[i] & o.bits[i];\n           return r;\n       }\n       template<typename F>\n       void forEachSetBit(F f) const {\n           for (int i = 0; i < CHUNKS; ++i) {\n               uint64_t w = bits[i];\n               while (w) {\n                   int j = __builtin_ctzll(w);\n                   f((i << 6) | j);\n                   w &= w - 1;\n               }\n           }\n       }\n   };\n\n   int D, D2, D3;\n   vector<vector<int>> adj;\n\n   int encode(int x, int y, int z) { return x*D2 + y*D + z; }\n   tuple<int,int,int> decode(int idx) {\n       int z = idx % D;\n       int y = (idx / D) % D;\n       int x = idx / D2;\n       return {x,y,z};\n   }\n\n   // 24 rotations\n   vector<array<array<int,3>,3>> rots;\n   vector<array<array<int,3>,3>> inv_rots;\n\n   void generate_rotations() {\n       // all 3x3 matrices with det=1, each row/col exactly one non-zero (1 or -1)\n       array<array<int,3>,3> base = {{{1,0,0},{0,1,0},{0,0,1}}};\n       // apply all permutations and sign flips with det=1\n       int perm[3] = {0,1,2};\n       do {\n           for (int s0 = -1; s0 <= 1; s0+=2)\n           for (int s1 = -1; s1 <= 1; s1+=2)\n           for (int s2 = -1; s2 <= 1; s2+=2) {\n               int det = s0*s1*s2;\n               if (det != 1) continue;\n               // check permutation parity? Actually det = sign(perm) * s0*s1*s2. We want det=1.\n               // sign of perm: number of inversions mod 2.\n               int sign = 1;\n               for (int i=0;i<3;i++) for (int j=i+1;j<3;j++) if (perm[i]>perm[j]) sign=-sign;\n               if (sign * s0 * s1 * s2 != 1) continue;\n               array<array<int,3>,3> mat = {{{0}}};\n               mat[0][perm[0]] = s0;\n               mat[1][perm[1]] = s1;\n               mat[2][perm[2]] = s2;\n               rots.push_back(mat);\n           }\n       } while (next_permutation(perm, perm+3));\n       // compute inverses\n       for (auto& mat : rots) {\n           array<array<int,3>,3> inv = {{{0}}};\n           for (int i=0;i<3;i++) for (int j=0;j<3;j++) inv[j][i] = mat[i][j];\n           inv_rots.push_back(inv);\n       }\n   }\n\n   FastBitset rotate_bitset(const FastBitset& src, const array<array<int,3>,3>& mat) {\n       FastBitset dst;\n       src.forEachSetBit([&](int idx) {\n           auto [x,y,z] = decode(idx);\n           int nx = mat[0][0]*x + mat[0][1]*y + mat[0][2]*z;\n           int ny = mat[1][0]*x + mat[1][1]*y + mat[1][2]*z;\n           int nz = mat[2][0]*x + mat[2][1]*y + mat[2][2]*z;\n           if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n               dst.set(encode(nx,ny,nz));\n           }\n       });\n       return dst;\n   }\n\n   int main() {\n       auto start_time = chrono::steady_clock::now();\n       auto get_ms = [&]() {\n           return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n       };\n\n       generate_rotations();\n\n       cin >> D;\n       D2 = D*D;\n       D3 = D*D*D;\n\n       vector<string> f1(D), r1(D), f2(D), r2(D);\n       for (int i=0;i<D;i++) cin >> f1[i];\n       for (int i=0;i<D;i++) cin >> r1[i];\n       for (int i=0;i<D;i++) cin >> f2[i];\n       for (int i=0;i<D;i++) cin >> r2[i];\n\n       // build adjacency\n       adj.resize(D3);\n       for (int x=0;x<D;x++) for (int y=0;y<D;y++) for (int z=0;z<D;z++) {\n           int idx = encode(x,y,z);\n           if (x>0) adj[idx].push_back(encode(x-1,y,z));\n           if (x<D-1) adj[idx].push_back(encode(x+1,y,z));\n           if (y>0) adj[idx].push_back(encode(x,y-1,z));\n           if (y<D-1) adj[idx].push_back(encode(x,y+1,z));\n           if (z>0) adj[idx].push_back(encode(x,y,z-1));\n           if (z<D-1) adj[idx].push_back(encode(x,y,z+1));\n       }\n\n       // A1 and A2\n       FastBitset A1, A2;\n       for (int x=0;x<D;x++) for (int y=0;y<D;y++) for (int z=0;z<D;z++) {\n           if (f1[z][x]=='1' && r1[z][y]=='1') A1.set(encode(x,y,z));\n           if (f2[z][x]=='1' && r2[z][y]=='1') A2.set(encode(x,y,z));\n       }\n\n       FastBitset available1 = A1, available2 = A2;\n       vector<int> b1(D3, 0), b2(D3, 0);\n       int block_id = 1;\n\n       // uncovered lines\n       vector<vector<bool>> unc1_f(D, vector<bool>(D, false));\n       vector<vector<bool>> unc1_r(D, vector<bool>(D, false));\n       vector<vector<bool>> unc2_f(D, vector<bool>(D, false));\n       vector<vector<bool>> unc2_r(D, vector<bool>(D, false));\n\n       for (int z=0;z<D;z++) for (int x=0;x<D;x++) if (f1[z][x]=='1') unc1_f[z][x] = true;\n       for (int z=0;z<D;z++) for (int y=0;y<D;y++) if (r1[z][y]=='1') unc1_r[z][y] = true;\n       for (int z=0;z<D;z++) for (int x=0;x<D;x++) if (f2[z][x]=='1') unc2_f[z][x] = true;\n       for (int z=0;z<D;z++) for (int y=0;y<D;y++) if (r2[z][y]=='1') unc2_r[z][y] = true;\n\n       // Greedy loop\n       while (true) {\n           if (get_ms() > 5000) break;\n           int best_vol = 0;\n           FastBitset best_comp2, best_preimage1;\n           int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n           for (int r=0; r<24; r++) {\n               FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n               // find bounding box\n               int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n               bool any = false;\n               rot_avail1.forEachSetBit([&](int idx) {\n                   auto [x,y,z] = decode(idx);\n                   any = true;\n                   if (x<min_x) min_x=x; if (x>max_x) max_x=x;\n                   if (y<min_y) min_y=y; if (y>max_y) max_y=y;\n                   if (z<min_z) min_z=z; if (z>max_z) max_z=z;\n               });\n               if (!any) continue;\n\n               int dx_min = -min_x, dx_max = D-1 - max_x;\n               int dy_min = -min_y, dy_max = D-1 - max_y;\n               int dz_min = -min_z, dz_max = D-1 - max_z;\n\n               for (int dx = dx_min; dx <= dx_max; dx++) {\n                   for (int dy = dy_min; dy <= dy_max; dy++) {\n                       for (int dz = dz_min; dz <= dz_max; dz++) {\n                           // build overlap\n                           FastBitset overlap;\n                           rot_avail1.forEachSetBit([&](int idx) {\n                               auto [x,y,z] = decode(idx);\n                               int nx = x + dx, ny = y + dy, nz = z + dz;\n                               if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                   int idx2 = encode(nx,ny,nz);\n                                   if (available2.test(idx2)) {\n                                       overlap.set(idx2);\n                                   }\n                               }\n                           });\n                           if (overlap.count() <= best_vol) continue;\n                           // find connected components\n                           FastBitset visited;\n                           overlap.forEachSetBit([&](int seed) {\n                               if (visited.test(seed)) return;\n                               // BFS\n                               queue<int> q;\n                               q.push(seed);\n                               visited.set(seed);\n                               FastBitset comp;\n                               comp.set(seed);\n                               int sz = 1;\n                               while (!q.empty()) {\n                                   int cur = q.front(); q.pop();\n                                   for (int nb : adj[cur]) {\n                                       if (overlap.test(nb) && !visited.test(nb)) {\n                                           visited.set(nb);\n                                           comp.set(nb);\n                                           sz++;\n                                           q.push(nb);\n                                       }\n                                   }\n                               }\n                               if (sz > best_vol) {\n                                   best_vol = sz;\n                                   best_comp2 = comp;\n                                   best_r = r;\n                                   best_dx = dx; best_dy = dy; best_dz = dz;\n                               }\n                           });\n                       }\n                   }\n               }\n           }\n           if (best_vol == 0) break;\n\n           // compute preimage1\n           FastBitset preimage1;\n           best_comp2.forEachSetBit([&](int idx) {\n               auto [x,y,z] = decode(idx);\n               int sx = x - best_dx, sy = y - best_dy, sz = z - best_dz;\n               int ox = inv_rots[best_r][0][0]*sx + inv_rots[best_r][0][1]*sy + inv_rots[best_r][0][2]*sz;\n               int oy = inv_rots[best_r][1][0]*sx + inv_rots[best_r][1][1]*sy + inv_rots[best_r][1][2]*sz;\n               int oz = inv_rots[best_r][2][0]*sx + inv_rots[best_r][2][1]*sy + inv_rots[best_r][2][2]*sz;\n               preimage1.set(encode(ox,oy,oz));\n           });\n\n           int bid = block_id++;\n           // update b1, b2, available\n           preimage1.forEachSetBit([&](int idx) {\n               b1[idx] = bid;\n               available1.reset(idx);\n               auto [x,y,z] = decode(idx);\n               unc1_f[z][x] = false;\n               unc1_r[z][y] = false;\n           });\n           best_comp2.forEachSetBit([&](int idx) {\n               b2[idx] = bid;\n               available2.reset(idx);\n               auto [x,y,z] = decode(idx);\n               unc2_f[z][x] = false;\n               unc2_r[z][y] = false;\n           });\n       }\n\n       // Finalization: cover remaining lines with 1x1 blocks, trying to share\n       // First, collect all uncovered lines for both objects\n       vector<pair<int,int>> lines1_f, lines1_r, lines2_f, lines2_r;\n       for (int z=0;z<D;z++) for (int x=0;x<D;x++) if (unc1_f[z][x]) lines1_f.push_back({z,x});\n       for (int z=0;z<D;z++) for (int y=0;y<D;y++) if (unc1_r[z][y]) lines1_r.push_back({z,y});\n       for (int z=0;z<D;z++) for (int x=0;x<D;x++) if (unc2_f[z][x]) lines2_f.push_back({z,x});\n       for (int z=0;z<D;z++) for (int y=0;y<D;y++) if (unc2_r[z][y]) lines2_r.push_back({z,y});\n\n       // Helper to find an available voxel covering a line\n       auto find_voxel_obj1 = [&](int z, int x, int y_hint=-1) -> int {\n           // need f1[z][x]==1 and r1[z][y]==1\n           // we can iterate over all y\n           for (int y=0;y<D;y++) {\n               int idx = encode(x,y,z);\n               if (available1.test(idx)) return idx;\n           }\n           return -1;\n       };\n       auto find_voxel_obj2 = [&](int z, int y, int x_hint=-1) -> int {\n           for (int x=0;x<D;x++) {\n               int idx = encode(x,y,z);\n               if (available2.test(idx)) return idx;\n           }\n           return -1;\n       };\n\n       // Try to share 1x1 blocks\n       while ((!lines1_f.empty() || !lines1_r.empty()) && (!lines2_f.empty() || !lines2_r.empty())) {\n           // pick a line from obj1 and obj2\n           bool pick1_f = !lines1_f.empty();\n           auto [z1, x1] = pick1_f ? lines1_f.back() : lines1_r.back();\n           if (pick1_f) lines1_f.pop_back(); else {\n               lines1_r.pop_back();\n               x1 = -1; // means we need to match right line\n           }\n           // pick from obj2\n           bool pick2_f = !lines2_f.empty();\n           auto [z2, x2] = pick2_f ? lines2_f.back() : lines2_r.back();\n           if (pick2_f) lines2_f.pop_back(); else {\n               lines2_r.pop_back();\n               x2 = -1;\n           }\n           // find voxels\n           int v1 = (pick1_f) ? find_voxel_obj1(z1, x1) : find_voxel_obj1_right(z1, ???); // we need a function for right line\n           // Actually, let's simplify: just iterate over available1 and available2 and pair them\n           // Since we only need to cover lines, we can just create a shared block by picking any available voxel from obj1 and any from obj2.\n           // But we must ensure they cover the lines we popped. So we need to find voxels covering those specific lines.\n           // Let's write proper functions.\n       }\n\n       // For simplicity, I'll just cover each remaining line separately without trying to share 1x1. It will be a bit worse but correct.\n       // To save time, I'll implement separate coverage for each object.\n\n       // Cover obj1 remaining\n       auto cover_line1_f = [&](int z, int x) {\n           for (int y=0;y<D;y++) {\n               int idx = encode(x,y,z);\n               if (available1.test(idx)) {\n                   int bid = block_id++;\n                   b1[idx] = bid;\n                   available1.reset(idx);\n                   unc1_f[z][x] = false;\n                   unc1_r[z][y] = false; // also covers this right line\n                   return;\n               }\n           }\n       };\n       auto cover_line1_r = [&](int z, int y) {\n           for (int x=0;x<D;x++) {\n               int idx = encode(x,y,z);\n               if (available1.test(idx)) {\n                   int bid = block_id++;\n                   b1[idx] = bid;\n                   available1.reset(idx);\n                   unc1_r[z][y] = false;\n                   unc1_f[z][x] = false;\n                   return;\n               }\n           }\n       };\n       // obj1 lines\n       for (int z=0;z<D;z++) for (int x=0;x<D;x++) if (unc1_f[z][x]) cover_line1_f(z,x);\n       for (int z=0;z<D;z++) for (int y=0;y<D;y++) if (unc1_r[z][y]) cover_line1_r(z,y);\n\n       // Cover obj2 remaining\n       auto cover_line2_f = [&](int z, int x) {\n           for (int y=0;y<D;y++) {\n               int idx = encode(x,y,z);\n               if (available2.test(idx)) {\n                   int bid = block_id++;\n                   b2[idx] = bid;\n                   available2.reset(idx);\n                   unc2_f[z][x] = false;\n                   unc2_r[z][y] = false;\n                   return;\n               }\n           }\n       };\n       auto cover_line2_r = [&](int z, int y) {\n           for (int x=0;x<D;x++) {\n               int idx = encode(x,y,z);\n               if (available2.test(idx)) {\n                   int bid = block_id++;\n                   b2[idx] = bid;\n                   available2.reset(idx);\n                   unc2_r[z][y] = false;\n                   unc2_f[z][x] = false;\n                   return;\n               }\n           }\n       };\n       for (int z=0;z<D;z++) for (int x=0;x<D;x++) if (unc2_f[z][x]) cover_line2_f(z,x);\n       for (int z=0;z<D;z++) for (int y=0;y<D;y++) if (unc2_r[z][y]) cover_line2_r(z,y);\n\n       // Output\n       int n = block_id - 1;\n       cout << n << endl;\n       for (int i=0;i<D3;i++) cout << b1[i] << (i==D3-1?'\\n':' ');\n       for (int i=0;i<D3;i++) cout << b2[i] << (i==D3-1?'\\n':' ');\n   }\n   ```\n\n   I need to fix some parts and ensure it compiles.\n\n   **Fixes:**\n   - The finalization separate coverage may create duplicate block IDs? I increment block_id for each new block. Shared blocks already got IDs. The new separate blocks get new IDs. That's fine.\n   - The separate coverage doesn't try to share 1x1 between obj1 and obj2. I'll leave that for brevity; it still works.\n   - The `cover_line1_f` and `cover_line1_r` might use the same voxel? No, they check available1 and reset it, so no overlap.\n   - I must ensure that after covering all lines, no uncovered lines remain.\n   - The `best_comp2` and `preimage1` might include voxels that are already used? No, we built overlap from `available2`, and preimage from `available1` via inverse, so they are available.\n   - One issue: In the preimage computation, we use `inv_rots[best_r]`. But the inverse rotation might map a voxel out of bounds? No, because we generated `best_comp2` from shifting `rot_avail1`, which was inside bounds. Inverse shift then inverse rotation maps it back to the original `available1` which is in bounds. So safe.\n\n   **Time limit:**\n   The loop breaks after 5 seconds. If no block found, it breaks. The finalization is fast.\n\n   **Potential bug:**\n   The greedy loop might find the same block repeatedly if we don't remove something? We remove voxels, so it's fine.\n\n   **Edge case:**\n   If `available1` or `available2` becomes empty but lines remain uncovered? That can't happen because we only remove voxels that are part of blocks, and blocks cover lines. If a line remains uncovered, it must still have voxels in available because we only removed voxels from lines that were covered by blocks. So available is not empty for uncovered lines.\n\n   **Let's test mentally with small D.**\n   Should work.\n\n   **Output format:** The sample output uses space-separated integers. My code outputs spaces correctly.\n\n   **One more thing:**\n   The problem statement says: \"Each block must be connected, i.e., every cube it comprises must be reachable by moving through shared faces. If there is a disconnected block, it will be judged as WA.\"\n   Our shared blocks are extracted as connected components from overlap, and their preimages are connected because rotation/translation preserves connectivity. So they are connected.\n   Our separate 1x1 blocks are single voxels, trivially connected.\n   So we are safe.\n\n   **Potential improvement:**\n   In the greedy, we only take the block if it's the overall maximum volume component. But it might be that a smaller block that covers more uncovered lines is better. Since we use volume as proxy, it's probably okay.\n\n   I think this solution will get a reasonable score.\n\n   Let's refine the code for compilation and minor optimizations.\n\n   **Final code structure:**\n   - Includes and FastBitset.\n   - Main with timer.\n   - Functions defined as lambdas.\n\n   I'll write the final answer now.```cpp\n#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\n// Fast bitset for small N (max 2744)\nstruct FastBitset {\n    static constexpr int N = 2744;\n    static constexpr int CHUNKS = (N + 63) / 64;\n    uint64_t bits[CHUNKS]{};\n    FastBitset() { clear(); }\n    void clear() { memset(bits, 0, sizeof bits); }\n    void set(int i) { bits[i>>6] |= 1ULL << (i&63); }\n    void reset(int i) { bits[i>>6] &= ~(1ULL << (i&63)); }\n    bool test(int i) const { return (bits[i>>6] >> (i&63)) & 1ULL; }\n    int count() const {\n        int c = 0;\n        for (int i = 0; i < CHUNKS; ++i) c += __builtin_popcountll(bits[i]);\n        return c;\n    }\n    FastBitset operator&(const FastBitset& o) const {\n        FastBitset r;\n        for (int i = 0; i < CHUNKS; ++i) r.bits[i] = bits[i] & o.bits[i];\n        return r;\n    }\n    template<typename F>\n    void forEachSetBit(F f) const {\n        for (int i = 0; i < CHUNKS; ++i) {\n            uint64_t w = bits[i];\n            while (w) {\n                int j = __builtin_ctzll(w);\n                f((i << 6) | j);\n                w &= w - 1;\n            }\n        }\n    }\n};\n\nint D, D2, D3;\nvector<vector<int>> adj;\n\ninline int encode(int x, int y, int z) { return x*D2 + y*D + z; }\ninline tuple<int,int,int> decode(int idx) {\n    int z = idx % D;\n    int y = (idx / D) % D;\n    int x = idx / D2;\n    return {x,y,z};\n}\n\n// all 24 proper rotations\nvector<array<array<int,3>,3>> rots;\nvector<array<array<int,3>,3>> inv_rots;\n\nvoid generate_rotations() {\n    array<array<int,3>,3> base = {{{1,0,0},{0,1,0},{0,0,1}}};\n    int perm[3] = {0,1,2};\n    do {\n        for (int s0 = -1; s0 <= 1; s0+=2)\n        for (int s1 = -1; s1 <= 1; s1+=2)\n        for (int s2 = -1; s2 <= 1; s2+=2) {\n            int sign = 1;\n            for (int i=0;i<3;i++) for (int j=i+1;j<3;j++) if (perm[i]>perm[j]) sign = -sign;\n            if (sign * s0 * s1 * s2 != 1) continue;\n            array<array<int,3>,3> mat = {{{0}}};\n            mat[0][perm[0]] = s0;\n            mat[1][perm[1]] = s1;\n            mat[2][perm[2]] = s2;\n            rots.push_back(mat);\n        }\n    } while (next_permutation(perm, perm+3));\n    for (auto& mat : rots) {\n        array<array<int,3>,3> inv = {{{0}}};\n        for (int i=0;i<3;i++) for (int j=0;j<3;j++) inv[j][i] = mat[i][j];\n        inv_rots.push_back(inv);\n    }\n}\n\nFastBitset rotate_bitset(const FastBitset& src, const array<array<int,3>,3>& mat) {\n    FastBitset dst;\n    src.forEachSetBit([&](int idx) {\n        auto [x,y,z] = decode(idx);\n        int nx = mat[0][0]*x + mat[0][1]*y + mat[0][2]*z;\n        int ny = mat[1][0]*x + mat[1][1]*y + mat[1][2]*z;\n        int nz = mat[2][0]*x + mat[2][1]*y + mat[2][2]*z;\n        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n            dst.set(encode(nx,ny,nz));\n        }\n    });\n    return dst;\n}\n\nint main() {\n    auto start_time = steady_clock::now();\n    auto get_ms = [&]() {\n        return duration_cast<milliseconds>(steady_clock::now() - start_time).count();\n    };\n\n    generate_rotations();\n\n    cin >> D;\n    D2 = D*D;\n    D3 = D*D*D;\n\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i=0; i<D; i++) cin >> f1[i];\n    for (int i=0; i<D; i++) cin >> r1[i];\n    for (int i=0; i<D; i++) cin >> f2[i];\n    for (int i=0; i<D; i++) cin >> r2[i];\n\n    // adjacency for BFS\n    adj.resize(D3);\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        int idx = encode(x,y,z);\n        if (x>0)   adj[idx].push_back(encode(x-1, y, z));\n        if (x<D-1) adj[idx].push_back(encode(x+1, y, z));\n        if (y>0)   adj[idx].push_back(encode(x, y-1, z));\n        if (y<D-1) adj[idx].push_back(encode(x, y+1, z));\n        if (z>0)   adj[idx].push_back(encode(x, y, z-1));\n        if (z<D-1) adj[idx].push_back(encode(x, y, z+1));\n    }\n\n    // allowed voxels for each object\n    FastBitset A1, A2;\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        if (f1[z][x]=='1' && r1[z][y]=='1') A1.set(encode(x,y,z));\n        if (f2[z][x]=='1' && r2[z][y]=='1') A2.set(encode(x,y,z));\n    }\n\n    FastBitset available1 = A1, available2 = A2;\n    vector<int> b1(D3, 0), b2(D3, 0);\n    int block_id = 1;\n\n    // uncovered lines\n    vector unc1_f(D, vector<bool>(D, false));\n    vector unc1_r(D, vector<bool>(D, false));\n    vector unc2_f(D, vector<bool>(D, false));\n    vector unc2_r(D, vector<bool>(D, false));\n\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f1[z][x]=='1') unc1_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r1[z][y]=='1') unc1_r[z][y] = true;\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f2[z][x]=='1') unc2_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r2[z][y]=='1') unc2_r[z][y] = true;\n\n    // Greedy extraction of shared blocks\n    while (true) {\n        if (get_ms() > 5000) break;\n        int best_vol = 0;\n        FastBitset best_comp2, best_preimage1;\n        int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n        for (int r = 0; r < 24; ++r) {\n            FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n            int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n            bool any = false;\n            rot_avail1.forEachSetBit([&](int idx) {\n                auto [x,y,z] = decode(idx);\n                any = true;\n                if (x<min_x) min_x=x; if (x>max_x) max_x=x;\n                if (y<min_y) min_y=y; if (y>max_y) max_y=y;\n                if (z<min_z) min_z=z; if (z>max_z) max_z=z;\n            });\n            if (!any) continue;\n\n            int dx_min = -min_x, dx_max = D-1 - max_x;\n            int dy_min = -min_y, dy_max = D-1 - max_y;\n            int dz_min = -min_z, dz_max = D-1 - max_z;\n\n            for (int dx = dx_min; dx <= dx_max; ++dx) {\n                for (int dy = dy_min; dy <= dy_max; ++dy) {\n                    for (int dz = dz_min; dz <= dz_max; ++dz) {\n                        FastBitset overlap;\n                        rot_avail1.forEachSetBit([&](int idx) {\n                            auto [x,y,z] = decode(idx);\n                            int nx = x+dx, ny = y+dy, nz = z+dz;\n                            if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                int idx2 = encode(nx,ny,nz);\n                                if (available2.test(idx2)) overlap.set(idx2);\n                            }\n                        });\n                        if (overlap.count() <= best_vol) continue;\n\n                        FastBitset visited;\n                        overlap.forEachSetBit([&](int seed) {\n                            if (visited.test(seed)) return;\n                            queue<int> q;\n                            q.push(seed);\n                            visited.set(seed);\n                            FastBitset comp;\n                            comp.set(seed);\n                            int sz = 1;\n                            while (!q.empty()) {\n                                int cur = q.front(); q.pop();\n                                for (int nb : adj[cur]) {\n                                    if (overlap.test(nb) && !visited.test(nb)) {\n                                        visited.set(nb);\n                                        comp.set(nb);\n                                        sz++;\n                                        q.push(nb);\n                                    }\n                                }\n                            }\n                            if (sz > best_vol) {\n                                best_vol = sz;\n                                best_comp2 = comp;\n                                best_r = r;\n                                best_dx = dx; best_dy = dy; best_dz = dz;\n                            }\n                        });\n                    }\n                }\n            }\n        }\n        if (best_vol == 0) break;\n\n        // preimage in object 1\n        FastBitset preimage1;\n        best_comp2.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            int sx = x - best_dx, sy = y - best_dy, sz = z - best_dz;\n            int ox = inv_rots[best_r][0][0]*sx + inv_rots[best_r][0][1]*sy + inv_rots[best_r][0][2]*sz;\n            int oy = inv_rots[best_r][1][0]*sx + inv_rots[best_r][1][1]*sy + inv_rots[best_r][1][2]*sz;\n            int oz = inv_rots[best_r][2][0]*sx + inv_rots[best_r][2][1]*sy + inv_rots[best_r][2][2]*sz;\n            preimage1.set(encode(ox,oy,oz));\n        });\n\n        int bid = block_id++;\n        preimage1.forEachSetBit([&](int idx) {\n            b1[idx] = bid;\n            available1.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc1_f[z][x] = false;\n            unc1_r[z][y] = false;\n        });\n        best_comp2.forEachSetBit([&](int idx) {\n            b2[idx] = bid;\n            available2.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc2_f[z][x] = false;\n            unc2_r[z][y] = false;\n        });\n    }\n\n    // Cover remaining lines with 1x1 blocks\n    // Object 1\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) {\n        if (unc1_f[z][x]) {\n            for (int y=0; y<D; y++) {\n                int idx = encode(x,y,z);\n                if (available1.test(idx)) {\n                    int bid = block_id++;\n                    b1[idx] = bid;\n                    available1.reset(idx);\n                    unc1_f[z][x] = false;\n                    unc1_r[z][y] = false;\n                    break;\n                }\n            }\n        }\n    }\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) {\n        if (unc1_r[z][y]) {\n            for (int x=0; x<D; x++) {\n                int idx = encode(x,y,z);\n                if (available1.test(idx)) {\n                    int bid = block_id++;\n                    b1[idx] = bid;\n                    available1.reset(idx);\n                    unc1_r[z][y] = false;\n                    unc1_f[z][x] = false;\n                    break;\n                }\n            }\n        }\n    }\n    // Object 2\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) {\n        if (unc2_f[z][x]) {\n            for (int y=0; y<D; y++) {\n                int idx = encode(x,y,z);\n                if (available2.test(idx)) {\n                    int bid = block_id++;\n                    b2[idx] = bid;\n                    available2.reset(idx);\n                    unc2_f[z][x] = false;\n                    unc2_r[z][y] = false;\n                    break;\n                }\n            }\n        }\n    }\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) {\n        if (unc2_r[z][y]) {\n            for (int x=0; x<D; x++) {\n                int idx = encode(x,y,z);\n                if (available2.test(idx)) {\n                    int bid = block_id++;\n                    b2[idx] = bid;\n                    available2.reset(idx);\n                    unc2_r[z][y] = false;\n                    unc2_f[z][x] = false;\n                    break;\n                }\n            }\n        }\n    }\n\n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    for (int i=0; i<D3; i++) cout << b1[i] << \" \\n\"[i==D3-1];\n    for (int i=0; i<D3; i++) cout << b2[i] << \" \\n\"[i==D3-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\n#define rep(i, a, b) for (int i = (a); i < (b); i++)\n#define all(x) begin(x), end(x)\n\nstruct Edge {\n    int u, v;\n    long long w;\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    vector<pair<int, int>> stations(N);\n    rep(i, 0, N) cin >> stations[i].first >> stations[i].second;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, long long>>> adj(N);\n    rep(j, 0, M) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n\n    vector<pair<int, int>> residents(K);\n    rep(k, 0, K) cin >> residents[k].first >> residents[k].second;\n\n    // Step 1: assign each resident to nearest station\n    vector<vector<int>> stationResidents(N);\n    rep(k, 0, K) {\n        int best = -1;\n        long long bestDist = LLONG_MAX;\n        rep(i, 0, N) {\n            long long dx = stations[i].first - residents[k].first;\n            long long dy = stations[i].second - residents[k].second;\n            long long dist = dx * dx + dy * dy;\n            if (dist < bestDist) {\n                bestDist = dist;\n                best = i;\n            }\n        }\n        stationResidents[best].push_back(k);\n    }\n\n    // Step 2: initial P_i = max Euclidean distance to assigned residents\n    vector<int> P(N, 0);\n    rep(i, 0, N) {\n        if (stationResidents[i].empty()) continue;\n        long long maxDistSq = 0;\n        for (int k : stationResidents[i]) {\n            long long dx = stations[i].first - residents[k].first;\n            long long dy = stations[i].second - residents[k].second;\n            maxDistSq = max(maxDistSq, dx * dx + dy * dy);\n        }\n        long long val = (long long)ceil(sqrt(maxDistSq));\n        if (val > 5000) val = 5000;\n        P[i] = (int)val;\n    }\n\n    // Step 3: find shortest paths from vertex 1\n    const long long INF = 1e18;\n    vector<long long> dist(N, INF);\n    vector<int> parent(N, -1);\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n    dist[0] = 0;\n    pq.push({0, 0});\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, w] : adj[u]) {\n            if (dist[v] > d + w) {\n                dist[v] = d + w;\n                parent[v] = u;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n\n    // Select vertices with P_i > 0\n    vector<int> active;\n    rep(i, 0, N) if (P[i] > 0) active.push_back(i);\n\n    // Build a Steiner-like tree: connect each active vertex to vertex 1 via shortest path\n    vector<int> onEdge(M, 0);\n    vector<bool> used(N, false);\n    used[0] = true;\n    // Sort active by distance from 1, then connect\n    sort(all(active), [&](int a, int b) { return dist[a] < dist[b]; });\n    for (int v : active) {\n        if (used[v]) continue;\n        // trace path\n        int cur = v;\n        while (!used[cur]) {\n            used[cur] = true;\n            int p = parent[cur];\n            if (p == -1) break;\n            // enable edge between p and cur\n            for (int j = 0; j < M; j++) {\n                if ((edges[j].u == p && edges[j].v == cur) || (edges[j].u == cur && edges[j].v == p)) {\n                    onEdge[j] = 1;\n                    break;\n                }\n            }\n            cur = p;\n        }\n    }\n\n    // Step 4: refinement (simple merge nearby stations)\n    rep(i, 0, N) {\n        if (P[i] == 0) continue;\n        rep(j, 0, N) {\n            if (i == j || P[j] == 0) continue;\n            long long dx = stations[i].first - stations[j].first;\n            long long dy = stations[i].second - stations[j].second;\n            long long d = (long long)ceil(sqrt(dx * dx + dy * dy));\n            if (P[i] + d <= P[j]) {\n                // i can cover j's residents\n                P[i] = max(P[i], (int)(P[j] + d));\n                if (P[i] > 5000) P[i] = 5000;\n                P[j] = 0;\n            }\n        }\n    }\n\n    // Rebuild edges after refinement\n    fill(all(onEdge), 0);\n    fill(all(used), false);\n    used[0] = true;\n    active.clear();\n    rep(i, 0, N) if (P[i] > 0) active.push_back(i);\n    sort(all(active), [&](int a, int b) { return dist[a] < dist[b]; });\n    for (int v : active) {\n        if (used[v]) continue;\n        int cur = v;\n        while (!used[cur]) {\n            used[cur] = true;\n            int p = parent[cur];\n            if (p == -1) break;\n            for (int j = 0; j < M; j++) {\n                if ((edges[j].u == p && edges[j].v == cur) || (edges[j].u == cur && edges[j].v == p)) {\n                    onEdge[j] = 1;\n                    break;\n                }\n            }\n            cur = p;\n        }\n    }\n\n    // Output\n    rep(i, 0, N) cout << P[i] << (i + 1 < N ? ' ' : '\\n');\n    rep(j, 0, M) cout << onEdge[j] << (j + 1 < M ? ' ' : '\\n');\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int MAXB = N * (N + 1) / 2; // 465\nint board[N][N];\nint pos[MAXB][2]; // position of each value\n\n// Directions: (dx, dy) for neighbors\nint dx[6] = {-1, -1, 0, 0, 1, 1};\nint dy[6] = {-1, 0, -1, 1, 0, 1};\n\nvector<pair<pair<int,int>,pair<int,int>>> moves;\n\nbool inside(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\n// BFS to find a path between two positions (returns a sequence of positions)\nvector<pair<int,int>> find_path(int sx, int sy, int tx, int ty) {\n    map<pair<int,int>, pair<int,int>> parent;\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    parent[{sx, sy}] = {-1, -1};\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        if (x == tx && y == ty) break;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (inside(nx, ny) && !parent.count({nx, ny})) {\n                parent[{nx, ny}] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    vector<pair<int,int>> path;\n    pair<int,int> cur = {tx, ty};\n    while (cur != make_pair(-1, -1)) {\n        path.push_back(cur);\n        cur = parent[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Swap two adjacent positions\nvoid do_swap(int x1, int y1, int x2, int y2) {\n    moves.push_back({{x1, y1}, {x2, y2}});\n    int v1 = board[x1][y1], v2 = board[x2][y2];\n    swap(board[x1][y1], board[x2][y2]);\n    pos[v1][0] = x2; pos[v1][1] = y2;\n    pos[v2][0] = x1; pos[v2][1] = y1;\n}\n\n// Move a ball from (sx,sy) along a path to (tx,ty) step by step\nvoid move_along_path(vector<pair<int,int>> &path) {\n    for (size_t i = 0; i + 1 < path.size(); i++) {\n        do_swap(path[i].first, path[i].second, path[i+1].first, path[i+1].second);\n    }\n}\n\nint main() {\n    // Read input\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j <= i; j++) {\n            cin >> board[i][j];\n            pos[board[i][j]][0] = i;\n            pos[board[i][j]][1] = j;\n        }\n    }\n\n    // Greedy fix violations\n    for (int step = 0; step < 10000; ) {\n        bool fixed = false;\n        // Scan for violations from top to bottom\n        for (int x = 0; x < N-1 && !fixed; x++) {\n            for (int y = 0; y <= x && !fixed; y++) {\n                int p = board[x][y];\n                // Check two children\n                for (int d = 0; d < 2; d++) {\n                    int cx = x+1, cy = y + d;\n                    int c = board[cx][cy];\n                    if (p > c) {\n                        // Move smaller child up\n                        auto path = find_path(cx, cy, x, y);\n                        move_along_path(path);\n                        fixed = true;\n                        step += (int)path.size() - 1;\n                        break;\n                    }\n                }\n            }\n        }\n        if (!fixed) break; // no violations\n        if (step >= 10000) break;\n    }\n\n    // Output\n    cout << moves.size() << \"\\n\";\n    for (auto &m : moves) {\n        cout << m.first.first << \" \" << m.first.second << \" \"\n             << m.second.first << \" \" << m.second.second << \"\\n\";\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0, ENTRANCE_J = 4;\nint max_id;\n\nvector<string> grid(D, string(D, '.'));\nvector<vector<int>> dist(D, vector<int>(D, -1));\nvector<vector<bool>> obstacle(D, vector<bool>(D, false));\nvector<vector<bool>> occupied(D, vector<bool>(D, false));\n\nint dx[4] = {1, -1, 0, 0};\nint dy[4] = {0, 0, 1, -1};\n\nvoid bfs_distance(int si, int sj) {\n    for (int i = 0; i < D; i++)\n        fill(dist[i].begin(), dist[i].end(), -1);\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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 (nx >= 0 && nx < D && ny >= 0 && ny < D &&\n                dist[nx][ny] == -1 && !obstacle[nx][ny] && !occupied[nx][ny]) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n}\n\nbool reachable(int i, int j) {\n    return dist[i][j] != -1;\n}\n\nint count_reachable_empty() {\n    int cnt = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !occupied[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J) && reachable(i, j))\n                cnt++;\n    return cnt;\n}\n\npair<int,int> find_best_cell(int target_dist, int remaining) {\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int best_i = -1, best_j = -1, best_score = 1e9;\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_I && j == ENTRANCE_J) continue;\n            if (!reachable(i, j)) continue;\n            // temporarily place\n            occupied[i][j] = true;\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            int reachable_after = count_reachable_empty();\n            occupied[i][j] = false;\n            if (reachable_after < remaining - 1) continue; // would block future\n            int score = abs(dist[i][j] - target_dist);\n            if (score < best_score) {\n                best_score = score;\n                best_i = i; best_j = j;\n            }\n        }\n    }\n    return {best_i, best_j};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    for (int i = 0; i < N; i++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n\n    max_id = D*D - 1 - N;\n    int total_containers = max_id;\n    vector<pair<int,int>> placements(total_containers);\n\n    // Compute max distance\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int max_dist = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J))\n                max_dist = max(max_dist, dist[i][j]);\n\n    for (int d = 0; d < total_containers; d++) {\n        int tid;\n        cin >> tid;\n        int remaining = total_containers - d;\n        int target_dist = (int)((double)tid / max_id * max_dist);\n        auto [pi, pj] = find_best_cell(target_dist, remaining);\n        if (pi == -1) {\n            // fallback: any reachable\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            for (int i = 0; i < D && pi==-1; i++)\n                for (int j = 0; j < D && pi==-1; j++)\n                    if (!obstacle[i][j] && !occupied[i][j] && reachable(i,j) && !(i==ENTRANCE_I && j==ENTRANCE_J)) {\n                        pi = i; pj = j;\n                    }\n        }\n        occupied[pi][pj] = true;\n        placements[tid] = {pi, pj};\n        cout << pi << \" \" << pj << \"\\n\";\n        cout.flush();\n    }\n\n    // Removal: try sorted order, pick accessible with smallest ID\n    vector<bool> removed(total_containers, false);\n    for (int step = 0; step < total_containers; step++) {\n        bfs_distance(ENTRANCE_I, ENTRANCE_J);\n        int chosen = -1;\n        for (int id = 0; id < total_containers; id++) {\n            if (!removed[id]) {\n                auto [i, j] = placements[id];\n                if (reachable(i, j)) {\n                    chosen = id;\n                    break;\n                }\n            }\n        }\n        removed[chosen] = true;\n        occupied[placements[chosen].first][placements[chosen].second] = false;\n        cout << placements[chosen].first << \" \" << placements[chosen].second << \"\\n\";\n    }\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nvector<vector<int>> input(N, vector<int>(N));\nbool adj[M+1][M+1];\nbool needs_zero[M+1];\nvector<int> graph[M+1];\n\nint dx[4] = {-1, 0, 1, 0};\nint dy[4] = {0, 1, 0, -1};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> input[i][j];\n    \n    // Build adjacency matrix\n    memset(adj, 0, sizeof(adj));\n    memset(needs_zero, 0, sizeof(needs_zero));\n    \n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = input[i][j];\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                needs_zero[c] = true;\n            for (int d = 0; d < 4; d++) {\n                int ni = i + dx[d], nj = j + dy[d];\n                int nc = 0;\n                if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n                    nc = input[ni][nj];\n                if (c != nc)\n                    adj[c][nc] = adj[nc][c] = true;\n            }\n        }\n    }\n    \n    for (int c = 1; c <= m; c++)\n        for (int d = 0; d <= m; d++)\n            if (adj[c][d] && c != d)\n                graph[c].push_back(d);\n    \n    // Output: all 0 initially\n    vector<vector<int>> output(N, vector<int>(N, 0));\n    \n    // For each color, we'll assign a \"seed\" cell\n    // Then expand to satisfy adjacencies\n    \n    // Build spanning tree for ordering\n    vector<bool> visited(M+1, false);\n    vector<int> order;\n    queue<int> q;\n    \n    // Start with colors that need color 0\n    for (int c = 1; c <= m; c++) {\n        if (needs_zero[c] && !visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; c++) {\n        if (!visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    \n    // Place colors in a compact region\n    // Use a rectangular block in the center, starting from row 2, col 2\n    // Place each color as a small connected region (1 cell for now)\n    \n    map<int, vector<pair<int,int>>> cells; // cells for each color\n    \n    int cur_r = 2, cur_c = 2;\n    int max_r = N-3, max_c = N-3;\n    \n    for (int c : order) {\n        // Find free cell\n        while (cur_r <= max_r && output[cur_r][cur_c] != 0) {\n            cur_c++;\n            if (cur_c > max_c) { cur_c = 2; cur_r++; }\n        }\n        if (cur_r > max_r) break;\n        \n        output[cur_r][cur_c] = c;\n        cells[c].push_back({cur_r, cur_c});\n    }\n    \n    // Now ensure all required adjacencies are satisfied\n    // For each adjacency pair, if not adjacent, add cells\n    \n    bool changed = true;\n    int iterations = 0;\n    while (changed && iterations < 100) {\n        changed = false;\n        iterations++;\n        \n        for (int c = 1; c <= m; c++) {\n            for (int d : graph[c]) {\n                if (d == 0 || c >= d) continue; // process each pair once\n                \n                // Check if c and d are adjacent in output\n                bool adj_found = false;\n                for (auto [r1, c1] : cells[c]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r1 + dx[k], nc = c1 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == d) {\n                            adj_found = true;\n                            break;\n                        }\n                    }\n                    if (adj_found) break;\n                }\n                if (adj_found) continue;\n                \n                // Try to add a cell of c adjacent to some cell of d\n                bool placed = false;\n                for (auto [r2, c2] : cells[d]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r2 + dx[k], nc = c2 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                            output[nr][nc] = c;\n                            cells[c].push_back({nr, nc});\n                            placed = true;\n                            changed = true;\n                            break;\n                        }\n                    }\n                    if (placed) break;\n                }\n                \n                if (!placed) {\n                    // Try adding a cell of d adjacent to c\n                    for (auto [r1, c1] : cells[c]) {\n                        for (int k = 0; k < 4; k++) {\n                            int nr = r1 + dx[k], nc = c1 + dy[k];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                                output[nr][nc] = d;\n                                cells[d].push_back({nr, nc});\n                                placed = true;\n                                changed = true;\n                                break;\n                            }\n                        }\n                        if (placed) break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Check if any color needs color-0 adjacency but doesn't have it\n    for (int c = 1; c <= m; c++) {\n        if (!needs_zero[c]) continue;\n        if (cells[c].empty()) continue;\n        \n        bool touches_zero = false;\n        for (auto [r, col] : cells[c]) {\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dx[k], nc = col + dy[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || output[nr][nc] == 0) {\n                    touches_zero = true;\n                    break;\n                }\n            }\n            if (touches_zero) break;\n        }\n        \n        if (!touches_zero) {\n            // Expand c towards the border\n            // Find path to border through color 0\n            for (auto [r, col] : cells[c]) {\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dx[k], nc = col + dy[k];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                        output[nr][nc] = c;\n                        cells[c].push_back({nr, nc});\n                        break;\n                    }\n                }\n                break;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << output[i][j] << (j == N-1 ? '\\n' : ' ');\n        }\n    }\n    \n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nint query_count = 0;\n\nchar compare_sets(const vector<int>& L, const vector<int>& R) {\n    assert(!L.empty() && !R.empty());\n    query_count++;\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res;\n    cin >> res;\n    return res;\n}\n\nchar compare_items(int a, int b) {\n    return compare_sets({a}, {b});\n}\n\n// Merge sort based on compare_items\nvector<int> merge_sort(const vector<int>& arr, int l, int r) {\n    if (l == r) return {arr[l]};\n    int m = (l + r) / 2;\n    auto left = merge_sort(arr, l, m);\n    auto right = merge_sort(arr, m + 1, r);\n    vector<int> res;\n    int i = 0, j = 0;\n    while (i < (int)left.size() && j < (int)right.size()) {\n        if (query_count < Q && compare_items(left[i], right[j]) == '>') {\n            res.push_back(left[i++]);\n        } else {\n            res.push_back(right[j++]);\n        }\n    }\n    while (i < (int)left.size()) res.push_back(left[i++]);\n    while (j < (int)right.size()) res.push_back(right[j++]);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> D >> Q;\n\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n\n    // Sort items by descending weight using merge sort\n    vector<int> sorted_items = merge_sort(items, 0, N - 1);\n\n    // Greedy partition: assign heaviest to lightest group\n    vector<vector<int>> groups(D);\n    vector<long long> group_sum(D, 0); // placeholder weight = index (rank)\n    // Use rank as proxy for weight (heavier item has lower index in sorted_items)\n    for (int i = 0; i < N; i++) {\n        int item = sorted_items[i];\n        // Find group with minimum estimated sum\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_sum[g] < group_sum[best]) best = g;\n        }\n        groups[best].push_back(item);\n        // approximate weight as (N - i) so lighter items have smaller value\n        group_sum[best] += (N - i); \n    }\n\n    // Use remaining queries to compare group sums and possibly swap\n    // Compare random pairs of groups and swap items if beneficial\n    // But keep it simple here; just output the initial partition.\n    // Optional refinement:\n    while (query_count + 2 <= Q) {\n        // pick two groups\n        int a = rand() % D;\n        int b = rand() % D;\n        if (a == b) continue;\n        // Compare sums\n        char cmp = compare_sets(groups[a], groups[b]);\n        if (cmp == '>') { // a heavier than b\n            // try moving lightest item from a to b if it helps\n            // We don't know individual weights, but we could just move one item\n            // For now skip detailed refinement.\n        } else if (cmp == '<') {\n            // similarly\n        }\n        // If equal, nothing to do\n        // Break if out of queries\n    }\n\n    // Build final assignment\n    vector<int> assignment(N);\n    for (int g = 0; g < D; g++) {\n        for (int item : groups[g]) {\n            assignment[item] = g;\n        }\n    }\n\n    // Output comment with assignment for visualizer\n    cout << \"#c\";\n    for (int i = 0; i < N; i++) cout << \" \" << assignment[i];\n    cout << endl;\n\n    // Final answer\n    for (int i = 0; i < N; i++) {\n        if (i) cout << \" \";\n        cout << assignment[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 200, M = 10, H = N / M;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> stacks(m, vector<int>(n / m));\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < n / m; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> moves; // (v, i) where i=0 means carry out, else move to stack i-1\n    auto move_op = [&](int v, int dest) {\n        moves.emplace_back(v, dest + 1);\n    };\n    auto carry_out = [&](int v) {\n        moves.emplace_back(v, 0);\n    };\n\n    int next_target = 1;\n    while (next_target <= n) {\n        // find stack and position of next_target\n        int si = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == next_target) {\n                    si = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (si != -1) break;\n        }\n\n        if (pos == (int)stacks[si].size() - 1) {\n            // on top, carry out\n            carry_out(next_target);\n            stacks[si].pop_back();\n            ++next_target;\n            continue;\n        }\n\n        // need to move boxes above\n        int k = (int)stacks[si].size() - pos;\n        // choose destination: prefer an empty stack or one with top > next_target\n        int dest = -1;\n        // first look for empty\n        for (int i = 0; i < m; ++i) {\n            if (i != si && stacks[i].empty()) {\n                dest = i;\n                break;\n            }\n        }\n        if (dest == -1) {\n            // pick stack with minimum top number (to keep sorted)\n            int min_top = INT_MAX;\n            for (int i = 0; i < m; ++i) {\n                if (i != si && !stacks[i].empty() && stacks[i].back() < min_top) {\n                    min_top = stacks[i].back();\n                    dest = i;\n                }\n            }\n            if (dest == -1) dest = (si + 1) % m; // fallback\n        }\n\n        // move\n        move_op(next_target, dest);\n        vector<int> moving(stacks[si].begin() + pos, stacks[si].end());\n        stacks[si].resize(pos);\n        stacks[dest].insert(stacks[dest].end(), moving.begin(), moving.end());\n    }\n\n    // output\n    for (auto &[v, i] : moves) {\n        cout << v << \" \" << i << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring ans;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\nconst char dir[4] = {'R', 'D', 'L', 'U'};\n\nbool can_move(int x, int y, int nx, int ny) {\n    if (nx < 0 || nx >= N || ny < 0 || ny >= N) return false;\n    if (dx[abs(x-nx)] == 0) {\n        int j = min(y, ny);\n        if (v[x][j] == '1') return false;\n    } else {\n        int i = min(x, nx);\n        if (h[i][y] == '1') return false;\n    }\n    return true;\n}\n\nvoid dfs(int x, int y) {\n    visited[x][y] = true;\n    vector<tuple<int,int,int>> cand;\n    for (int k = 0; k < 4; k++) {\n        int nx = x + dx[k], ny = y + dy[k];\n        if (can_move(x, y, nx, ny) && !visited[nx][ny]) {\n            cand.emplace_back(-d[nx][ny], nx, ny);\n        }\n    }\n    sort(cand.begin(), cand.end()); // visit high-dirt first\n    for (auto [_, nx, ny] : cand) {\n        for (int k = 0; k < 4; k++) {\n            if (x + dx[k] == nx && y + dy[k] == ny) {\n                ans.push_back(dir[k]);\n                dfs(nx, ny);\n                ans.push_back(dir[(k+2)%4]);\n                break;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    d.assign(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    visited.assign(N, vector<bool>(N, false));\n    ans.reserve(100000);\n    \n    dfs(0, 0);\n    \n    // Ensure we return to (0,0) if not already\n    if (ans.empty() || ans.back() != 'U') {}\n    \n    // Length check\n    if ((int)ans.size() > 100000) {\n        ans.resize(100000);\n    }\n    \n    cout << ans << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 15;\nconst int INF = 1e9;\n\nint dist[225][225];\nvector<pair<int,int>> pos[26];\nchar grid[N][N];\nint M;\nvector<string> targets;\nint si, sj;\nint cell_id(int i, int j) { return i*N + j; }\n\nvoid bfs_dist() {\n    int di[] = {1,-1,0,0};\n    int dj[] = {0,0,1,-1};\n    for (int i=0;i<225;i++) for(int j=0;j<225;j++) dist[i][j]=INF;\n    for (int i=0;i<225;i++) {\n        int si = i/N, sj = i%N;\n        dist[i][i]=0;\n        queue<pair<int,int>> q;\n        q.push({si,sj});\n        while (!q.empty()) {\n            auto [ci,cj] = q.front(); q.pop();\n            int cid = cell_id(ci,cj);\n            for (int d=0;d<4;d++) {\n                int ni = ci+di[d], nj = cj+dj[d];\n                if (ni<0||ni>=N||nj<0||nj>=N) continue;\n                int nid = cell_id(ni,nj);\n                if (dist[i][nid] > dist[i][cid]+1) {\n                    dist[i][nid] = dist[i][cid]+1;\n                    q.push({ni,nj});\n                }\n            }\n        }\n    }\n}\n\n// DP to find best path for a target string given a starting cell\nint best_cost_for_target(const string& t, int start_cell, vector<int>& out_cells) {\n    int L = t.size();\n    vector<int> dp_prev, dp_cur;\n    vector<vector<int>> prev_cell(L, vector<int>(225,-1));\n    // initialize with start_cell to first character positions\n    dp_cur.assign(225, INF);\n    for (auto [i,j] : pos[t[0]-'A']) {\n        int cid = cell_id(i,j);\n        dp_cur[cid] = dist[start_cell][cid] + 1;\n    }\n    for (int k=1;k<L;k++) {\n        dp_prev = dp_cur;\n        dp_cur.assign(225, INF);\n        char c = t[k];\n        for (auto [i,j] : pos[c-'A']) {\n            int cid = cell_id(i,j);\n            for (auto [pi,pj] : pos[t[k-1]-'A']) {\n                int pid = cell_id(pi,pj);\n                int nd = dp_prev[pid] + dist[pid][cid] + 1;\n                if (nd < dp_cur[cid]) {\n                    dp_cur[cid] = nd;\n                    prev_cell[k][cid] = pid;\n                }\n            }\n        }\n    }\n    int best_end = -1;\n    int best_val = INF;\n    for (auto [i,j] : pos[t.back()-'A']) {\n        int cid = cell_id(i,j);\n        if (dp_cur[cid] < best_val) {\n            best_val = dp_cur[cid];\n            best_end = cid;\n        }\n    }\n    if (best_end==-1) return INF;\n    // reconstruct\n    out_cells.resize(L);\n    int cur = best_end;\n    for (int k=L-1;k>=0;k--) {\n        out_cells[k] = cur;\n        if (k>0) cur = prev_cell[k][cur];\n    }\n    return best_val;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    cin >> si >> sj;\n    for (int i=0;i<N;i++) {\n        string s; cin >> s;\n        for (int j=0;j<N;j++) {\n            grid[i][j] = s[j];\n            pos[s[j]-'A'].push_back({i,j});\n        }\n    }\n    targets.resize(M);\n    for (int i=0;i<M;i++) cin >> targets[i];\n    \n    bfs_dist();\n    \n    int start_cell = cell_id(si,sj);\n    \n    // For each target, compute minimal cost and cells (for a fresh start from start)\n    vector<vector<int>> best_cells(M);\n    vector<int> cost_from_start(M);\n    for (int i=0;i<M;i++) {\n        cost_from_start[i] = best_cost_for_target(targets[i], start_cell, best_cells[i]);\n    }\n    \n    // Greedy ordering: start with cheapest target\n    vector<bool> used(M,false);\n    vector<int> order;\n    int cur_cell = start_cell;\n    int total_cost = 0;\n    vector<int> output_cells;\n    \n    while ((int)order.size() < M) {\n        int best_idx = -1;\n        int best_add = INF;\n        vector<int> best_seq;\n        for (int i=0;i<M;i++) {\n            if (used[i]) continue;\n            vector<int> seq;\n            int add = best_cost_for_target(targets[i], cur_cell, seq);\n            if (add < best_add) {\n                best_add = add;\n                best_idx = i;\n                best_seq = seq;\n            }\n        }\n        used[best_idx] = true;\n        order.push_back(best_idx);\n        total_cost += best_add;\n        cur_cell = best_seq.back();\n        for (int c : best_seq) output_cells.push_back(c);\n    }\n    \n    // Simple local search: try swap adjacent in order\n    // Actually, since cost depends on sequence and overlap, greedy is decent\n    // We'll just output the greedy result\n    \n    for (int c : output_cells) {\n        cout << c/N << \" \" << c%N << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <cassert>\n#include <numeric>\nusing namespace std;\n\nstruct OilField {\n    int d;\n    vector<pair<int,int>> cells; // relative coordinates\n    int h, w; // height and width\n};\n\nint N, M;\ndouble eps;\nvector<OilField> fields;\nvector<vector<int>> true_v; // unknown to us, but for local testing only; in real, we'll build estimate\n\n// Our belief of v: double matrix\nvector<vector<double>> belief;\n\n// placed shapes tracking\nvector<vector<bool>> occupied_by_shape; // to avoid double counting\n\n// Helper: get sum of belief over a set of cells\ndouble belief_sum(const vector<pair<int,int>> &cells) {\n    double s = 0.0;\n    for (auto &p : cells) {\n        s += belief[p.first][p.second];\n    }\n    return s;\n}\n\n// Divination function (in real usage, we output query and read response)\ndouble divine(const vector<pair<int,int>> &cells) {\n    int k = (int)cells.size();\n    // Output query\n    cout << \"q \" << k;\n    for (auto &p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    double o;\n    cin >> o;\n    return o;\n}\n\n// Drill function\nint drill(int i, int j) {\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    int v;\n    cin >> v;\n    return v;\n}\n\n// Answer function\nvoid answer(const vector<pair<int,int>> &pos) {\n    cout << \"a \" << pos.size();\n    for (auto &p : pos) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int res;\n    cin >> res;\n    if (res == 1) exit(0);\n}\n\nint main() {\n    // Read initial info\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        fields[k].d = d;\n        fields[k].cells.resize(d);\n        int min_i = N, min_j = N, max_i = 0, max_j = 0;\n        for (int t = 0; t < d; ++t) {\n            int i, j;\n            cin >> i >> j;\n            fields[k].cells[t] = {i, j};\n            min_i = min(min_i, i);\n            min_j = min(min_j, j);\n            max_i = max(max_i, i);\n            max_j = max(max_j, j);\n        }\n        fields[k].h = max_i - min_i + 1;\n        fields[k].w = max_j - min_j + 1;\n        // normalize to (0,0)\n        for (auto &p : fields[k].cells) {\n            p.first -= min_i;\n            p.second -= min_j;\n        }\n    }\n\n    // Initialize belief to 0\n    belief.assign(N, vector<double>(N, 0.0));\n    occupied_by_shape.assign(N, vector<bool>(N, false));\n    vector<pair<int,int>> positive_cells;\n\n    // Phase 1: large set divinations to get rough estimate\n    // Example: divination on all cells (cost ~1/sqrt(N^2) very small)\n    {\n        vector<pair<int,int>> all;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                all.push_back({i, j});\n        double o = divine(all);\n        double k = (double)all.size();\n        double v_total = (o - k * eps) / (1 - 2*eps);\n        double avg = v_total / k;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                belief[i][j] = avg;\n    }\n\n    // Phase 2: row and column divinations for better localization\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int,int>> row;\n        for (int j = 0; j < N; ++j) row.push_back({i, j});\n        double o = divine(row);\n        double k = (double)row.size();\n        double v_row = (o - k * eps) / (1 - 2*eps);\n        double avg = v_row / k;\n        for (int j = 0; j < N; ++j) belief[i][j] = (belief[i][j] + avg) / 2.0;\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int,int>> col;\n        for (int i = 0; i < N; ++i) col.push_back({i, j});\n        double o = divine(col);\n        double k = (double)col.size();\n        double v_col = (o - k * eps) / (1 - 2*eps);\n        double avg = v_col / k;\n        for (int i = 0; i < N; ++i) belief[i][j] = (belief[i][j] + avg) / 2.0;\n    }\n\n    // Phase 3: Place shapes using belief\n    vector<bool> placed(M, false);\n    for (int k = 0; k < M; ++k) {\n        if (placed[k]) continue;\n        double best_score = -1e9;\n        int best_i = -1, best_j = -1;\n        // Slide shape\n        for (int di = 0; di + fields[k].h <= N; ++di) {\n            for (int dj = 0; dj + fields[k].w <= N; ++dj) {\n                vector<pair<int,int>> cand;\n                bool overlap_occupied = false;\n                for (auto &p : fields[k].cells) {\n                    int ni = di + p.first, nj = dj + p.second;\n                    cand.push_back({ni, nj});\n                    if (occupied_by_shape[ni][nj]) overlap_occupied = true;\n                }\n                if (overlap_occupied) continue;\n                double sum_belief = belief_sum(cand);\n                if (sum_belief > best_score) {\n                    best_score = sum_belief;\n                    best_i = di;\n                    best_j = dj;\n                }\n            }\n        }\n        if (best_i == -1) continue; // no place found\n        // Verify by divination\n        vector<pair<int,int>> verify_cells;\n        for (auto &p : fields[k].cells) verify_cells.push_back({best_i + p.first, best_j + p.second});\n        double o = divine(verify_cells);\n        double expected = fields[k].d; // if exactly one shape there, but could be more\n        double var = verify_cells.size() * eps * (1 - eps);\n        double stddev = sqrt(var);\n        // accept if within 2 sigma\n        if (fabs(o - expected) <= 2 * stddev + 1e-6) {\n            // place shape\n            placed[k] = true;\n            for (auto &p : verify_cells) {\n                occupied_by_shape[p.first][p.second] = true;\n                belief[p.first][p.second] += 1.0; // adjust belief\n            }\n        }\n    }\n\n    // Phase 4: Drill uncertain positive cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (belief[i][j] > 0.5 && !occupied_by_shape[i][j]) {\n                int v = drill(i, j);\n                if (v > 0) occupied_by_shape[i][j] = true;\n                belief[i][j] = v;\n            }\n        }\n    }\n\n    // Collect all positive cells\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (occupied_by_shape[i][j] || belief[i][j] > 0.5)\n                positive_cells.push_back({i, j});\n\n    answer(positive_cells);\n\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <cmath>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\n// Recursively assign regions to slots.\nvoid assign_regions(vector<Rect>& rects, const vector<pair<int,int>>& slot_order,\n                    int start_idx, int end_idx,\n                    int i0, int j0, int i1, int j1) {\n    // slot_order is sorted by target_area descending, but we only use the indices.\n    if (start_idx >= end_idx) return;\n    if (start_idx + 1 == end_idx) {\n        int idx = slot_order[start_idx].second;\n        rects[idx] = {i0, j0, i1, j1};\n        return;\n    }\n    // Compute total target areas of these slots\n    // We need target areas, which are stored in slot_order's first element.\n    long long total_area = 0;\n    for (int i = start_idx; i < end_idx; ++i) {\n        total_area += slot_order[i].first;\n    }\n    // Split region along longer side\n    int height = i1 - i0;\n    int width = j1 - j0;\n    if (height >= width) {\n        // split horizontally\n        long long area_up = 0;\n        int split_pos = start_idx;\n        long long half_area = (total_area + 1) / 2; // try to split area roughly in half\n        long long cumulative = 0;\n        for (int i = start_idx; i < end_idx - 1; ++i) {\n            cumulative += slot_order[i].first;\n            if (cumulative >= half_area) {\n                split_pos = i + 1;\n                break;\n            }\n        }\n        // Convert area to height\n        long long area_first_half = 0;\n        for (int i = start_idx; i < split_pos; ++i) area_first_half += slot_order[i].first;\n        int split_i = i0 + (int)((area_first_half * (long long)height + total_area/2) / total_area);\n        if (split_i <= i0) split_i = i0 + 1;\n        if (split_i >= i1) split_i = i1 - 1;\n        assign_regions(rects, slot_order, start_idx, split_pos, i0, j0, split_i, j1);\n        assign_regions(rects, slot_order, split_pos, end_idx, split_i, j0, i1, j1);\n    } else {\n        // split vertically\n        long long area_left = 0;\n        int split_pos = start_idx;\n        long long half_area = (total_area + 1) / 2;\n        long long cumulative = 0;\n        for (int i = start_idx; i < end_idx - 1; ++i) {\n            cumulative += slot_order[i].first;\n            if (cumulative >= half_area) {\n                split_pos = i + 1;\n                break;\n            }\n        }\n        long long area_first_half = 0;\n        for (int i = start_idx; i < split_pos; ++i) area_first_half += slot_order[i].first;\n        int split_j = j0 + (int)((area_first_half * (long long)width + total_area/2) / total_area);\n        if (split_j <= j0) split_j = j0 + 1;\n        if (split_j >= j1) split_j = j1 - 1;\n        assign_regions(rects, slot_order, start_idx, split_pos, i0, j0, i1, split_j);\n        assign_regions(rects, slot_order, split_pos, end_idx, i0, split_j, i1, j1);\n    }\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    // Compute target areas for each slot: use 90th percentile of demands.\n    vector<long long> target(N);\n    for (int k = 0; k < N; ++k) {\n        vector<int> vals(D);\n        for (int d = 0; d < D; ++d) vals[d] = a[d][k];\n        sort(vals.begin(), vals.end());\n        int idx = (int)(D * 0.9);\n        if (idx >= D) idx = D - 1;\n        target[k] = vals[idx];\n    }\n\n    // Scale targets if total exceeds available area.\n    long long total_target = 0;\n    for (long long t : target) total_target += t;\n    long long avail_area = (long long)W * W;\n    if (total_target > avail_area) {\n        for (int k = 0; k < N; ++k) {\n            target[k] = target[k] * avail_area / total_target;\n            if (target[k] < 1) target[k] = 1; // at least 1\n        }\n    }\n\n    // Sort slots by target area descending\n    vector<pair<int,int>> slot_order; // (area, index)\n    for (int k = 0; k < N; ++k) {\n        slot_order.emplace_back((int)target[k], k);\n    }\n    sort(slot_order.begin(), slot_order.end(), greater<pair<int,int>>());\n\n    vector<Rect> rects(N);\n    assign_regions(rects, slot_order, 0, N, 0, 0, W, W);\n\n    // Output same rectangles for all days\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cout << rects[k].i0 << \" \" << rects[k].j0 << \" \"\n                 << rects[k].i1 << \" \" << rects[k].j1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\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<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> a[i][j];\n\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int s = 0; s < M; s++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> stamps[s][i][j];\n\n    vector<vector<int>> board = a;\n    vector<tuple<int,int,int>> ops;\n\n    // Greedy selection\n    for (int step = 0; step < K; step++) {\n        int best_m = -1, best_p = -1, best_q = -1;\n        long long best_gain = -1;\n\n        for (int m_idx = 0; m_idx < M; m_idx++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    long long gain = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            int old_val = board[p+i][q+j];\n                            int new_val = old_val + stamps[m_idx][i][j];\n                            gain += (new_val % MOD) - (old_val % MOD);\n                        }\n                    }\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_m = m_idx;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_m == -1) break;\n        ops.emplace_back(best_m, best_p, best_q);\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                board[best_p+i][best_q+j] += stamps[best_m][i][j];\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &[m_idx, p, q] : ops)\n        cout << m_idx << ' ' << p << ' ' << q << '\\n';\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\n// Direction vectors: U, D, L, R\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dir_chars[] = {'U', 'D', 'L', 'R'};\n\nstruct Crane {\n    int x, y;\n    bool holding;\n    int container_id;\n    bool is_large;\n    bool bombed;\n};\n\nstruct State {\n    vector<vector<int>> grid; // -1 if empty, else container id\n    vector<Crane> cranes;\n    vector<queue<int>> receiving_queues; // containers waiting at each receiving gate\n    vector<vector<int>> dispatch_target; // expected dispatch order for each gate\n    int dispatched_count;\n    vector<int> dispatched_containers[5]; // actual dispatch log per gate\n    \n    State() : grid(N, vector<int>(N, -1)) {}\n};\n\n// BFS to find path avoiding obstacles\nvector<pair<int,int>> find_path(int sx, int sy, int ex, int ey, \n                                 const vector<vector<int>>& grid,\n                                 const set<pair<int,int>>& occupied,\n                                 int crane_idx, bool carrying, bool is_large) {\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    queue<pair<int,int>> q;\n    \n    q.push({sx, sy});\n    visited[sx][sy] = true;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        \n        if (x == ex && y == ey) {\n            // Reconstruct path\n            vector<pair<int,int>> path;\n            int cx = x, cy = y;\n            while (cx != sx || cy != sy) {\n                path.push_back({cx, cy});\n                tie(cx, cy) = parent[cx][cy];\n            }\n            reverse(path.begin(), path.end());\n            return path;\n        }\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) continue;\n            if (visited[nx][ny]) continue;\n            \n            // Check if we can move there\n            if (carrying && !is_large && grid[nx][ny] != -1) continue;\n            if (occupied.count({nx, ny})) continue;\n            \n            visited[nx][ny] = true;\n            parent[nx][ny] = {x, y};\n            q.push({nx, ny});\n        }\n    }\n    return {}; // No path found\n}\n\n// Get direction from (x1,y1) to (x2,y2)\nchar get_dir(int x1, int y1, int x2, int y2) {\n    if (x2 == x1 - 1) return 'U';\n    if (x2 == x1 + 1) return 'D';\n    if (y2 == y1 - 1) return 'L';\n    if (y2 == y1 + 1) return 'R';\n    return '.';\n}\n\n// Check if a container is at a dispatch gate and should be dispatched\nbool can_dispatch(int container_id, int gate_row) {\n    int expected_gate = container_id / N;\n    return expected_gate == gate_row;\n}\n\n// Target dispatch order for each gate: N*i to N*i+N-1 in order\nint get_target_gate(int container_id) {\n    return container_id / N;\n}\n\nint get_target_order(int container_id) {\n    return container_id % N;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<vector<int>> A(N, vector<int>(N));\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    // Initialize state\n    State state;\n    state.receiving_queues.resize(N);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            state.receiving_queues[i].push(A[i][j]);\n        }\n    }\n    \n    // Initialize cranes\n    for (int i = 0; i < N; i++) {\n        Crane c;\n        c.x = i;\n        c.y = 0;\n        c.holding = false;\n        c.container_id = -1;\n        c.is_large = (i == 0);\n        c.bombed = false;\n        state.cranes.push_back(c);\n    }\n    \n    // Dispatch target: for each gate row i, we need N*i to N*i+N-1 in order\n    for (int i = 0; i < N; i++) {\n        vector<int> expected;\n        for (int j = 0; j < N; j++) {\n            expected.push_back(i * N + j);\n        }\n        state.dispatch_target.push_back(expected);\n    }\n    \n    vector<string> output(N); // One string per crane\n    \n    // Simple strategy:\n    // For each turn up to MAX_TURNS\n    // 1. Check receiving gates and spawn containers\n    // 2. Large crane: pick up containers and deliver to correct dispatch gate area\n    // 3. Small cranes: help move containers around\n    // 4. Dispatch containers at gates\n    \n    // We'll use a greedy approach:\n    // - Large crane picks up containers from receiving gates or buffer and delivers to dispatch gates\n    // - Small cranes help arrange containers\n    \n    // For each dispatch gate, we want containers in order\n    // Keep track of next expected container for each gate\n    vector<int> next_expected(N);\n    for (int i = 0; i < N; i++) next_expected[i] = i * N;\n    \n    // Buffer positions: columns 1-3 can be used\n    // Prioritize delivering to correct dispatch gates\n    \n    auto get_occupied = [&]() {\n        set<pair<int,int>> occ;\n        for (int c = 0; c < N; c++) {\n            if (!state.cranes[c].bombed) {\n                occ.insert({state.cranes[c].x, state.cranes[c].y});\n            }\n        }\n        return occ;\n    };\n    \n    // Main simulation loop\n    int turn = 0;\n    bool all_dispatched = false;\n    \n    while (turn < MAX_TURNS && !all_dispatched) {\n        vector<char> actions(N, '.');\n        \n        // Step 1: Spawn containers at receiving gates\n        for (int i = 0; i < N; i++) {\n            if (!state.receiving_queues[i].empty() && state.grid[i][0] == -1) {\n                bool crane_there = false;\n                for (auto& c : state.cranes) {\n                    if (!c.bombed && c.x == i && c.y == 0 && c.holding) {\n                        crane_there = true;\n                        break;\n                    }\n                }\n                if (!crane_there) {\n                    state.grid[i][0] = state.receiving_queues[i].front();\n                    state.receiving_queues[i].pop();\n                }\n            }\n        }\n        \n        // Step 2: Determine actions for each crane\n        auto occ = get_occupied();\n        \n        for (int c = 0; c < N; c++) {\n            if (state.cranes[c].bombed) continue;\n            \n            auto& crane = state.cranes[c];\n            char action = '.';\n            \n            if (crane.is_large) {\n                // Large crane strategy:\n                // If holding a container, deliver to its target dispatch gate\n                // If not holding, pick up a container that needs to be delivered\n                \n                if (crane.holding) {\n                    int target_gate = get_target_gate(crane.container_id);\n                    int target_x = target_gate;\n                    int target_y = N - 1;\n                    \n                    // If at dispatch gate, release\n                    if (crane.y == target_y && crane.x == target_x) {\n                        action = 'Q';\n                    } else {\n                        // Move towards dispatch gate\n                        // Find path\n                        auto path = find_path(crane.x, crane.y, target_x, target_y, \n                                             state.grid, occ, c, true, true);\n                        if (!path.empty()) {\n                            int nx = path[0].first, ny = path[0].second;\n                            action = get_dir(crane.x, crane.y, nx, ny);\n                        }\n                    }\n                } else {\n                    // Find a container to pick up\n                    // Priority: containers that are at receiving gates or buffer\n                    // that need to go to dispatch gates\n                    \n                    // Look for containers near dispatch gates that are out of order\n                    // Simple: find any container and deliver it\n                    bool found = false;\n                    \n                    // Check receiving gates first\n                    for (int i = 0; i < N && !found; i++) {\n                        if (state.grid[i][0] != -1 && state.grid[i][0] != -1) {\n                            int cid = state.grid[i][0];\n                            int tg = get_target_gate(cid);\n                            // If large crane can get there\n                            auto path = find_path(crane.x, crane.y, i, 0, \n                                                 state.grid, occ, c, false, true);\n                            if (!path.empty()) {\n                                if (crane.x == i && crane.y == 0) {\n                                    action = 'P';\n                                    found = true;\n                                } else {\n                                    action = get_dir(crane.x, crane.y, path[0].first, path[0].second);\n                                    found = true;\n                                }\n                            }\n                        }\n                    }\n                    \n                    // Check buffer areas\n                    if (!found) {\n                        for (int i = 0; i < N && !found; i++) {\n                            for (int j = 1; j < N - 1 && !found; j++) {\n                                if (state.grid[i][j] != -1) {\n                                    int cid = state.grid[i][j];\n                                    auto path = find_path(crane.x, crane.y, i, j, \n                                                         state.grid, occ, c, false, true);\n                                    if (!path.empty()) {\n                                        if (crane.x == i && crane.y == j) {\n                                            action = 'P';\n                                            found = true;\n                                        } else {\n                                            action = get_dir(crane.x, crane.y, path[0].first, path[0].second);\n                                            found = true;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    \n                    // Check dispatch gates for containers that need to be reordered\n                    if (!found) {\n                        for (int i = 0; i < N && !found; i++) {\n                            if (state.grid[i][N-1] != -1) {\n                                int cid = state.grid[i][N-1];\n                                if (cid != next_expected[i]) {\n                                    auto path = find_path(crane.x, crane.y, i, N-1, \n                                                         state.grid, occ, c, false, true);\n                                    if (!path.empty()) {\n                                        if (crane.x == i && crane.y == N-1) {\n                                            action = 'P';\n                                            found = true;\n                                        } else {\n                                            action = get_dir(crane.x, crane.y, path[0].first, path[0].second);\n                                            found = true;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            } else {\n                // Small crane strategy: help move containers from receiving gates to buffer\n                // or help with sorting near dispatch gates\n                \n                if (crane.holding) {\n                    // Move to buffer area (columns 1-3) and release\n                    // Target: nearest empty buffer spot\n                    bool released = false;\n                    \n                    // Try to find empty buffer spot\n                    for (int j = 1; j < N - 1 && !released; j++) {\n                        for (int i = 0; i < N && !released; i++) {\n                            if (state.grid[i][j] == -1) {\n                                if (crane.x == i && crane.y == j) {\n                                    action = 'Q';\n                                    released = true;\n                                } else {\n                                    auto path = find_path(crane.x, crane.y, i, j, \n                                                         state.grid, occ, c, true, false);\n                                    if (!path.empty()) {\n                                        action = get_dir(crane.x, crane.y, path[0].first, path[0].second);\n                                        released = true;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (!released) {\n                        // Move towards receiving gate area and release\n                        for (int j = 1; j < N - 1; j++) {\n                            if (crane.y == j) {\n                                action = 'Q';\n                                break;\n                            }\n                        }\n                        if (action == '.') {\n                            // Move right\n                            if (crane.y < N - 2) {\n                                auto path = find_path(crane.x, crane.y, crane.x, crane.y + 1, \n                                                     state.grid, occ, c, true, false);\n                                if (!path.empty()) action = 'R';\n                            }\n                        }\n                    }\n                } else {\n                    // Pick up container from receiving gate\n                    if (crane.y == 0 && state.grid[crane.x][0] != -1) {\n                        action = 'P';\n                    } else {\n                        // Move to own receiving gate\n                        if (crane.y > 0) {\n                            auto path = find_path(crane.x, crane.y, crane.x, 0, \n                                                 state.grid, occ, c, false, false);\n                            if (!path.empty()) {\n                                action = get_dir(crane.x, crane.y, path[0].first, path[0].second);\n                            }\n                        }\n                    }\n                }\n            }\n            \n            actions[c] = action;\n        }\n        \n        // Step 3: Apply actions\n        // First, validate all actions to avoid conflicts\n        vector<int> new_x(N), new_y(N);\n        vector<bool> will_pickup(N, false), will_release(N, false);\n        vector<bool> will_bomb(N, false);\n        \n        for (int c = 0; c < N; c++) {\n            if (state.cranes[c].bombed) continue;\n            new_x[c] = state.cranes[c].x;\n            new_y[c] = state.cranes[c].y;\n            \n            char act = actions[c];\n            if (act == 'U') new_x[c]--;\n            else if (act == 'D') new_x[c]++;\n            else if (act == 'L') new_y[c]--;\n            else if (act == 'R') new_y[c]++;\n            else if (act == 'P') will_pickup[c] = true;\n            else if (act == 'Q') will_release[c] = true;\n            else if (act == 'B') will_bomb[c] = true;\n        }\n        \n        // Check for conflicts (two cranes trying to occupy same square or swap)\n        bool conflict = false;\n        for (int c1 = 0; c1 < N && !conflict; c1++) {\n            if (state.cranes[c1].bombed) continue;\n            for (int c2 = c1 + 1; c2 < N && !conflict; c2++) {\n                if (state.cranes[c2].bombed) continue;\n                // They shouldn't end in same square\n                if (new_x[c1] == new_x[c2] && new_y[c1] == new_y[c2]) {\n                    conflict = true;\n                }\n                // They shouldn't swap positions\n                if (new_x[c1] == state.cranes[c2].x && new_y[c1] == state.cranes[c2].y &&\n                    new_x[c2] == state.cranes[c1].x && new_y[c2] == state.cranes[c1].y) {\n                    conflict = true;\n                }\n            }\n        }\n        \n        // Also check small cranes moving onto containers while carrying\n        for (int c = 0; c < N; c++) {\n            if (state.cranes[c].bombed || state.cranes[c].is_large) continue;\n            if (state.cranes[c].holding) {\n                if (state.grid[new_x[c]][new_y[c]] != -1) {\n                    conflict = true;\n                }\n            }\n        }\n        \n        if (conflict) {\n            // Cancel all movements, just do '.'\n            for (int c = 0; c < N; c++) actions[c] = '.';\n            for (int c = 0; c < N; c++) {\n                new_x[c] = state.cranes[c].x;\n                new_y[c] = state.cranes[c].y;\n            }\n            fill(will_pickup.begin(), will_pickup.end(), false);\n            fill(will_release.begin(), will_release.end(), false);\n            fill(will_bomb.begin(), will_bomb.end(), false);\n        }\n        \n        // Apply actions\n        for (int c = 0; c < N; c++) {\n            if (state.cranes[c].bombed) continue;\n            \n            if (will_pickup[c]) {\n                if (!state.cranes[c].holding && state.grid[state.cranes[c].x][state.cranes[c].y] != -1) {\n                    state.cranes[c].holding = true;\n                    state.cranes[c].container_id = state.grid[state.cranes[c].x][state.cranes[c].y];\n                    state.grid[state.cranes[c].x][state.cranes[c].y] = -1;\n                }\n            } else if (will_release[c]) {\n                if (state.cranes[c].holding && state.grid[state.cranes[c].x][state.cranes[c].y] == -1) {\n                    state.grid[state.cranes[c].x][state.cranes[c].y] = state.cranes[c].container_id;\n                    state.cranes[c].holding = false;\n                    state.cranes[c].container_id = -1;\n                }\n            } else if (will_bomb[c]) {\n                if (!state.cranes[c].holding) {\n                    state.cranes[c].bombed = true;\n                }\n            } else {\n                state.cranes[c].x = new_x[c];\n                state.cranes[c].y = new_y[c];\n            }\n        }\n        \n        // Step 3 (after): Dispatch containers\n        for (int i = 0; i < N; i++) {\n            if (state.grid[i][N-1] != -1) {\n                int cid = state.grid[i][N-1];\n                if (cid == next_expected[i]) {\n                    // Correct container at correct gate\n                    state.dispatched_containers[i].push_back(cid);\n                    state.grid[i][N-1] = -1;\n                    state.dispatched_count++;\n                    next_expected[i]++;\n                    if (next_expected[i] >= (i + 1) * N) next_expected[i] = (i + 1) * N; // Done\n                }\n                // Otherwise leave it (wrong gate or wrong order)\n            }\n        }\n        \n        // Record actions\n        for (int c = 0; c < N; c++) {\n            output[c] += actions[c];\n        }\n        \n        turn++;\n        \n        // Check if all dispatched\n        all_dispatched = (state.dispatched_count == N * N);\n        \n        // Safety: check if all cranes bombed and nothing happening\n        bool all_bombed = true;\n        for (auto& cr : state.cranes) if (!cr.bombed) all_bombed = false;\n        if (all_bombed) break;\n    }\n    \n    // Pad all strings to same length\n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)output[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)output[i].size() < max_len) output[i] += '.';\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << output[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> h[i][j];\n\n    const int max_turns = 100000;\n    vector<string> operations;\n    int x = 0, y = 0, load = 0;\n\n    auto move_to = [&](int tx, int ty) {\n        while (x < tx) { operations.push_back(\"D\"); x++; }\n        while (x > tx) { operations.push_back(\"U\"); x--; }\n        while (y < ty) { operations.push_back(\"R\"); y++; }\n        while (y > ty) { operations.push_back(\"L\"); y--; }\n    };\n\n    while (true) {\n        // find positive cell\n        int best_dist = 1e9, px = -1, py = -1;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (h[i][j] > 0) {\n                    int dist = abs(x - i) + abs(y - j);\n                    if (dist < best_dist) {\n                        best_dist = dist;\n                        px = i; py = j;\n                    }\n                }\n            }\n        }\n        if (px == -1) break; // no more positives\n\n        move_to(px, py);\n        int amount = h[px][py];\n        operations.push_back(\"+\" + to_string(amount));\n        h[px][py] = 0;\n        load += amount;\n\n        // find nearest negative\n        best_dist = 1e9;\n        int nx = -1, ny = -1;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (h[i][j] < 0) {\n                    int dist = abs(x - i) + abs(y - j);\n                    if (dist < best_dist) {\n                        best_dist = dist;\n                        nx = i; ny = j;\n                    }\n                }\n            }\n        }\n        if (nx == -1) break; // should not happen since sum zero\n\n        move_to(nx, ny);\n        int need = -h[nx][ny];\n        int unload = min(load, need);\n        operations.push_back(\"-\" + to_string(unload));\n        h[nx][ny] += unload;\n        load -= unload;\n    }\n\n    // output\n    for (const auto &s : operations) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <set>\n#include <tuple>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1); // 60\n    vector<vector<int>> X(seed_count, vector<int>(M, 0));\n\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 each turn\n    for (int t = 0; t < T; t++) {\n        // Calculate value (sum) for each seed\n        vector<pair<int, int>> seed_values; // (value, index)\n        for (int i = 0; i < seed_count; i++) {\n            int sum = 0;\n            for (int j = 0; j < M; j++) {\n                sum += X[i][j];\n            }\n            seed_values.push_back({sum, i});\n        }\n        \n        // Sort by value descending\n        sort(seed_values.begin(), seed_values.end(), greater<pair<int, int>>());\n        \n        // Select top N*N seeds for planting\n        vector<int> selected;\n        for (int i = 0; i < N * N; i++) {\n            selected.push_back(seed_values[i].second);\n        }\n        \n        // Arrange on grid\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        \n        if (t < 3) {\n            // Early turns: snake pattern to bring similar-quality seeds together\n            // Sort selected by value for snake\n            vector<pair<int, int>> sel_vals;\n            for (int idx : selected) {\n                int sum = 0;\n                for (int j = 0; j < M; j++) sum += X[idx][j];\n                sel_vals.push_back({sum, idx});\n            }\n            sort(sel_vals.begin(), sel_vals.end(), greater<pair<int, int>>());\n            \n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                if (i % 2 == 0) {\n                    for (int j = 0; j < N; j++) {\n                        A[i][j] = sel_vals[pos++].second;\n                    }\n                } else {\n                    for (int j = N - 1; j >= 0; j--) {\n                        A[i][j] = sel_vals[pos++].second;\n                    }\n                }\n            }\n        } else if (t < 7) {\n            // Middle turns: block pattern - checkerboard of top seeds\n            // Place top seeds in a block at center, others around\n            vector<pair<int, int>> sel_vals;\n            for (int idx : selected) {\n                int sum = 0;\n                for (int j = 0; j < M; j++) sum += X[idx][j];\n                sel_vals.push_back({sum, idx});\n            }\n            sort(sel_vals.begin(), sel_vals.end(), greater<pair<int, int>>());\n            \n            // Place in a spiral-like pattern from center\n            int cx = N / 2, cy = N / 2;\n            int pos = 0;\n            vector<pair<int, int>> order;\n            for (int r = 0; r < N; r++) {\n                for (int i = cx - r; i <= cx + r; i++) {\n                    for (int j = cy - r; j <= cy + r; j++) {\n                        if (i >= 0 && i < N && j >= 0 && j < N && A[i][j] == -1) {\n                            if (abs(i - cx) == r || abs(j - cy) == r) {\n                                order.push_back({i, j});\n                            }\n                        }\n                    }\n                }\n            }\n            for (auto [i, j] : order) {\n                if (pos < (int)sel_vals.size()) {\n                    A[i][j] = sel_vals[pos++].second;\n                }\n            }\n        } else {\n            // Late turns: concentrate best seeds together\n            // Find the best seed and place it with other good seeds around it\n            vector<pair<int, int>> sel_vals;\n            for (int idx : selected) {\n                int sum = 0;\n                for (int j = 0; j < M; j++) sum += X[idx][j];\n                sel_vals.push_back({sum, idx});\n            }\n            sort(sel_vals.begin(), sel_vals.end(), greater<pair<int, int>>());\n            \n            // Checkerboard pattern: alternating high and medium seeds\n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if ((i + j) % 2 == 0 && pos < (int)sel_vals.size()) {\n                        A[i][j] = sel_vals[pos++].second;\n                    }\n                }\n            }\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if ((i + j) % 2 == 1 && pos < (int)sel_vals.size()) {\n                        A[i][j] = sel_vals[pos++].second;\n                    }\n                }\n            }\n        }\n        \n        // Output 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 << endl;\n        }\n        cout.flush();\n        \n        // Read new 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 <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <cassert>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\nusing namespace std;\n\n// ---------- Constants ----------\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char MOVE_CHAR[4] = {'R', 'D', 'L', 'U'};\n\n// ---------- Types ----------\nstruct Point {\n    int x, y;\n    Point operator+(Point o) const { return {x+o.x, y+o.y}; }\n    bool operator==(Point o) const { return x==o.x && y==o.y; }\n};\n\n// ---------- Global state ----------\nint N, M, V;\nvector<string> start_grid, target_grid;\nvector<pair<int,int>> start_positions, target_positions;\nvector<int> parent;\nvector<int> length_to_parent;\nvector<int> leaf_order; // leaves index\nint root_x, root_y;\nvector<int> angles; // direction index (0: right, 1: down, 2: left, 3: up)\nvector<bool> holding; // true if fingertip carrying takoyaki\nvector<Point> fingertip_positions;\nvector<vector<int>> children;\n\n// ---------- Function declarations ----------\nvoid design_tree();\nvoid compute_fingertip_positions();\nvoid simulate_turn(vector<string>& commands, int& turn);\nbool pick_if_possible(int leaf_idx);\nbool place_if_possible(int leaf_idx);\nvoid move_root_to_target(Point target, vector<string>& commands);\nvoid set_angle(int node, int desired_angle, vector<string>& commands);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N >> M >> V;\n    start_grid.resize(N);\n    target_grid.resize(N);\n    for (int i = 0; i < N; i++) cin >> start_grid[i];\n    for (int i = 0; i < N; i++) cin >> target_grid[i];\n\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (start_grid[i][j] == '1')\n                start_positions.emplace_back(i, j);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (target_grid[i][j] == '1')\n                target_positions.emplace_back(i, j);\n\n    // Design tree\n    design_tree();\n\n    // Set initial root near center of start positions\n    int sumx = 0, sumy = 0;\n    for (auto& p : start_positions) { sumx += p.first; sumy += p.second; }\n    root_x = sumx / M;\n    root_y = sumy / M;\n    root_x = min(max(root_x, 0), N-1);\n    root_y = min(max(root_y, 0), N-1);\n\n    // Output tree info\n    int Vp = parent.size();\n    cout << Vp << \"\\n\";\n    for (int i = 1; i < Vp; i++)\n        cout << parent[i] << \" \" << length_to_parent[i] << \"\\n\";\n    cout << root_x << \" \" << root_y << \"\\n\";\n\n    angles.assign(Vp, 0); // all edges initially to the right\n    holding.assign(Vp, false);\n\n    // Identify leaves\n    vector<bool> is_leaf(Vp, false);\n    for (int i = 0; i < Vp; i++) {\n        if (children[i].empty()) {\n            is_leaf[i] = true;\n            leaf_order.push_back(i);\n        }\n    }\n\n    // Simulation\n    vector<string> commands;\n    int turn = 0;\n    const int MAX_TURNS = 100000;\n\n    // Simple greedy assignment: for each leaf, find nearest start->target pair\n    vector<tuple<int,int,int>> tasks; // (dist, start_idx, target_idx)\n    for (size_t si = 0; si < start_positions.size(); si++) {\n        int best_ti = -1;\n        int best_dist = 1e9;\n        for (size_t ti = 0; ti < target_positions.size(); ti++) {\n            int d = abs(start_positions[si].first - target_positions[ti].first)\n                   + abs(start_positions[si].second - target_positions[ti].second);\n            if (d < best_dist) {\n                best_dist = d;\n                best_ti = ti;\n            }\n        }\n        tasks.emplace_back(best_dist, si, best_ti);\n    }\n    sort(tasks.begin(), tasks.end());\n\n    vector<bool> start_done(start_positions.size(), false);\n    vector<bool> target_done(target_positions.size(), false);\n    int placed = 0;\n\n    auto try_move_leaf_to = [&](int leaf, Point target) {\n        // move root toward target, then set leaf angle\n        while (turn < MAX_TURNS) {\n            Point cur = fingertip_positions[leaf];\n            if (cur.x == target.x && cur.y == target.y) break;\n            // move root greedily\n            int dx = target.x - cur.x;\n            int dy = target.y - cur.y;\n            int mx = (dx > 0) - (dx < 0);\n            int my = (dy > 0) - (dy < 0);\n            if (mx != 0 || my != 0) {\n                int dir = -1;\n                if (mx == 1 && my == 0) dir = 1; // down\n                else if (mx == -1 && my == 0) dir = 3; // up\n                else if (mx == 0 && my == 1) dir = 0; // right\n                else if (mx == 0 && my == -1) dir = 2; // left\n                else if (mx == 1 && my == 1) dir = (rand()%2) ? 1 : 0;\n                else if (mx == -1 && my == 1) dir = (rand()%2) ? 3 : 0;\n                else if (mx == 1 && my == -1) dir = (rand()%2) ? 1 : 2;\n                else if (mx == -1 && my == -1) dir = (rand()%2) ? 3 : 2;\n                if (dir >= 0) {\n                    int nx = root_x + DX[dir];\n                    int ny = root_y + DY[dir];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        root_x = nx; root_y = ny;\n                        string cmd(2*Vp, '.');\n                        cmd[0] = MOVE_CHAR[dir];\n                        commands.push_back(cmd);\n                        turn++;\n                        compute_fingertip_positions();\n                        continue;\n                    }\n                }\n            }\n            // rotation to adjust fingertip if close\n            if (abs(cur.x - target.x) <= 1 && abs(cur.y - target.y) <= 1) {\n                for (int a = 0; a < 4; a++) {\n                    angles[leaf] = a;\n                    compute_fingertip_positions();\n                    if (fingertip_positions[leaf].x == target.x && fingertip_positions[leaf].y == target.y) {\n                        string cmd(2*Vp, '.');\n                        cmd[leaf] = (a == (angles[leaf]+3)%4) ? 'L' : ((a == (angles[leaf]+1)%4) ? 'R' : '.');\n                        commands.push_back(cmd);\n                        turn++;\n                        return;\n                    }\n                }\n            }\n        }\n    };\n\n    for (auto& [dist, si, ti] : tasks) {\n        if (start_done[si] || target_done[ti]) continue;\n        Point sp = {start_positions[si].first, start_positions[si].second};\n        Point tp = {target_positions[ti].first, target_positions[ti].second};\n\n        int leaf = leaf_order[0]; // simple: use first leaf for everything\n\n        // go to start\n        try_move_leaf_to(leaf, sp);\n        // pick\n        if (fingertip_positions[leaf] == sp && !holding[leaf] && start_grid[sp.x][sp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = true;\n            start_grid[sp.x][sp.y] = '0';\n            turn++;\n        }\n        // go to target\n        try_move_leaf_to(leaf, tp);\n        // place\n        if (fingertip_positions[leaf] == tp && holding[leaf] && target_grid[tp.x][tp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = false;\n            target_grid[tp.x][tp.y] = '0';\n            placed++;\n            turn++;\n        }\n        start_done[si] = true;\n        target_done[ti] = true;\n    }\n\n    for (auto& s : commands) cout << s << \"\\n\";\n    return 0;\n}\n\nvoid design_tree() {\n    // simple star-like: root + V-1 leaves with length 1..N-1\n    parent.push_back(-1);\n    length_to_parent.push_back(0);\n    children.resize(1);\n    for (int i = 1; i < V; i++) {\n        parent.push_back(0);\n        length_to_parent.push_back(1);\n        children[0].push_back(i);\n        children.push_back({});\n    }\n}\n\nvoid compute_fingertip_positions() {\n    fingertip_positions.resize(parent.size());\n    fingertip_positions[0] = {root_x, root_y};\n    for (int i = 1; i < (int)parent.size(); i++) {\n        int p = parent[i];\n        int len = length_to_parent[i];\n        int dir = angles[i];\n        Point offset = {DX[dir]*len, DY[dir]*len};\n        fingertip_positions[i] = fingertip_positions[p] + offset;\n    }\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_COORD = 100000;\n\nstruct Point {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<Point> mackerels(N), sardines(N);\n    for (int i = 0; i < N; i++) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; i++) cin >> sardines[i].x >> sardines[i].y;\n    \n    // Strategy: Use a grid to approximate density, then refine with actual coordinates\n    \n    const int G = 100;\n    int cellW = (MAX_COORD + G - 1) / G;\n    int cellH = (MAX_COORD + G - 1) / G;\n    \n    vector<vector<int>> mGrid(G, vector<int>(G, 0));\n    vector<vector<int>> sGrid(G, vector<int>(G, 0));\n    \n    for (const auto& p : mackerels) {\n        int cx = min(p.x / cellW, G - 1);\n        int cy = min(p.y / cellH, G - 1);\n        mGrid[cy][cx]++;\n    }\n    for (const auto& p : sardines) {\n        int cx = min(p.x / cellW, G - 1);\n        int cy = min(p.y / cellH, G - 1);\n        sGrid[cy][cx]++;\n    }\n    \n    // Value grid\n    vector<vector<int>> val(G, vector<int>(G, 0));\n    for (int i = 0; i < G; i++)\n        for (int j = 0; j < G; j++)\n            val[i][j] = mGrid[i][j] - sGrid[i][j];\n    \n    // 2D prefix sum\n    vector<vector<int>> pref(G + 1, vector<int>(G + 1, 0));\n    for (int i = 0; i < G; i++)\n        for (int j = 0; j < G; j++)\n            pref[i + 1][j + 1] = val[i][j] + pref[i][j + 1] + \n                                 pref[i + 1][j] - pref[i][j];\n    \n    auto getGridSum = [&](int r1, int c1, int r2, int c2) {\n        if (r1 > r2 || c1 > c2) return 0;\n        return pref[r2 + 1][c2 + 1] - pref[r1][c2 + 1] - \n               pref[r2 + 1][c1] + pref[r1][c1];\n    };\n    \n    // Find best rectangle\n    int bestVal = -1e9;\n    int br1 = 0, bc1 = 0, br2 = 0, bc2 = 0;\n    \n    for (int r1 = 0; r1 < G; r1++) {\n        vector<int> rowSum(G, 0);\n        for (int r2 = r1; r2 < G; r2++) {\n            for (int c = 0; c < G; c++) rowSum[c] += val[r2][c];\n            \n            int curr = 0, maxSum = -1e9;\n            int cStart = 0, cBest = 0, cEnd = 0;\n            for (int c = 0; c < G; c++) {\n                if (curr <= 0) { curr = rowSum[c]; cStart = c; }\n                else curr += rowSum[c];\n                if (curr > maxSum) { maxSum = curr; cBest = cStart; cEnd = c; }\n            }\n            if (maxSum > bestVal) {\n                bestVal = maxSum;\n                br1 = r1; br2 = r2; bc1 = cBest; bc2 = cEnd;\n            }\n        }\n    }\n    \n    // Convert to coordinates\n    int x1 = bc1 * cellW;\n    int y1 = br1 * cellH;\n    int x2 = min(MAX_COORD, (bc2 + 1) * cellW);\n    int y2 = min(MAX_COORD, (br2 + 1) * cellH);\n    \n    // Helper to count actual fish\n    auto countInRect = [&](int xl, int xr, int yl, int yr) -> pair<int,int> {\n        int m = 0, s = 0;\n        for (const auto& p : mackerels)\n            if (p.x >= xl && p.x <= xr && p.y >= yl && p.y <= yr) m++;\n        for (const auto& p : sardines)\n            if (p.x >= xl && p.x <= xr && p.y >= yl && p.y <= yr) s++;\n        return {m, s};\n    };\n    \n    // Try to refine boundaries by scanning through sorted fish coordinates\n    vector<int> xs, ys;\n    xs.push_back(0); xs.push_back(MAX_COORD);\n    ys.push_back(0); ys.push_back(MAX_COORD);\n    for (const auto& p : mackerels) { xs.push_back(p.x); ys.push_back(p.y); }\n    for (const auto& p : sardines) { xs.push_back(p.x); ys.push_back(p.y); }\n    \n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n    \n    // Build compressed 2D array for faster counting\n    int XS = xs.size(), YS = ys.size();\n    vector<vector<int>> compM(YS, vector<int>(XS, 0));\n    vector<vector<int>> compS(YS, vector<int>(XS, 0));\n    \n    for (const auto& p : mackerels) {\n        int cx = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int cy = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        compM[cy][cx]++;\n    }\n    for (const auto& p : sardines) {\n        int cx = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int cy = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        compS[cy][cx]++;\n    }\n    \n    // 2D prefix for compressed\n    vector<vector<int>> compPrefM(YS + 1, vector<int>(XS + 1, 0));\n    vector<vector<int>> compPrefS(YS + 1, vector<int>(XS + 1, 0));\n    for (int i = 0; i < YS; i++) {\n        for (int j = 0; j < XS; j++) {\n            compPrefM[i + 1][j + 1] = compM[i][j] + compPrefM[i][j + 1] + \n                                       compPrefM[i + 1][j] - compPrefM[i][j];\n            compPrefS[i + 1][j + 1] = compS[i][j] + compPrefS[i][j + 1] + \n                                       compPrefS[i + 1][j] - compPrefS[i][j];\n        }\n    }\n    \n    auto compCount = [&](int xl, int xr, int yl, int yr) -> pair<int,int> {\n        int ix1 = lower_bound(xs.begin(), xs.end(), xl) - xs.begin();\n        int ix2 = upper_bound(xs.begin(), xs.end(), xr) - xs.begin() - 1;\n        int iy1 = lower_bound(ys.begin(), ys.end(), yl) - ys.begin();\n        int iy2 = upper_bound(ys.begin(), ys.end(), yr) - ys.begin() - 1;\n        \n        if (ix1 > ix2 || iy1 > iy2) return {0, 0};\n        \n        int m = compPrefM[iy2 + 1][ix2 + 1] - compPrefM[iy1][ix2 + 1] - \n                compPrefM[iy2 + 1][ix1] + compPrefM[iy1][ix1];\n        int s = compPrefS[iy2 + 1][ix2 + 1] - compPrefS[iy1][ix2 + 1] - \n                compPrefS[iy2 + 1][ix1] + compPrefS[iy1][ix1];\n        return {m, s};\n    };\n    \n    // Refine each boundary\n    auto [curM, curS] = compCount(x1, x2, y1, y2);\n    int curScore = curM - curS;\n    \n    bool improved = true;\n    while (improved) {\n        improved = false;\n        \n        // Left boundary\n        for (int nx : xs) {\n            if (nx >= x2) continue;\n            auto [m, s] = compCount(nx, x2, y1, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                x1 = nx;\n                improved = true;\n            }\n        }\n        \n        // Right boundary\n        for (int nx : xs) {\n            if (nx <= x1) continue;\n            auto [m, s] = compCount(x1, nx, y1, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                x2 = nx;\n                improved = true;\n            }\n        }\n        \n        // Bottom boundary\n        for (int ny : ys) {\n            if (ny >= y2) continue;\n            auto [m, s] = compCount(x1, x2, ny, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                y1 = ny;\n                improved = true;\n            }\n        }\n        \n        // Top boundary\n        for (int ny : ys) {\n            if (ny <= y1) continue;\n            auto [m, s] = compCount(x1, x2, y1, ny);\n            if (m - s > curScore) {\n                curScore = m - s;\n                y2 = ny;\n                improved = true;\n            }\n        }\n    }\n    \n    // Try L-shaped polygons by cutting out bad corners\n    // We'll evaluate all possible L-shapes and pick the best\n    \n    struct LShape {\n        int type; // 0: \u2518 (bottom-left missing), 1: \u2514 (bottom-right), 2: \u250c (top-right), 3: \u2510 (top-left)\n        int cx, cy; // Inner corner coordinates\n        int score;\n        vector<pair<int,int>> verts;\n    };\n    \n    vector<LShape> candidates;\n    \n    // Simple rectangle as baseline\n    {\n        LShape rect;\n        rect.type = -1;\n        rect.score = curScore;\n        rect.verts = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n        candidates.push_back(rect);\n    }\n    \n    // Try all meaningful inner corner positions\n    // Bottom-left missing: region is [cx,x2]\u00d7[y1,y2] \u222a [x1,x2]\u00d7[cy,y2]\n    // i.e., missing [x1,cx)\u00d7[y1,cy)\n    for (int cx : xs) {\n        if (cx <= x1 || cx > x2) continue;\n        for (int cy : ys) {\n            if (cy <= y1 || cy > y2) continue;\n            \n            // Type 0: bottom-left cut\n            // The polygon is: (cx,y1) -> (x2,y1) -> (x2,y2) -> (x1,y2) -> (x1,cy) -> (cx,cy)\n            // But we need to check score\n            auto [m1, s1] = compCount(cx, x2, y1, y2);  // Right part\n            auto [m2, s2] = compCount(x1, x2, cy, y2);  // Top part (overlaps with right part)\n            auto [mOverlap, sOverlap] = compCount(cx, x2, cy, y2); // Overlap\n            // Actually, simpler: total = right part + left-top part (above cy, left of cx)\n            auto [mLeft, sLeft] = compCount(x1, cx - 1, cy, y2); // Left part above cy\n            \n            int totalM = m1 + mLeft;\n            int totalS = s1 + sLeft;\n            int score = totalM - totalS;\n            \n            if (score > 0) {\n                LShape shape;\n                shape.type = 0;\n                shape.cx = cx; shape.cy = cy;\n                shape.score = score;\n                // Create vertices: start from (cx,cy) go right to (x2,cy) up to (x2,y2) left to (x1,y2) down to (x1,y1) right to (cx,y1) up to (cx,cy)\n                shape.verts = {{cx, cy}, {x2, cy}, {x2, y2}, {x1, y2}, {x1, y1}, {cx, y1}};\n                candidates.push_back(shape);\n            }\n        }\n    }\n    \n    // Similar for other 3 corners (omitted for brevity, but same pattern)\n    // Bottom-right missing\n    for (int cx : xs) {\n        if (cx < x1 || cx >= x2) continue;\n        for (int cy : ys) {\n            if (cy <= y1 || cy > y2) continue;\n            \n            auto [m1, s1] = compCount(x1, cx, y1, y2);  // Left part\n            auto [mRight, sRight] = compCount(cx + 1, x2, cy, y2); // Right part above cy\n            \n            int totalM = m1 + mRight;\n            int totalS = s1 + sRight;\n            int score = totalM - totalS;\n            \n            if (score > 0) {\n                LShape shape;\n                shape.type = 1;\n                shape.cx = cx; shape.cy = cy;\n                shape.score = score;\n                shape.verts = {{cx, cy}, {x1, cy}, {x1, y2}, {x2, y2}, {x2, y1}, {cx, y1}};\n                candidates.push_back(shape);\n            }\n        }\n    }\n    \n    // Top-right missing\n    for (int cx : xs) {\n        if (cx < x1 || cx >= x2) continue;\n        for (int cy : ys) {\n            if (cy < y1 || cy >= y2) continue;\n            \n            auto [m1, s1] = compCount(x1, x2, y1, cy);  // Bottom part\n            auto [mLeft, sLeft] = compCount(x1, cx, cy + 1, y2); // Left part above cy\n            \n            int totalM = m1 + mLeft;\n            int totalS = s1 + sLeft;\n            int score = totalM - totalS;\n            \n            if (score > 0) {\n                LShape shape;\n                shape.type = 2;\n                shape.cx = cx; shape.cy = cy;\n                shape.score = score;\n                shape.verts = {{cx, cy}, {x1, cy}, {x1, y1}, {x2, y1}, {x2, y2}, {cx, y2}};\n                candidates.push_back(shape);\n            }\n        }\n    }\n    \n    // Top-left missing\n    for (int cx : xs) {\n        if (cx <= x1 || cx > x2) continue;\n        for (int cy : ys) {\n            if (cy < y1 || cy >= y2) continue;\n            \n            auto [m1, s1] = compCount(x1, x2, y1, cy);  // Bottom part\n            auto [mRight, sRight] = compCount(cx, x2, cy + 1, y2); // Right part above cy\n            \n            int totalM = m1 + mRight;\n            int totalS = s1 + sRight;\n            int score = totalM - totalS;\n            \n            if (score > 0) {\n                LShape shape;\n                shape.type = 3;\n                shape.cx = cx; shape.cy = cy;\n                shape.score = score;\n                shape.verts = {{cx, cy}, {x2, cy}, {x2, y1}, {x1, y1}, {x1, y2}, {cx, y2}};\n                candidates.push_back(shape);\n            }\n        }\n    }\n    \n    // Pick the best shape\n    sort(candidates.begin(), candidates.end(), \n         [](const LShape& a, const LShape& b) { return a.score > b.score; });\n    \n    // Compute perimeter and ensure constraints\n    auto getPerimeter = [](const vector<pair<int,int>>& verts) {\n        long long p = 0;\n        int n = verts.size();\n        for (int i = 0; i < n; i++) {\n            int j = (i + 1) % n;\n            p += abs(verts[i].first - verts[j].first) + \n                 abs(verts[i].second - verts[j].second);\n        }\n        return p;\n    };\n    \n    vector<pair<int, int>> bestVerts;\n    for (const auto& cand : candidates) {\n        if (cand.verts.size() <= 1000 && getPerimeter(cand.verts) <= 400000) {\n            bestVerts = cand.verts;\n            break;\n        }\n    }\n    \n    if (bestVerts.empty()) {\n        // Fallback: simple rectangle\n        bestVerts = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n    }\n    \n    // Check if all edges are axis-aligned and simplify collinear points\n    vector<pair<int, int>> simplified;\n    for (int i = 0; i < (int)bestVerts.size(); i++) {\n        int prev = (i - 1 + bestVerts.size()) % bestVerts.size();\n        int next = (i + 1) % bestVerts.size();\n        \n        // Check if current vertex is collinear with prev and next\n        bool collinear = false;\n        if (bestVerts[prev].first == bestVerts[i].first && \n            bestVerts[i].first == bestVerts[next].first) {\n            collinear = true; // Vertical line\n        }\n        if (bestVerts[prev].second == bestVerts[i].second && \n            bestVerts[i].second == bestVerts[next].second) {\n            collinear = true; // Horizontal line\n        }\n        \n        if (!collinear) {\n            simplified.push_back(bestVerts[i]);\n        }\n    }\n    \n    if (simplified.size() >= 4) {\n        bestVerts = simplified;\n    }\n    \n    // Output\n    cout << bestVerts.size() << \"\\n\";\n    for (const auto& v : bestVerts) {\n        cout << v.first << \" \" << v.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int id;\n    long long w, h;\n};\n\nstruct Placement {\n    int p, r, d; // d: 0 for U, 1 for L\n    int b;\n};\n\nint N, T, sigma;\nvector<Rect> rects;\nvector<long long> est_w, est_h;\n\n// Simulate placement\npair<long long, long long> simulate(const vector<Placement>& placements) {\n    vector<tuple<long long, long long, long long, long long, int>> placed; // x, y, w, h, id\n    unordered_map<int, int> id_to_idx;\n    long long max_x = 0, max_y = 0;\n    \n    for (const auto& pl : placements) {\n        long long w = est_w[pl.p];\n        long long h = est_h[pl.p];\n        if (pl.r == 1) swap(w, h);\n        \n        long long x = 0, y = 0;\n        \n        if (pl.d == 0) { // U\n            if (pl.b == -1) {\n                x = 0;\n            } else {\n                auto it = id_to_idx.find(pl.b);\n                if (it != id_to_idx.end()) {\n                    x = get<0>(placed[it->second]) + get<2>(placed[it->second]);\n                }\n            }\n            y = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (x < px + pw && x + w > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else { // L\n            if (pl.b == -1) {\n                y = 0;\n            } else {\n                auto it = id_to_idx.find(pl.b);\n                if (it != id_to_idx.end()) {\n                    y = get<1>(placed[it->second]) + get<3>(placed[it->second]);\n                }\n            }\n            x = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (y < py + ph && y + h > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        id_to_idx[pl.p] = (int)placed.size();\n        placed.emplace_back(x, y, w, h, pl.p);\n        max_x = max(max_x, x + w);\n        max_y = max(max_y, y + h);\n    }\n    \n    return {max_x, max_y};\n}\n\n// Query\npair<long long, long long> query(const vector<Placement>& placements) {\n    cout << placements.size() << \"\\n\";\n    for (const auto& pl : placements) {\n        cout << pl.p << \" \" << pl.r << \" \" << (pl.d == 0 ? \"U\" : \"L\") << \" \" << pl.b << \"\\n\";\n    }\n    cout.flush();\n    long long W, H;\n    cin >> W >> H;\n    return {W, H};\n}\n\n// Greedy best-fit packing\nvector<Placement> greedy_packing(const vector<int>& order, const vector<bool>& rotate) {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long, int>> placed; // x, y, w, h, id\n    unordered_map<int, int> id_to_idx;\n    \n    for (int oi = 0; oi < (int)order.size(); oi++) {\n        int idx = order[oi];\n        long long w = est_w[idx];\n        long long h = est_h[idx];\n        bool rot = rotate[oi];\n        if (rot) swap(w, h);\n        \n        struct Option {\n            Placement p;\n            long long x, y, new_W, new_H;\n        };\n        \n        Option best;\n        best.new_W = LLONG_MAX;\n        best.new_H = LLONG_MAX;\n        \n        // Helper to evaluate\n        auto evaluate = [&](Placement p, long long x, long long y) {\n            Option opt;\n            opt.p = p;\n            opt.x = x;\n            opt.y = y;\n            opt.new_W = x + w;\n            opt.new_H = y + h;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                opt.new_W = max(opt.new_W, px + pw);\n                opt.new_H = max(opt.new_H, py + ph);\n            }\n            return opt;\n        };\n        \n        // U with b=-1\n        {\n            long long x = 0, y = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (x < px + pw && x + w > px) y = max(y, py + ph);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 0; p.b = -1;\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        // U with reference to placed\n        for (int pi = 0; pi < (int)placed.size(); pi++) {\n            long long x = get<0>(placed[pi]) + get<2>(placed[pi]);\n            long long y = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (x < px + pw && x + w > px) y = max(y, py + ph);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 0; p.b = get<4>(placed[pi]);\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        // L with b=-1\n        {\n            long long y = 0, x = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (y < py + ph && y + h > py) x = max(x, px + pw);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 1; p.b = -1;\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        // L with reference to placed\n        for (int pi = 0; pi < (int)placed.size(); pi++) {\n            long long y = get<1>(placed[pi]) + get<3>(placed[pi]);\n            long long x = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (y < py + ph && y + h > py) x = max(x, px + pw);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 1; p.b = get<4>(placed[pi]);\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        placements.push_back(best.p);\n        placed.emplace_back(best.x, best.y, w, h, idx);\n        id_to_idx[idx] = (int)placed.size() - 1;\n    }\n    \n    return placements;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> T >> sigma;\n    rects.resize(N);\n    est_w.resize(N);\n    est_h.resize(N);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> rects[i].w >> rects[i].h;\n        rects[i].id = i;\n        est_w[i] = rects[i].w;\n        est_h[i] = rects[i].h;\n    }\n    \n    // Generate diverse strategies\n    vector<pair<vector<int>, vector<bool>>> strategies;\n    \n    // Different sortings\n    vector<pair<string, function<bool(int,int)>>> sortings = {\n        {\"area_desc\", [&](int a, int b) { return est_w[a]*est_h[a] > est_w[b]*est_h[b]; }},\n        {\"maxdim_desc\", [&](int a, int b) { return max(est_w[a],est_h[a]) > max(est_w[b],est_h[b]); }},\n        {\"sum_desc\", [&](int a, int b) { return est_w[a]+est_h[a] > est_w[b]+est_h[b]; }},\n        {\"width_desc\", [&](int a, int b) { return est_w[a] > est_w[b]; }},\n        {\"height_desc\", [&](int a, int b) { return est_h[a] > est_h[b]; }},\n        {\"mindim_desc\", [&](int a, int b) { return min(est_w[a],est_h[a]) > min(est_w[b],est_h[b]); }},\n    };\n    \n    // For each sorting, try two rotation strategies\n    for (auto& [name, cmp] : sortings) {\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), cmp);\n        \n        // Rotation: make width >= height (landscape)\n        {\n            vector<bool> rot(N, false);\n            for (int i = 0; i < N; i++) {\n                if (est_h[order[i]] > est_w[order[i]]) rot[i] = true;\n            }\n            strategies.push_back({order, rot});\n        }\n        \n        // Rotation: make height >= width (portrait)\n        {\n            vector<bool> rot(N, false);\n            for (int i = 0; i < N; i++) {\n                if (est_w[order[i]] > est_h[order[i]]) rot[i] = true;\n            }\n            strategies.push_back({order, rot});\n        }\n        \n        // No rotation\n        {\n            vector<bool> rot(N, false);\n            strategies.push_back({order, rot});\n        }\n        \n        // All rotated\n        {\n            vector<bool> rot(N, true);\n            strategies.push_back({order, rot});\n        }\n    }\n    \n    // Shuffle strategies for diversity\n    mt19937 rng(42);\n    shuffle(strategies.begin(), strategies.end(), rng);\n    \n    // Track best\n    long long best_score = LLONG_MAX;\n    \n    auto time_limit = chrono::milliseconds(2900);\n    \n    for (int turn = 0; turn < T; turn++) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time);\n        if (elapsed > time_limit) break;\n        \n        auto& [order, rot] = strategies[turn % strategies.size()];\n        \n        // Maybe add some perturbation in later turns\n        vector<int> perturbed_order = order;\n        vector<bool> perturbed_rot = rot;\n        \n        if (turn >= (int)strategies.size()) {\n            // Add small random perturbations\n            for (int i = 0; i < min(5, N); i++) {\n                int a = rng() % N;\n                int b = rng() % N;\n                swap(perturbed_order[a], perturbed_order[b]);\n            }\n            for (int i = 0; i < min(3, N); i++) {\n                perturbed_rot[rng() % N] = !perturbed_rot[rng() % N];\n            }\n        }\n        \n        vector<Placement> placements = greedy_packing(perturbed_order, perturbed_rot);\n        auto [W, H] = query(placements);\n        \n        long long score = W + H;\n        if (score < best_score) {\n            best_score = score;\n        }\n    }\n    \n    return 0;\n}","ahc041":"#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, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<pair<int,int>> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].first >> edges[i].second;\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n    }\n\n    // Build adjacency\n    vector<vector<int>> adj(N);\n    for (auto &e : edges) {\n        adj[e.first].push_back(e.second);\n        adj[e.second].push_back(e.first);\n    }\n\n    // Initialize: every vertex is a root\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);  // depth = height\n\n    // Quick sanity: compute current score\n    auto compute_score = [&]() {\n        long long sc = 1;\n        for (int v = 0; v < N; ++v) {\n            sc += (depth[v] + 1LL) * A[v];\n        }\n        return sc;\n    };\n\n    // We'll try to push vertices deeper by local search\n    // We maintain a list of vertices that could be deepened\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n\n    // Function to check if setting u's parent to p is valid\n    auto can_attach = [&](int u, int p) {\n        if (depth[p] + 1 > H) return false;\n        // Check no cycle: u must not be ancestor of p\n        int cur = p;\n        while (cur != -1) {\n            if (cur == u) return false;\n            cur = parent[cur];\n        }\n        return true;\n    };\n\n    // Hill climbing\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        // random order to avoid bias\n        shuffle(order.begin(), order.end(), mt19937(random_device{}()));\n        for (int u : order) {\n            int old_p = parent[u];\n            int old_d = depth[u];\n            int best_p = old_p;\n            int best_d = old_d;\n            long long best_gain = 0;\n            // try neighbors as potential parent\n            for (int p : adj[u]) {\n                if (p == u) continue;\n                if (!can_attach(u, p)) continue;\n                int new_d = depth[p] + 1;\n                long long gain = (new_d - old_d) * 1LL * A[u];\n                if (gain > best_gain) {\n                    best_gain = gain;\n                    best_p = p;\n                    best_d = new_d;\n                }\n            }\n            if (best_p != old_p) {\n                // update parent and depth for u and its subtree\n                // Since we only move u deeper, we need to update depth of u's subtree\n                // We'll just recompute depths by BFS from roots after each change? Too slow.\n                // Instead, we can do a single update: old subtree depths remain same relative to u if they stay with u.\n                // But if u changes depth, the whole subtree of u needs depth shift.\n                // To keep it simple and fast, we just recompute depths for all nodes after each change?\n                // N=1000, recompute is cheap.\n                parent[u] = best_p;\n                // Recompute all depths:\n                vector<int> indeg(N, 0);\n                for (int i = 0; i < N; ++i) if (parent[i] != -1) indeg[parent[i]]++;\n                queue<int> q;\n                for (int i = 0; i < N; ++i) if (parent[i] == -1) { depth[i] = 0; q.push(i); }\n                while (!q.empty()) {\n                    int v = q.front(); q.pop();\n                    for (int nb : adj[v]) {\n                        if (parent[nb] == v) {\n                            depth[nb] = depth[v] + 1;\n                            q.push(nb);\n                        }\n                    }\n                }\n                changed = true;\n                break; // restart after change\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    int N;\n    cin >> N;\n    vector<string> board(N);\n    for (int i = 0; i < N; ++i) cin >> board[i];\n\n    vector<pair<int,int>> oni;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (board[i][j] == 'x') oni.push_back({i, j});\n\n    struct Move {\n        char d;\n        int p;\n        int steps;\n    };\n    vector<Move> moves;\n\n    // Process each Oni independently (simple + safe)\n    for (auto [i, j] : oni) {\n        // Check up\n        bool up_ok = true;\n        for (int k = 0; k < i; ++k) if (board[k][j] == 'o') up_ok = false;\n        // Check down\n        bool down_ok = true;\n        for (int k = i+1; k < N; ++k) if (board[k][j] == 'o') down_ok = false;\n        // Check left\n        bool left_ok = true;\n        for (int k = 0; k < j; ++k) if (board[i][k] == 'o') left_ok = false;\n        // Check right\n        bool right_ok = true;\n        for (int k = j+1; k < N; ++k) if (board[i][k] == 'o') right_ok = false;\n\n        int best_dist = 1e9;\n        char best_dir = 0;\n        if (up_ok && i+1 < best_dist) { best_dist = i+1; best_dir = 'U'; }\n        if (down_ok && N-i < best_dist) { best_dist = N-i; best_dir = 'D'; }\n        if (left_ok && j+1 < best_dist) { best_dist = j+1; best_dir = 'L'; }\n        if (right_ok && N-j < best_dist) { best_dist = N-j; best_dir = 'R'; }\n\n        // Perform removal\n        if (best_dir == 'U') {\n            for (int s = 0; s < i+1; ++s) {\n                moves.push_back({'U', j, 1});\n                // update board\n                char removed = board[0][j];\n                for (int r = 0; r < N-1; ++r) board[r][j] = board[r+1][j];\n                board[N-1][j] = removed;\n            }\n            for (int s = 0; s < i+1; ++s) {\n                moves.push_back({'D', j, 1});\n                char removed = board[N-1][j];\n                for (int r = N-1; r > 0; --r) board[r][j] = board[r-1][j];\n                board[0][j] = removed;\n            }\n        } else if (best_dir == 'D') {\n            for (int s = 0; s < N-i; ++s) {\n                moves.push_back({'D', j, 1});\n                char removed = board[N-1][j];\n                for (int r = N-1; r > 0; --r) board[r][j] = board[r-1][j];\n                board[0][j] = removed;\n            }\n            for (int s = 0; s < N-i; ++s) {\n                moves.push_back({'U', j, 1});\n                char removed = board[0][j];\n                for (int r = 0; r < N-1; ++r) board[r][j] = board[r+1][j];\n                board[N-1][j] = removed;\n            }\n        } else if (best_dir == 'L') {\n            for (int s = 0; s < j+1; ++s) {\n                moves.push_back({'L', i, 1});\n                char removed = board[i][0];\n                for (int c = 0; c < N-1; ++c) board[i][c] = board[i][c+1];\n                board[i][N-1] = removed;\n            }\n            for (int s = 0; s < j+1; ++s) {\n                moves.push_back({'R', i, 1});\n                char removed = board[i][N-1];\n                for (int c = N-1; c > 0; --c) board[i][c] = board[i][c-1];\n                board[i][0] = removed;\n            }\n        } else if (best_dir == 'R') {\n            for (int s = 0; s < N-j; ++s) {\n                moves.push_back({'R', i, 1});\n                char removed = board[i][N-1];\n                for (int c = N-1; c > 0; --c) board[i][c] = board[i][c-1];\n                board[i][0] = removed;\n            }\n            for (int s = 0; s < N-j; ++s) {\n                moves.push_back({'L', i, 1});\n                char removed = board[i][0];\n                for (int c = 0; c < N-1; ++c) board[i][c] = board[i][c+1];\n                board[i][N-1] = removed;\n            }\n        }\n    }\n\n    // Output moves\n    for (auto &mv : moves) {\n        cout << mv.d << ' ' << mv.p << '\\n';\n    }\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nint a[N], b[N];\nint best_a[N], best_b[N];\nint cnt[N];\nlong long best_error;\n\nvoid simulate() {\n    memset(cnt, 0, sizeof(cnt));\n    int cur = 0;\n    for (int week = 0; week < L; ++week) {\n        cnt[cur]++;\n        if (cnt[cur] % 2 == 1) {\n            cur = a[cur];\n        } else {\n            cur = b[cur];\n        }\n    }\n}\n\nlong long calc_error() {\n    long long 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    // Read input\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Initialize with round-robin\n    for (int i = 0; i < N; ++i) {\n        a[i] = (i + 1) % N;\n        b[i] = (i + 1) % N;\n    }\n\n    simulate();\n    best_error = calc_error();\n    memcpy(best_a, a, sizeof(a));\n    memcpy(best_b, b, sizeof(b));\n\n    auto start_time = steady_clock::now();\n    const double time_limit = 1.9; // seconds\n    mt19937 rng(42);\n    uniform_int_distribution<int> rand_emp(0, N-1);\n    uniform_real_distribution<double> rand_real(0.0, 1.0);\n\n    double temp = 1000.0;\n    long long current_error = best_error;\n    int iter = 0;\n\n    while (true) {\n        auto now = steady_clock::now();\n        double elapsed = duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n\n        // Save current state\n        int old_a[N], old_b[N];\n        memcpy(old_a, a, sizeof(a));\n        memcpy(old_b, b, sizeof(b));\n        int old_cnt[N];\n        memcpy(old_cnt, cnt, sizeof(cnt));\n\n        // Random modification\n        int i = rand_emp(rng);\n        if (rand_real(rng) < 0.5) {\n            a[i] = rand_emp(rng);\n        } else {\n            b[i] = rand_emp(rng);\n        }\n\n        simulate();\n        long long new_error = calc_error();\n\n        double prob = exp((current_error - new_error) / temp);\n        if (new_error < current_error || rand_real(rng) < prob) {\n            current_error = new_error;\n            if (new_error < best_error) {\n                best_error = new_error;\n                memcpy(best_a, a, sizeof(a));\n                memcpy(best_b, b, sizeof(b));\n            }\n        } else {\n            // Revert\n            memcpy(a, old_a, sizeof(a));\n            memcpy(b, old_b, sizeof(b));\n            memcpy(cnt, old_cnt, sizeof(cnt));\n        }\n\n        temp *= 0.99999;\n        ++iter;\n    }\n\n    // Output best found\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Union-Find\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        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    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    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // Compute rectangle centers as estimated positions\n    vector<long long> estX(N), estY(N);\n    for (int i = 0; i < N; i++) {\n        estX[i] = (lx[i] + rx[i]) / 2;\n        estY[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Sort city indices by center coordinates\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (estX[a] != estX[b]) return estX[a] < estX[b];\n        return estY[a] < estY[b];\n    });\n\n    // Partition into groups\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < G[i]; j++) {\n            groups[i].push_back(order[idx++]);\n        }\n    }\n\n    // Store final edges per group\n    vector<vector<pair<int,int>>> final_edges(M);\n\n    // DSU per group for connectivity during construction\n    vector<DSU> dsu;\n    dsu.reserve(M);\n    for (int i = 0; i < M; i++) {\n        dsu.emplace_back(G[i]);\n    }\n\n    // Used queries counter\n    int queries_used = 0;\n\n    // For each group, use queries to get edges\n    for (int i = 0; i < M; i++) {\n        int sz = G[i];\n        if (sz <= 2) {\n            // Group size 2: no query possible or needed, just connect directly\n            if (sz == 2) {\n                final_edges[i].emplace_back(0, 1);\n                dsu[i].unite(0, 1);\n            }\n            continue;\n        }\n\n        // Sliding window queries of size up to L\n        int step = L - 1; // overlap 1 city between windows\n        for (int start = 0; start + 1 < sz && queries_used < Q; start += step) {\n            int end = min(start + L, sz);\n            if (end - start < 2) break; // need at least 2 cities\n\n            // Build query\n            vector<int> subset;\n            for (int j = start; j < end; j++) {\n                subset.push_back(groups[i][j]);\n            }\n            int l = subset.size();\n            cout << \"? \" << l;\n            for (int c : subset) cout << \" \" << c;\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n\n            // Read response\n            for (int j = 0; j < l - 1; j++) {\n                int a, b;\n                cin >> a >> b;\n                // Find local indices in group\n                auto ita = find(subset.begin(), subset.end(), a);\n                auto itb = find(subset.begin(), subset.end(), b);\n                int idx_a = start + distance(subset.begin(), ita);\n                int idx_b = start + distance(subset.begin(), itb);\n                // Add edge to final if it connects new components\n                if (dsu[i].unite(idx_a, idx_b)) {\n                    final_edges[i].emplace_back(idx_a, idx_b);\n                }\n            }\n        }\n    }\n\n    // End queries\n    cout << \"!\\n\";\n    cout.flush();\n\n    // For groups still not fully connected, add edges based on estimated distances\n    for (int i = 0; i < M; i++) {\n        int sz = G[i];\n        if (sz <= 1) continue;\n        // Collect components\n        unordered_map<int, vector<int>> comps;\n        for (int j = 0; j < sz; j++) {\n            comps[dsu[i].find(j)].push_back(j);\n        }\n        if (comps.size() == 1) continue; // already connected\n\n        // Build list of all possible edges between different components\n        vector<tuple<long long, int, int>> cand_edges;\n        vector<int> comp_keys;\n        for (auto &kv : comps) comp_keys.push_back(kv.first);\n        for (size_t ci = 0; ci < comp_keys.size(); ci++) {\n            for (size_t cj = ci + 1; cj < comp_keys.size(); cj++) {\n                for (int u : comps[comp_keys[ci]]) {\n                    for (int v : comps[comp_keys[cj]]) {\n                        long long dx = estX[groups[i][u]] - estX[groups[i][v]];\n                        long long dy = estY[groups[i][u]] - estY[groups[i][v]];\n                        long long dist = dx*dx + dy*dy; // squared distance for ordering\n                        cand_edges.emplace_back(dist, u, v);\n                    }\n                }\n            }\n        }\n        sort(cand_edges.begin(), cand_edges.end());\n\n        // Kruskal-like addition\n        for (auto &e : cand_edges) {\n            int u = get<1>(e), v = get<2>(e);\n            if (dsu[i].unite(u, v)) {\n                final_edges[i].emplace_back(u, v);\n            }\n            if (comps.size() == 1) break; // actually comps count won't update dynamically here; just loop til enough edges\n        }\n    }\n\n    // Output final answer\n    for (int i = 0; i < M; i++) {\n        // Print group cities\n        for (int j = 0; j < G[i]; j++) {\n            if (j) cout << \" \";\n            cout << groups[i][j];\n        }\n        cout << \"\\n\";\n        // Print edges\n        for (auto &e : final_edges[i]) {\n            cout << groups[i][e.first] << \" \" << groups[i][e.second] << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int M = 40;\nconst int MAX_ACTIONS = 2 * N * M;\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dir_char[4] = {'U', 'D', 'L', 'R'};\n\nstruct State {\n    int x, y;\n    vector<string> blocks; // we will store blocks as vector<string> for BFS state\n    bool operator==(const State& other) const {\n        return x == other.x && y == other.y && blocks == other.blocks;\n    }\n};\n\nnamespace std {\n    template<> struct hash<State> {\n        size_t operator()(const State& s) const {\n            size_t h = hash<int>()(s.x) ^ hash<int>()(s.y);\n            for (const auto& row : s.blocks)\n                h ^= hash<string>()(row);\n            return h;\n        }\n    };\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    vector<pair<int,int>> targets(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> targets[i].first >> targets[i].second;\n    }\n\n    vector<string> grid(N, string(N, '.'));\n    vector<pair<char,char>> actions;\n\n    // Place border blocks initially\n    for (int i = 0; i < N; ++i) {\n        if (grid[0][i] == '.') {\n            actions.push_back({'A', 'U'}); // We need to be at (1,i) to place at (0,i) if possible\n            // Instead, we'll do placement when standing at correct position\n        }\n    }\n\n    // For simplicity, we'll just move to target directly with moves\n    // This is a fallback basic solution\n\n    int cx = targets[0].first, cy = targets[0].second;\n    // Move to first target\n    // We start at (i0, j0) which is targets[0]\n    // Actually the input has i0 j0 first then M-1 targets? Yes: i0 j0 is starting point\n    // Wait: The problem says: first line is i0 j0, then M lines of targets.\n    // So targets[0] is first target? Let's re-read: \"i0 j0\" then M lines of targets.\n    // So total M+1 lines? Actually M targets: (i1,j1)...(iM-1,jM-1). Input gives M lines.\n    // The statement: $i_0$ $j_0$ then $M$ lines for targets? Let's check: They say initial position then targets.\n    // In sample they show: N M then i0 j0 then M lines of targets.\n    // So we have M targets, starting pos given separately.\n    // I'll read it correctly.\n\n    // Re-read input because I misused targets\n    // Let's redo\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y, r, id;\n};\n\nint n;\nvector<Point> pts;\nvector<Rect> ans;\n\n// Recursively assign rectangles\nvoid solve(int x1, int y1, int x2, int y2, vector<int> idxs) {\n    if (idxs.empty()) return;\n    if (idxs.size() == 1) {\n        int i = idxs[0];\n        // ensure point is inside\n        // make rectangle as given\n        ans[i] = {x1, y1, x2, y2};\n        // adjust if point not inside? but point is inside by construction.\n        return;\n    }\n    // total area of this box\n    long long totalArea = 1LL * (x2 - x1) * (y2 - y1);\n    long long sumR = 0;\n    for (int i : idxs) sumR += pts[i].r;\n\n    // try split by x\n    sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n    int bestSplit = -1;\n    double bestScore = -1e100;\n    // We'll decide to split between idxs[k] and idxs[k+1] at some x coordinate\n    for (int k = 0; k < (int)idxs.size() - 1; k++) {\n        int leftX = pts[idxs[k]].x; // max x of left\n        int rightX = pts[idxs[k+1]].x; // min x of right\n        // we can split anywhere between leftX+1 and rightX\n        // we choose split line = rightX (so left gets up to rightX)\n        int splitX = rightX;\n        if (splitX <= x1 || splitX >= x2) continue;\n        long long leftArea = 1LL * (splitX - x1) * (y2 - y1);\n        long long leftR = 0;\n        for (int i = 0; i <= k; i++) leftR += pts[idxs[i]].r;\n        double leftRatio = (double)leftArea / totalArea;\n        double rightRatio = 1.0 - leftRatio;\n        double targetRatio = (double)leftR / sumR;\n        double score = -fabs(leftRatio - targetRatio);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSplit = k;\n        }\n    }\n    // try split by y\n    sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n    int bestSplitY = -1;\n    double bestScoreY = -1e100;\n    for (int k = 0; k < (int)idxs.size() - 1; k++) {\n        int bottomY = pts[idxs[k]].y; // max y of bottom\n        int topY = pts[idxs[k+1]].y; // min y of top\n        int splitY = topY;\n        if (splitY <= y1 || splitY >= y2) continue;\n        long long bottomArea = 1LL * (x2 - x1) * (splitY - y1);\n        long long bottomR = 0;\n        for (int i = 0; i <= k; i++) bottomR += pts[idxs[i]].r;\n        double bottomRatio = (double)bottomArea / totalArea;\n        double targetRatio = (double)bottomR / sumR;\n        double score = -fabs(bottomRatio - targetRatio);\n        if (score > bestScoreY) {\n            bestScoreY = score;\n            bestSplitY = k;\n        }\n    }\n\n    if (bestScore > bestScoreY) {\n        // split by x at bestSplit\n        sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n        int splitX = pts[idxs[bestSplit+1]].x;\n        vector<int> left(idxs.begin(), idxs.begin() + bestSplit + 1);\n        vector<int> right(idxs.begin() + bestSplit + 1, idxs.end());\n        solve(x1, y1, splitX, y2, left);\n        solve(splitX, y1, x2, y2, right);\n    } else if (bestSplitY != -1) {\n        sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n        int splitY = pts[idxs[bestSplitY+1]].y;\n        vector<int> bottom(idxs.begin(), idxs.begin() + bestSplitY + 1);\n        vector<int> top(idxs.begin() + bestSplitY + 1, idxs.end());\n        solve(x1, y1, x2, splitY, bottom);\n        solve(x1, splitY, x2, y2, top);\n    } else {\n        // fallback: just assign whole to first? shouldn't happen\n        int i = idxs[0];\n        ans[i] = {x1, y1, x2, y2};\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n;\n    pts.resize(n);\n    ans.resize(n);\n    for (int i = 0; i < n; i++) {\n        cin >> pts[i].x >> pts[i].y >> pts[i].r;\n        pts[i].id = i;\n    }\n    vector<int> all(n);\n    iota(all.begin(), all.end(), 0);\n    solve(0, 0, 10000, 10000, all);\n    for (int i = 0; i < n; i++) {\n        cout << ans[i].a << \" \" << ans[i].b << \" \" << ans[i].c << \" \" << ans[i].d << \"\\n\";\n    }\n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <bitset>\n#include <queue>\n#include <cstring>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_TILES = 2500;\nconst int BEAM_WIDTH = 150;\nconst int MAX_DEPTH = 2000;\n\nstruct State {\n    int score;\n    int est_score;\n    short i, j;         // current position\n    short pi, pj;       // previous position (to avoid immediate backtrack)\n    bitset<MAX_TILES> visited;\n    int prev_idx;       // index in the previous beam\n    char move_char;     // move that led to this state\n};\n\nint si, sj;\nint tile_id[N][N];\nint p[N][N];\nint M; // number of tiles\nvector<pair<short, short>> tile_squares[MAX_TILES];\nint tile_value[MAX_TILES];\nvector<int> tile_adj[MAX_TILES];\nint bfs_tag[MAX_TILES];\nint current_bfs_tag = 0;\n\n// Heuristic: sum of values of all unvisited tiles reachable from the current tile\nint compute_potential(const State& st) {\n    current_bfs_tag++;\n    int start_tile = tile_id[st.i][st.j];\n    queue<int> q;\n    int pot = 0;\n    // Start BFS from unvisited neighbors of the current tile\n    for (int v : tile_adj[start_tile]) {\n        if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n            bfs_tag[v] = current_bfs_tag;\n            q.push(v);\n            pot += tile_value[v];\n        }\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int v : tile_adj[u]) {\n            if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n                bfs_tag[v] = current_bfs_tag;\n                q.push(v);\n                pot += tile_value[v];\n            }\n        }\n    }\n    return pot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(1950);\n\n    cin >> si >> sj;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    // Determine the number of tiles\n    M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (tile_id[i][j] >= M) M = tile_id[i][j] + 1;\n\n    // Collect tile squares and values\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            tile_squares[tile_id[i][j]].emplace_back(i, j);\n    for (int t = 0; t < M; ++t) {\n        int val = 0;\n        for (auto& sq : tile_squares[t])\n            val += p[sq.first][sq.second];\n        tile_value[t] = val;\n    }\n\n    // Build inter-tile adjacency\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int nt = tile_id[ni][nj];\n                    if (nt != t)\n                        tile_adj[t].push_back(nt);\n                }\n            }\n        }\n    }\n    for (int t = 0; t < M; ++t) {\n        sort(tile_adj[t].begin(), tile_adj[t].end());\n        tile_adj[t].erase(unique(tile_adj[t].begin(), tile_adj[t].end()), tile_adj[t].end());\n    }\n\n    // Initial state\n    State init;\n    init.score = p[si][sj];\n    init.i = si; init.j = sj;\n    init.pi = -1; init.pj = -1;\n    init.visited.reset();\n    init.visited[tile_id[si][sj]] = 1;\n    init.prev_idx = -1;\n    init.est_score = init.score + compute_potential(init);\n\n    vector<State> beam;\n    beam.push_back(init);\n    vector<vector<State>> beam_history;\n    beam_history.push_back(beam);\n\n    int best_score = init.score;\n    int best_depth = 0;\n    int best_state_idx = 0;\n\n    // Beam search\n    for (int depth = 1; depth <= MAX_DEPTH; ++depth) {\n        if (chrono::steady_clock::now() - start_time > time_limit) break;\n\n        vector<State> next_beam;\n        for (int s_idx = 0; s_idx < (int)beam.size(); ++s_idx) {\n            const State& st = beam[s_idx];\n            short i = st.i, j = st.j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (ni == st.pi && nj == st.pj) continue;   // immediate backtrack\n\n                int nt = tile_id[ni][nj];\n                bool same_tile = (nt == tile_id[i][j]);\n\n                if (!same_tile && st.visited[nt]) continue; // tile already used\n\n                State nxt = st;\n                nxt.i = ni; nxt.j = nj;\n                nxt.pi = i; nxt.pj = j;\n                nxt.score += p[ni][nj];\n                if (!same_tile) nxt.visited[nt] = 1;\n                nxt.prev_idx = s_idx;\n                nxt.move_char = (k == 0 ? 'U' : (k == 1 ? 'D' : (k == 2 ? 'L' : 'R')));\n                nxt.est_score = nxt.score + compute_potential(nxt);\n                next_beam.push_back(move(nxt));\n            }\n        }\n        if (next_beam.empty()) break;\n\n        sort(next_beam.begin(), next_beam.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)next_beam.size() > BEAM_WIDTH)\n            next_beam.resize(BEAM_WIDTH);\n\n        if (next_beam[0].score > best_score) {\n            best_score = next_beam[0].score;\n            best_depth = depth;\n            best_state_idx = 0;\n        }\n\n        beam = move(next_beam);\n        beam_history.push_back(beam);\n    }\n\n    // Retrieve the absolute best state from the whole history\n    for (int d = 0; d < (int)beam_history.size(); ++d) {\n        for (int idx = 0; idx < (int)beam_history[d].size(); ++idx) {\n            if (beam_history[d][idx].score > best_score) {\n                best_score = beam_history[d][idx].score;\n                best_depth = d;\n                best_state_idx = idx;\n            }\n        }\n    }\n\n    // Reconstruct the path\n    string path;\n    int cur_depth = best_depth;\n    int cur_idx = best_state_idx;\n    while (cur_depth > 0) {\n        const State& st = beam_history[cur_depth][cur_idx];\n        path.push_back(st.move_char);\n        cur_idx = st.prev_idx;\n        --cur_depth;\n    }\n    reverse(path.begin(), path.end());\n    cout << path << '\\n';\n\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int INF = 1e9;\n\nstruct EdgeEstimator {\n    // Model: edge = row_base + row_split * (j >= split_point) + local_noise\n    // For horizontal edges: row i, between col j and j+1\n    // For vertical edges: col j, between row i and i+1\n    \n    // Horizontal edge estimates\n    double row_base_H[N];           // Base value for each row\n    double row_split_H[N];         // Split adjustment for each row (could be 0 if no split)\n    double local_H[N][N-1];        // Local deviation\n    int split_col[N];              // Where the split occurs (-1 if no split detected yet)\n    double split_col_conf[N];      // Confidence in split location\n    \n    // Vertical edge estimates\n    double col_base_V[N];           // Base value for each column\n    double col_split_V[N];         // Split adjustment for each column\n    double local_V[N-1][N];        // Local deviation\n    int split_row[N];              // Where the split occurs (-1 if no split)\n    double split_row_conf[N];      // Confidence in split location\n    \n    // Counts for exploration\n    int cnt_H[N][N-1];\n    int cnt_V[N-1][N];\n    \n    EdgeEstimator() {\n        // Initialize with reasonable defaults\n        for (int i = 0; i < N; i++) {\n            row_base_H[i] = 5000;\n            row_split_H[i] = 0;\n            split_col[i] = -1;\n            split_col_conf[i] = 0;\n            \n            col_base_V[i] = 5000;\n            col_split_V[i] = 0;\n            split_row[i] = -1;\n            split_row_conf[i] = 0;\n        }\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N-1; j++) {\n                local_H[i][j] = 0;\n                cnt_H[i][j] = 0;\n            }\n        }\n        for (int i = 0; i < N-1; i++) {\n            for (int j = 0; j < N; j++) {\n                local_V[i][j] = 0;\n                cnt_V[i][j] = 0;\n            }\n        }\n    }\n    \n    double get_H(int i, int j) const {\n        if (split_col[i] >= 0) {\n            return max(100.0, row_base_H[i] + (j >= split_col[i] ? row_split_H[i] : 0) + local_H[i][j]);\n        }\n        return max(100.0, row_base_H[i] + local_H[i][j]);\n    }\n    \n    double get_V(int i, int j) const {\n        if (split_row[j] >= 0) {\n            return max(100.0, col_base_V[j] + (i >= split_row[j] ? col_split_V[j] : 0) + local_V[i][j]);\n        }\n        return max(100.0, col_base_V[j] + local_V[i][j]);\n    }\n    \n    double get_H_with_exploration(int i, int j, double bonus) const {\n        return get_H(i, j) + bonus / (cnt_H[i][j] + 1);\n    }\n    \n    double get_V_with_exploration(int i, int j, double bonus) const {\n        return get_V(i, j) + bonus / (cnt_V[i][j] + 1);\n    }\n};\n\n// Track statistics for split detection\nstruct SplitDetector {\n    // For each row, track path usage in two halves\n    vector<double> first_half_avg[N];\n    vector<double> second_half_avg[N];\n    int first_cnt[N], second_cnt[N];\n    \n    // For each column\n    vector<double> top_half_avg[N];\n    vector<double> bottom_half_avg[N];\n    int top_cnt[N], bottom_cnt[N];\n    \n    SplitDetector() {\n        for (int i = 0; i < N; i++) {\n            first_cnt[i] = second_cnt[i] = 0;\n            top_cnt[i] = bottom_cnt[i] = 0;\n        }\n    }\n};\n\nstring path_to_string(const vector<pair<int,int>>& path) {\n    string s;\n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        if (c == a-1) s += 'U';\n        else if (c == a+1) s += 'D';\n        else if (d == b-1) s += 'L';\n        else s += 'R';\n    }\n    return s;\n}\n\npair<vector<pair<int,int>>, double> dijkstra(int si, int sj, int ti, int tj, \n                                               EdgeEstimator& est, double explore_bonus) {\n    vector dist(N, vector<double>(N, INF));\n    vector prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector prev_dir(N, vector<int>(N, -1));\n    \n    dist[si][sj] = 0;\n    using State = tuple<double, int, int>;\n    priority_queue<State, vector<State>, greater<State>> pq;\n    pq.push({0, si, sj});\n    \n    while (!pq.empty()) {\n        auto [d, i, j] = pq.top(); pq.pop();\n        if (d != dist[i][j]) continue;\n        if (i == ti && j == tj) break;\n        \n        // Try all 4 directions\n        // Up\n        if (i > 0) {\n            double w = est.get_V_with_exploration(i-1, j, explore_bonus);\n            if (dist[i-1][j] > d + w) {\n                dist[i-1][j] = d + w;\n                prev[i-1][j] = {i, j};\n                prev_dir[i-1][j] = 0;\n                pq.push({dist[i-1][j], i-1, j});\n            }\n        }\n        // Down\n        if (i < N-1) {\n            double w = est.get_V_with_exploration(i, j, explore_bonus);\n            if (dist[i+1][j] > d + w) {\n                dist[i+1][j] = d + w;\n                prev[i+1][j] = {i, j};\n                prev_dir[i+1][j] = 1;\n                pq.push({dist[i+1][j], i+1, j});\n            }\n        }\n        // Left\n        if (j > 0) {\n            double w = est.get_H_with_exploration(i, j-1, explore_bonus);\n            if (dist[i][j-1] > d + w) {\n                dist[i][j-1] = d + w;\n                prev[i][j-1] = {i, j};\n                prev_dir[i][j-1] = 2;\n                pq.push({dist[i][j-1], i, j-1});\n            }\n        }\n        // Right\n        if (j < N-1) {\n            double w = est.get_H_with_exploration(i, j, explore_bonus);\n            if (dist[i][j+1] > d + w) {\n                dist[i][j+1] = d + w;\n                prev[i][j+1] = {i, j};\n                prev_dir[i][j+1] = 3;\n                pq.push({dist[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    double est_len = 0;\n    \n    while (!(ci == si && cj == sj)) {\n        path.push_back({ci, cj});\n        auto [pi, pj] = prev[ci][cj];\n        if (ci == pi-1) est_len += est.get_V(pi, pj);     // Up\n        else if (ci == pi+1) est_len += est.get_V(ci-1, pj); // Down  \n        else if (cj == pj-1) est_len += est.get_H(pi, pj);   // Left\n        else est_len += est.get_H(pi, ci-1);                  // Right\n        ci = pi; cj = pj;\n    }\n    path.push_back({si, sj});\n    reverse(path.begin(), path.end());\n    \n    return {path, est_len};\n}\n\nvoid update_estimates(EdgeEstimator& est, const vector<pair<int,int>>& path, \n                     double observed_len, double est_len, int query_idx) {\n    if (est_len <= 0) return;\n    \n    double ratio = observed_len / est_len;\n    double learning_rate = 0.3 / sqrt(1 + query_idx * 0.001);\n    \n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        \n        if (c == a-1) { // Up\n            est.cnt_V[c][d]++;\n            est.local_V[c][d] += learning_rate * (est.get_V(c, d) * (ratio - 1));\n            // Update column base\n            est.col_base_V[d] += learning_rate * 0.1 * (est.get_V(c, d) * (ratio - 1));\n        } else if (c == a+1) { // Down\n            est.cnt_V[a][b]++;\n            est.local_V[a][b] += learning_rate * (est.get_V(a, b) * (ratio - 1));\n            est.col_base_V[b] += learning_rate * 0.1 * (est.get_V(a, b) * (ratio - 1));\n        } else if (d == b-1) { // Left\n            est.cnt_H[c][d]++;\n            est.local_H[c][d] += learning_rate * (est.get_H(c, d) * (ratio - 1));\n            est.row_base_H[c] += learning_rate * 0.1 * (est.get_H(c, d) * (ratio - 1));\n        } else { // Right\n            est.cnt_H[a][b]++;\n            est.local_H[a][b] += learning_rate * (est.get_H(a, b) * (ratio - 1));\n            est.row_base_H[a] += learning_rate * 0.1 * (est.get_H(a, b) * (ratio - 1));\n        }\n    }\n}\n\nvoid detect_splits(EdgeEstimator& est, int query_idx) {\n    // Simple split detection: look for rows/columns where local deviations\n    // show a clear pattern shift\n    \n    if (query_idx < 50) return; // Need enough data\n    \n    for (int i = 0; i < N; i++) {\n        if (est.split_col[i] >= 0) continue; // Already detected\n        \n        // Check horizontal edges in this row\n        double avg_first = 0, avg_second = 0;\n        int cnt_first = 0, cnt_second = 0;\n        \n        for (int j = 0; j < 14; j++) {\n            if (est.cnt_H[i][j] > 0) {\n                avg_first += est.get_H(i, j);\n                cnt_first++;\n            }\n        }\n        for (int j = 14; j < 28; j++) {\n            if (est.cnt_H[i][j] > 0) {\n                avg_second += est.get_H(i, j);\n                cnt_second++;\n            }\n        }\n        \n        if (cnt_first >= 5 && cnt_second >= 5) {\n            avg_first /= cnt_first;\n            avg_second /= cnt_second;\n            \n            if (abs(avg_first - avg_second) > 500) {\n                // Potential split detected\n                int best_split = 14;\n                double best_diff = 0;\n                \n                for (int s = 1; s < 28; s++) {\n                    double left_avg = 0, right_avg = 0;\n                    int left_cnt = 0, right_cnt = 0;\n                    \n                    for (int j = 0; j < s; j++) {\n                        if (est.cnt_H[i][j] > 0) {\n                            left_avg += est.get_H(i, j);\n                            left_cnt++;\n                        }\n                    }\n                    for (int j = s; j < 28; j++) {\n                        if (est.cnt_H[i][j] > 0) {\n                            right_avg += est.get_H(i, j);\n                            right_cnt++;\n                        }\n                    }\n                    \n                    if (left_cnt >= 3 && right_cnt >= 3) {\n                        left_avg /= left_cnt;\n                        right_avg /= right_cnt;\n                        double diff = abs(left_avg - right_avg);\n                        if (diff > best_diff) {\n                            best_diff = diff;\n                            best_split = s;\n                        }\n                    }\n                }\n                \n                if (best_diff > 500) {\n                    est.split_col[i] = best_split;\n                    // Calculate split adjustment\n                    double left_avg = 0, right_avg = 0;\n                    int left_cnt = 0, right_cnt = 0;\n                    for (int j = 0; j < best_split; j++) {\n                        if (est.cnt_H[i][j] > 0) {\n                            left_avg += est.get_H(i, j) - est.row_base_H[i] - est.local_H[i][j];\n                            left_cnt++;\n                        }\n                    }\n                    for (int j = best_split; j < 28; j++) {\n                        if (est.cnt_H[i][j] > 0) {\n                            right_avg += est.get_H(i, j) - est.row_base_H[i] - est.local_H[i][j];\n                            right_cnt++;\n                        }\n                    }\n                    if (left_cnt > 0) left_avg /= left_cnt;\n                    if (right_cnt > 0) right_avg /= right_cnt;\n                    est.row_split_H[i] = right_avg - left_avg;\n                }\n            }\n        }\n    }\n    \n    // Similar for vertical edges\n    for (int j = 0; j < N; j++) {\n        if (est.split_row[j] >= 0) continue;\n        \n        double avg_top = 0, avg_bottom = 0;\n        int cnt_top = 0, cnt_bottom = 0;\n        \n        for (int i = 0; i < 14; i++) {\n            if (est.cnt_V[i][j] > 0) {\n                avg_top += est.get_V(i, j);\n                cnt_top++;\n            }\n        }\n        for (int i = 14; i < 28; i++) {\n            if (est.cnt_V[i][j] > 0) {\n                avg_bottom += est.get_V(i, j);\n                cnt_bottom++;\n            }\n        }\n        \n        if (cnt_top >= 5 && cnt_bottom >= 5) {\n            avg_top /= cnt_top;\n            avg_bottom /= cnt_bottom;\n            \n            if (abs(avg_top - avg_bottom) > 500) {\n                int best_split = 14;\n                double best_diff = 0;\n                \n                for (int s = 1; s < 28; s++) {\n                    double top_avg = 0, bottom_avg = 0;\n                    int top_cnt = 0, bottom_cnt = 0;\n                    \n                    for (int i = 0; i < s; i++) {\n                        if (est.cnt_V[i][j] > 0) {\n                            top_avg += est.get_V(i, j);\n                            top_cnt++;\n                        }\n                    }\n                    for (int i = s; i < 28; i++) {\n                        if (est.cnt_V[i][j] > 0) {\n                            bottom_avg += est.get_V(i, j);\n                            bottom_cnt++;\n                        }\n                    }\n                    \n                    if (top_cnt >= 3 && bottom_cnt >= 3) {\n                        top_avg /= top_cnt;\n                        bottom_avg /= bottom_cnt;\n                        double diff = abs(top_avg - bottom_avg);\n                        if (diff > best_diff) {\n                            best_diff = diff;\n                            best_split = s;\n                        }\n                    }\n                }\n                \n                if (best_diff > 500) {\n                    est.split_row[j] = best_split;\n                    double top_avg = 0, bottom_avg = 0;\n                    int top_cnt = 0, bottom_cnt = 0;\n                    for (int i = 0; i < best_split; i++) {\n                        if (est.cnt_V[i][j] > 0) {\n                            top_avg += est.get_V(i, j) - est.col_base_V[j] - est.local_V[i][j];\n                            top_cnt++;\n                        }\n                    }\n                    for (int i = best_split; i < 28; i++) {\n                        if (est.cnt_V[i][j] > 0) {\n                            bottom_avg += est.get_V(i, j) - est.col_base_V[j] - est.local_V[i][j];\n                            bottom_cnt++;\n                        }\n                    }\n                    if (top_cnt > 0) top_avg /= top_cnt;\n                    if (bottom_cnt > 0) bottom_avg /= bottom_cnt;\n                    est.col_split_V[j] = bottom_avg - top_avg;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    EdgeEstimator est;\n    double explore_bonus = 5000;\n    \n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Detect splits every 20 queries\n        if (k % 20 == 0) {\n            detect_splits(est, k);\n        }\n        \n        // Find path\n        auto [path, est_len] = dijkstra(si, sj, ti, tj, est, explore_bonus);\n        \n        // Ensure we have a valid path\n        if (path.empty()) {\n            // Fallback: simple Manhattan path\n            path.push_back({si, sj});\n            // Just output something valid\n            cerr << \"Empty path!\" << endl;\n        }\n        \n        cout << path_to_string(path) << endl;\n        \n        int observed;\n        cin >> observed;\n        \n        // Update estimates\n        update_estimates(est, path, observed, est_len, k);\n        \n        // Decay exploration bonus\n        explore_bonus *= 0.997;\n    }\n    \n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nconst int N = 20;\nint M;\nvector<string> strings;\nvector<int> string_lens;\n\n// directions: 0 horizontal, 1 vertical\nstruct MatchPos {\n    int r, c, dir, idx;\n};\n\nvector<vector<MatchPos>> candidates_per_string;\n\n// current grid\nchar grid[N][N];\n\n// precomputed: which strings are currently matched? For speed, we keep a count of matched and bool array\nbitset<800> matched;\nint matched_count = 0;\nint empty_count = 0;\n\n// For each cell, list of matches that use it (so we can quickly recompute on change)\nstruct CellDep {\n    int string_idx;\n    int pos_idx; // which candidate for that string\n};\nvector<CellDep> cell_deps[N][N];\n\n// Score with all matched: 10^8 * 2*N^2 / (2*N^2 - d)\n// Otherwise: 10^8 * c / M\ndouble calc_score() {\n    if (matched_count < M) {\n        return 1e8 * matched_count / M;\n    } else {\n        return 1e8 * (2.0 * N * N) / (2.0 * N * N - empty_count);\n    }\n}\n\n// Check if a specific candidate matches current grid\nbool check_candidate(const MatchPos &mp) {\n    const string &s = strings[mp.idx];\n    int len = s.size();\n    if (mp.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            char c = grid[mp.r][(mp.c + p) % N];\n            if (c != '.' && c != s[p]) return false;\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            char c = grid[(mp.r + p) % N][mp.c];\n            if (c != '.' && c != s[p]) return false;\n        }\n    }\n    return true;\n}\n\n// Update matched status for all strings that depend on a cell (r,c)\nvoid update_after_change(int r, int c) {\n    for (auto &dep : cell_deps[r][c]) {\n        int sidx = dep.string_idx;\n        bool was = matched[sidx];\n        const MatchPos &mp = candidates_per_string[sidx][dep.pos_idx];\n        bool now = check_candidate(mp);\n        if (was && !now) {\n            matched[sidx] = false;\n            --matched_count;\n        } else if (!was && now) {\n            matched[sidx] = true;\n            ++matched_count;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    strings.resize(M);\n    string_lens.resize(M);\n    candidates_per_string.resize(M);\n\n    // Generate candidates for each string\n    for (int i = 0; i < M; ++i) {\n        cin >> strings[i];\n        int len = strings[i].size();\n        string_lens[i] = len;\n        // horizontal candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                candidates_per_string[i].push_back({r, c, 0, i});\n            }\n        }\n        // vertical candidates\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                candidates_per_string[i].push_back({r, c, 1, i});\n            }\n        }\n    }\n\n    // Initialize grid with random letters\n    const char letters[] = {'A','B','C','D','E','F','G','H'};\n    mt19937 rng(42);\n    uniform_int_distribution<int> letter_dist(0,7);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = letters[letter_dist(rng)];\n\n    // Build dependencies\n    for (int i = 0; i < M; ++i) {\n        for (int p = 0; p < (int)candidates_per_string[i].size(); ++p) {\n            const auto &mp = candidates_per_string[i][p];\n            const string &s = strings[i];\n            int len = s.size();\n            if (mp.dir == 0) {\n                for (int k = 0; k < len; ++k) {\n                    int rr = mp.r;\n                    int cc = (mp.c + k) % N;\n                    cell_deps[rr][cc].push_back({i, p});\n                }\n            } else {\n                for (int k = 0; k < len; ++k) {\n                    int rr = (mp.r + k) % N;\n                    int cc = mp.c;\n                    cell_deps[rr][cc].push_back({i, p});\n                }\n            }\n        }\n    }\n\n    // Initial match count\n    for (int i = 0; i < M; ++i) {\n        for (auto &mp : candidates_per_string[i]) {\n            if (check_candidate(mp)) {\n                matched[i] = true;\n                ++matched_count;\n                break;\n            }\n        }\n    }\n    empty_count = 0;\n\n    // Simulated Annealing parameters\n    double temp_start = 2.0;\n    double temp_end = 0.01;\n    int max_iter = 200000;\n    uniform_real_distribution<double> prob_dist(0.0, 1.0);\n    uniform_int_distribution<int> cell_dist(0, N-1);\n    uniform_int_distribution<int> letter_dist2(0, 7);\n    auto start_time = high_resolution_clock::now();\n\n    double best_score = calc_score();\n    char best_grid[N][N];\n    memcpy(best_grid, grid, sizeof(grid));\n\n    for (int iter = 0; iter < max_iter; ++iter) {\n        double progress = (double)iter / max_iter;\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n\n        int r = cell_dist(rng);\n        int c = cell_dist(rng);\n        char old_char = grid[r][c];\n        char new_char;\n        if (prob_dist(rng) < 0.1) {\n            new_char = '.';\n        } else {\n            new_char = letters[letter_dist2(rng)];\n        }\n        if (new_char == old_char) continue;\n\n        int old_empty = empty_count;\n        if (old_char == '.') --empty_count;\n        if (new_char == '.') ++empty_count;\n\n        grid[r][c] = new_char;\n        update_after_change(r, c);\n\n        double new_score = calc_score();\n        double score_diff = new_score - best_score;\n        if (score_diff >= 0 || prob_dist(rng) < exp(score_diff / (best_score * temp + 1e-9))) {\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_grid, grid, sizeof(grid));\n            }\n        } else {\n            // revert\n            grid[r][c] = old_char;\n            empty_count = old_empty;\n            update_after_change(r, c);\n        }\n    }\n\n    // Output best found\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dir[4] = {'U', 'D', 'L', 'R'};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> cost;\nvector<vector<bool>> road;\nvector<vector<bitset<5000>>> visMask;\nint totalRoads = 0;\nvector<vector<int>> roadId;\n\nbool inside(int i, int j) {\n    return i>=0 && i<N && j>=0 && j<N;\n}\n\nvector<pair<int,int>> shortestPath(int si, int sj, int ti, int tj) {\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    priority_queue<pair<int,pair<int,int>>, vector<pair<int,pair<int,int>>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, {si, sj}});\n    while(!pq.empty()) {\n        auto [d, pos] = pq.top(); pq.pop();\n        auto [i, j] = pos;\n        if(d != dist[i][j]) continue;\n        if(i==ti && j==tj) break;\n        for(int k=0;k<4;k++) {\n            int ni = i+dx[k], nj = j+dy[k];\n            if(inside(ni,nj) && road[ni][nj]) {\n                int nd = d + cost[ni][nj];\n                if(nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i,j};\n                    pq.push({nd, {ni,nj}});\n                }\n            }\n        }\n    }\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; cj = p.second;\n    }\n    path.push_back({si,sj});\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstring pathToDir(const vector<pair<int,int>>& path) {\n    string res;\n    for(int i=0;i+1<(int)path.size();i++) {\n        int di = path[i+1].first - path[i].first;\n        int dj = path[i+1].second - path[i].second;\n        if(di == -1) res += 'U';\n        else if(di == 1) res += 'D';\n        else if(dj == -1) res += 'L';\n        else res += 'R';\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    cost.assign(N, vector<int>(N,0));\n    road.assign(N, vector<bool>(N,false));\n    roadId.assign(N, vector<int>(N,-1));\n    \n    for(int i=0;i<N;i++) {\n        cin >> grid[i];\n        for(int j=0;j<N;j++) {\n            if(grid[i][j] != '#') {\n                road[i][j] = true;\n                cost[i][j] = grid[i][j] - '0';\n                roadId[i][j] = totalRoads++;\n            }\n        }\n    }\n    \n    // compute visibility masks - now as 2D vector of bitsets\n    visMask.assign(N, vector<bitset<5000>>(N));\n    for(int i=0;i<N;i++) {\n        for(int j=0;j<N;j++) {\n            if(!road[i][j]) continue;\n            // horizontal\n            for(int jj=j; jj<N && road[i][jj]; jj++) \n                visMask[i][j].set(roadId[i][jj]);\n            for(int jj=j-1; jj>=0 && road[i][jj]; jj--) \n                visMask[i][j].set(roadId[i][jj]);\n            // vertical\n            for(int ii=i; ii<N && road[ii][j]; ii++) \n                visMask[i][j].set(roadId[ii][j]);\n            for(int ii=i-1; ii>=0 && road[ii][j]; ii--) \n                visMask[i][j].set(roadId[ii][j]);\n        }\n    }\n    \n    // Greedy set cover to choose points\n    bitset<5000> covered;\n    vector<pair<int,int>> chosen;\n    covered.set(roadId[si][sj]);\n    chosen.push_back({si,sj});\n    \n    while((int)covered.count() < totalRoads) {\n        int best = -1, bi = -1, bj = -1;\n        for(int i=0;i<N;i++) {\n            for(int j=0;j<N;j++) {\n                if(!road[i][j]) continue;\n                bitset<5000> newCov = visMask[i][j] | covered;\n                int gain = (int)newCov.count() - (int)covered.count();\n                if(gain > best) {\n                    best = gain;\n                    bi = i; bj = j;\n                }\n            }\n        }\n        if(best<=0) break;\n        covered |= visMask[bi][bj];\n        chosen.push_back({bi,bj});\n    }\n    \n    // Build route in nearest-neighbor order\n    vector<pair<int,int>> order;\n    vector<bool> used(chosen.size(), false);\n    order.push_back(chosen[0]);\n    used[0] = true;\n    int cur = 0;\n    for(int step=1; step<(int)chosen.size(); step++) {\n        int bestIdx = -1;\n        int bestDist = 1e9;\n        for(int i=1;i<(int)chosen.size();i++) {\n            if(!used[i]) {\n                int d = abs(chosen[cur].first - chosen[i].first) + abs(chosen[cur].second - chosen[i].second);\n                if(d < bestDist) {\n                    bestDist = d;\n                    bestIdx = i;\n                }\n            }\n        }\n        used[bestIdx] = true;\n        order.push_back(chosen[bestIdx]);\n        cur = bestIdx;\n    }\n    order.push_back(chosen[0]); // return to start\n    \n    // 2-opt improvement\n    auto distEst = [&](int a, int b) {\n        return abs(order[a].first - order[b].first) + abs(order[a].second - order[b].second);\n    };\n    bool improved = true;\n    int m = (int)order.size();\n    while(improved) {\n        improved = false;\n        for(int i=1;i<m-2;i++) {\n            for(int j=i+1;j<m-1;j++) {\n                int oldCost = distEst(i-1,i) + distEst(j,j+1);\n                int newCost = distEst(i-1,j) + distEst(i,j+1);\n                if(newCost < oldCost) {\n                    reverse(order.begin()+i, order.begin()+j+1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // Build full path\n    vector<pair<int,int>> fullPath;\n    for(int i=0;i+1<(int)order.size();i++) {\n        auto pp = shortestPath(order[i].first, order[i].second,\n                                order[i+1].first, order[i+1].second);\n        if(!fullPath.empty()) fullPath.pop_back(); // avoid duplicate junction\n        fullPath.insert(fullPath.end(), pp.begin(), pp.end());\n    }\n    \n    string ans = pathToDir(fullPath);\n    cout << ans << \"\\n\";\n    \n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N_MAX = 1000;\nconst int M_MAX = 20;\nconst int K_MAX = 20;\nconst int MAX_DAY = 2000;\n\nint N, M, K, R;\nvector<vector<int>> d; // task difficulties\nvector<vector<int>> dep; // dependencies: dep[i] = list of tasks that task i depends on\nvector<vector<int>> rev_dep; // reverse dependencies\nvector<int> in_degree;\n\nvector<vector<double>> s_est; // estimated skills [M][K]\nvector<vector<int>> observed_t; // observed times for each (task, member)\nvector<vector<pair<int,int>>> task_member_obs; // (task, member) -> list of (predicted_t, actual_t)\n\n// For each member, track which skills we've observed\nvector<vector<int>> skill_observations; // [M][K] count of observations\n\nenum TaskStatus { NOT_STARTED = 0, IN_PROGRESS = 1, COMPLETED = 2 };\nvector<TaskStatus> task_status;\nvector<int> task_assigned_to; // which member is doing task (-1 if none)\nvector<int> task_start_day; // when task was started\nvector<int> member_busy_until; // day until which member is busy\nvector<int> completed_tasks;\n\n// For estimation\nvector<vector<double>> skill_gaps_sum; // sum of observed gaps for each (member, skill)\nvector<vector<int>> skill_gaps_count; // count of observations for each (member, skill)\n\nvoid parse_input() {\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            cin >> d[i][k];\n        }\n    }\n    dep.resize(N);\n    rev_dep.resize(N);\n    in_degree.resize(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        dep[v].push_back(u);\n        rev_dep[u].push_back(v);\n        in_degree[v]++;\n    }\n}\n\nvoid init_estimation() {\n    s_est.assign(M, vector<double>(K, 0.0));\n    // Initialize with average expected skill (middle of range 20-60)\n    // We'll estimate as we observe\n    skill_observations.assign(M, vector<int>(K, 0));\n    observed_t.assign(N, vector<int>(M, -1));\n    task_member_obs.resize(N * M);\n    skill_gaps_sum.assign(M, vector<double>(K, 0.0));\n    skill_gaps_count.assign(M, vector<int>(K, 0));\n    \n    // Initialize s_est with moderate values\n    for (int j = 0; j < M; j++) {\n        for (int k = 0; k < K; k++) {\n            s_est[j][k] = 30.0; // prior estimate\n        }\n    }\n}\n\nvoid init_scheduling() {\n    task_status.assign(N, NOT_STARTED);\n    task_assigned_to.assign(N, -1);\n    task_start_day.assign(N, -1);\n    member_busy_until.assign(M, 0);\n    completed_tasks.clear();\n}\n\n// Estimate w_i,j based on current s_est\ndouble estimate_w(int i, int j) {\n    double w = 0;\n    for (int k = 0; k < K; k++) {\n        w += max(0.0, (double)d[i][k] - s_est[j][k]);\n    }\n    return w;\n}\n\n// Estimate t_i,j based on w\nint estimate_t(int i, int j) {\n    double w = estimate_w(i, j);\n    if (w < 0.5) return 1; // effectively zero\n    return max(1, (int)round(w));\n}\n\n// Update skill estimates based on observation\nvoid update_skill_estimate(int task, int member, int actual_t) {\n    // actual_t = 1 means w_i,j was likely 0 (or very small)\n    // actual_t > 1 means w_i,j was approximately actual_t (with noise -3 to +3)\n    \n    if (actual_t == 1) {\n        // All skills of member are at least d[task][k]\n        for (int k = 0; k < K; k++) {\n            if (d[task][k] > 0) {\n                // We know s[member][k] >= d[task][k]\n                s_est[member][k] = max(s_est[member][k], (double)d[task][k] + 0.5);\n            }\n        }\n    } else {\n        // w_i,j is roughly actual_t (with noise)\n        // We can't easily decompose which skills contributed\n        // Use gradient-like update\n        double current_w = estimate_w(task, member);\n        double target_w = actual_t;\n        \n        // Distribute the difference proportionally to skills where d > s_est\n        double diff = target_w - current_w;\n        if (abs(diff) > 0.01) {\n            double total_weight = 0;\n            vector<double> gaps(K, 0);\n            for (int k = 0; k < K; k++) {\n                gaps[k] = max(0.0, (double)d[task][k] - s_est[member][k]);\n                total_weight += gaps[k];\n            }\n            if (total_weight > 0.01) {\n                for (int k = 0; k < K; k++) {\n                    if (gaps[k] > 0.01) {\n                        double update = diff * gaps[k] / total_weight;\n                        s_est[member][k] -= update * 0.5; // learning rate\n                        s_est[member][k] = max(0.0, s_est[member][k]);\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Calculate critical path length (longest path to completion)\nvector<int> compute_critical_path() {\n    vector<int> topo;\n    vector<int> indeg = in_degree;\n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (indeg[i] == 0 && task_status[i] != COMPLETED) {\n            q.push(i);\n        }\n    }\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) {\n                q.push(u);\n            }\n        }\n    }\n    \n    vector<int> est_time(N, 0);\n    // Process in reverse topological order\n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        if (task_status[v] == COMPLETED) {\n            est_time[v] = 0;\n        } else {\n            int best_t = 1000000;\n            for (int j = 0; j < M; j++) {\n                best_t = min(best_t, estimate_t(v, j));\n            }\n            est_time[v] = best_t;\n            int max_succ = 0;\n            for (int u : rev_dep[v]) {\n                max_succ = max(max_succ, est_time[u]);\n            }\n            est_time[v] += max_succ;\n        }\n    }\n    \n    return est_time;\n}\n\n// Check if task is ready (all dependencies completed)\nbool is_task_ready(int task, int current_day) {\n    if (task_status[task] != NOT_STARTED) return false;\n    for (int dep_task : dep[task]) {\n        if (task_status[dep_task] != COMPLETED) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    parse_input();\n    init_estimation();\n    init_scheduling();\n    \n    int current_day = 0;\n    vector<int> last_completed;\n    \n    while (true) {\n        current_day++;\n        \n        // Process completions from previous day\n        for (int member : last_completed) {\n            // Find which task this member was doing\n            for (int i = 0; i < N; i++) {\n                if (task_assigned_to[i] == member && task_status[i] == IN_PROGRESS) {\n                    task_status[i] = COMPLETED;\n                    completed_tasks.push_back(i);\n                    \n                    // Update skill estimates\n                    int actual_t = current_day - task_start_day[i];\n                    update_skill_estimate(i, member, actual_t);\n                    \n                    task_assigned_to[i] = -1;\n                    break;\n                }\n            }\n        }\n        \n        // Check if all tasks completed\n        if ((int)completed_tasks.size() == N) {\n            break;\n        }\n        if (current_day > MAX_DAY) {\n            break;\n        }\n        \n        // Compute task priorities\n        vector<int> crit_path = compute_critical_path();\n        \n        // Find available tasks\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (is_task_ready(i, current_day)) {\n                ready_tasks.push_back(i);\n            }\n        }\n        \n        // Sort ready tasks by critical path length (descending - more urgent first)\n        sort(ready_tasks.begin(), ready_tasks.end(), [&](int a, int b) {\n            return crit_path[a] > crit_path[b];\n        });\n        \n        // Find available members\n        vector<int> available_members;\n        for (int j = 0; j < M; j++) {\n            if (member_busy_until[j] <= current_day) {\n                available_members.push_back(j);\n            }\n        }\n        \n        // Track which members we assign to ensure no double assignment\n        vector<bool> member_used(M, false);\n        \n        // Assignment strategy\n        vector<pair<int,int>> assignments;\n        \n        // First pass: assign tasks that can be done in 1 day by some member\n        for (int task : ready_tasks) {\n            if (assignments.size() >= available_members.size()) break;\n            \n            int best_member = -1;\n            int best_t = 1000000;\n            \n            for (int j : available_members) {\n                if (member_used[j]) continue;\n                int est_t = estimate_t(task, j);\n                if (est_t < best_t) {\n                    best_t = est_t;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1 && best_t == 1) {\n                assignments.push_back({best_member, task});\n                member_used[best_member] = true;\n            }\n        }\n        \n        // Second pass: assign remaining tasks to best available members\n        for (int task : ready_tasks) {\n            if (assignments.size() >= available_members.size()) break;\n            \n            // Skip if already assigned\n            bool already = false;\n            for (auto &p : assignments) {\n                if (p.second == task) { already = true; break; }\n            }\n            if (already) continue;\n            \n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int j : available_members) {\n                if (member_used[j]) continue;\n                int est_t = estimate_t(task, j);\n                // Prioritize lower time, but also consider exploration\n                double score = -est_t;\n                \n                // Add exploration bonus for tasks with few observations\n                int obs_count = 0;\n                for (int k = 0; k < K; k++) {\n                    if (d[task][k] > 0) obs_count += skill_gaps_count[j][k];\n                }\n                if (obs_count < 5) score += 10.0; // exploration bonus\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                assignments.push_back({best_member, task});\n                member_used[best_member] = true;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            int member = p.first;\n            int task = p.second;\n            cout << \" \" << (member + 1) << \" \" << (task + 1);\n            \n            // Update state\n            task_status[task] = IN_PROGRESS;\n            task_assigned_to[task] = member;\n            task_start_day[task] = current_day;\n            int duration = estimate_t(task, member);\n            member_busy_until[member] = current_day + duration;\n        }\n        cout << \"\\n\";\n        \n        // Output skill predictions as comments\n        for (int j = 0; j < M; j++) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << \" \" << (int)round(s_est[j][k]);\n            }\n            cout << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read input\n        string line;\n        getline(cin, line);\n        if (line.empty()) continue;\n        \n        istringstream iss(line);\n        vector<int> vals;\n        int x;\n        while (iss >> x) vals.push_back(x);\n        \n        if (vals.size() == 1 && vals[0] == -1) {\n            break;\n        }\n        \n        last_completed.clear();\n        if (vals.size() > 0) {\n            int n_comp = vals[0];\n            for (int i = 0; i < n_comp; i++) {\n                last_completed.push_back(vals[i + 1] - 1);\n            }\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <cassert>\n#include <climits>\n\nusing namespace std;\n\n// ------------------------------------------------------------\n// geometry / distance\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ------------------------------------------------------------\n// order structure\nstruct Order {\n    int id;\n    int ax, ay; // restaurant\n    int cx, cy; // destination\n};\n\n// ------------------------------------------------------------\n// route node kinds\nenum NodeType { PICKUP, DELIVERY, DEPOT };\n\nstruct Node {\n    NodeType type;\n    int order_id; // -1 for depot\n    int x, y;\n};\n\n// ------------------------------------------------------------\n// compute total Manhattan distance of a route\nint routeLength(const vector<Node>& route) {\n    int total = 0;\n    for (size_t i = 0; i + 1 < route.size(); ++i) {\n        total += manhattan(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// check if route satisfies pickup before delivery for all orders\nbool feasibleRoute(const vector<Node>& route) {\n    map<int, int> firstSeen;\n    for (size_t i = 0; i < route.size(); ++i) {\n        if (route[i].type == DEPOT) continue;\n        int oid = route[i].order_id;\n        if (route[i].type == PICKUP) {\n            if (firstSeen.find(oid) == firstSeen.end()) {\n                firstSeen[oid] = i;\n            }\n        } else { // DELIVERY\n            if (firstSeen.find(oid) == firstSeen.end()) return false;\n        }\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// insert one order (pickup then delivery) at best positions to minimize extra distance\npair<int,int> bestInsert(const vector<Node>& route, const Order& ord) {\n    int bestCost = INT_MAX;\n    int bestP = -1, bestD = -1;\n    // we cannot insert at pos 0 (depot) and pos N-1 (depot)\n    int n = (int)route.size();\n    // pickup can go after position i (0 <= i < n-1), delivery after position j (i+1 <= j < n-1)\n    for (int i = 0; i < n-1; ++i) {\n        // tentative pickup position after i\n        int pi = i+1;\n        int distPBefore = manhattan(route[i].x, route[i].y, ord.ax, ord.ay);\n        int distPAfter  = manhattan(ord.ax, ord.ay, route[pi].x, route[pi].y);\n        int extraP = distPBefore + distPAfter - manhattan(route[i].x, route[i].y, route[pi].x, route[pi].y);\n        for (int j = i; j < n-1; ++j) {\n            // delivery position after j, but after pickup inserted, indices shift\n            int dj = j+1;\n            int distDBefore = manhattan(route[j].x, route[j].y, ord.cx, ord.cy);\n            int distDAfter  = manhattan(ord.cx, ord.cy, route[dj].x, route[dj].y);\n            int extraD = distDBefore + distDAfter - manhattan(route[j].x, route[j].y, route[dj].x, route[dj].y);\n            int totalExtra = extraP + extraD;\n            if (totalExtra < bestCost) {\n                bestCost = totalExtra;\n                bestP = pi;\n                // delivery shift due to pickup inserted before j\n                bestD = (j >= i) ? dj + 1 : dj;\n            }\n        }\n    }\n    return {bestP, bestD};\n}\n\n// ------------------------------------------------------------\n// insert order at given positions (indices in the current route)\nvector<Node> insertOrder(const vector<Node>& route, const Order& ord, int posP, int posD) {\n    vector<Node> newRoute = route;\n    Node pNode = {PICKUP, ord.id, ord.ax, ord.ay};\n    Node dNode = {DELIVERY, ord.id, ord.cx, ord.cy};\n    if (posP < posD) {\n        newRoute.insert(newRoute.begin() + posD, dNode);\n        newRoute.insert(newRoute.begin() + posP, pNode);\n    } else {\n        newRoute.insert(newRoute.begin() + posP, pNode);\n        newRoute.insert(newRoute.begin() + posD, dNode);\n    }\n    return newRoute;\n}\n\n// ------------------------------------------------------------\n// build initial route with selected orders (simple greedy insertion)\nvector<Node> buildInitialRoute(const vector<Order>& orders, const vector<int>& selected) {\n    vector<Node> route;\n    route.push_back({DEPOT, -1, 400, 400});\n    route.push_back({DEPOT, -1, 400, 400});\n    \n    for (int id : selected) {\n        auto [p, d] = bestInsert(route, orders[id]);\n        route = insertOrder(route, orders[id], p, d);\n    }\n    return route;\n}\n\n// ------------------------------------------------------------\n// random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// main optimization\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    const int N = 1000;\n    const int K = 50;\n    const int DEPOT_X = 400, DEPOT_Y = 400;\n    \n    vector<Order> orders(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        orders[i].id = i;\n    }\n    \n    // initial selection: first 50\n    vector<int> selected(K);\n    iota(selected.begin(), selected.end(), 0);\n    \n    // build initial route\n    vector<Node> route = buildInitialRoute(orders, selected);\n    int bestLen = routeLength(route);\n    vector<Node> bestRoute = route;\n    vector<int> bestSelected = selected;\n    \n    // set of available orders (not selected)\n    set<int> available;\n    for (int i = K; i < N; ++i) available.insert(i);\n    \n    // hill climbing with random restarts limited by time\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.8; // seconds\n    int iterations = 0;\n    \n    uniform_int_distribution<int> selDist(0, K-1);\n    uniform_int_distribution<int> availIdx(0, N-K-1);\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        iterations++;\n        \n        // Try to replace one selected order with an unchosen one\n        int idxRemove = selDist(rng);\n        int oldOrderId = selected[idxRemove];\n        \n        // pick a random available order\n        int pick = availIdx(rng) % (int)available.size();\n        auto it = available.begin();\n        advance(it, pick);\n        int newOrderId = *it;\n        \n        // new selection\n        vector<int> newSel = selected;\n        newSel[idxRemove] = newOrderId;\n        \n        // build route with new selection using greedy insertion from scratch\n        vector<Node> candRoute;\n        candRoute.push_back({DEPOT, -1, DEPOT_X, DEPOT_Y});\n        candRoute.push_back({DEPOT, -1, DEPOT_X, DEPOT_Y});\n        \n        for (int oid : newSel) {\n            auto [p, d] = bestInsert(candRoute, orders[oid]);\n            candRoute = insertOrder(candRoute, orders[oid], p, d);\n        }\n        \n        int candLen = routeLength(candRoute);\n        if (candLen < bestLen) {\n            bestLen = candLen;\n            bestRoute = candRoute;\n            bestSelected = newSel;\n            \n            // update available set\n            available.erase(newOrderId);\n            available.insert(oldOrderId);\n            selected = newSel;\n        }\n        \n        // also try some local search moves on the current best route\n        // for simplicity just 2-opt like relocation of single node\n        if (iterations % 10 == 0) {\n            int n = (int)bestRoute.size();\n            // try moving a node to another position maintaining feasibility\n            for (int i = 1; i < n-1; ++i) {\n                for (int j = 1; j < n-1; ++j) {\n                    if (i == j) continue;\n                    vector<Node> newRoute = bestRoute;\n                    Node moved = newRoute[i];\n                    newRoute.erase(newRoute.begin() + i);\n                    if (j > i) j--;\n                    newRoute.insert(newRoute.begin() + j, moved);\n                    if (feasibleRoute(newRoute)) {\n                        int len = routeLength(newRoute);\n                        if (len < bestLen) {\n                            bestLen = len;\n                            bestRoute = newRoute;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Output final\n    cout << K;\n    for (int id : bestSelected) cout << \" \" << id+1;\n    cout << \"\\n\";\n    cout << bestRoute.size();\n    for (const auto& node : bestRoute) {\n        cout << \" \" << node.x << \" \" << node.y;\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <random>\n#include <queue>\n#include <tuple>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    double d;  // Euclidean distance\n    int index;\n};\n\nclass UnionFind {\npublic:\n    vector<int> parent, rank;\n    \n    UnionFind(int n) {\n        parent.resize(n);\n        rank.resize(n, 0);\n        iota(parent.begin(), parent.end(), 0);\n    }\n    \n    int find(int x) {\n        if (parent[x] != x)\n            parent[x] = find(parent[x]);\n        return parent[x];\n    }\n    \n    bool unite(int x, int y) {\n        int px = find(x), py = find(y);\n        if (px == py) return false;\n        if (rank[px] < rank[py])\n            parent[px] = py;\n        else if (rank[px] > rank[py])\n            parent[py] = px;\n        else {\n            parent[py] = px;\n            rank[px]++;\n        }\n        return true;\n    }\n    \n    bool connected(int x, int y) {\n        return find(x) == find(y);\n    }\n    \n    int countComponents() {\n        int cnt = 0;\n        for (int i = 0; i < parent.size(); i++)\n            if (find(i) == i) cnt++;\n        return cnt;\n    }\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>> coords(N);\n    for (int i = 0; i < N; i++) {\n        cin >> coords[i].first >> coords[i].second;\n    }\n    \n    // Read edges\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        edges[i].index = i;\n        int dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        int dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = round(sqrt(dx*dx + dy*dy));\n    }\n    \n    // Pre-compute offline MST using d_i to understand edge importance\n    vector<int> edgeImportance(M, 2);  // 0: MST edge, 1: 2nd round, etc.\n    \n    // We'll do 5 rounds of MST extraction to label edges\n    vector<bool> used(M, false);\n    for (int round = 0; round < 5; round++) {\n        vector<pair<double, int>> remaining;\n        for (int i = 0; i < M; i++) {\n            if (!used[i]) {\n                remaining.push_back({edges[i].d, i});\n            }\n        }\n        sort(remaining.begin(), remaining.end());\n        \n        UnionFind uf(N);\n        for (auto& [d, idx] : remaining) {\n            if (uf.unite(edges[idx].u, edges[idx].v)) {\n                used[idx] = true;\n                edgeImportance[idx] = round;\n            }\n        }\n    }\n    \n    // Now process edges online\n    UnionFind uf(N);\n    vector<int> accepted;\n    int remainingEdges = M;\n    int neededEdges = N - 1;\n    int acceptedCount = 0;\n    \n    // Track how many edges of each importance level we've seen\n    vector<int> seenByImportance(5, 0);\n    vector<int> acceptedByImportance(5, 0);\n    \n    for (int i = 0; i < M; i++) {\n        int li;\n        cin >> li;\n        \n        bool accept = false;\n        int importance = edgeImportance[i];\n        seenByImportance[importance]++;\n        \n        if (uf.connected(edges[i].u, edges[i].v)) {\n            // Edge creates a cycle, reject\n            accept = false;\n        } else {\n            // Edge connects two components\n            double ratio = (double)li / edges[i].d;\n            \n            // Dynamic threshold based on importance and progress\n            double threshold;\n            if (importance == 0) {\n                // MST edges: be more lenient\n                threshold = 2.5;\n            } else if (importance == 1) {\n                threshold = 2.0;\n            } else if (importance == 2) {\n                threshold = 1.5;\n            } else {\n                threshold = 1.2;\n            }\n            \n            // Adjust threshold based on how many edges we still need\n            int componentsRemaining = 0;\n            for (int j = 0; j < N; j++) {\n                if (uf.find(j) == j) componentsRemaining++;\n            }\n            \n            if (componentsRemaining <= 10) {\n                // Desperate: accept almost anything\n                threshold = 3.0;\n            }\n            \n            // Also consider how many edges remain\n            double progressRatio = (double)(M - i - 1) / (double)(componentsRemaining - 1);\n            if (progressRatio < 2.0) {\n                // Running out of edges, be more aggressive\n                threshold = max(threshold, 2.5);\n            }\n            \n            if (ratio <= threshold) {\n                accept = true;\n            } else {\n                // Even if expensive, accept if we're running out of options\n                if (progressRatio < 1.5) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept) {\n            uf.unite(edges[i].u, edges[i].v);\n            accepted.push_back(i);\n            acceptedCount++;\n            acceptedByImportance[importance]++;\n        }\n        \n        cout << (accept ? 1 : 0) << endl;\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int TURNS = 300;\n\n// Directions\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dir_char[] = {'u', 'd', 'l', 'r'};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n    Pos(int x=0, int y=0) : x(x), y(y) {}\n    bool operator==(const Pos& o) const { return x==o.x && y==o.y; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n    bool valid() const { return x>=0 && x<GRID && y>=0 && y<GRID; }\n    Pos operator+(int d) const { return Pos(x+dx[d], y+dy[d]); }\n};\n\nstruct Pet {\n    Pos pos;\n    int type;\n};\n\n// Global state\nint N, M;\nvector<Pet> pets;\nvector<Pos> humans;\nvector<vector<bool>> impassable;\nvector<Pos> human_start;\n\n// BFS for reachable area\nint bfs_area(Pos start) {\n    vector<vector<bool>> vis(GRID, vector<bool>(GRID, false));\n    queue<Pos> q;\n    q.push(start);\n    vis[start.x][start.y] = true;\n    int area = 0;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        area++;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur + d;\n            if(nxt.valid() && !impassable[nxt.x][nxt.y] && !vis[nxt.x][nxt.y]) {\n                vis[nxt.x][nxt.y] = true;\n                q.push(nxt);\n            }\n        }\n    }\n    return area;\n}\n\n// Check if pet is adjacent to a position\nbool pet_adjacent(Pos p) {\n    for(const auto& pet : pets) {\n        if(abs(pet.pos.x - p.x) + abs(pet.pos.y - p.y) <= 1) return true;\n    }\n    return false;\n}\n\n// Check if human is at a position\nbool human_at(Pos p) {\n    for(const auto& h : humans) {\n        if(h == p) return true;\n    }\n    return false;\n}\n\n// Check if pet is at a position\nbool pet_at(Pos p) {\n    for(const auto& pet : pets) {\n        if(pet.pos == p) return true;\n    }\n    return false;\n}\n\n// Can build wall at position\nbool can_build(Pos p, int human_idx) {\n    if(!p.valid()) return false;\n    if(impassable[p.x][p.y]) return true; // already impassable\n    if(pet_at(p)) return false;\n    if(human_at(p)) return false;\n    if(pet_adjacent(p)) return false;\n    return true;\n}\n\n// Manhattan distance\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\n// Direction from a to b\nint dir_to(Pos from, Pos to) {\n    if(to.x < from.x) return 0; // up\n    if(to.x > from.x) return 1; // down\n    if(to.y < from.y) return 2; // left\n    if(to.y > from.y) return 3; // right\n    return -1;\n}\n\n// BFS path\nvector<int> find_path(Pos from, Pos to) {\n    vector<vector<int>> prev(GRID, vector<int>(GRID, -1));\n    vector<vector<int>> prev_dir(GRID, vector<int>(GRID, -1));\n    queue<Pos> q;\n    q.push(from);\n    prev[from.x][from.y] = -2;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        if(cur == to) break;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur + d;\n            if(nxt.valid() && !impassable[nxt.x][nxt.y] && prev[nxt.x][nxt.y] == -1) {\n                prev[nxt.x][nxt.y] = d;\n                prev_dir[nxt.x][nxt.y] = d;\n                q.push(nxt);\n            }\n        }\n    }\n    \n    if(prev[to.x][to.y] == -1) return {};\n    \n    vector<int> path;\n    Pos cur = to;\n    while(cur != from) {\n        int d = prev[cur.x][cur.y];\n        path.push_back(d);\n        cur = Pos(cur.x - dx[d], cur.y - dy[d]);\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    \n    // Read input\n    cin >> N;\n    pets.resize(N);\n    for(int i=0; i<N; i++) {\n        cin >> pets[i].pos.x >> pets[i].pos.y >> pets[i].type;\n        pets[i].pos.x--; pets[i].pos.y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    human_start.resize(M);\n    for(int i=0; i<M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n        human_start[i] = humans[i];\n    }\n    \n    // Initialize grid\n    impassable.assign(GRID, vector<bool>(GRID, false));\n    \n    // Strategy state\n    enum State { MOVING, BUILDING };\n    vector<State> state(M, MOVING);\n    vector<Pos> target(M);\n    vector<vector<Pos>> wall_plan(M);\n    vector<int> wall_idx(M, 0);\n    \n    // Assign targets: spread humans to different corners\n    vector<Pos> corners = {\n        Pos(0, 0), Pos(0, GRID-1), \n        Pos(GRID-1, 0), Pos(GRID-1, GRID-1),\n        Pos(0, GRID/2), Pos(GRID/2, 0),\n        Pos(GRID-1, GRID/2), Pos(GRID/2, GRID-1)\n    };\n    \n    // Assign each human to nearest unassigned corner\n    vector<bool> corner_used(corners.size(), false);\n    for(int i=0; i<M; i++) {\n        int best_c = -1;\n        int best_dist = 1e9;\n        for(int c=0; c<(int)corners.size(); c++) {\n            if(!corner_used[c]) {\n                int dist = manhattan(humans[i], corners[c]);\n                if(dist < best_dist) {\n                    best_dist = dist;\n                    best_c = c;\n                }\n            }\n        }\n        if(best_c != -1) {\n            target[i] = corners[best_c];\n            corner_used[best_c] = true;\n        }\n    }\n    \n    // Wall building plan: each human builds walls to create their region\n    // Simple plan: build walls extending from their target corner\n    for(int i=0; i<M; i++) {\n        Pos tgt = target[i];\n        // Build walls to create a rectangular area around their starting position\n        // For simplicity, build a wall along two edges from the corner\n        \n        if(tgt.x == 0 && tgt.y == 0) {\n            // Top-left corner: build right and down\n            for(int y=tgt.y; y<GRID; y++) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x+1; x<GRID; x++) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == 0 && tgt.y == GRID-1) {\n            // Top-right corner\n            for(int y=tgt.y; y>=0; y--) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x+1; x<GRID; x++) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == GRID-1 && tgt.y == 0) {\n            // Bottom-left corner\n            for(int y=tgt.y; y<GRID; y++) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x-1; x>=0; x--) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == GRID-1 && tgt.y == GRID-1) {\n            // Bottom-right corner\n            for(int y=tgt.y; y>=0; y--) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x-1; x>=0; x--) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else {\n            // Other positions - build a small enclosure\n            wall_plan[i].push_back(tgt);\n        }\n    }\n    \n    // Main game loop\n    for(int turn = 0; turn < TURNS; turn++) {\n        string actions(M, '.');\n        \n        for(int i=0; i<M; i++) {\n            if(state[i] == MOVING) {\n                // Move toward target\n                if(humans[i] == target[i]) {\n                    state[i] = BUILDING;\n                    wall_idx[i] = 0;\n                } else {\n                    auto path = find_path(humans[i], target[i]);\n                    if(!path.empty()) {\n                        int d = path[0];\n                        Pos next_pos = humans[i] + d;\n                        bool blocked = false;\n                        // Check if any other human is building there\n                        // (simplified check)\n                        actions[i] = move_char[d];\n                    } else {\n                        // Path blocked, try to build walls\n                        state[i] = BUILDING;\n                        wall_idx[i] = 0;\n                    }\n                }\n            }\n            \n            if(state[i] == BUILDING) {\n                if(wall_idx[i] < (int)wall_plan[i].size()) {\n                    Pos build_pos = wall_plan[i][wall_idx[i]];\n                    // Check if we can build here\n                    if(can_build(build_pos, i)) {\n                        int d = dir_to(humans[i], build_pos);\n                        if(d != -1 && manhattan(humans[i], build_pos) == 1) {\n                            actions[i] = dir_char[d];\n                            wall_idx[i]++;\n                        } else {\n                            // Need to move closer\n                            auto path = find_path(humans[i], build_pos);\n                            if(!path.empty() && path.size() == 1) {\n                                actions[i] = dir_char[path[0]];\n                                wall_idx[i]++;\n                            } else if(!path.empty()) {\n                                actions[i] = move_char[path[0]];\n                            }\n                        }\n                    } else {\n                        // Can't build here, skip this wall segment\n                        wall_idx[i]++;\n                    }\n                } else {\n                    // Done building, stay\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        // Output actions\n        cout << actions << endl;\n        cout.flush();\n        \n        // Read pet movements\n        for(int i=0; i<N; i++) {\n            string movement;\n            cin >> movement;\n            if(movement != \".\") {\n                for(char m : movement) {\n                    if(m == 'U') pets[i].pos.x--;\n                    else if(m == 'D') pets[i].pos.x++;\n                    else if(m == 'L') pets[i].pos.y--;\n                    else if(m == 'R') pets[i].pos.y++;\n                }\n            }\n        }\n        \n        // Update human positions and grid\n        for(int i=0; i<M; i++) {\n            char act = actions[i];\n            if(act == 'U') humans[i].x--;\n            else if(act == 'D') humans[i].x++;\n            else if(act == 'L') humans[i].y--;\n            else if(act == 'R') humans[i].y++;\n            else if(act == 'u') impassable[humans[i].x-1][humans[i].y] = true;\n            else if(act == 'd') impassable[humans[i].x+1][humans[i].y] = true;\n            else if(act == 'l') impassable[humans[i].x][humans[i].y-1] = true;\n            else if(act == 'r') impassable[humans[i].x][humans[i].y+1] = true;\n        }\n        \n        // Emergency: if human is trapped with many pets nearby, try to escape\n        // (simplified: just continue with plan)\n    }\n    \n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int MAXL = 200;\n\nint di[] = {-1, 1, 0, 0};\nint dj[] = {0, 0, -1, 1};\nchar dir[] = {'U', 'D', 'L', 'R'};\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), v(19);\n    for (int i = 0; i < 20; i++) cin >> h[i];\n    for (int i = 0; i < 19; i++) cin >> v[i];\n    \n    // Precompute valid moves\n    auto canMove = [&](int i, int j, int d) {\n        int ni = i + di[d], nj = j + dj[d];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n        if (d == 0 && i > 0 && v[i-1][j] == '1') return false;\n        if (d == 1 && i < N-1 && v[i][j] == '1') return false;\n        if (d == 2 && j > 0 && h[i][j-1] == '1') return false;\n        if (d == 3 && j < N-1 && h[i][j] == '1') return false;\n        return true;\n    };\n    \n    // BFS shortest path\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<char>> moveTo(N, vector<char>(N, ' '));\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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            if (!canMove(i, j, d)) continue;\n            int ni = i + di[d], nj = j + dj[d];\n            if (dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                prev[ni][nj] = {i, j};\n                moveTo[ni][nj] = dir[d];\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    string path;\n    {\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path.push_back(moveTo[ci][cj]);\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi; cj = pj;\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    // Initial sequence: repeat shortest path to fill 200\n    string bestSeq;\n    for (int i = 0; i < MAXL; i++) {\n        bestSeq.push_back(path[i % path.size()]);\n    }\n    \n    // Evaluate expected score for a sequence\n    auto eval = [&](const string &seq) {\n        int L = seq.size();\n        vector<vector<double>> prob(N, vector<double>(N, 0));\n        prob[si][sj] = 1.0;\n        double expScore = 0;\n        double probGoalBefore = 0;\n        for (int t = 0; t < L; t++) {\n            char c = seq[t];\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 d = 3;\n            \n            vector<vector<double>> nextProb(N, vector<double>(N, 0));\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (prob[i][j] == 0) continue;\n                    if (i == ti && j == tj) continue; // already absorbed\n                    // forget\n                    nextProb[i][j] += prob[i][j] * p;\n                    // move\n                    if (canMove(i, j, d)) {\n                        int ni = i + di[d], nj = j + dj[d];\n                        nextProb[ni][nj] += prob[i][j] * (1 - p);\n                    } else {\n                        nextProb[i][j] += prob[i][j] * (1 - p);\n                    }\n                }\n            }\n            prob = move(nextProb);\n            double probHere = prob[ti][tj];\n            double newlyReached = probHere - probGoalBefore;\n            expScore += newlyReached * (401 - (t + 1));\n            probGoalBefore = probHere;\n        }\n        return expScore;\n    };\n    \n    double bestScore = eval(bestSeq);\n    \n    // Local search: random modifications\n    mt19937 rng(42);\n    uniform_int_distribution<int> posDist(0, MAXL-1);\n    uniform_int_distribution<int> dirDist(0, 3);\n    \n    for (int iter = 0; iter < 500; iter++) {\n        string cand = bestSeq;\n        int changePos = posDist(rng);\n        char newC = dir[dirDist(rng)];\n        cand[changePos] = newC;\n        double candScore = eval(cand);\n        if (candScore > bestScore) {\n            bestScore = candScore;\n            bestSeq = cand;\n        }\n    }\n    \n    cout << bestSeq << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 30;\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\nconst int to[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1}\n};\n\nint tile_type[N][N];\nint rot[N][N]; // 0..3\n\nint get_exit(int type, int rot, int dir) {\n    if (to[type][dir] == -1) return -1;\n    return (to[type][dir] + rot) % 4;\n}\n\nint edge_id[N][N][4]; // node index for each edge of each tile\nint node_count = 0;\n\nvector<int> graph[3600]; // max N*N*4 = 3600\nint adj_edge[3600]; // each node has at most one neighbor (degree <= 2 in cycle graph)\n\nvoid build_graph() {\n    node_count = 0;\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                edge_id[i][j][d] = node_count++;\n    for (int i = 0; i < node_count; i++) graph[i].clear();\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 exit_dir = get_exit(tile_type[i][j], rot[i][j], d);\n                if (exit_dir == -1) continue;\n                int ni = i + di[exit_dir];\n                int nj = j + dj[exit_dir];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nd = (exit_dir + 2) % 4;\n                int exit2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                if (exit2 == d) {\n                    int u = edge_id[i][j][d];\n                    int v = edge_id[ni][nj][exit_dir];\n                    graph[u].push_back(v);\n                }\n            }\n        }\n    }\n}\n\nbool vis[3600];\nint comp[3600];\nint comp_len[3600];\nint comp_count = 0;\n\nvoid find_cycles() {\n    fill(vis, vis + node_count, false);\n    comp_count = 0;\n    for (int i = 0; i < node_count; i++) {\n        if (vis[i]) continue;\n        if (graph[i].empty()) { vis[i] = true; continue; }\n        // follow the cycle/path\n        vector<int> nodes;\n        int cur = i;\n        while (!vis[cur]) {\n            vis[cur] = true;\n            nodes.push_back(cur);\n            if (graph[cur].empty()) break;\n            int nxt = graph[cur][0];\n            if (vis[nxt]) break;\n            cur = nxt;\n        }\n        if (graph[nodes.back()].empty()) {\n            for (int x : nodes) comp[x] = -1; // path\n        } else if (graph[nodes.back()][0] == nodes[0]) {\n            // cycle\n            int len = nodes.size();\n            for (int x : nodes) comp[x] = comp_count;\n            comp_len[comp_count] = len;\n            comp_count++;\n        } else {\n            for (int x : nodes) comp[x] = -1; // dead end\n        }\n    }\n}\n\nint get_score() {\n    build_graph();\n    find_cycles();\n    vector<int> lengths;\n    for (int c = 0; c < comp_count; c++) lengths.push_back(comp_len[c]);\n    sort(lengths.rbegin(), lengths.rend());\n    if (lengths.size() < 2) return 0;\n    return lengths[0] * lengths[1];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = high_resolution_clock::now();\n\n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++) {\n            tile_type[i][j] = s[j] - '0';\n        }\n    }\n\n    // initial random rotations\n    mt19937 rng(42);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            rot[i][j] = rng() % 4;\n\n    int best_score = get_score();\n    int cur_score = best_score;\n    int best_rot[N][N];\n    memcpy(best_rot, rot, sizeof(rot));\n\n    double temp_start = 100.0, temp_end = 0.1;\n    int iterations = 0;\n    const int max_iter = 500000;\n\n    uniform_real_distribution<> prob(0, 1);\n    uniform_int_distribution<> pos(0, N-1);\n    uniform_int_distribution<> rrot(1, 3);\n\n    while (true) {\n        auto now = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(now - start_time).count() > 1900) break;\n        if (iterations >= max_iter) break;\n        iterations++;\n\n        int i = pos(rng);\n        int j = pos(rng);\n        int old_r = rot[i][j];\n        int new_r = (old_r + rrot(rng)) % 4;\n        rot[i][j] = new_r;\n        int new_score = get_score();\n\n        if (new_score > best_score) {\n            best_score = new_score;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n\n        if (new_score >= cur_score) {\n            cur_score = new_score;\n        } else {\n            double t = temp_start * pow(temp_end / temp_start, (double)iterations / max_iter);\n            double p = exp((new_score - cur_score) / t);\n            if (prob(rng) < p) {\n                cur_score = new_score;\n            } else {\n                rot[i][j] = old_r;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cout << best_rot[i][j];\n    cout << endl;\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 10;\nint N, T;\nint empty_r, empty_c;\n\nconst int dr[] = {0, -1, 0, 1};\nconst int dc[] = {-1, 0, 1, 0};\nconst char dir_char[] = {'L', 'U', 'R', 'D'};\nconst int bit[] = {1, 2, 4, 8};\n\nbool in_board(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nint tile_val(char c) {\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return c - '0';\n}\n\nchar val_to_char(int v) {\n    if (v < 10) return '0' + v;\n    return 'a' + (v - 10);\n}\n\nbool has_line(char tile, int d) {\n    return (tile_val(tile) & bit[d]) != 0;\n}\n\nbool is_connected(const vector<string>& b, int r1, int c1, int r2, int c2) {\n    if (!in_board(r1, c1) || !in_board(r2, c2)) return false;\n    if (b[r1][c1] == '0' || b[r2][c2] == '0') return false;\n    if (r1 == r2 && c1 + 1 == c2) {\n        return has_line(b[r1][c1], 2) && has_line(b[r2][c2], 0);\n    }\n    if (r1 == r2 && c1 - 1 == c2) {\n        return has_line(b[r1][c1], 0) && has_line(b[r2][c2], 2);\n    }\n    if (r1 + 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 3) && has_line(b[r2][c2], 1);\n    }\n    if (r1 - 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 1) && has_line(b[r2][c2], 3);\n    }\n    return false;\n}\n\n// Count size of largest tree in board\nint evaluate(const vector<string>& b) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    int max_tree = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] == '0' || vis[i][j]) continue;\n            \n            // BFS\n            vector<pair<int,int>> comp;\n            queue<pair<int,int>> q;\n            q.push({i, j});\n            vis[i][j] = true;\n            int edges = 0;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front(); q.pop();\n                comp.push_back({r, c});\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (in_board(nr, nc) && b[nr][nc] != '0') {\n                        if (is_connected(b, r, c, nr, nc)) {\n                            edges++;\n                            if (!vis[nr][nc]) {\n                                vis[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        }\n                    }\n                }\n            }\n            \n            edges /= 2;\n            int nodes = comp.size();\n            if (edges == nodes - 1) {\n                max_tree = max(max_tree, nodes);\n            }\n        }\n    }\n    return max_tree;\n}\n\n// Beam search state\nstruct State {\n    vector<string> board;\n    int er, ec;\n    string moves;\n    int score;\n    \n    State(vector<string> b, int r, int c, string m) \n        : board(move(b)), er(r), ec(c), moves(move(m)) {\n        score = evaluate(board);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    vector<string> board(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0') {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // Beam search parameters\n    const int BEAM_WIDTH = 50;\n    const int MAX_DEPTH = min(T, 200); // Don't search too deep\n    \n    vector<State> beam;\n    beam.emplace_back(board, empty_r, empty_c, \"\");\n    \n    int best_tree = evaluate(board);\n    string best_moves = \"\";\n    \n    for (int depth = 0; depth < MAX_DEPTH; depth++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2500) {\n            break;\n        }\n        \n        vector<State> next;\n        unordered_set<string> seen;\n        \n        for (auto& s : beam) {\n            // Try all 4 moves\n            for (int d = 0; d < 4; d++) {\n                int nr = s.er + dr[d];\n                int nc = s.ec + dc[d];\n                if (!in_board(nr, nc)) continue;\n                if (!s.moves.empty()) {\n                    char last = s.moves.back();\n                    if ((last == 'L' && d == 2) || (last == 'R' && d == 0) ||\n                        (last == 'U' && d == 3) || (last == 'D' && d == 1)) {\n                        continue; // Don't undo last move\n                    }\n                }\n                \n                vector<string> nb = s.board;\n                swap(nb[s.er][s.ec], nb[nr][nc]);\n                \n                // Create hash for dedup\n                string hash;\n                for (int i = 0; i < N; i++) hash += nb[i];\n                \n                if (seen.count(hash)) continue;\n                seen.insert(hash);\n                \n                string nm = s.moves + dir_char[d];\n                State ns(move(nb), nr, nc, nm);\n                \n                if (ns.score > best_tree) {\n                    best_tree = ns.score;\n                    best_moves = ns.moves;\n                }\n                \n                next.push_back(move(ns));\n            }\n        }\n        \n        if (next.empty()) break;\n        \n        // Sort by score and keep top BEAM_WIDTH\n        sort(next.begin(), next.end(), [](const State& a, const State& b) {\n            return a.score > b.score;\n        });\n        \n        beam.clear();\n        for (int i = 0; i < min((int)next.size(), BEAM_WIDTH); i++) {\n            beam.push_back(move(next[i]));\n        }\n    }\n    \n    // If beam search found improvements, use them\n    if (!best_moves.empty()) {\n        cout << best_moves;\n    } else {\n        // Fall back: make some random moves\n        string output;\n        for (int i = 0; i < min(T, 100); i++) {\n            int d = rand() % 4;\n            int nr = empty_r + dr[d];\n            int nc = empty_c + dc[d];\n            if (in_board(nr, nc)) {\n                output += dir_char[d];\n                swap(board[empty_r][empty_c], board[nr][nc]);\n                empty_r = nr;\n                empty_c = nc;\n            }\n        }\n        cout << output;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n    Point(long long x = 0, long long y = 0) : x(x), y(y) {}\n    \n    Point operator-(const Point& other) const {\n        return Point(x - other.x, y - other.y);\n    }\n    \n    long long dot(const Point& other) const {\n        return x * other.x + y * other.y;\n    }\n    \n    long long cross(const Point& other) const {\n        return x * other.y - y * other.x;\n    }\n    \n    long long dist2() const {\n        return x * x + y * y;\n    }\n    \n    double dist() const {\n        return sqrt(dist2());\n    }\n    \n    double angle() const {\n        return atan2(y, x);\n    }\n    \n    bool operator<(const Point& other) const {\n        return angle() < other.angle();\n    }\n};\n\nstruct Strawberry {\n    double x, y;\n    int id;\n    Strawberry(double x = 0, double y = 0, int id = 0) : x(x), y(y), id(id) {}\n};\n\n// Generate a line that separates two points\npair<pair<long long, long long>, pair<long long, long long>> \nseparatingLine(const Point& p1, const Point& p2) {\n    // Midpoint\n    double mx = (p1.x + p2.x) / 2.0;\n    double my = (p1.y + p2.y) / 2.0;\n    \n    // Direction perpendicular to the line connecting p1 and p2\n    double dx = p2.y - p1.y;\n    double dy = p1.x - p2.x;\n    \n    // Scale to get integer coordinates within range\n    double scale = 1e9 / max(abs(dx), abs(dy));\n    dx *= scale;\n    dy *= scale;\n    \n    long long px = (long long)(mx - dx);\n    long long py = (long long)(my - dy);\n    long long qx = (long long)(mx + dx);\n    long long qy = (long long)(my + dy);\n    \n    // Clamp to valid range\n    auto clamp = [](long long& v) {\n        v = max(-1000000000LL, min(1000000000LL, v));\n    };\n    clamp(px); clamp(py); clamp(qx); clamp(qy);\n    \n    return {{px, py}, {qx, qy}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(10);\n    for (int i = 0; i < 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Strategy: Use angular partitioning + some additional cuts\n    vector<pair<double, int>> angles;\n    for (int i = 0; i < N; i++) {\n        angles.push_back({atan2(strawberries[i].y, strawberries[i].x), i});\n    }\n    sort(angles.begin(), angles.end());\n    \n    vector<pair<pair<long long, long long>, pair<long long, long long>>> lines;\n    \n    // Create pie-slice cuts from center\n    int num_cuts = min(K, N);\n    \n    // Try to make cuts that separate groups of strawberries\n    // Use lines through origin at specific angles\n    for (int i = 0; i < num_cuts; i++) {\n        double angle1 = 2.0 * M_PI * i / num_cuts;\n        double angle2 = angle1 + M_PI;\n        \n        long long x1 = (long long)(1000000000.0 * cos(angle1));\n        long long y1 = (long long)(1000000000.0 * sin(angle1));\n        long long x2 = (long long)(1000000000.0 * cos(angle2));\n        long long y2 = (long long)(1000000000.0 * sin(angle2));\n        \n        // Ensure points are distinct\n        if (abs(x1 - x2) < 2 && abs(y1 - y2) < 2) {\n            x2 = -x1;\n            y2 = -y1;\n        }\n        \n        lines.push_back({{x1, y1}, {x2, y2}});\n    }\n    \n    // Add some grid-like cuts to better isolate strawberries\n    int remaining_cuts = K - num_cuts;\n    if (remaining_cuts > 0) {\n        // Add horizontal and vertical cuts\n        for (int i = 0; i < min(remaining_cuts / 2, 20); i++) {\n            long long offset = (long long)((i + 1) * 5000);\n            // Horizontal line\n            lines.push_back({{-1000000000, offset}, {1000000000, offset}});\n            if (lines.size() >= K) break;\n            // Vertical line\n            lines.push_back({{offset, -1000000000}, {offset, 1000000000}});\n            if (lines.size() >= K) break;\n        }\n    }\n    \n    // Also add some diagonal cuts for better separation\n    remaining_cuts = K - lines.size();\n    if (remaining_cuts > 0) {\n        for (int i = 0; i < min(remaining_cuts, 10); i++) {\n            long long offset = (long long)((i + 1) * 3000);\n            lines.push_back({{-1000000000, -1000000000 + offset * 2}, \n                           {1000000000 - offset * 2, 1000000000}});\n        }\n    }\n    \n    // Ensure we don't exceed K\n    if (lines.size() > K) {\n        lines.resize(K);\n    }\n    \n    // Output\n    cout << lines.size() << '\\n';\n    for (const auto& line : lines) {\n        cout << line.first.first << ' ' << line.first.second << ' '\n             << line.second.first << ' ' << line.second.second << '\\n';\n    }\n    \n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing P = pair<int, int>;\n\nconst int MAX_N = 65;\n\nint N, M;\nvector<P> initial_dots;\nset<P> dot_set;\nset<array<P, 4>> used_segments; // unordered set of segment endpoints pairs\nvector<array<P, 4>> operations;\nll weight_sum = 0;\nll total_weight_sum = 0;\n\nll weight(int x, int y) {\n    int c = (N - 1) / 2;\n    return (ll)(x - c) * (x - c) + (ll)(y - c) * (y - c) + 1;\n}\n\nbool in_grid(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\nvoid add_segment(P a, P b) {\n    if (a > b) swap(a, b);\n    used_segments.insert({a, b, {0,0}, {0,0}}); // dummy\n}\n\nbool has_segment(P a, P b) {\n    if (a > b) swap(a, b);\n    return used_segments.count({a, b, {0,0}, {0,0}});\n}\n\nbool dot_exists(int x, int y) {\n    return dot_set.count({x, y});\n}\n\n// Check if line from p to q has no dots except endpoints (and the 3 known dots)\nbool clear_path(P p, P q, const set<P> &allowed) {\n    int dx = q.first - p.first;\n    int dy = q.second - p.second;\n    int g = gcd(abs(dx), abs(dy));\n    int stepx = dx / g;\n    int stepy = dy / g;\n    for (int i = 1; i < g; ++i) {\n        int cx = p.first + i * stepx;\n        int cy = p.second + i * stepy;\n        if (dot_exists(cx, cy) && !allowed.count({cx, cy}))\n            return false;\n    }\n    return true;\n}\n\nbool rect_valid(P p1, P p2, P p3, P p4) {\n    // p1 is new dot (no dot), p2,p3,p4 have dots\n    if (dot_exists(p1.first, p1.second)) return false;\n    if (!dot_exists(p2.first, p2.second)) return false;\n    if (!dot_exists(p3.first, p3.second)) return false;\n    if (!dot_exists(p4.first, p4.second)) return false;\n\n    set<P> allowed = {p2, p3, p4};\n    // check all edges\n    vector<pair<P,P>> edges = {{p1,p2},{p2,p3},{p3,p4},{p4,p1}};\n    for (auto &e : edges) {\n        if (!clear_path(e.first, e.second, allowed)) return false;\n        if (has_segment(e.first, e.second)) 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    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        initial_dots.push_back({x, y});\n        dot_set.insert({x, y});\n        weight_sum += weight(x, y);\n    }\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y < N; ++y)\n            total_weight_sum += weight(x, y);\n\n    // Precompute all possible rectangles (axis-aligned and 45-degree)\n    vector<array<P,4>> candidates;\n    int c = (N - 1) / 2;\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            if (dot_exists(x, y)) continue;\n            // axis-aligned\n            for (int dx = 1; dx < N; ++dx) {\n                for (int dy = 1; dy < N; ++dy) {\n                    vector<array<P,4>> rects = {\n                        {{{x,y},{x+dx,y},{x+dx,y+dy},{x,y+dy}}},\n                        {{{x,y},{x,y+dy},{x+dx,y+dy},{x+dx,y}}},\n                        {{{x,y},{x-dx,y},{x-dx,y-dy},{x,y-dy}}},\n                        {{{x,y},{x,y-dy},{x-dx,y-dy},{x-dx,y}}}\n                    };\n                    for (auto &r : rects) {\n                        bool ok = true;\n                        for (auto &p : r) if (!in_grid(p.first, p.second)) ok = false;\n                        if (ok) candidates.push_back(r);\n                    }\n                }\n            }\n            // 45-degree rotated\n            for (int d = 1; d < N; ++d) {\n                vector<array<P,4>> diag = {\n                    {{{x,y},{x+d,y+d},{x+d+d, y},{x+d, y-d}}},\n                    {{{x,y},{x+d,y-d},{x,y-d-d},{x-d,y-d}}},\n                    {{{x,y},{x-d,y-d},{x-d-d,y},{x-d,y+d}}},\n                    {{{x,y},{x-d,y+d},{x,y+d+d},{x+d,y+d}}}\n                };\n                for (auto &r : diag) {\n                    bool ok = true;\n                    for (auto &p : r) if (!in_grid(p.first, p.second)) ok = false;\n                    if (ok) candidates.push_back(r);\n                }\n            }\n        }\n    }\n\n    // Greedy loop\n    while (true) {\n        array<P,4> best_move;\n        ll best_gain = -1;\n        for (auto &r : candidates) {\n            if (rect_valid(r[0], r[1], r[2], r[3])) {\n                ll gain = weight(r[0].first, r[0].second);\n                if (gain > best_gain) {\n                    best_gain = gain;\n                    best_move = r;\n                }\n            }\n        }\n        if (best_gain == -1) break;\n\n        // perform move\n        operations.push_back(best_move);\n        dot_set.insert(best_move[0]);\n        weight_sum += best_gain;\n        add_segment(best_move[0], best_move[1]);\n        add_segment(best_move[1], best_move[2]);\n        add_segment(best_move[2], best_move[3]);\n        add_segment(best_move[3], best_move[0]);\n    }\n\n    // output\n    cout << operations.size() << \"\\n\";\n    for (auto &op : operations) {\n        for (int i = 0; i < 4; ++i) {\n            cout << op[i].first << \" \" << op[i].second << (i == 3 ? \"\\n\" : \" \");\n        }\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\nint grid[N][N];\nint flavor[100];\n\nint dx[4] = {0, 0, -1, 1}; // L, R, F, B\nint dy[4] = {-1, 1, 0, 0};\nchar dirs[4] = {'L', 'R', 'F', 'B'};\n\nvoid tilt(int d) {\n    if (d == 0) { // L\n        for (int i = 0; i < N; i++) {\n            int pos = 0;\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0) {\n                    grid[i][pos++] = grid[i][j];\n                }\n            }\n            while (pos < N) grid[i][pos++] = 0;\n        }\n    } else if (d == 1) { // R\n        for (int i = 0; i < N; i++) {\n            int pos = N-1;\n            for (int j = N-1; j >= 0; j--) {\n                if (grid[i][j] != 0) {\n                    grid[i][pos--] = grid[i][j];\n                }\n            }\n            while (pos >= 0) grid[i][pos--] = 0;\n        }\n    } else if (d == 2) { // F (up)\n        for (int j = 0; j < N; j++) {\n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                if (grid[i][j] != 0) {\n                    grid[pos++][j] = grid[i][j];\n                }\n            }\n            while (pos < N) grid[pos++][j] = 0;\n        }\n    } else if (d == 3) { // B (down)\n        for (int j = 0; j < N; j++) {\n            int pos = N-1;\n            for (int i = N-1; i >= 0; i--) {\n                if (grid[i][j] != 0) {\n                    grid[pos--][j] = grid[i][j];\n                }\n            }\n            while (pos >= 0) grid[pos--][j] = 0;\n        }\n    }\n}\n\nint64_t eval() {\n    bool vis[N][N] = {false};\n    int64_t sum_sq = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != 0 && !vis[i][j]) {\n                int flav = 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 k = 0; k < 4; k++) {\n                        int nx = x + dx[k], ny = y + dy[k];\n                        if (nx >= 0 && nx < N && ny >= 0 && ny < N &&\n                            !vis[nx][ny] && grid[nx][ny] == flav) {\n                            vis[nx][ny] = true;\n                            q.push({nx,ny});\n                        }\n                    }\n                }\n                sum_sq += 1LL * cnt * cnt;\n            }\n        }\n    }\n    return sum_sq;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < 100; i++) {\n        cin >> flavor[i];\n    }\n    \n    memset(grid, 0, sizeof(grid));\n    \n    int empty_count = 100;\n    \n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n        // find p-th empty cell\n        int placed = 0;\n        int r, c;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    placed++;\n                    if (placed == p) {\n                        r = i; c = j;\n                    }\n                }\n            }\n        }\n        grid[r][c] = flavor[t];\n        \n        // save grid\n        int old_grid[N][N];\n        memcpy(old_grid, grid, sizeof(grid));\n        \n        int64_t best_score = -1;\n        int best_dir = 0;\n        \n        for (int d = 0; d < 4; d++) {\n            memcpy(grid, old_grid, sizeof(grid));\n            tilt(d);\n            int64_t score = eval();\n            if (score > best_score) {\n                best_score = score;\n                best_dir = d;\n            }\n        }\n        \n        memcpy(grid, old_grid, sizeof(grid));\n        tilt(best_dir);\n        cout << dirs[best_dir] << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Compute degree sequence from graph string\nvector<int> get_degrees(const string& g, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute feature vector for a graph\nvector<double> compute_features(const string& g, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    int edges = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n                edges++;\n            }\n            idx++;\n        }\n    }\n    \n    // Feature 1: Number of edges (normalized)\n    double max_edges = N * (N - 1) / 2.0;\n    double edge_ratio = edges / max_edges;\n    \n    // Feature 2: Degree statistics\n    sort(deg.begin(), deg.end());\n    double mean_deg = 0, var_deg = 0;\n    for (int d : deg) mean_deg += d;\n    mean_deg /= N;\n    for (int d : deg) var_deg += (d - mean_deg) * (d - mean_deg);\n    var_deg /= N;\n    \n    // Feature 3: Degree distribution quantiles\n    vector<double> features;\n    features.push_back(edge_ratio);\n    features.push_back(mean_deg / (N - 1));\n    features.push_back(sqrt(var_deg) / (N - 1));\n    \n    // Quantiles of degree distribution\n    for (int p : {10, 25, 50, 75, 90}) {\n        features.push_back(deg[min(N-1, N * p / 100)] / (double)(N - 1));\n    }\n    \n    return features;\n}\n\n// Generate a graph with specified edge probability\nstring generate_random_graph(int N, double p) {\n    string g;\n    int m = N * (N - 1) / 2;\n    uniform_real_distribution<> dis(0.0, 1.0);\n    for (int i = 0; i < m; i++) {\n        g += (dis(rng) < p) ? '1' : '0';\n    }\n    return g;\n}\n\n// Generate M distinctive graphs\nvector<string> generate_graphs(int N, int M, double eps) {\n    vector<string> graphs;\n    set<string> used;\n    \n    // Strategy: Generate graphs with different edge densities\n    // Use multiple rounds to ensure diversity\n    double base_p = 0.1;\n    double step = 0.8 / max(1, M - 1);\n    \n    for (int k = 0; k < M; k++) {\n        double p = base_p + k * step;\n        p = min(0.9, max(0.05, p));\n        \n        string best_g;\n        double best_dist = -1;\n        \n        // Try multiple times to get well-separated features\n        for (int trial = 0; trial < 20; trial++) {\n            string g = generate_random_graph(N, p);\n            if (used.count(g)) continue;\n            \n            auto feat = compute_features(g, N);\n            \n            // Calculate minimum distance to existing graphs\n            double min_dist = 1e9;\n            for (const auto& existing : graphs) {\n                auto feat2 = compute_features(existing, N);\n                double dist = 0;\n                for (size_t i = 0; i < feat.size(); i++) {\n                    dist += (feat[i] - feat2[i]) * (feat[i] - feat2[i]);\n                }\n                min_dist = min(min_dist, sqrt(dist));\n            }\n            \n            if (graphs.empty() || min_dist > best_dist) {\n                best_dist = min_dist;\n                best_g = g;\n            }\n        }\n        \n        if (best_dist < 0) {\n            best_g = generate_random_graph(N, p);\n        }\n        \n        graphs.push_back(best_g);\n        used.insert(best_g);\n    }\n    \n    return graphs;\n}\n\n// Predict which original graph generated H\nint predict(const string& H, const vector<string>& graphs, int N, double eps) {\n    auto feat_H = compute_features(H, N);\n    \n    int best_idx = 0;\n    double best_score = -1e9;\n    \n    // Calculate expected noise variance\n    double noise_std = sqrt(eps * (1 - eps));\n    \n    for (int k = 0; k < (int)graphs.size(); k++) {\n        auto feat_G = compute_features(graphs[k], N);\n        \n        // Compute weighted distance\n        double score = 0;\n        for (size_t i = 0; i < feat_H.size(); i++) {\n            double diff = feat_H[i] - feat_G[i];\n            // Weight by feature importance and noise sensitivity\n            double weight = 1.0;\n            if (i == 0) weight = 5.0;  // Edge ratio is very informative\n            score -= weight * diff * diff / (noise_std * noise_std + 0.01);\n        }\n        \n        if (score > best_score) {\n            best_score = score;\n            best_idx = k;\n        }\n    }\n    \n    return best_idx;\n}\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 N based on M and eps\n    // Smaller N for easier cases, larger N for harder cases\n    int N;\n    if (eps <= 0.05 && M <= 30) {\n        N = max(10, min(20, M + 5));\n    } else if (eps <= 0.15 && M <= 50) {\n        N = max(15, min(40, M + 10));\n    } else if (eps <= 0.25) {\n        N = max(20, min(60, M * 2 / 3 + 20));\n    } else {\n        N = max(30, min(80, M + 20));\n    }\n    N = min(N, 100);\n    N = max(N, 4);\n    \n    // Generate graphs\n    auto graphs = generate_graphs(N, M, eps);\n    \n    // Output graphs\n    cout << N << endl;\n    for (const auto& g : graphs) {\n        cout << g << endl;\n    }\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n        \n        int t = predict(H, graphs, N, eps);\n        cout << t << endl;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = 1e18;\nconst int PENALTY = 1e9;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\n// Timer\nchrono::steady_clock::time_point start_time;\n\nlong long elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n}\n\nbool time_left(long long limit = 5800) {\n    return elapsed_ms() < limit;\n}\n\n// DSU for connectivity checking\nstruct DSU {\n    vector<int> parent, sz;\n    DSU(int n) {\n        parent.resize(n);\n        sz.resize(n, 1);\n        iota(parent.begin(), parent.end(), 0);\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); y = find(y);\n        if (x == y) return false;\n        if (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        return true;\n    }\n};\n\n// Check if removing a set of edges keeps graph connected\nbool is_connected_after_removal(int N, const vector<Edge>& edges, const vector<bool>& removed) {\n    DSU dsu(N);\n    for (const auto& e : edges) {\n        if (!removed[e.id]) {\n            dsu.unite(e.u, e.v);\n        }\n    }\n    int root = dsu.find(0);\n    for (int i = 1; i < N; i++) {\n        if (dsu.find(i) != root) return false;\n    }\n    return true;\n}\n\n// Compute frustration for a specific day (approximate with sampling)\ndouble compute_day_frustration(int N, const vector<Edge>& edges, const vector<bool>& day_removed,\n                               const vector<vector<long long>>& orig_dist, int samples = 30) {\n    // Build adjacency for this day\n    vector<vector<pair<int,int>>> adj(N);\n    for (const auto& e : edges) {\n        if (!day_removed[e.id]) {\n            adj[e.u].push_back({e.v, e.id});\n            adj[e.v].push_back({e.u, e.id});\n        }\n    }\n    \n    double total_increase = 0;\n    int pair_count = 0;\n    \n    // Sample source vertices\n    vector<int> sample_srcs;\n    int step = max(1, N / samples);\n    for (int i = 0; i < N; i += step) {\n        sample_srcs.push_back(i);\n        if (sample_srcs.size() >= samples) break;\n    }\n    \n    for (int src : sample_srcs) {\n        vector<long long> dist(N, INF);\n        dist[src] = 0;\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, eid] : adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        \n        // Sample destination vertices\n        for (int dst = 0; dst < N; dst += step) {\n            if (src == dst) continue;\n            long long dk = (dist[dst] >= INF) ? PENALTY : dist[dst];\n            long long d_orig = orig_dist[src][dst];\n            total_increase += max(0LL, dk - d_orig);\n            pair_count++;\n        }\n    }\n    \n    return pair_count > 0 ? total_increase / pair_count : 0;\n}\n\n// Compute frustration more accurately for final evaluation\nvector<double> compute_all_day_frustrations(int N, int M, int D,\n                                            const vector<Edge>& edges,\n                                            const vector<int>& assignment,\n                                            const vector<vector<long long>>& orig_dist) {\n    vector<double> frustrations(D, 0);\n    \n    // Build removed sets per day\n    vector<vector<bool>> day_removed(D, vector<bool>(M, false));\n    for (int i = 0; i < M; i++) {\n        day_removed[assignment[i]][i] = true;\n    }\n    \n    // Sample vertices\n    int samples = 40;\n    vector<int> sample_verts;\n    int step = max(1, N / samples);\n    for (int i = 0; i < N; i += step) {\n        sample_verts.push_back(i);\n    }\n    \n    for (int d = 0; d < D; d++) {\n        // Build adjacency\n        vector<vector<pair<int,int>>> adj(N);\n        for (const auto& e : edges) {\n            if (!day_removed[d][e.id]) {\n                adj[e.u].push_back({e.v, e.id});\n                adj[e.v].push_back({e.u, e.id});\n            }\n        }\n        \n        double total_inc = 0;\n        int cnt = 0;\n        \n        for (int src : sample_verts) {\n            vector<long long> dist(N, INF);\n            dist[src] = 0;\n            priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n            pq.push({0, src});\n            \n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != dist[u]) continue;\n                for (auto [v, eid] : adj[u]) {\n                    long long nd = d + edges[eid].w;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        pq.push({nd, v});\n                    }\n                }\n            }\n            \n            for (int dst : sample_verts) {\n                if (src == dst) continue;\n                long long dk = (dist[dst] >= INF) ? PENALTY : dist[dst];\n                total_inc += max(0LL, dk - orig_dist[src][dst]);\n                cnt++;\n            }\n        }\n        \n        frustrations[d] = cnt > 0 ? total_inc / cnt : 0;\n    }\n    \n    return frustrations;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::steady_clock::now();\n    \n    srand(time(0));\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>>> adj(N);\n    \n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        adj[edges[i].u].push_back({edges[i].v, i});\n        adj[edges[i].v].push_back({edges[i].u, 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    // Compute original all-pairs shortest paths\n    vector<vector<long long>> orig_dist(N, vector<long long>(N, INF));\n    for (int src = 0; src < N; src++) {\n        orig_dist[src][src] = 0;\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != orig_dist[src][u]) continue;\n            for (auto [v, eid] : adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < orig_dist[src][v]) {\n                    orig_dist[src][v] = nd;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n    \n    // Compute edge importance: edge betweenness centrality\n    vector<double> edge_importance(M, 0.0);\n    int sample_srcs = min(N, 150);\n    for (int i = 0; i < sample_srcs; i++) {\n        int src = (i * N) / sample_srcs;\n        \n        vector<long long> dist(N, INF);\n        vector<long long> path_count(N, 0);\n        vector<int> prev_edge(N, -1);\n        vector<vector<int>> prev_edges(N);\n        \n        dist[src] = 0;\n        path_count[src] = 1;\n        \n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            \n            for (auto [v, eid] : adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    path_count[v] = path_count[u];\n                    prev_edges[v] = {eid};\n                    pq.push({nd, v});\n                } else if (nd == dist[v]) {\n                    path_count[v] += path_count[u];\n                    prev_edges[v].push_back(eid);\n                }\n            }\n        }\n        \n        // Backward propagation for betweenness\n        vector<double> node_score(N, 1.0);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return dist[a] > dist[b];\n        });\n        \n        for (int u : order) {\n            if (dist[u] >= INF) continue;\n            for (int eid : prev_edges[u]) {\n                int v = (edges[eid].u == u) ? edges[eid].v : edges[eid].u;\n                if (dist[v] + edges[eid].w == dist[u]) {\n                    double contrib = node_score[u] * (double)path_count[v] / path_count[u];\n                    edge_importance[eid] += contrib;\n                    node_score[v] += contrib;\n                }\n            }\n        }\n    }\n    \n    // Normalize\n    double max_imp = *max_element(edge_importance.begin(), edge_importance.end());\n    if (max_imp > 0) {\n        for (auto& imp : edge_importance) imp /= max_imp;\n    }\n    \n    // Phase 1: Initial assignment - iterative greedy with connectivity check\n    vector<int> assignment(M);\n    vector<int> day_counts(D, 0);\n    vector<vector<bool>> day_removed(D, vector<bool>(M, false));\n    \n    // Sort edges by importance\n    vector<pair<double,int>> edge_order;\n    for (int i = 0; i < M; i++) {\n        edge_order.push_back({edge_importance[i], i});\n    }\n    sort(edge_order.rbegin(), edge_order.rend());\n    \n    // Assign high-importance edges first, ensuring connectivity\n    for (auto [imp, eid] : edge_order) {\n        int best_day = -1;\n        double best_score = -1e18;\n        \n        for (int d = 0; d < D; d++) {\n            if (day_counts[d] >= K) continue;\n            \n            // Check if adding this edge to day d would disconnect\n            vector<bool> test_removed = day_removed[d];\n            test_removed[eid] = true;\n            \n            if (!is_connected_after_removal(N, edges, test_removed)) {\n                continue; // Would disconnect - unacceptable\n            }\n            \n            // Score: prefer days with fewer edges and lower total importance\n            double total_imp = 0;\n            for (int i = 0; i < M; i++) {\n                if (day_removed[d][i]) total_imp += edge_importance[i];\n            }\n            double score = -total_imp - edge_importance[eid] * 10; // Penalize concentrating important edges\n            \n            if (score > best_score) {\n                best_score = score;\n                best_day = d;\n            }\n        }\n        \n        if (best_day == -1) {\n            // Fallback: find any day with capacity\n            for (int d = 0; d < D; d++) {\n                if (day_counts[d] < K) {\n                    best_day = d;\n                    break;\n                }\n            }\n        }\n        \n        assignment[eid] = best_day;\n        day_removed[best_day][eid] = true;\n        day_counts[best_day]++;\n    }\n    \n    // Phase 2: Ensure all days are connected (fix any disconnections)\n    for (int d = 0; d < D; d++) {\n        if (!is_connected_after_removal(N, edges, day_removed[d])) {\n            // Try to move some low-importance edges to other days\n            vector<int> day_edges;\n            for (int i = 0; i < M; i++) {\n                if (assignment[i] == d) day_edges.push_back(i);\n            }\n            \n            // Sort by importance (move least important first)\n            sort(day_edges.begin(), day_edges.end(), [&](int a, int b) {\n                return edge_importance[a] < edge_importance[b];\n            });\n            \n            for (int eid : day_edges) {\n                // Try to move this edge to another day\n                for (int d2 = 0; d2 < D; d2++) {\n                    if (d2 == d || day_counts[d2] >= K) continue;\n                    \n                    vector<bool> test_d = day_removed[d];\n                    test_d[eid] = false;\n                    vector<bool> test_d2 = day_removed[d2];\n                    test_d2[eid] = true;\n                    \n                    if (is_connected_after_removal(N, edges, test_d) &&\n                        is_connected_after_removal(N, edges, test_d2)) {\n                        // Move edge\n                        assignment[eid] = d2;\n                        day_removed[d][eid] = false;\n                        day_removed[d2][eid] = true;\n                        day_counts[d]--;\n                        day_counts[d2]++;\n                        break;\n                    }\n                }\n                \n                if (is_connected_after_removal(N, edges, day_removed[d])) break;\n            }\n        }\n    }\n    \n    // Phase 3: Local search with simulated annealing\n    vector<double> current_frustrations = compute_all_day_frustrations(N, M, D, edges, assignment, orig_dist);\n    double current_avg = 0;\n    for (double f : current_frustrations) current_avg += f;\n    current_avg /= D;\n    \n    double temperature = 1000.0;\n    int iterations = 0;\n    long long max_iterations = 500000;\n    \n    while (time_left() && iterations < max_iterations) {\n        iterations++;\n        temperature *= 0.9999;\n        if (temperature < 0.01) temperature = 0.01;\n        \n        // Random operation: swap two edges between different days\n        if (rand() % 2 == 0) {\n            int e1 = rand() % M;\n            int e2 = rand() % M;\n            int d1 = assignment[e1];\n            int d2 = assignment[e2];\n            \n            if (d1 == d2) continue;\n            \n            // Test swap\n            vector<bool> test_d1 = day_removed[d1];\n            test_d1[e1] = false;\n            test_d1[e2] = true;\n            vector<bool> test_d2 = day_removed[d2];\n            test_d2[e2] = false;\n            test_d2[e1] = true;\n            \n            if (!is_connected_after_removal(N, edges, test_d1) ||\n                !is_connected_after_removal(N, edges, test_d2)) {\n                continue;\n            }\n            \n            // Apply swap temporarily\n            assignment[e1] = d2;\n            assignment[e2] = d1;\n            day_removed[d1][e1] = false;\n            day_removed[d2][e2] = false;\n            day_removed[d1][e2] = true;\n            day_removed[d2][e1] = true;\n            \n            // Evaluate new frustrations (only for affected days)\n            vector<double> new_frustrations = current_frustrations;\n            new_frustrations[d1] = compute_day_frustration(N, edges, day_removed[d1], orig_dist);\n            new_frustrations[d2] = compute_day_frustration(N, edges, day_removed[d2], orig_dist);\n            \n            double new_avg = 0;\n            for (int d = 0; d < D; d++) new_avg += new_frustrations[d];\n            new_avg /= D;\n            \n            double delta = new_avg - current_avg;\n            \n            if (delta < 0 || (temperature > 0 && exp(-delta / temperature) > (double)rand() / RAND_MAX)) {\n                // Accept\n                current_frustrations = new_frustrations;\n                current_avg = new_avg;\n            } else {\n                // Reject\n                assignment[e1] = d1;\n                assignment[e2] = d2;\n                day_removed[d1][e1] = true;\n                day_removed[d2][e2] = true;\n                day_removed[d1][e2] = false;\n                day_removed[d2][e1] = false;\n            }\n        } else {\n            // Move a single edge to a different day\n            int e = rand() % M;\n            int d1 = assignment[e];\n            int d2 = rand() % D;\n            \n            if (d1 == d2 || day_counts[d2] >= K) continue;\n            \n            vector<bool> test_d1 = day_removed[d1];\n            test_d1[e] = false;\n            vector<bool> test_d2 = day_removed[d2];\n            test_d2[e] = true;\n            \n            if (!is_connected_after_removal(N, edges, test_d1) ||\n                !is_connected_after_removal(N, edges, test_d2)) {\n                continue;\n            }\n            \n            // Apply move\n            assignment[e] = d2;\n            day_removed[d1][e] = false;\n            day_removed[d2][e] = true;\n            day_counts[d1]--;\n            day_counts[d2]++;\n            \n            vector<double> new_frustrations = current_frustrations;\n            new_frustrations[d1] = compute_day_frustration(N, edges, day_removed[d1], orig_dist);\n            new_frustrations[d2] = compute_day_frustration(N, edges, day_removed[d2], orig_dist);\n            \n            double new_avg = 0;\n            for (int d = 0; d < D; d++) new_avg += new_frustrations[d];\n            new_avg /= D;\n            \n            double delta = new_avg - current_avg;\n            \n            if (delta < 0 || (temperature > 0 && exp(-delta / temperature) > (double)rand() / RAND_MAX)) {\n                current_frustrations = new_frustrations;\n                current_avg = new_avg;\n            } else {\n                // Revert\n                assignment[e] = d1;\n                day_removed[d1][e] = true;\n                day_removed[d2][e] = false;\n                day_counts[d1]++;\n                day_counts[d2]--;\n            }\n        }\n    }\n    \n    // Output result\n    for (int i = 0; i < M; i++) {\n        if (i > 0) cout << \" \";\n        cout << assignment[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct FastBitset {\n    static constexpr int N = 2744;\n    static constexpr int CHUNKS = (N + 63) / 64;\n    uint64_t bits[CHUNKS]{};\n    FastBitset() { clear(); }\n    void clear() { memset(bits, 0, sizeof bits); }\n    void set(int i) { bits[i>>6] |= 1ULL << (i&63); }\n    void reset(int i) { bits[i>>6] &= ~(1ULL << (i&63)); }\n    bool test(int i) const { return (bits[i>>6] >> (i&63)) & 1ULL; }\n    int count() const {\n        int c = 0;\n        for (int i = 0; i < CHUNKS; ++i) c += __builtin_popcountll(bits[i]);\n        return c;\n    }\n    FastBitset operator&(const FastBitset& o) const {\n        FastBitset r;\n        for (int i = 0; i < CHUNKS; ++i) r.bits[i] = bits[i] & o.bits[i];\n        return r;\n    }\n    template<typename F>\n    void forEachSetBit(F f) const {\n        for (int i = 0; i < CHUNKS; ++i) {\n            uint64_t w = bits[i];\n            while (w) {\n                int j = __builtin_ctzll(w);\n                f((i << 6) | j);\n                w &= w - 1;\n            }\n        }\n    }\n};\n\nint D, D2, D3;\nvector<vector<int>> adj;\n\ninline int encode(int x, int y, int z) { return x*D2 + y*D + z; }\ninline tuple<int,int,int> decode(int idx) {\n    int z = idx % D;\n    int y = (idx / D) % D;\n    int x = idx / D2;\n    return {x,y,z};\n}\n\nvector<array<array<int,3>,3>> rots;\nvector<array<array<int,3>,3>> inv_rots;\n\nvoid generate_rotations() {\n    int perm[3] = {0,1,2};\n    do {\n        for (int s0 = -1; s0 <= 1; s0+=2)\n        for (int s1 = -1; s1 <= 1; s1+=2)\n        for (int s2 = -1; s2 <= 1; s2+=2) {\n            int sign = 1;\n            for (int i=0;i<3;i++) for (int j=i+1;j<3;j++) if (perm[i]>perm[j]) sign = -sign;\n            if (sign * s0 * s1 * s2 != 1) continue;\n            array<array<int,3>,3> mat = {{{0}}};\n            mat[0][perm[0]] = s0;\n            mat[1][perm[1]] = s1;\n            mat[2][perm[2]] = s2;\n            rots.push_back(mat);\n        }\n    } while (next_permutation(perm, perm+3));\n    for (auto& mat : rots) {\n        array<array<int,3>,3> inv = {{{0}}};\n        for (int i=0;i<3;i++) for (int j=0;j<3;j++) inv[j][i] = mat[i][j];\n        inv_rots.push_back(inv);\n    }\n}\n\nFastBitset rotate_bitset(const FastBitset& src, const array<array<int,3>,3>& mat) {\n    FastBitset dst;\n    src.forEachSetBit([&](int idx) {\n        auto [x,y,z] = decode(idx);\n        int nx = mat[0][0]*x + mat[0][1]*y + mat[0][2]*z;\n        int ny = mat[1][0]*x + mat[1][1]*y + mat[1][2]*z;\n        int nz = mat[2][0]*x + mat[2][1]*y + mat[2][2]*z;\n        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n            dst.set(encode(nx,ny,nz));\n        }\n    });\n    return dst;\n}\n\nint main() {\n    auto start_time = steady_clock::now();\n    auto get_ms = [&]() {\n        return duration_cast<milliseconds>(steady_clock::now() - start_time).count();\n    };\n\n    generate_rotations();\n\n    cin >> D;\n    D2 = D*D;\n    D3 = D*D*D;\n\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i=0; i<D; i++) cin >> f1[i];\n    for (int i=0; i<D; i++) cin >> r1[i];\n    for (int i=0; i<D; i++) cin >> f2[i];\n    for (int i=0; i<D; i++) cin >> r2[i];\n\n    adj.resize(D3);\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        int idx = encode(x,y,z);\n        if (x>0)   adj[idx].push_back(encode(x-1, y, z));\n        if (x<D-1) adj[idx].push_back(encode(x+1, y, z));\n        if (y>0)   adj[idx].push_back(encode(x, y-1, z));\n        if (y<D-1) adj[idx].push_back(encode(x, y+1, z));\n        if (z>0)   adj[idx].push_back(encode(x, y, z-1));\n        if (z<D-1) adj[idx].push_back(encode(x, y, z+1));\n    }\n\n    FastBitset A1, A2;\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        if (f1[z][x]=='1' && r1[z][y]=='1') A1.set(encode(x,y,z));\n        if (f2[z][x]=='1' && r2[z][y]=='1') A2.set(encode(x,y,z));\n    }\n\n    FastBitset available1 = A1, available2 = A2;\n    vector<int> b1(D3, 0), b2(D3, 0);\n    int block_id = 1;\n\n    vector unc1_f(D, vector<bool>(D, false));\n    vector unc1_r(D, vector<bool>(D, false));\n    vector unc2_f(D, vector<bool>(D, false));\n    vector unc2_r(D, vector<bool>(D, false));\n\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f1[z][x]=='1') unc1_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r1[z][y]=='1') unc1_r[z][y] = true;\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f2[z][x]=='1') unc2_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r2[z][y]=='1') unc2_r[z][y] = true;\n\n    while (true) {\n        if (get_ms() > 5000) break;\n        int best_vol = 0;\n        FastBitset best_comp2, best_preimage1;\n        int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n        for (int r = 0; r < 24; ++r) {\n            FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n            int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n            bool any = false;\n            rot_avail1.forEachSetBit([&](int idx) {\n                auto [x,y,z] = decode(idx);\n                any = true;\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                min_z = min(min_z, z); max_z = max(max_z, z);\n            });\n            if (!any) continue;\n\n            int dx_min = -min_x, dx_max = D-1 - max_x;\n            int dy_min = -min_y, dy_max = D-1 - max_y;\n            int dz_min = -min_z, dz_max = D-1 - max_z;\n\n            for (int dx = dx_min; dx <= dx_max; ++dx) {\n                for (int dy = dy_min; dy <= dy_max; ++dy) {\n                    for (int dz = dz_min; dz <= dz_max; ++dz) {\n                        FastBitset overlap;\n                        rot_avail1.forEachSetBit([&](int idx) {\n                            auto [x,y,z] = decode(idx);\n                            int nx = x+dx, ny = y+dy, nz = z+dz;\n                            if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                int idx2 = encode(nx,ny,nz);\n                                if (available2.test(idx2)) overlap.set(idx2);\n                            }\n                        });\n                        if (overlap.count() <= best_vol) continue;\n\n                        FastBitset visited;\n                        overlap.forEachSetBit([&](int seed) {\n                            if (visited.test(seed)) return;\n                            queue<int> q;\n                            q.push(seed);\n                            visited.set(seed);\n                            FastBitset comp;\n                            comp.set(seed);\n                            int sz = 1;\n                            while (!q.empty()) {\n                                int cur = q.front(); q.pop();\n                                for (int nb : adj[cur]) {\n                                    if (overlap.test(nb) && !visited.test(nb)) {\n                                        visited.set(nb);\n                                        comp.set(nb);\n                                        sz++;\n                                        q.push(nb);\n                                    }\n                                }\n                            }\n                            if (sz > best_vol) {\n                                best_vol = sz;\n                                best_comp2 = comp;\n                                best_r = r;\n                                best_dx = dx; best_dy = dy; best_dz = dz;\n                            }\n                        });\n                    }\n                }\n            }\n        }\n        if (best_vol == 0) break;\n\n        FastBitset preimage1;\n        best_comp2.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            int sx = x - best_dx, sy = y - best_dy, sz = z - best_dz;\n            int ox = inv_rots[best_r][0][0]*sx + inv_rots[best_r][0][1]*sy + inv_rots[best_r][0][2]*sz;\n            int oy = inv_rots[best_r][1][0]*sx + inv_rots[best_r][1][1]*sy + inv_rots[best_r][1][2]*sz;\n            int oz = inv_rots[best_r][2][0]*sx + inv_rots[best_r][2][1]*sy + inv_rots[best_r][2][2]*sz;\n            preimage1.set(encode(ox,oy,oz));\n        });\n\n        int bid = block_id++;\n        preimage1.forEachSetBit([&](int idx) {\n            b1[idx] = bid;\n            available1.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc1_f[z][x] = false;\n            unc1_r[z][y] = false;\n        });\n        best_comp2.forEachSetBit([&](int idx) {\n            b2[idx] = bid;\n            available2.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc2_f[z][x] = false;\n            unc2_r[z][y] = false;\n        });\n    }\n\n    // Cover remaining f1 lines\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) {\n        if (unc1_f[z][x]) {\n            for (int y=0; y<D; y++) {\n                int idx = encode(x,y,z);\n                if (available1.test(idx)) {\n                    int bid = block_id++;\n                    b1[idx] = bid;\n                    available1.reset(idx);\n                    unc1_f[z][x] = false;\n                    unc1_r[z][y] = false;\n                    break;\n                }\n            }\n        }\n    }\n    // Cover remaining r1 lines\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) {\n        if (unc1_r[z][y]) {\n            for (int x=0; x<D; x++) {\n                int idx = encode(x,y,z);\n                if (available1.test(idx)) {\n                    int bid = block_id++;\n                    b1[idx] = bid;\n                    available1.reset(idx);\n                    unc1_r[z][y] = false;\n                    unc1_f[z][x] = false;\n                    break;\n                }\n            }\n        }\n    }\n    // Cover remaining f2 lines\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) {\n        if (unc2_f[z][x]) {\n            for (int y=0; y<D; y++) {\n                int idx = encode(x,y,z);\n                if (available2.test(idx)) {\n                    int bid = block_id++;\n                    b2[idx] = bid;\n                    available2.reset(idx);\n                    unc2_f[z][x] = false;\n                    unc2_r[z][y] = false;\n                    break;\n                }\n            }\n        }\n    }\n    // Cover remaining r2 lines\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) {\n        if (unc2_r[z][y]) {\n            for (int x=0; x<D; x++) {\n                int idx = encode(x,y,z);\n                if (available2.test(idx)) {\n                    int bid = block_id++;\n                    b2[idx] = bid;\n                    available2.reset(idx);\n                    unc2_r[z][y] = false;\n                    unc2_f[z][x] = false;\n                    break;\n                }\n            }\n        }\n    }\n\n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    for (int i=0; i<D3; i++) cout << b1[i] << \" \\n\"[i==D3-1];\n    for (int i=0; i<D3; i++) cout << b2[i] << \" \\n\"[i==D3-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\n#define rep(i, a, b) for (int i = (a); i < (b); i++)\n#define all(x) begin(x), end(x)\n\nstruct Edge {\n    int u, v;\n    long long w;\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    vector<pair<int, int>> stations(N);\n    rep(i, 0, N) cin >> stations[i].first >> stations[i].second;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, long long>>> adj(N);\n    rep(j, 0, M) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n\n    vector<pair<int, int>> residents(K);\n    rep(k, 0, K) cin >> residents[k].first >> residents[k].second;\n\n    // Step 1: assign each resident to nearest station\n    vector<vector<int>> stationResidents(N);\n    rep(k, 0, K) {\n        int best = -1;\n        long long bestDist = LLONG_MAX;\n        rep(i, 0, N) {\n            long long dx = stations[i].first - residents[k].first;\n            long long dy = stations[i].second - residents[k].second;\n            long long dist = dx * dx + dy * dy;\n            if (dist < bestDist) {\n                bestDist = dist;\n                best = i;\n            }\n        }\n        stationResidents[best].push_back(k);\n    }\n\n    // Step 2: initial P_i = max Euclidean distance to assigned residents\n    vector<int> P(N, 0);\n    rep(i, 0, N) {\n        if (stationResidents[i].empty()) continue;\n        long long maxDistSq = 0;\n        for (int k : stationResidents[i]) {\n            long long dx = stations[i].first - residents[k].first;\n            long long dy = stations[i].second - residents[k].second;\n            maxDistSq = max(maxDistSq, dx * dx + dy * dy);\n        }\n        long long val = (long long)ceil(sqrt(maxDistSq));\n        if (val > 5000) val = 5000;\n        P[i] = (int)val;\n    }\n\n    // Step 3: find shortest paths from vertex 1\n    const long long INF = 1e18;\n    vector<long long> dist(N, INF);\n    vector<int> parent(N, -1);\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n    dist[0] = 0;\n    pq.push({0, 0});\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, w] : adj[u]) {\n            if (dist[v] > d + w) {\n                dist[v] = d + w;\n                parent[v] = u;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n\n    // Select vertices with P_i > 0\n    vector<int> active;\n    rep(i, 0, N) if (P[i] > 0) active.push_back(i);\n\n    // Build a Steiner-like tree: connect each active vertex to vertex 1 via shortest path\n    vector<int> onEdge(M, 0);\n    vector<bool> used(N, false);\n    used[0] = true;\n    // Sort active by distance from 1, then connect\n    sort(all(active), [&](int a, int b) { return dist[a] < dist[b]; });\n    for (int v : active) {\n        if (used[v]) continue;\n        // trace path\n        int cur = v;\n        while (!used[cur]) {\n            used[cur] = true;\n            int p = parent[cur];\n            if (p == -1) break;\n            // enable edge between p and cur\n            for (int j = 0; j < M; j++) {\n                if ((edges[j].u == p && edges[j].v == cur) || (edges[j].u == cur && edges[j].v == p)) {\n                    onEdge[j] = 1;\n                    break;\n                }\n            }\n            cur = p;\n        }\n    }\n\n    // Step 4: refinement (simple merge nearby stations)\n    rep(i, 0, N) {\n        if (P[i] == 0) continue;\n        rep(j, 0, N) {\n            if (i == j || P[j] == 0) continue;\n            long long dx = stations[i].first - stations[j].first;\n            long long dy = stations[i].second - stations[j].second;\n            long long d = (long long)ceil(sqrt(dx * dx + dy * dy));\n            if (P[i] + d <= P[j]) {\n                // i can cover j's residents\n                P[i] = max(P[i], (int)(P[j] + d));\n                if (P[i] > 5000) P[i] = 5000;\n                P[j] = 0;\n            }\n        }\n    }\n\n    // Rebuild edges after refinement\n    fill(all(onEdge), 0);\n    fill(all(used), false);\n    used[0] = true;\n    active.clear();\n    rep(i, 0, N) if (P[i] > 0) active.push_back(i);\n    sort(all(active), [&](int a, int b) { return dist[a] < dist[b]; });\n    for (int v : active) {\n        if (used[v]) continue;\n        int cur = v;\n        while (!used[cur]) {\n            used[cur] = true;\n            int p = parent[cur];\n            if (p == -1) break;\n            for (int j = 0; j < M; j++) {\n                if ((edges[j].u == p && edges[j].v == cur) || (edges[j].u == cur && edges[j].v == p)) {\n                    onEdge[j] = 1;\n                    break;\n                }\n            }\n            cur = p;\n        }\n    }\n\n    // Output\n    rep(i, 0, N) cout << P[i] << (i + 1 < N ? ' ' : '\\n');\n    rep(j, 0, M) cout << onEdge[j] << (j + 1 < M ? ' ' : '\\n');\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int MAXB = N * (N + 1) / 2; // 465\nint board[N][N];\npair<int,int> pos[MAXB]; // position of each value\n\n// Directions: (dx, dy) for neighbors\nint dx[6] = {-1, -1, 0, 0, 1, 1};\nint dy[6] = {-1, 0, -1, 1, 0, 1};\n\nvector<pair<pair<int,int>,pair<int,int>>> moves;\n\nbool inside(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\n// BFS to find shortest path between two positions\nvector<pair<int,int>> find_path(int sx, int sy, int tx, int ty) {\n    if (sx == tx && sy == ty) return {{sx, sy}};\n    \n    map<pair<int,int>, pair<int,int>> parent;\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    parent[{sx, sy}] = {-1, -1};\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        if (x == tx && y == ty) break;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (inside(nx, ny) && !parent.count({nx, ny})) {\n                parent[{nx, ny}] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    vector<pair<int,int>> path;\n    pair<int,int> cur = {tx, ty};\n    while (cur != make_pair(-1, -1)) {\n        path.push_back(cur);\n        cur = parent[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Swap two adjacent positions\nvoid do_swap(int x1, int y1, int x2, int y2) {\n    moves.push_back({{x1, y1}, {x2, y2}});\n    int v1 = board[x1][y1], v2 = board[x2][y2];\n    swap(board[x1][y1], board[x2][y2]);\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n}\n\n// Move a ball along a path by swapping step by step\nvoid move_along_path(const vector<pair<int,int>> &path) {\n    for (size_t i = 0; i + 1 < path.size(); i++) {\n        do_swap(path[i].first, path[i].second, \n                path[i+1].first, path[i+1].second);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j <= i; j++) {\n            cin >> board[i][j];\n            pos[board[i][j]] = {i, j};\n        }\n    }\n    \n    // Build heap: assign values to positions in BFS order (top to bottom, left to right)\n    // The target arrangement: value 0 at top, then 1,2 at row 1, then 3,4,5 at row 2, etc.\n    // This satisfies the heap property naturally\n    int next_val = 0;\n    vector<pair<int,int>> target_pos(MAXB);\n    \n    // Assign target positions in level order\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            target_pos[next_val] = {x, y};\n            next_val++;\n        }\n    }\n    \n    // For each position (starting from bottom-right to top-left), \n    // bring the correct value there\n    // Strategy: process positions from bottom to top, right to left\n    // This way, once we place a value, it's less likely to be disturbed\n    \n    for (int val = MAXB - 1; val >= 0; val--) {\n        int tx = target_pos[val].first;\n        int ty = target_pos[val].second;\n        auto [sx, sy] = pos[val];\n        \n        if (sx == tx && sy == ty) continue;\n        \n        // Find path from current position to target\n        vector<pair<int,int>> path = find_path(sx, sy, tx, ty);\n        \n        if (path.size() > 1) {\n            move_along_path(path);\n            \n            // Check if we exceeded move limit\n            if (moves.size() >= 10000) break;\n        }\n    }\n    \n    // If we still have moves left and there are violations, fix them\n    // (should rarely happen with the systematic approach)\n    if (moves.size() < 10000) {\n        bool changed = true;\n        while (changed && moves.size() < 10000) {\n            changed = false;\n            for (int x = 0; x < N-1 && !changed; x++) {\n                for (int y = 0; y <= x && !changed; y++) {\n                    int p = board[x][y];\n                    for (int d = 0; d < 2; d++) {\n                        int cx = x+1, cy = y+d;\n                        int c = board[cx][cy];\n                        if (p > c) {\n                            auto path = find_path(cx, cy, x, y);\n                            if (moves.size() + path.size() - 1 <= 10000) {\n                                move_along_path(path);\n                                changed = true;\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Ensure we don't exceed 10000 moves\n    if (moves.size() > 10000) {\n        moves.resize(10000);\n    }\n    \n    // Output\n    cout << moves.size() << \"\\n\";\n    for (auto &m : moves) {\n        cout << m.first.first << \" \" << m.first.second << \" \"\n             << m.second.first << \" \" << m.second.second << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0, ENTRANCE_J = 4;\nint max_id;\n\nvector<string> grid(D, string(D, '.'));\nvector<vector<int>> dist(D, vector<int>(D, -1));\nvector<vector<bool>> obstacle(D, vector<bool>(D, false));\nvector<vector<bool>> occupied(D, vector<bool>(D, false));\n\nint dx[4] = {1, -1, 0, 0};\nint dy[4] = {0, 0, 1, -1};\n\nvoid bfs_distance(int si, int sj) {\n    for (int i = 0; i < D; i++)\n        fill(dist[i].begin(), dist[i].end(), -1);\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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 (nx >= 0 && nx < D && ny >= 0 && ny < D &&\n                dist[nx][ny] == -1 && !obstacle[nx][ny] && !occupied[nx][ny]) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n}\n\nbool reachable(int i, int j) {\n    return dist[i][j] != -1;\n}\n\nint count_reachable_empty() {\n    int cnt = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !occupied[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J) && reachable(i, j))\n                cnt++;\n    return cnt;\n}\n\npair<int,int> find_best_cell(int target_dist, int remaining) {\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int best_i = -1, best_j = -1, best_score = 1e9;\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_I && j == ENTRANCE_J) continue;\n            if (!reachable(i, j)) continue;\n            // temporarily place\n            occupied[i][j] = true;\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            int reachable_after = count_reachable_empty();\n            occupied[i][j] = false;\n            if (reachable_after < remaining - 1) continue; // would block future\n            int score = abs(dist[i][j] - target_dist);\n            if (score < best_score) {\n                best_score = score;\n                best_i = i; best_j = j;\n            }\n        }\n    }\n    return {best_i, best_j};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    for (int i = 0; i < N; i++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n\n    max_id = D*D - 1 - N;\n    int total_containers = max_id;\n    vector<pair<int,int>> placements(total_containers);\n\n    // Compute max distance\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int max_dist = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J))\n                max_dist = max(max_dist, dist[i][j]);\n\n    for (int d = 0; d < total_containers; d++) {\n        int tid;\n        cin >> tid;\n        int remaining = total_containers - d;\n        int target_dist = (int)((double)tid / max_id * max_dist);\n        auto [pi, pj] = find_best_cell(target_dist, remaining);\n        if (pi == -1) {\n            // fallback: any reachable\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            for (int i = 0; i < D && pi==-1; i++)\n                for (int j = 0; j < D && pi==-1; j++)\n                    if (!obstacle[i][j] && !occupied[i][j] && reachable(i,j) && !(i==ENTRANCE_I && j==ENTRANCE_J)) {\n                        pi = i; pj = j;\n                    }\n        }\n        occupied[pi][pj] = true;\n        placements[tid] = {pi, pj};\n        cout << pi << \" \" << pj << \"\\n\";\n        cout.flush();\n    }\n\n    // Removal: try sorted order, pick accessible with smallest ID\n    vector<bool> removed(total_containers, false);\n    for (int step = 0; step < total_containers; step++) {\n        bfs_distance(ENTRANCE_I, ENTRANCE_J);\n        int chosen = -1;\n        for (int id = 0; id < total_containers; id++) {\n            if (!removed[id]) {\n                auto [i, j] = placements[id];\n                if (reachable(i, j)) {\n                    chosen = id;\n                    break;\n                }\n            }\n        }\n        removed[chosen] = true;\n        occupied[placements[chosen].first][placements[chosen].second] = false;\n        cout << placements[chosen].first << \" \" << placements[chosen].second << \"\\n\";\n    }\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nvector<vector<int>> input(N, vector<int>(N));\nbool adj[M+1][M+1];\nbool needs_zero[M+1];\nvector<int> graph[M+1];\n\nint dx[4] = {-1, 0, 1, 0};\nint dy[4] = {0, 1, 0, -1};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> input[i][j];\n    \n    // Build adjacency matrix\n    memset(adj, 0, sizeof(adj));\n    memset(needs_zero, 0, sizeof(needs_zero));\n    \n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = input[i][j];\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                needs_zero[c] = true;\n            for (int d = 0; d < 4; d++) {\n                int ni = i + dx[d], nj = j + dy[d];\n                int nc = 0;\n                if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n                    nc = input[ni][nj];\n                if (c != nc)\n                    adj[c][nc] = adj[nc][c] = true;\n            }\n        }\n    }\n    \n    for (int c = 1; c <= m; c++)\n        for (int d = 0; d <= m; d++)\n            if (adj[c][d] && c != d)\n                graph[c].push_back(d);\n    \n    // Output: all 0 initially\n    vector<vector<int>> output(N, vector<int>(N, 0));\n    \n    // For each color, we'll assign a \"seed\" cell\n    // Then expand to satisfy adjacencies\n    \n    // Build spanning tree for ordering\n    vector<bool> visited(M+1, false);\n    vector<int> order;\n    queue<int> q;\n    \n    // Start with colors that need color 0\n    for (int c = 1; c <= m; c++) {\n        if (needs_zero[c] && !visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; c++) {\n        if (!visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    \n    // Place colors in a compact region\n    // Use a rectangular block in the center, starting from row 2, col 2\n    // Place each color as a small connected region (1 cell for now)\n    \n    map<int, vector<pair<int,int>>> cells; // cells for each color\n    \n    int cur_r = 2, cur_c = 2;\n    int max_r = N-3, max_c = N-3;\n    \n    for (int c : order) {\n        // Find free cell\n        while (cur_r <= max_r && output[cur_r][cur_c] != 0) {\n            cur_c++;\n            if (cur_c > max_c) { cur_c = 2; cur_r++; }\n        }\n        if (cur_r > max_r) break;\n        \n        output[cur_r][cur_c] = c;\n        cells[c].push_back({cur_r, cur_c});\n    }\n    \n    // Now ensure all required adjacencies are satisfied\n    // For each adjacency pair, if not adjacent, add cells\n    \n    bool changed = true;\n    int iterations = 0;\n    while (changed && iterations < 100) {\n        changed = false;\n        iterations++;\n        \n        for (int c = 1; c <= m; c++) {\n            for (int d : graph[c]) {\n                if (d == 0 || c >= d) continue; // process each pair once\n                \n                // Check if c and d are adjacent in output\n                bool adj_found = false;\n                for (auto [r1, c1] : cells[c]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r1 + dx[k], nc = c1 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == d) {\n                            adj_found = true;\n                            break;\n                        }\n                    }\n                    if (adj_found) break;\n                }\n                if (adj_found) continue;\n                \n                // Try to add a cell of c adjacent to some cell of d\n                bool placed = false;\n                for (auto [r2, c2] : cells[d]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r2 + dx[k], nc = c2 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                            output[nr][nc] = c;\n                            cells[c].push_back({nr, nc});\n                            placed = true;\n                            changed = true;\n                            break;\n                        }\n                    }\n                    if (placed) break;\n                }\n                \n                if (!placed) {\n                    // Try adding a cell of d adjacent to c\n                    for (auto [r1, c1] : cells[c]) {\n                        for (int k = 0; k < 4; k++) {\n                            int nr = r1 + dx[k], nc = c1 + dy[k];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                                output[nr][nc] = d;\n                                cells[d].push_back({nr, nc});\n                                placed = true;\n                                changed = true;\n                                break;\n                            }\n                        }\n                        if (placed) break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Check if any color needs color-0 adjacency but doesn't have it\n    for (int c = 1; c <= m; c++) {\n        if (!needs_zero[c]) continue;\n        if (cells[c].empty()) continue;\n        \n        bool touches_zero = false;\n        for (auto [r, col] : cells[c]) {\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dx[k], nc = col + dy[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || output[nr][nc] == 0) {\n                    touches_zero = true;\n                    break;\n                }\n            }\n            if (touches_zero) break;\n        }\n        \n        if (!touches_zero) {\n            // Expand c towards the border\n            // Find path to border through color 0\n            for (auto [r, col] : cells[c]) {\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dx[k], nc = col + dy[k];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                        output[nr][nc] = c;\n                        cells[c].push_back({nr, nc});\n                        break;\n                    }\n                }\n                break;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << output[i][j] << (j == N-1 ? '\\n' : ' ');\n        }\n    }\n    \n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nint query_count = 0;\n\n// Compare two sets, return '<', '>', or '='\nchar compare_sets(const vector<int>& L, const vector<int>& R) {\n    query_count++;\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res;\n    cin >> res;\n    if (cin.eof()) {\n        // Should not happen, but handle gracefully\n        exit(0);\n    }\n    return res;\n}\n\n// Compare single items\nchar compare_items(int a, int b) {\n    return compare_sets({a}, {b});\n}\n\n// Merge sort - returns sorted indices (heaviest first)\nvector<int> merge_sort(const vector<int>& arr, int l, int r) {\n    if (l == r) return {arr[l]};\n    int m = (l + r) / 2;\n    auto left = merge_sort(arr, l, m);\n    auto right = merge_sort(arr, m + 1, r);\n    vector<int> res;\n    int i = 0, j = 0;\n    int nl = left.size(), nr = right.size();\n    while (i < nl && j < nr) {\n        if (query_count >= Q) {\n            // Out of queries, just append remaining in arbitrary order\n            while (i < nl) res.push_back(left[i++]);\n            while (j < nr) res.push_back(right[j++]);\n            return res;\n        }\n        char cmp = compare_items(left[i], right[j]);\n        if (cmp == '>') {\n            res.push_back(left[i++]);\n        } else if (cmp == '<') {\n            res.push_back(right[j++]);\n        } else {\n            // Equal weights, just take both (order doesn't matter)\n            res.push_back(left[i++]);\n            res.push_back(right[j++]);\n        }\n    }\n    while (i < nl) res.push_back(left[i++]);\n    while (j < nr) res.push_back(right[j++]);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> D >> Q;\n    query_count = 0;\n\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n\n    // Phase 1: Sort items by weight (heaviest first)\n    vector<int> sorted = merge_sort(items, 0, N - 1);\n\n    // Phase 2: Greedy assignment\n    // Since we only know relative order, use rank as proxy for weight\n    // Heavier items come first (index 0 is heaviest)\n    vector<vector<int>> groups(D);\n    vector<long long> est_sum(D, 0);\n    \n    for (int idx = 0; idx < N; idx++) {\n        int item = sorted[idx];\n        // Find group with minimum estimated sum\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (est_sum[g] < est_sum[best]) best = g;\n        }\n        groups[best].push_back(item);\n        // Use (N - idx) as weight proxy: heaviest = N, lightest = 1\n        est_sum[best] += (N - idx);\n    }\n\n    // Phase 3: Use remaining queries to refine\n    // We'll repeatedly pick two groups, compare them, and try to balance\n    int refinement_iterations = 0;\n    while (query_count + 2 <= Q) {\n        // Find the group with max estimated sum and min estimated sum\n        int max_g = 0, min_g = 0;\n        for (int g = 1; g < D; g++) {\n            if (est_sum[g] > est_sum[max_g]) max_g = g;\n            if (est_sum[g] < est_sum[min_g]) min_g = g;\n        }\n        if (max_g == min_g) break; // All equal\n        if (groups[max_g].empty() || groups[min_g].empty()) break;\n        \n        // Compare the two groups\n        char cmp = compare_sets(groups[max_g], groups[min_g]);\n        if (cmp == '>') {\n            // max_g is indeed heavier\n            // Try moving the lightest item from max_g to min_g\n            // The lightest item in max_g is the one with smallest weight proxy\n            // (which is the one added last to that group, or the one with highest index in sorted)\n            // Since we don't know exact weights, move the \"lightest\" by our proxy\n            // Find item in max_g with smallest weight estimate\n            int move_item = -1;\n            long long min_est = LLONG_MAX;\n            for (int item : groups[max_g]) {\n                // Find its position in sorted to get its weight proxy\n                int pos = find(sorted.begin(), sorted.end(), item) - sorted.begin();\n                long long w = N - pos;\n                if (w < min_est) {\n                    min_est = w;\n                    move_item = item;\n                }\n            }\n            if (move_item != -1 && groups[max_g].size() > 1) {\n                // Move item from max_g to min_g\n                auto& v = groups[max_g];\n                v.erase(remove(v.begin(), v.end(), move_item), v.end());\n                groups[min_g].push_back(move_item);\n                est_sum[max_g] -= min_est;\n                est_sum[min_g] += min_est;\n            } else {\n                break; // Can't move\n            }\n        } else if (cmp == '<') {\n            // Our estimates were wrong: min_g is actually heavier\n            // Swap the labels\n            swap(est_sum[max_g], est_sum[min_g]);\n            swap(groups[max_g], groups[min_g]);\n            // Now max_g is the heavier one\n            // Try moving lightest from max_g to min_g\n            int move_item = -1;\n            long long min_est = LLONG_MAX;\n            for (int item : groups[max_g]) {\n                int pos = find(sorted.begin(), sorted.end(), item) - sorted.begin();\n                long long w = N - pos;\n                if (w < min_est) {\n                    min_est = w;\n                    move_item = item;\n                }\n            }\n            if (move_item != -1 && groups[max_g].size() > 1) {\n                auto& v = groups[max_g];\n                v.erase(remove(v.begin(), v.end(), move_item), v.end());\n                groups[min_g].push_back(move_item);\n                est_sum[max_g] -= min_est;\n                est_sum[min_g] += min_est;\n                // Swap back labels\n                swap(est_sum[max_g], est_sum[min_g]);\n                swap(groups[max_g], groups[min_g]);\n            } else {\n                // Swap back\n                swap(est_sum[max_g], est_sum[min_g]);\n                swap(groups[max_g], groups[min_g]);\n                break;\n            }\n        } else {\n            // They are equal, no need to adjust\n            break;\n        }\n        refinement_iterations++;\n        if (refinement_iterations > 1000) break; // Safety\n    }\n\n    // Phase 4: Burn remaining queries if any (must use exactly Q)\n    while (query_count < Q) {\n        // Just compare single items (dummy queries)\n        compare_items(0, 1);\n    }\n\n    // Build assignment\n    vector<int> assignment(N);\n    for (int g = 0; g < D; g++) {\n        for (int item : groups[g]) {\n            assignment[item] = g;\n        }\n    }\n\n    // Output comment for visualizer\n    cout << \"#c\";\n    for (int i = 0; i < N; i++) cout << \" \" << assignment[i];\n    cout << endl;\n\n    // Output final division\n    for (int i = 0; i < N; i++) {\n        if (i > 0) cout << \" \";\n        cout << assignment[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 200, M = 10, H = N / M;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> stacks(m, vector<int>(n / m));\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < n / m; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> moves; // (v, i) where i=0 means carry out, else move to stack i-1\n    auto move_op = [&](int v, int dest) {\n        moves.emplace_back(v, dest + 1);\n    };\n    auto carry_out = [&](int v) {\n        moves.emplace_back(v, 0);\n    };\n\n    int next_target = 1;\n    while (next_target <= n) {\n        // find stack and position of next_target\n        int si = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == next_target) {\n                    si = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (si != -1) break;\n        }\n\n        if (pos == (int)stacks[si].size() - 1) {\n            // on top, carry out\n            carry_out(next_target);\n            stacks[si].pop_back();\n            ++next_target;\n            continue;\n        }\n\n        // need to move boxes above\n        int k = (int)stacks[si].size() - pos;\n        // choose destination: prefer an empty stack or one with top > next_target\n        int dest = -1;\n        // first look for empty\n        for (int i = 0; i < m; ++i) {\n            if (i != si && stacks[i].empty()) {\n                dest = i;\n                break;\n            }\n        }\n        if (dest == -1) {\n            // pick stack with minimum top number (to keep sorted)\n            int min_top = INT_MAX;\n            for (int i = 0; i < m; ++i) {\n                if (i != si && !stacks[i].empty() && stacks[i].back() < min_top) {\n                    min_top = stacks[i].back();\n                    dest = i;\n                }\n            }\n            if (dest == -1) dest = (si + 1) % m; // fallback\n        }\n\n        // move\n        move_op(next_target, dest);\n        vector<int> moving(stacks[si].begin() + pos, stacks[si].end());\n        stacks[si].resize(pos);\n        stacks[dest].insert(stacks[dest].end(), moving.begin(), moving.end());\n    }\n\n    // output\n    for (auto &[v, i] : moves) {\n        cout << v << \" \" << i << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring ans;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\nconst char dir[4] = {'R', 'D', 'L', 'U'};\n\nbool can_move(int x, int y, int nx, int ny) {\n    if (nx < 0 || nx >= N || ny < 0 || ny >= N) return false;\n    if (dx[abs(x-nx)] == 0) {\n        int j = min(y, ny);\n        if (v[x][j] == '1') return false;\n    } else {\n        int i = min(x, nx);\n        if (h[i][y] == '1') return false;\n    }\n    return true;\n}\n\nvoid dfs(int x, int y) {\n    visited[x][y] = true;\n    vector<tuple<int,int,int>> cand;\n    for (int k = 0; k < 4; k++) {\n        int nx = x + dx[k], ny = y + dy[k];\n        if (can_move(x, y, nx, ny) && !visited[nx][ny]) {\n            cand.emplace_back(-d[nx][ny], nx, ny);\n        }\n    }\n    sort(cand.begin(), cand.end()); // visit high-dirt first\n    for (auto [_, nx, ny] : cand) {\n        for (int k = 0; k < 4; k++) {\n            if (x + dx[k] == nx && y + dy[k] == ny) {\n                ans.push_back(dir[k]);\n                dfs(nx, ny);\n                ans.push_back(dir[(k+2)%4]);\n                break;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    d.assign(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    visited.assign(N, vector<bool>(N, false));\n    ans.reserve(100000);\n    \n    dfs(0, 0);\n    \n    // Ensure we return to (0,0) if not already\n    if (ans.empty() || ans.back() != 'U') {}\n    \n    // Length check\n    if ((int)ans.size() > 100000) {\n        ans.resize(100000);\n    }\n    \n    cout << ans << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 15;\nconst int INF = 1e9;\n\nint dist[225][225];\nvector<pair<int,int>> pos[26];\nchar grid[N][N];\nint M;\nvector<string> targets;\nint si, sj;\nint cell_id(int i, int j) { return i*N + j; }\n\nvoid bfs_dist() {\n    int di[] = {1,-1,0,0};\n    int dj[] = {0,0,1,-1};\n    for (int i=0;i<225;i++) for(int j=0;j<225;j++) dist[i][j]=INF;\n    for (int i=0;i<225;i++) {\n        int si = i/N, sj = i%N;\n        dist[i][i]=0;\n        queue<pair<int,int>> q;\n        q.push({si,sj});\n        while (!q.empty()) {\n            auto [ci,cj] = q.front(); q.pop();\n            int cid = cell_id(ci,cj);\n            for (int d=0;d<4;d++) {\n                int ni = ci+di[d], nj = cj+dj[d];\n                if (ni<0||ni>=N||nj<0||nj>=N) continue;\n                int nid = cell_id(ni,nj);\n                if (dist[i][nid] > dist[i][cid]+1) {\n                    dist[i][nid] = dist[i][cid]+1;\n                    q.push({ni,nj});\n                }\n            }\n        }\n    }\n}\n\n// DP to find best path for a target string given a starting cell\nint best_cost_for_target(const string& t, int start_cell, vector<int>& out_cells) {\n    int L = t.size();\n    vector<int> dp_prev, dp_cur;\n    vector<vector<int>> prev_cell(L, vector<int>(225,-1));\n    // initialize with start_cell to first character positions\n    dp_cur.assign(225, INF);\n    for (auto [i,j] : pos[t[0]-'A']) {\n        int cid = cell_id(i,j);\n        dp_cur[cid] = dist[start_cell][cid] + 1;\n    }\n    for (int k=1;k<L;k++) {\n        dp_prev = dp_cur;\n        dp_cur.assign(225, INF);\n        char c = t[k];\n        for (auto [i,j] : pos[c-'A']) {\n            int cid = cell_id(i,j);\n            for (auto [pi,pj] : pos[t[k-1]-'A']) {\n                int pid = cell_id(pi,pj);\n                int nd = dp_prev[pid] + dist[pid][cid] + 1;\n                if (nd < dp_cur[cid]) {\n                    dp_cur[cid] = nd;\n                    prev_cell[k][cid] = pid;\n                }\n            }\n        }\n    }\n    int best_end = -1;\n    int best_val = INF;\n    for (auto [i,j] : pos[t.back()-'A']) {\n        int cid = cell_id(i,j);\n        if (dp_cur[cid] < best_val) {\n            best_val = dp_cur[cid];\n            best_end = cid;\n        }\n    }\n    if (best_end==-1) return INF;\n    // reconstruct\n    out_cells.resize(L);\n    int cur = best_end;\n    for (int k=L-1;k>=0;k--) {\n        out_cells[k] = cur;\n        if (k>0) cur = prev_cell[k][cur];\n    }\n    return best_val;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    cin >> si >> sj;\n    for (int i=0;i<N;i++) {\n        string s; cin >> s;\n        for (int j=0;j<N;j++) {\n            grid[i][j] = s[j];\n            pos[s[j]-'A'].push_back({i,j});\n        }\n    }\n    targets.resize(M);\n    for (int i=0;i<M;i++) cin >> targets[i];\n    \n    bfs_dist();\n    \n    int start_cell = cell_id(si,sj);\n    \n    // For each target, compute minimal cost and cells (for a fresh start from start)\n    vector<vector<int>> best_cells(M);\n    vector<int> cost_from_start(M);\n    for (int i=0;i<M;i++) {\n        cost_from_start[i] = best_cost_for_target(targets[i], start_cell, best_cells[i]);\n    }\n    \n    // Greedy ordering: start with cheapest target\n    vector<bool> used(M,false);\n    vector<int> order;\n    int cur_cell = start_cell;\n    int total_cost = 0;\n    vector<int> output_cells;\n    \n    while ((int)order.size() < M) {\n        int best_idx = -1;\n        int best_add = INF;\n        vector<int> best_seq;\n        for (int i=0;i<M;i++) {\n            if (used[i]) continue;\n            vector<int> seq;\n            int add = best_cost_for_target(targets[i], cur_cell, seq);\n            if (add < best_add) {\n                best_add = add;\n                best_idx = i;\n                best_seq = seq;\n            }\n        }\n        used[best_idx] = true;\n        order.push_back(best_idx);\n        total_cost += best_add;\n        cur_cell = best_seq.back();\n        for (int c : best_seq) output_cells.push_back(c);\n    }\n    \n    // Simple local search: try swap adjacent in order\n    // Actually, since cost depends on sequence and overlap, greedy is decent\n    // We'll just output the greedy result\n    \n    for (int c : output_cells) {\n        cout << c/N << \" \" << c%N << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <cassert>\n#include <numeric>\nusing namespace std;\n\nstruct OilField {\n    int d;\n    vector<pair<int,int>> cells; // relative coordinates\n    int h, w; // height and width\n};\n\nint N, M;\ndouble eps;\nvector<OilField> fields;\nvector<vector<int>> true_v; // unknown to us, but for local testing only; in real, we'll build estimate\n\n// Our belief of v: double matrix\nvector<vector<double>> belief;\n\n// placed shapes tracking\nvector<vector<bool>> occupied_by_shape; // to avoid double counting\n\n// Helper: get sum of belief over a set of cells\ndouble belief_sum(const vector<pair<int,int>> &cells) {\n    double s = 0.0;\n    for (auto &p : cells) {\n        s += belief[p.first][p.second];\n    }\n    return s;\n}\n\n// Divination function (in real usage, we output query and read response)\ndouble divine(const vector<pair<int,int>> &cells) {\n    int k = (int)cells.size();\n    // Output query\n    cout << \"q \" << k;\n    for (auto &p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    double o;\n    cin >> o;\n    return o;\n}\n\n// Drill function\nint drill(int i, int j) {\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    int v;\n    cin >> v;\n    return v;\n}\n\n// Answer function\nvoid answer(const vector<pair<int,int>> &pos) {\n    cout << \"a \" << pos.size();\n    for (auto &p : pos) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int res;\n    cin >> res;\n    if (res == 1) exit(0);\n}\n\nint main() {\n    // Read initial info\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        fields[k].d = d;\n        fields[k].cells.resize(d);\n        int min_i = N, min_j = N, max_i = 0, max_j = 0;\n        for (int t = 0; t < d; ++t) {\n            int i, j;\n            cin >> i >> j;\n            fields[k].cells[t] = {i, j};\n            min_i = min(min_i, i);\n            min_j = min(min_j, j);\n            max_i = max(max_i, i);\n            max_j = max(max_j, j);\n        }\n        fields[k].h = max_i - min_i + 1;\n        fields[k].w = max_j - min_j + 1;\n        // normalize to (0,0)\n        for (auto &p : fields[k].cells) {\n            p.first -= min_i;\n            p.second -= min_j;\n        }\n    }\n\n    // Initialize belief to 0\n    belief.assign(N, vector<double>(N, 0.0));\n    occupied_by_shape.assign(N, vector<bool>(N, false));\n    vector<pair<int,int>> positive_cells;\n\n    // Phase 1: large set divinations to get rough estimate\n    // Example: divination on all cells (cost ~1/sqrt(N^2) very small)\n    {\n        vector<pair<int,int>> all;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                all.push_back({i, j});\n        double o = divine(all);\n        double k = (double)all.size();\n        double v_total = (o - k * eps) / (1 - 2*eps);\n        double avg = v_total / k;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                belief[i][j] = avg;\n    }\n\n    // Phase 2: row and column divinations for better localization\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int,int>> row;\n        for (int j = 0; j < N; ++j) row.push_back({i, j});\n        double o = divine(row);\n        double k = (double)row.size();\n        double v_row = (o - k * eps) / (1 - 2*eps);\n        double avg = v_row / k;\n        for (int j = 0; j < N; ++j) belief[i][j] = (belief[i][j] + avg) / 2.0;\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int,int>> col;\n        for (int i = 0; i < N; ++i) col.push_back({i, j});\n        double o = divine(col);\n        double k = (double)col.size();\n        double v_col = (o - k * eps) / (1 - 2*eps);\n        double avg = v_col / k;\n        for (int i = 0; i < N; ++i) belief[i][j] = (belief[i][j] + avg) / 2.0;\n    }\n\n    // Phase 3: Place shapes using belief\n    vector<bool> placed(M, false);\n    for (int k = 0; k < M; ++k) {\n        if (placed[k]) continue;\n        double best_score = -1e9;\n        int best_i = -1, best_j = -1;\n        // Slide shape\n        for (int di = 0; di + fields[k].h <= N; ++di) {\n            for (int dj = 0; dj + fields[k].w <= N; ++dj) {\n                vector<pair<int,int>> cand;\n                bool overlap_occupied = false;\n                for (auto &p : fields[k].cells) {\n                    int ni = di + p.first, nj = dj + p.second;\n                    cand.push_back({ni, nj});\n                    if (occupied_by_shape[ni][nj]) overlap_occupied = true;\n                }\n                if (overlap_occupied) continue;\n                double sum_belief = belief_sum(cand);\n                if (sum_belief > best_score) {\n                    best_score = sum_belief;\n                    best_i = di;\n                    best_j = dj;\n                }\n            }\n        }\n        if (best_i == -1) continue; // no place found\n        // Verify by divination\n        vector<pair<int,int>> verify_cells;\n        for (auto &p : fields[k].cells) verify_cells.push_back({best_i + p.first, best_j + p.second});\n        double o = divine(verify_cells);\n        double expected = fields[k].d; // if exactly one shape there, but could be more\n        double var = verify_cells.size() * eps * (1 - eps);\n        double stddev = sqrt(var);\n        // accept if within 2 sigma\n        if (fabs(o - expected) <= 2 * stddev + 1e-6) {\n            // place shape\n            placed[k] = true;\n            for (auto &p : verify_cells) {\n                occupied_by_shape[p.first][p.second] = true;\n                belief[p.first][p.second] += 1.0; // adjust belief\n            }\n        }\n    }\n\n    // Phase 4: Drill uncertain positive cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (belief[i][j] > 0.5 && !occupied_by_shape[i][j]) {\n                int v = drill(i, j);\n                if (v > 0) occupied_by_shape[i][j] = true;\n                belief[i][j] = v;\n            }\n        }\n    }\n\n    // Collect all positive cells\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (occupied_by_shape[i][j] || belief[i][j] > 0.5)\n                positive_cells.push_back({i, j});\n\n    answer(positive_cells);\n\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <cstdint>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\n// Compute area of a rectangle\nlong long area(const Rect& r) {\n    return (long long)(r.i1 - r.i0) * (r.j1 - r.j0);\n}\n\n// Compute partition change cost between two layouts\nlong long partition_change_cost(const vector<Rect>& prev, const vector<Rect>& curr, int W) {\n    if (prev.empty()) {\n        // Day 0: cost is total perimeter of all rectangles (excluding outer boundary)\n        long long cost = 0;\n        for (const auto& r : curr) {\n            cost += 2 * (r.i1 - r.i0) + 2 * (r.j1 - r.j0);\n        }\n        // Subtract outer boundary segments that are shared\n        // Actually, we need to count interior segments exactly.\n        // Let's compute properly using the grid representation.\n        // But for now, approximate: total perimeter minus outer edges.\n        return cost;\n    }\n    \n    // Build partition maps for both layouts\n    // Horizontal segments: for each i (1 to W-1), j (0 to W-1)\n    // Vertical segments: for each i (0 to W-1), j (1 to W-1)\n    vector<vector<bool>> H_prev(W, vector<bool>(W, false));\n    vector<vector<bool>> V_prev(W, vector<bool>(W, false));\n    vector<vector<bool>> H_curr(W, vector<bool>(W, false));\n    vector<vector<bool>> V_curr(W, vector<bool>(W, false));\n    \n    for (const auto& r : prev) {\n        // Top edge (i0, j) to (i0, j+1) for j in [j0, j1-1]\n        if (r.i0 > 0 && r.i0 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H_prev[r.i0][j] = true;\n            }\n        }\n        // Bottom edge\n        if (r.i1 > 0 && r.i1 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H_prev[r.i1][j] = true;\n            }\n        }\n        // Left edge\n        if (r.j0 > 0 && r.j0 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V_prev[i][r.j0] = true;\n            }\n        }\n        // Right edge\n        if (r.j1 > 0 && r.j1 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V_prev[i][r.j1] = true;\n            }\n        }\n    }\n    \n    for (const auto& r : curr) {\n        if (r.i0 > 0 && r.i0 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H_curr[r.i0][j] = true;\n            }\n        }\n        if (r.i1 > 0 && r.i1 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H_curr[r.i1][j] = true;\n            }\n        }\n        if (r.j0 > 0 && r.j0 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V_curr[i][r.j0] = true;\n            }\n        }\n        if (r.j1 > 0 && r.j1 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V_curr[i][r.j1] = true;\n            }\n        }\n    }\n    \n    long long cost = 0;\n    for (int i = 0; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (H_prev[i][j] != H_curr[i][j]) cost++;\n            if (V_prev[i][j] != V_curr[i][j]) cost++;\n        }\n    }\n    return cost;\n}\n\n// Compute area deficit penalty\nlong long area_penalty(const vector<Rect>& rects, const vector<int>& demands) {\n    long long penalty = 0;\n    for (int k = 0; k < demands.size(); ++k) {\n        long long rect_area = area(rects[k]);\n        if (rect_area < demands[k]) {\n            penalty += 100 * (demands[k] - rect_area);\n        }\n    }\n    return penalty;\n}\n\n// Recursive partitioning to create rectangles meeting target areas\nvoid assign_regions(vector<Rect>& rects, const vector<pair<long long,int>>& slot_order,\n                    int start_idx, int end_idx,\n                    int i0, int j0, int i1, int j1) {\n    if (start_idx >= end_idx) return;\n    if (start_idx + 1 == end_idx) {\n        int idx = slot_order[start_idx].second;\n        rects[idx] = {i0, j0, i1, j1};\n        return;\n    }\n    \n    // Compute total target areas\n    long long total_area = 0;\n    for (int i = start_idx; i < end_idx; ++i) {\n        total_area += slot_order[i].first;\n    }\n    \n    int height = i1 - i0;\n    int width = j1 - j0;\n    \n    if (height >= width) {\n        // Split horizontally\n        long long cumulative = 0;\n        int split_pos = start_idx;\n        long long half_area = total_area / 2;\n        for (int i = start_idx; i < end_idx - 1; ++i) {\n            cumulative += slot_order[i].first;\n            if (cumulative >= half_area) {\n                split_pos = i + 1;\n                break;\n            }\n        }\n        if (split_pos == start_idx) split_pos = start_idx + 1;\n        \n        long long area_first = 0;\n        for (int i = start_idx; i < split_pos; ++i) area_first += slot_order[i].first;\n        int split_i = i0 + (int)((area_first * height + total_area/2) / total_area);\n        if (split_i <= i0) split_i = i0 + 1;\n        if (split_i >= i1) split_i = i1 - 1;\n        \n        assign_regions(rects, slot_order, start_idx, split_pos, i0, j0, split_i, j1);\n        assign_regions(rects, slot_order, split_pos, end_idx, split_i, j0, i1, j1);\n    } else {\n        // Split vertically\n        long long cumulative = 0;\n        int split_pos = start_idx;\n        long long half_area = total_area / 2;\n        for (int i = start_idx; i < end_idx - 1; ++i) {\n            cumulative += slot_order[i].first;\n            if (cumulative >= half_area) {\n                split_pos = i + 1;\n                break;\n            }\n        }\n        if (split_pos == start_idx) split_pos = start_idx + 1;\n        \n        long long area_first = 0;\n        for (int i = start_idx; i < split_pos; ++i) area_first += slot_order[i].first;\n        int split_j = j0 + (int)((area_first * width + total_area/2) / total_area);\n        if (split_j <= j0) split_j = j0 + 1;\n        if (split_j >= j1) split_j = j1 - 1;\n        \n        assign_regions(rects, slot_order, start_idx, split_pos, i0, j0, i1, split_j);\n        assign_regions(rects, slot_order, split_pos, end_idx, i0, split_j, i1, j1);\n    }\n}\n\n// Create layout optimized for given demands\nvector<Rect> create_layout(const vector<int>& demands) {\n    int N = demands.size();\n    vector<pair<long long,int>> slot_order;\n    for (int k = 0; k < N; ++k) {\n        slot_order.emplace_back(demands[k], k);\n    }\n    sort(slot_order.begin(), slot_order.end(), greater<pair<long long,int>>());\n    \n    vector<Rect> rects(N);\n    assign_regions(rects, slot_order, 0, N, 0, 0, 1000, 1000);\n    return rects;\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    vector<vector<Rect>> all_rects(D);\n    \n    // Day 0: create optimal layout\n    vector<Rect> prev_layout = create_layout(a[0]);\n    all_rects[0] = prev_layout;\n    \n    // For subsequent days\n    for (int d = 1; d < D; ++d) {\n        // Option 1: keep previous layout\n        long long penalty_keep = area_penalty(prev_layout, a[d]);\n        \n        // Option 2: create new layout for current demands\n        vector<Rect> new_layout = create_layout(a[d]);\n        long long change_cost = partition_change_cost(prev_layout, new_layout, W);\n        long long penalty_new = area_penalty(new_layout, a[d]);\n        \n        long long cost_keep = penalty_keep;\n        long long cost_new = change_cost + penalty_new;\n        \n        if (cost_new <= cost_keep) {\n            prev_layout = new_layout;\n            all_rects[d] = new_layout;\n        } else {\n            all_rects[d] = prev_layout;\n        }\n    }\n\n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cout << all_rects[d][k].i0 << \" \" << all_rects[d][k].j0 << \" \"\n                 << all_rects[d][k].i1 << \" \" << all_rects[d][k].j1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\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<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> a[i][j];\n\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int s = 0; s < M; s++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> stamps[s][i][j];\n\n    vector<vector<int>> board = a;\n    vector<tuple<int,int,int>> ops;\n\n    // Greedy selection\n    for (int step = 0; step < K; step++) {\n        int best_m = -1, best_p = -1, best_q = -1;\n        long long best_gain = -1;\n\n        for (int m_idx = 0; m_idx < M; m_idx++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    long long gain = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            int old_val = board[p+i][q+j];\n                            int new_val = old_val + stamps[m_idx][i][j];\n                            gain += (new_val % MOD) - (old_val % MOD);\n                        }\n                    }\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_m = m_idx;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_m == -1) break;\n        ops.emplace_back(best_m, best_p, best_q);\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                board[best_p+i][best_q+j] += stamps[best_m][i][j];\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &[m_idx, p, q] : ops)\n        cout << m_idx << ' ' << p << ' ' << q << '\\n';\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\n// Direction mappings\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dc[] = {'U', 'D', 'L', 'R'};\n\nstruct Position {\n    int x, y;\n    bool operator==(const Position& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Position& o) const { return !(*this == o); }\n};\n\n// BFS to find shortest path with obstacle avoidance\nvector<Position> bfs(const vector<vector<int>>& grid, \n                     Position start, Position goal,\n                     const set<pair<int,int>>& crane_positions,\n                     int exclude_idx = -1) {\n    vector<vector<Position>> parent(N, vector<Position>(N, {-1, -1}));\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<Position> q;\n    \n    q.push(start);\n    dist[start.x][start.y] = 0;\n    \n    while (!q.empty()) {\n        Position cur = q.front(); q.pop();\n        if (cur == goal) break;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = cur.x + dx[d], ny = cur.y + dy[d];\n            if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n            if (dist[nx][ny] != -1) continue;\n            \n            // Check if occupied by another crane\n            bool occupied = false;\n            for (auto& cp : crane_positions) {\n                if (cp.first == nx && cp.second == ny) {\n                    occupied = true;\n                    break;\n                }\n            }\n            if (occupied) continue;\n            \n            dist[nx][ny] = dist[cur.x][cur.y] + 1;\n            parent[nx][ny] = cur;\n            q.push({nx, ny});\n        }\n    }\n    \n    if (dist[goal.x][goal.y] == -1) return {};\n    \n    vector<Position> path;\n    Position cur = goal;\n    while (!(cur == start)) {\n        path.push_back(cur);\n        cur = parent[cur.x][cur.y];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nchar get_move_dir(Position from, Position to) {\n    if (to.x == from.x - 1) return 'U';\n    if (to.x == from.x + 1) return 'D';\n    if (to.y == from.y - 1) return 'L';\n    if (to.y == from.y + 1) return 'R';\n    return '.';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> A[i][j];\n    \n    // Grid: -1 = empty, otherwise container ID\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    \n    // Receiving queues per gate row\n    vector<queue<int>> recv_queue(N);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            recv_queue[i].push(A[i][j]);\n    \n    // Crane state\n    struct Crane {\n        int x, y;\n        bool holding;\n        int container;\n        bool bombed;\n        bool large; // large crane can move over containers while carrying\n    };\n    vector<Crane> cranes(N);\n    for (int i = 0; i < N; i++) {\n        cranes[i] = {i, 0, false, -1, false, i == 0};\n    }\n    \n    // Which containers have been dispatched\n    vector<bool> dispatched(N * N, false);\n    int dispatched_count = 0;\n    \n    // Dispatch log per gate\n    vector<vector<int>> dispatch_log(N);\n    \n    // Next expected container per gate\n    vector<int> next_expected(N);\n    for (int i = 0; i < N; i++) next_expected[i] = i * N;\n    \n    vector<string> output(N);\n    \n    // Helper: get target gate for a container\n    auto target_gate = [](int cid) { return cid / N; };\n    \n    // Main loop\n    for (int turn = 0; turn < MAX_TURNS && dispatched_count < N * N; turn++) {\n        // Step 1: Spawn containers at empty receiving gates\n        for (int i = 0; i < N; i++) {\n            if (!recv_queue[i].empty() && grid[i][0] == -1) {\n                bool crane_holding_at_gate = false;\n                for (auto& cr : cranes) {\n                    if (!cr.bombed && cr.x == i && cr.y == 0 && cr.holding)\n                        crane_holding_at_gate = true;\n                }\n                if (!crane_holding_at_gate) {\n                    int cid = recv_queue[i].front(); recv_queue[i].pop();\n                    grid[i][0] = cid;\n                }\n            }\n        }\n        \n        // Step 2: Dispatch containers at gates (dispatch ALL containers at gates)\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N-1] != -1) {\n                int cid = grid[i][N-1];\n                dispatch_log[i].push_back(cid);\n                dispatched[cid] = true;\n                dispatched_count++;\n                grid[i][N-1] = -1;\n            }\n        }\n        \n        if (dispatched_count == N * N) break;\n        \n        // Step 3: Plan actions for each crane\n        vector<char> actions(N, '.');\n        vector<Position> new_pos(N);\n        for (int i = 0; i < N; i++) {\n            new_pos[i] = {cranes[i].x, cranes[i].y};\n        }\n        \n        // Build set of occupied positions for pathfinding\n        set<pair<int,int>> occupied;\n        for (int i = 0; i < N; i++) {\n            if (!cranes[i].bombed) {\n                occupied.insert({cranes[i].x, cranes[i].y});\n            }\n        }\n        \n        // Process cranes in order: large crane first\n        vector<int> crane_order;\n        for (int i = 0; i < N; i++) if (cranes[i].large) crane_order.push_back(i);\n        for (int i = 0; i < N; i++) if (!cranes[i].large) crane_order.push_back(i);\n        \n        for (int ci : crane_order) {\n            if (cranes[ci].bombed) continue;\n            auto& cr = cranes[ci];\n            \n            if (cr.large) {\n                // LARGE CRANE: Main transporter\n                if (cr.holding) {\n                    int tgt = target_gate(cr.container);\n                    // Deliver to target dispatch gate\n                    if (cr.y == N-1 && cr.x == tgt) {\n                        // At correct dispatch gate, release\n                        if (grid[cr.x][cr.y] == -1) {\n                            actions[ci] = 'Q';\n                        }\n                    } else {\n                        // Move towards target gate\n                        Position goal = {tgt, N-1};\n                        auto path = bfs(grid, {cr.x, cr.y}, goal, occupied, ci);\n                        if (!path.empty()) {\n                            Position next = path[0];\n                            // Check if we can move there (large crane can move over containers)\n                            // But need to ensure no crane is there\n                            bool other_crane_there = false;\n                            for (int j = 0; j < N; j++) {\n                                if (j != ci && !cranes[j].bombed && \n                                    new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                    other_crane_there = true;\n                                }\n                            }\n                            if (!other_crane_there) {\n                                actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                            }\n                        }\n                    }\n                } else {\n                    // Find a container to pick up\n                    // Priority: containers that belong to correct gates\n                    // Check all grid positions\n                    bool found_target = false;\n                    Position pickup_target;\n                    \n                    // First priority: containers at receiving gates\n                    for (int i = 0; i < N && !found_target; i++) {\n                        if (grid[i][0] != -1 && !dispatched[grid[i][0]]) {\n                            pickup_target = {i, 0};\n                            found_target = true;\n                        }\n                    }\n                    \n                    // Second: containers in buffer area\n                    if (!found_target) {\n                        for (int i = 0; i < N && !found_target; i++) {\n                            for (int j = 1; j < N-1 && !found_target; j++) {\n                                if (grid[i][j] != -1 && !dispatched[grid[i][j]]) {\n                                    pickup_target = {i, j};\n                                    found_target = true;\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (found_target) {\n                        if (cr.x == pickup_target.x && cr.y == pickup_target.y) {\n                            if (grid[cr.x][cr.y] != -1) {\n                                actions[ci] = 'P';\n                            }\n                        } else {\n                            auto path = bfs(grid, {cr.x, cr.y}, pickup_target, occupied, ci);\n                            if (!path.empty()) {\n                                Position next = path[0];\n                                bool other_crane_there = false;\n                                for (int j = 0; j < N; j++) {\n                                    if (j != ci && !cranes[j].bombed && \n                                        new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                        other_crane_there = true;\n                                    }\n                                }\n                                if (!other_crane_there) {\n                                    actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                                }\n                            }\n                        }\n                    }\n                }\n            } else {\n                // SMALL CRANE: Help move containers from receiving gate to buffer\n                if (cr.holding) {\n                    // Move to nearest empty buffer spot and drop\n                    Position buffer_target = {-1, -1};\n                    // Try column 2 first (middle buffer)\n                    for (int col = 1; col <= 3 && buffer_target.x == -1; col++) {\n                        for (int row = 0; row < N && buffer_target.x == -1; row++) {\n                            if (grid[row][col] == -1) {\n                                // Check if no crane plans to go there\n                                bool taken = false;\n                                for (int j = 0; j < N; j++) {\n                                    if (j != ci && !cranes[j].bombed && \n                                        new_pos[j].x == row && new_pos[j].y == col) {\n                                        taken = true;\n                                    }\n                                }\n                                if (!taken) {\n                                    buffer_target = {row, col};\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (buffer_target.x != -1) {\n                        if (cr.x == buffer_target.x && cr.y == buffer_target.y) {\n                            if (grid[cr.x][cr.y] == -1) {\n                                actions[ci] = 'Q';\n                            }\n                        } else {\n                            auto path = bfs(grid, {cr.x, cr.y}, buffer_target, occupied, ci);\n                            if (!path.empty()) {\n                                Position next = path[0];\n                                // Check if next position has a container (small crane can't move there while carrying)\n                                if (grid[next.x][next.y] != -1) continue;\n                                bool other_crane_there = false;\n                                for (int j = 0; j < N; j++) {\n                                    if (j != ci && !cranes[j].bombed && \n                                        new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                        other_crane_there = true;\n                                    }\n                                }\n                                if (!other_crane_there) {\n                                    actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                                }\n                            }\n                        }\n                    }\n                } else {\n                    // Pick up from receiving gate (own row)\n                    if (cr.y == 0 && grid[cr.x][0] != -1) {\n                        actions[ci] = 'P';\n                    } else if (cr.y > 0 && grid[cr.x][0] != -1) {\n                        // Move to receiving gate\n                        Position goal = {cr.x, 0};\n                        auto path = bfs(grid, {cr.x, cr.y}, goal, occupied, ci);\n                        if (!path.empty()) {\n                            Position next = path[0];\n                            if (grid[next.x][next.y] != -1) continue;\n                            bool other_crane_there = false;\n                            for (int j = 0; j < N; j++) {\n                                if (j != ci && !cranes[j].bombed && \n                                    new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                    other_crane_there = true;\n                                }\n                            }\n                            if (!other_crane_there) {\n                                actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Update new_pos for this crane based on action\n            if (actions[ci] == 'U') new_pos[ci] = {cr.x-1, cr.y};\n            else if (actions[ci] == 'D') new_pos[ci] = {cr.x+1, cr.y};\n            else if (actions[ci] == 'L') new_pos[ci] = {cr.x, cr.y-1};\n            else if (actions[ci] == 'R') new_pos[ci] = {cr.x, cr.y+1};\n            // For P, Q, B, . position stays same\n        }\n        \n        // Step 4: Resolve conflicts\n        bool has_conflict = false;\n        \n        // Check for position conflicts\n        for (int i = 0; i < N && !has_conflict; i++) {\n            if (cranes[i].bombed) continue;\n            for (int j = i+1; j < N && !has_conflict; j++) {\n                if (cranes[j].bombed) continue;\n                if (new_pos[i] == new_pos[j]) {\n                    has_conflict = true;\n                }\n                // Swap conflict\n                if (new_pos[i].x == cranes[j].x && new_pos[i].y == cranes[j].y &&\n                    new_pos[j].x == cranes[i].x && new_pos[j].y == cranes[i].y) {\n                    has_conflict = true;\n                }\n            }\n        }\n        \n        // Check small cranes moving onto containers while carrying\n        for (int i = 0; i < N && !has_conflict; i++) {\n            if (cranes[i].bombed || cranes[i].large) continue;\n            if (cranes[i].holding && actions[i] != 'P' && actions[i] != 'Q' && actions[i] != 'B' && actions[i] != '.') {\n                if (grid[new_pos[i].x][new_pos[i].y] != -1) {\n                    has_conflict = true;\n                }\n            }\n        }\n        \n        // If conflict, cancel all non-P/Q movements (keep P/Q if valid)\n        if (has_conflict) {\n            for (int i = 0; i < N; i++) {\n                if (actions[i] != 'P' && actions[i] != 'Q' && actions[i] != 'B') {\n                    actions[i] = '.';\n                }\n                new_pos[i] = {cranes[i].x, cranes[i].y};\n            }\n            \n            // Re-check P/Q actions\n            for (int i = 0; i < N; i++) {\n                if (actions[i] == 'P') {\n                    if (cranes[i].holding || grid[cranes[i].x][cranes[i].y] == -1) {\n                        actions[i] = '.';\n                    }\n                }\n                if (actions[i] == 'Q') {\n                    if (!cranes[i].holding || grid[cranes[i].x][cranes[i].y] != -1) {\n                        actions[i] = '.';\n                    }\n                }\n            }\n        }\n        \n        // Step 5: Apply actions\n        for (int i = 0; i < N; i++) {\n            if (cranes[i].bombed) continue;\n            \n            if (actions[i] == 'P') {\n                if (!cranes[i].holding && grid[cranes[i].x][cranes[i].y] != -1) {\n                    cranes[i].holding = true;\n                    cranes[i].container = grid[cranes[i].x][cranes[i].y];\n                    grid[cranes[i].x][cranes[i].y] = -1;\n                }\n            } else if (actions[i] == 'Q') {\n                if (cranes[i].holding && grid[cranes[i].x][cranes[i].y] == -1) {\n                    grid[cranes[i].x][cranes[i].y] = cranes[i].container;\n                    cranes[i].holding = false;\n                    cranes[i].container = -1;\n                }\n            } else if (actions[i] == 'B') {\n                if (!cranes[i].holding) {\n                    cranes[i].bombed = true;\n                }\n            } else {\n                cranes[i].x = new_pos[i].x;\n                cranes[i].y = new_pos[i].y;\n            }\n        }\n        \n        // Record actions\n        for (int i = 0; i < N; i++) {\n            output[i] += actions[i];\n        }\n    }\n    \n    // Pad to equal length\n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)output[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)output[i].size() < max_len) output[i] += '.';\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << output[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> h[i][j];\n\n    const int MOVE_COST_BASE = 100;\n    int x = 0, y = 0, load = 0;\n    vector<string> ops;\n\n    auto dist = [&](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_to = [&](int tx, int ty) {\n        while (x < tx) { ops.push_back(\"D\"); x++; }\n        while (x > tx) { ops.push_back(\"U\"); x--; }\n        while (y < ty) { ops.push_back(\"R\"); y++; }\n        while (y > ty) { ops.push_back(\"L\"); y--; }\n    };\n\n    while (true) {\n        // Check if any positive remains\n        bool has_pos = false;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (h[i][j] > 0) { has_pos = true; break; }\n        if (!has_pos) break;\n\n        if (load == 0) {\n            // Find best positive-negative pair\n            int best_cost = 1e9;\n            int best_px = -1, best_py = -1, best_nx = -1, best_ny = -1;\n            \n            for (int pi = 0; pi < N; pi++) {\n                for (int pj = 0; pj < N; pj++) {\n                    if (h[pi][pj] <= 0) continue;\n                    // Find nearest negative for this positive\n                    int near_ni = -1, near_nj = -1, near_dist = 1e9;\n                    for (int ni = 0; ni < N; ni++) {\n                        for (int nj = 0; nj < N; nj++) {\n                            if (h[ni][nj] >= 0) continue;\n                            int d = dist(pi, pj, ni, nj);\n                            if (d < near_dist) {\n                                near_dist = d;\n                                near_ni = ni;\n                                near_nj = nj;\n                            }\n                        }\n                    }\n                    if (near_ni == -1) continue;\n                    // Cost: move to positive (empty) + move to negative (loaded with h[pi][pj])\n                    int amount = h[pi][pj];\n                    int cost = dist(x, y, pi, pj) * MOVE_COST_BASE \n                             + near_dist * (MOVE_COST_BASE + amount);\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_px = pi;\n                        best_py = pj;\n                        best_nx = near_ni;\n                        best_ny = near_nj;\n                    }\n                }\n            }\n            \n            if (best_px == -1) break;\n            \n            // Move to positive, load\n            move_to(best_px, best_py);\n            int amount = h[best_px][best_py];\n            ops.push_back(\"+\" + to_string(amount));\n            load += amount;\n            h[best_px][best_py] = 0;\n            \n            // Move to negative, unload\n            move_to(best_nx, best_ny);\n            int need = -h[best_nx][best_ny];\n            int unload = min(load, need);\n            ops.push_back(\"-\" + to_string(unload));\n            h[best_nx][best_ny] += unload;\n            load -= unload;\n            \n        } else {\n            // We have remaining load, find nearest negative\n            int best_dist = 1e9, best_nx = -1, best_ny = -1;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (h[i][j] >= 0) continue;\n                    int d = dist(x, y, i, j);\n                    if (d < best_dist) {\n                        best_dist = d;\n                        best_nx = i;\n                        best_ny = j;\n                    }\n                }\n            }\n            if (best_nx == -1) {\n                // No more negatives? Should not happen if sum is zero\n                break;\n            }\n            move_to(best_nx, best_ny);\n            int need = -h[best_nx][best_ny];\n            int unload = min(load, need);\n            ops.push_back(\"-\" + to_string(unload));\n            h[best_nx][best_ny] += unload;\n            load -= unload;\n        }\n    }\n\n    for (const auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <set>\n#include <tuple>\n#include <cmath>\n#include <queue>\n#include <map>\n#include <cstring>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1); // 60\n    vector<vector<int>> X(seed_count, vector<int>(M, 0));\n\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    // Track global maximums per dimension (initial)\n    vector<int> global_max(M, 0);\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            global_max[j] = max(global_max[j], X[i][j]);\n        }\n    }\n\n    // For each turn\n    for (int t = 0; t < T; t++) {\n        // Calculate value for each seed\n        vector<pair<int, int>> seed_values; // (value, index)\n        for (int i = 0; i < seed_count; i++) {\n            int sum = 0;\n            for (int j = 0; j < M; j++) {\n                sum += X[i][j];\n            }\n            seed_values.push_back({sum, i});\n        }\n        \n        // Sort by value descending\n        sort(seed_values.begin(), seed_values.end(), greater<pair<int, int>>());\n        \n        // Select top N*N seeds for planting\n        vector<int> selected;\n        // Use a set to avoid duplicates\n        set<int> selected_set;\n        \n        // Strategy: select top seeds, but also ensure diversity\n        // First, take the absolute top seeds\n        for (int i = 0; i < N * N && i < seed_count; i++) {\n            selected.push_back(seed_values[i].second);\n            selected_set.insert(seed_values[i].second);\n        }\n        \n        // If we don't have enough (shouldn't happen with 60 seeds and 36 slots)\n        while ((int)selected.size() < N * N) {\n            for (int i = 0; i < seed_count && (int)selected.size() < N * N; i++) {\n                if (selected_set.find(i) == selected_set.end()) {\n                    selected.push_back(i);\n                    selected_set.insert(i);\n                }\n            }\n        }\n        \n        // Now arrange the selected seeds on the grid\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        \n        // Calculate values for selected seeds\n        vector<pair<int, int>> sel_vals; // (value, index)\n        for (int idx : selected) {\n            int sum = 0;\n            for (int j = 0; j < M; j++) sum += X[idx][j];\n            sel_vals.push_back({sum, idx});\n        }\n        sort(sel_vals.begin(), sel_vals.end(), greater<pair<int, int>>());\n        \n        if (t <= 1) {\n            // First two turns: snake pattern sorted by value\n            // This brings seeds with similar total values adjacent,\n            // allowing good seeds to exchange traits\n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                if (i % 2 == 0) {\n                    for (int j = 0; j < N; j++) {\n                        A[i][j] = sel_vals[pos++].second;\n                    }\n                } else {\n                    for (int j = N - 1; j >= 0; j--) {\n                        A[i][j] = sel_vals[pos++].second;\n                    }\n                }\n            }\n        } else if (t <= 4) {\n            // Middle turns: Concentrate top seeds in center\n            // Create a \"breeding ground\" in the middle\n            vector<int> sorted_idx;\n            for (auto& p : sel_vals) sorted_idx.push_back(p.second);\n            \n            // Place best seeds in a 4x4 block in center, others around\n            // Center positions (1,1) to (4,4) in a 6x6 grid\n            int pos = 0;\n            // Inner 4x4 (rows 1-4, cols 1-4)\n            vector<pair<int,int>> inner_positions;\n            for (int i = 1; i < N-1; i++) {\n                for (int j = 1; j < N-1; j++) {\n                    inner_positions.push_back({i, j});\n                }\n            }\n            // Sort inner positions by distance from center\n            double cx = (N-1) / 2.0, cy = (N-1) / 2.0;\n            sort(inner_positions.begin(), inner_positions.end(), \n                 [cx, cy](const pair<int,int>& a, const pair<int,int>& b) {\n                     double da = pow(a.first - cx, 2) + pow(a.second - cy, 2);\n                     double db = pow(b.first - cx, 2) + pow(b.second - cy, 2);\n                     return da < db;\n                 });\n            \n            // Place best seeds in inner positions\n            for (auto [i, j] : inner_positions) {\n                if (pos < (int)sorted_idx.size()) {\n                    A[i][j] = sorted_idx[pos++];\n                }\n            }\n            \n            // Fill border positions with remaining seeds\n            vector<pair<int,int>> border_positions;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (A[i][j] == -1) {\n                        border_positions.push_back({i, j});\n                    }\n                }\n            }\n            for (auto [i, j] : border_positions) {\n                if (pos < (int)sorted_idx.size()) {\n                    A[i][j] = sorted_idx[pos++];\n                }\n            }\n        } else {\n            // Late turns: Maximize adjacency between complementary seeds\n            // Use a greedy placement: start with best seed in center,\n            // then place seeds that have complementary strengths around it\n            \n            vector<int> sorted_idx;\n            for (auto& p : sel_vals) sorted_idx.push_back(p.second);\n            \n            // Build adjacency graph greedily\n            // Start with center\n            int center_i = N/2, center_j = N/2;\n            A[center_i][center_j] = sorted_idx[0];\n            set<int> placed;\n            placed.insert(center_i * N + center_j);\n            \n            // BFS-like placement\n            queue<pair<int,int>> q;\n            q.push({center_i, center_j});\n            \n            int seed_pos = 1;\n            \n            while (!q.empty() && seed_pos < (int)sorted_idx.size()) {\n                auto [i, j] = q.front();\n                q.pop();\n                \n                // Check 4 neighbors\n                int di[] = {-1, 1, 0, 0};\n                int dj[] = {0, 0, -1, 1};\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = i + di[d];\n                    int nj = j + dj[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N && \n                        placed.find(ni * N + nj) == placed.end()) {\n                        if (seed_pos < (int)sorted_idx.size()) {\n                            A[ni][nj] = sorted_idx[seed_pos++];\n                            placed.insert(ni * N + nj);\n                            q.push({ni, nj});\n                        }\n                    }\n                }\n            }\n            \n            // Fill any remaining spots\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (A[i][j] == -1 && seed_pos < (int)sorted_idx.size()) {\n                        A[i][j] = sorted_idx[seed_pos++];\n                    }\n                }\n            }\n        }\n        \n        // Output 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 << endl;\n        }\n        cout.flush();\n        \n        // Read new seeds\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                global_max[j] = max(global_max[j], X[i][j]);\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <cassert>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\nusing namespace std;\n\n// ---------- Constants ----------\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char MOVE_CHAR[4] = {'R', 'D', 'L', 'U'};\n\n// ---------- Types ----------\nstruct Point {\n    int x, y;\n    Point operator+(Point o) const { return {x+o.x, y+o.y}; }\n    bool operator==(Point o) const { return x==o.x && y==o.y; }\n};\n\n// ---------- Global state ----------\nint N, M, V;\nvector<string> start_grid, target_grid;\nvector<pair<int,int>> start_positions, target_positions;\nvector<int> parent;\nvector<int> length_to_parent;\nvector<int> leaf_order; // leaves index\nint root_x, root_y;\nvector<int> angles; // direction index (0: right, 1: down, 2: left, 3: up)\nvector<bool> holding; // true if fingertip carrying takoyaki\nvector<Point> fingertip_positions;\nvector<vector<int>> children;\n\n// ---------- Function declarations ----------\nvoid design_tree();\nvoid compute_fingertip_positions();\nvoid simulate_turn(vector<string>& commands, int& turn);\nbool pick_if_possible(int leaf_idx);\nbool place_if_possible(int leaf_idx);\nvoid move_root_to_target(Point target, vector<string>& commands);\nvoid set_angle(int node, int desired_angle, vector<string>& commands);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N >> M >> V;\n    start_grid.resize(N);\n    target_grid.resize(N);\n    for (int i = 0; i < N; i++) cin >> start_grid[i];\n    for (int i = 0; i < N; i++) cin >> target_grid[i];\n\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (start_grid[i][j] == '1')\n                start_positions.emplace_back(i, j);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (target_grid[i][j] == '1')\n                target_positions.emplace_back(i, j);\n\n    // Design tree\n    design_tree();\n\n    // Set initial root near center of start positions\n    int sumx = 0, sumy = 0;\n    for (auto& p : start_positions) { sumx += p.first; sumy += p.second; }\n    root_x = sumx / M;\n    root_y = sumy / M;\n    root_x = min(max(root_x, 0), N-1);\n    root_y = min(max(root_y, 0), N-1);\n\n    // Output tree info\n    int Vp = parent.size();\n    cout << Vp << \"\\n\";\n    for (int i = 1; i < Vp; i++)\n        cout << parent[i] << \" \" << length_to_parent[i] << \"\\n\";\n    cout << root_x << \" \" << root_y << \"\\n\";\n\n    angles.assign(Vp, 0); // all edges initially to the right\n    holding.assign(Vp, false);\n\n    // Identify leaves\n    vector<bool> is_leaf(Vp, false);\n    for (int i = 0; i < Vp; i++) {\n        if (children[i].empty()) {\n            is_leaf[i] = true;\n            leaf_order.push_back(i);\n        }\n    }\n\n    // Simulation\n    vector<string> commands;\n    int turn = 0;\n    const int MAX_TURNS = 100000;\n\n    // Simple greedy assignment: for each leaf, find nearest start->target pair\n    vector<tuple<int,int,int>> tasks; // (dist, start_idx, target_idx)\n    for (size_t si = 0; si < start_positions.size(); si++) {\n        int best_ti = -1;\n        int best_dist = 1e9;\n        for (size_t ti = 0; ti < target_positions.size(); ti++) {\n            int d = abs(start_positions[si].first - target_positions[ti].first)\n                   + abs(start_positions[si].second - target_positions[ti].second);\n            if (d < best_dist) {\n                best_dist = d;\n                best_ti = ti;\n            }\n        }\n        tasks.emplace_back(best_dist, si, best_ti);\n    }\n    sort(tasks.begin(), tasks.end());\n\n    vector<bool> start_done(start_positions.size(), false);\n    vector<bool> target_done(target_positions.size(), false);\n    int placed = 0;\n\n    auto try_move_leaf_to = [&](int leaf, Point target) {\n        // move root toward target, then set leaf angle\n        while (turn < MAX_TURNS) {\n            Point cur = fingertip_positions[leaf];\n            if (cur.x == target.x && cur.y == target.y) break;\n            // move root greedily\n            int dx = target.x - cur.x;\n            int dy = target.y - cur.y;\n            int mx = (dx > 0) - (dx < 0);\n            int my = (dy > 0) - (dy < 0);\n            if (mx != 0 || my != 0) {\n                int dir = -1;\n                if (mx == 1 && my == 0) dir = 1; // down\n                else if (mx == -1 && my == 0) dir = 3; // up\n                else if (mx == 0 && my == 1) dir = 0; // right\n                else if (mx == 0 && my == -1) dir = 2; // left\n                else if (mx == 1 && my == 1) dir = (rand()%2) ? 1 : 0;\n                else if (mx == -1 && my == 1) dir = (rand()%2) ? 3 : 0;\n                else if (mx == 1 && my == -1) dir = (rand()%2) ? 1 : 2;\n                else if (mx == -1 && my == -1) dir = (rand()%2) ? 3 : 2;\n                if (dir >= 0) {\n                    int nx = root_x + DX[dir];\n                    int ny = root_y + DY[dir];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        root_x = nx; root_y = ny;\n                        string cmd(2*Vp, '.');\n                        cmd[0] = MOVE_CHAR[dir];\n                        commands.push_back(cmd);\n                        turn++;\n                        compute_fingertip_positions();\n                        continue;\n                    }\n                }\n            }\n            // rotation to adjust fingertip if close\n            if (abs(cur.x - target.x) <= 1 && abs(cur.y - target.y) <= 1) {\n                for (int a = 0; a < 4; a++) {\n                    angles[leaf] = a;\n                    compute_fingertip_positions();\n                    if (fingertip_positions[leaf].x == target.x && fingertip_positions[leaf].y == target.y) {\n                        string cmd(2*Vp, '.');\n                        cmd[leaf] = (a == (angles[leaf]+3)%4) ? 'L' : ((a == (angles[leaf]+1)%4) ? 'R' : '.');\n                        commands.push_back(cmd);\n                        turn++;\n                        return;\n                    }\n                }\n            }\n        }\n    };\n\n    for (auto& [dist, si, ti] : tasks) {\n        if (start_done[si] || target_done[ti]) continue;\n        Point sp = {start_positions[si].first, start_positions[si].second};\n        Point tp = {target_positions[ti].first, target_positions[ti].second};\n\n        int leaf = leaf_order[0]; // simple: use first leaf for everything\n\n        // go to start\n        try_move_leaf_to(leaf, sp);\n        // pick\n        if (fingertip_positions[leaf] == sp && !holding[leaf] && start_grid[sp.x][sp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = true;\n            start_grid[sp.x][sp.y] = '0';\n            turn++;\n        }\n        // go to target\n        try_move_leaf_to(leaf, tp);\n        // place\n        if (fingertip_positions[leaf] == tp && holding[leaf] && target_grid[tp.x][tp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = false;\n            target_grid[tp.x][tp.y] = '0';\n            placed++;\n            turn++;\n        }\n        start_done[si] = true;\n        target_done[ti] = true;\n    }\n\n    for (auto& s : commands) cout << s << \"\\n\";\n    return 0;\n}\n\nvoid design_tree() {\n    // simple star-like: root + V-1 leaves with length 1..N-1\n    parent.push_back(-1);\n    length_to_parent.push_back(0);\n    children.resize(1);\n    for (int i = 1; i < V; i++) {\n        parent.push_back(0);\n        length_to_parent.push_back(1);\n        children[0].push_back(i);\n        children.push_back({});\n    }\n}\n\nvoid compute_fingertip_positions() {\n    fingertip_positions.resize(parent.size());\n    fingertip_positions[0] = {root_x, root_y};\n    for (int i = 1; i < (int)parent.size(); i++) {\n        int p = parent[i];\n        int len = length_to_parent[i];\n        int dir = angles[i];\n        Point offset = {DX[dir]*len, DY[dir]*len};\n        fingertip_positions[i] = fingertip_positions[p] + offset;\n    }\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_COORD = 100000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<int> mx(N), my(N), sx(N), sy(N);\n    for (int i = 0; i < N; i++) cin >> mx[i] >> my[i];\n    for (int i = 0; i < N; i++) cin >> sx[i] >> sy[i];\n    \n    // Use a coarse grid for initial approximation\n    const int G = 50;\n    int cellW = (MAX_COORD + G - 1) / G;\n    int cellH = (MAX_COORD + G - 1) / G;\n    \n    vector<vector<int>> mGrid(G, vector<int>(G, 0));\n    vector<vector<int>> sGrid(G, vector<int>(G, 0));\n    \n    for (int i = 0; i < N; i++) {\n        mGrid[min(my[i]/cellH, G-1)][min(mx[i]/cellW, G-1)]++;\n        sGrid[min(sy[i]/cellH, G-1)][min(sx[i]/cellW, G-1)]++;\n    }\n    \n    // Value grid\n    vector<vector<int>> val(G, vector<int>(G, 0));\n    for (int i = 0; i < G; i++)\n        for (int j = 0; j < G; j++)\n            val[i][j] = mGrid[i][j] - sGrid[i][j];\n    \n    // 2D prefix sum\n    vector<vector<int>> pref(G + 1, vector<int>(G + 1, 0));\n    for (int i = 0; i < G; i++)\n        for (int j = 0; j < G; j++)\n            pref[i + 1][j + 1] = val[i][j] + pref[i][j + 1] + \n                                 pref[i + 1][j] - pref[i][j];\n    \n    auto getSum = [&](int r1, int c1, int r2, int c2) {\n        return pref[r2 + 1][c2 + 1] - pref[r1][c2 + 1] - \n               pref[r2 + 1][c1] + pref[r1][c1];\n    };\n    \n    // Find best rectangle using 2D maximum subarray\n    int bestVal = -1e9;\n    int br1 = 0, bc1 = 0, br2 = 0, bc2 = 0;\n    \n    for (int r1 = 0; r1 < G; r1++) {\n        vector<int> rowSum(G, 0);\n        for (int r2 = r1; r2 < G; r2++) {\n            for (int c = 0; c < G; c++) rowSum[c] += val[r2][c];\n            \n            int curr = 0, maxSum = -1e9;\n            int cStart = 0, cBest = 0, cEnd = 0;\n            for (int c = 0; c < G; c++) {\n                if (curr <= 0) { curr = rowSum[c]; cStart = c; }\n                else curr += rowSum[c];\n                if (curr > maxSum) { maxSum = curr; cBest = cStart; cEnd = c; }\n            }\n            if (maxSum > bestVal) {\n                bestVal = maxSum;\n                br1 = r1; br2 = r2; bc1 = cBest; bc2 = cEnd;\n            }\n        }\n    }\n    \n    // Convert to coordinates\n    int x1 = bc1 * cellW;\n    int y1 = br1 * cellH;\n    int x2 = min(MAX_COORD, (bc2 + 1) * cellW);\n    int y2 = min(MAX_COORD, (br2 + 1) * cellH);\n    \n    // Simple count function (avoid building large data structures)\n    auto countInRect = [&](int xl, int xr, int yl, int yr) -> pair<int,int> {\n        int m = 0, s = 0;\n        for (int i = 0; i < N; i++) {\n            if (mx[i] >= xl && mx[i] <= xr && my[i] >= yl && my[i] <= yr) m++;\n            if (sx[i] >= xl && sx[i] <= xr && sy[i] >= yl && sy[i] <= yr) s++;\n        }\n        return {m, s};\n    };\n    \n    // Refine boundaries using binary search on sorted coordinates\n    vector<int> uniqX, uniqY;\n    uniqX.push_back(0); uniqX.push_back(MAX_COORD);\n    uniqY.push_back(0); uniqY.push_back(MAX_COORD);\n    for (int i = 0; i < N; i++) {\n        uniqX.push_back(mx[i]); uniqX.push_back(sx[i]);\n        uniqY.push_back(my[i]); uniqY.push_back(sy[i]);\n    }\n    sort(uniqX.begin(), uniqX.end());\n    uniqX.erase(unique(uniqX.begin(), uniqX.end()), uniqX.end());\n    sort(uniqY.begin(), uniqY.end());\n    uniqY.erase(unique(uniqY.begin(), uniqY.end()), uniqY.end());\n    \n    // Limit the number of candidate coordinates for refinement\n    if (uniqX.size() > 1000) {\n        // Keep only a subset: start, end, and every k-th element\n        vector<int> newX;\n        int step = uniqX.size() / 500;\n        for (int i = 0; i < (int)uniqX.size(); i += step) newX.push_back(uniqX[i]);\n        if (newX.back() != uniqX.back()) newX.push_back(uniqX.back());\n        uniqX = newX;\n    }\n    if (uniqY.size() > 1000) {\n        vector<int> newY;\n        int step = uniqY.size() / 500;\n        for (int i = 0; i < (int)uniqY.size(); i += step) newY.push_back(uniqY[i]);\n        if (newY.back() != uniqY.back()) newY.push_back(uniqY.back());\n        uniqY = newY;\n    }\n    \n    auto [curM, curS] = countInRect(x1, x2, y1, y2);\n    int curScore = curM - curS;\n    \n    // Refinement with limited iterations\n    for (int iter = 0; iter < 3; iter++) {\n        bool improved = false;\n        \n        // Left boundary\n        for (int nx : uniqX) {\n            if (nx >= x2) continue;\n            auto [m, s] = countInRect(nx, x2, y1, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                x1 = nx;\n                improved = true;\n                break;\n            }\n        }\n        \n        // Right boundary\n        for (int nx : uniqX) {\n            if (nx <= x1) continue;\n            auto [m, s] = countInRect(x1, nx, y1, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                x2 = nx;\n                improved = true;\n                break;\n            }\n        }\n        \n        // Bottom boundary\n        for (int ny : uniqY) {\n            if (ny >= y2) continue;\n            auto [m, s] = countInRect(x1, x2, ny, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                y1 = ny;\n                improved = true;\n                break;\n            }\n        }\n        \n        // Top boundary\n        for (int ny : uniqY) {\n            if (ny <= y1) continue;\n            auto [m, s] = countInRect(x1, x2, y1, ny);\n            if (m - s > curScore) {\n                curScore = m - s;\n                y2 = ny;\n                improved = true;\n                break;\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Try L-shaped polygons with limited candidate points\n    // Sample a subset of inner corner positions\n    vector<pair<int,int>> innerPoints;\n    int stepX = max(1, (int)uniqX.size() / 30);\n    int stepY = max(1, (int)uniqY.size() / 30);\n    \n    for (int ix = 0; ix < (int)uniqX.size(); ix += stepX) {\n        int cx = uniqX[ix];\n        if (cx <= x1 || cx >= x2) continue;\n        for (int iy = 0; iy < (int)uniqY.size(); iy += stepY) {\n            int cy = uniqY[iy];\n            if (cy <= y1 || cy >= y2) continue;\n            innerPoints.push_back({cx, cy});\n        }\n    }\n    \n    struct Candidate {\n        vector<pair<int,int>> verts;\n        int score;\n    };\n    \n    vector<Candidate> candidates;\n    \n    // Rectangle\n    {\n        Candidate c;\n        c.verts = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n        c.score = curScore;\n        candidates.push_back(c);\n    }\n    \n    // L-shapes\n    for (auto [cx, cy] : innerPoints) {\n        // Bottom-left cut\n        {\n            auto [m1, s1] = countInRect(cx, x2, y1, y2);\n            auto [m2, s2] = countInRect(x1, cx - 1, cy, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x2, cy}, {x2, y2}, {x1, y2}, {x1, y1}, {cx, y1}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n        \n        // Bottom-right cut\n        {\n            auto [m1, s1] = countInRect(x1, cx, y1, y2);\n            auto [m2, s2] = countInRect(cx + 1, x2, cy, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x1, cy}, {x1, y2}, {x2, y2}, {x2, y1}, {cx, y1}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n        \n        // Top-right cut\n        {\n            auto [m1, s1] = countInRect(x1, x2, y1, cy);\n            auto [m2, s2] = countInRect(x1, cx, cy + 1, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x1, cy}, {x1, y1}, {x2, y1}, {x2, y2}, {cx, y2}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n        \n        // Top-left cut\n        {\n            auto [m1, s1] = countInRect(x1, x2, y1, cy);\n            auto [m2, s2] = countInRect(cx, x2, cy + 1, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x2, cy}, {x2, y1}, {x1, y1}, {x1, y2}, {cx, y2}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n    }\n    \n    // Sort by score\n    sort(candidates.begin(), candidates.end(), \n         [](const Candidate& a, const Candidate& b) { return a.score > b.score; });\n    \n    // Pick best valid candidate\n    vector<pair<int,int>> bestVerts;\n    for (auto& cand : candidates) {\n        // Check perimeter\n        long long perim = 0;\n        int sz = cand.verts.size();\n        for (int i = 0; i < sz; i++) {\n            int j = (i + 1) % sz;\n            perim += abs(cand.verts[i].first - cand.verts[j].first) + \n                     abs(cand.verts[i].second - cand.verts[j].second);\n        }\n        if (sz <= 1000 && perim <= 400000) {\n            // Simplify collinear vertices\n            vector<pair<int,int>> simp;\n            for (int i = 0; i < sz; i++) {\n                int prev = (i - 1 + sz) % sz;\n                int next = (i + 1) % sz;\n                bool col = false;\n                if (cand.verts[prev].first == cand.verts[i].first && \n                    cand.verts[i].first == cand.verts[next].first) col = true;\n                if (cand.verts[prev].second == cand.verts[i].second && \n                    cand.verts[i].second == cand.verts[next].second) col = true;\n                if (!col) simp.push_back(cand.verts[i]);\n            }\n            if (simp.size() >= 4) {\n                bestVerts = simp;\n            } else {\n                bestVerts = cand.verts;\n            }\n            break;\n        }\n    }\n    \n    if (bestVerts.empty()) {\n        bestVerts = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n    }\n    \n    // Output\n    cout << bestVerts.size() << \"\\n\";\n    for (auto [x, y] : bestVerts) {\n        cout << x << \" \" << y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int id;\n    long long w, h;\n};\n\nstruct Placement {\n    int p, r, d; // d: 0 for U, 1 for L\n    int b;\n};\n\nint N, T, sigma;\nvector<Rect> rects;\nvector<long long> est_w, est_h;\n\n// Simulate placement\npair<long long, long long> simulate(const vector<Placement>& placements) {\n    vector<tuple<long long, long long, long long, long long, int>> placed; // x, y, w, h, id\n    unordered_map<int, int> id_to_idx;\n    long long max_x = 0, max_y = 0;\n    \n    for (const auto& pl : placements) {\n        long long w = est_w[pl.p];\n        long long h = est_h[pl.p];\n        if (pl.r == 1) swap(w, h);\n        \n        long long x = 0, y = 0;\n        \n        if (pl.d == 0) { // U\n            if (pl.b == -1) {\n                x = 0;\n            } else {\n                auto it = id_to_idx.find(pl.b);\n                if (it != id_to_idx.end()) {\n                    x = get<0>(placed[it->second]) + get<2>(placed[it->second]);\n                }\n            }\n            y = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (x < px + pw && x + w > px) {\n                    y = max(y, py + ph);\n                }\n            }\n        } else { // L\n            if (pl.b == -1) {\n                y = 0;\n            } else {\n                auto it = id_to_idx.find(pl.b);\n                if (it != id_to_idx.end()) {\n                    y = get<1>(placed[it->second]) + get<3>(placed[it->second]);\n                }\n            }\n            x = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (y < py + ph && y + h > py) {\n                    x = max(x, px + pw);\n                }\n            }\n        }\n        \n        id_to_idx[pl.p] = (int)placed.size();\n        placed.emplace_back(x, y, w, h, pl.p);\n        max_x = max(max_x, x + w);\n        max_y = max(max_y, y + h);\n    }\n    \n    return {max_x, max_y};\n}\n\n// Query\npair<long long, long long> query(const vector<Placement>& placements) {\n    cout << placements.size() << \"\\n\";\n    for (const auto& pl : placements) {\n        cout << pl.p << \" \" << pl.r << \" \" << (pl.d == 0 ? \"U\" : \"L\") << \" \" << pl.b << \"\\n\";\n    }\n    cout.flush();\n    long long W, H;\n    cin >> W >> H;\n    return {W, H};\n}\n\n// Greedy best-fit packing\nvector<Placement> greedy_packing(const vector<int>& order, const vector<bool>& rotate) {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long, int>> placed; // x, y, w, h, id\n    unordered_map<int, int> id_to_idx;\n    \n    for (int oi = 0; oi < (int)order.size(); oi++) {\n        int idx = order[oi];\n        long long w = est_w[idx];\n        long long h = est_h[idx];\n        bool rot = rotate[oi];\n        if (rot) swap(w, h);\n        \n        struct Option {\n            Placement p;\n            long long x, y, new_W, new_H;\n        };\n        \n        Option best;\n        best.new_W = LLONG_MAX;\n        best.new_H = LLONG_MAX;\n        \n        // Helper to evaluate\n        auto evaluate = [&](Placement p, long long x, long long y) {\n            Option opt;\n            opt.p = p;\n            opt.x = x;\n            opt.y = y;\n            opt.new_W = x + w;\n            opt.new_H = y + h;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                opt.new_W = max(opt.new_W, px + pw);\n                opt.new_H = max(opt.new_H, py + ph);\n            }\n            return opt;\n        };\n        \n        // U with b=-1\n        {\n            long long x = 0, y = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (x < px + pw && x + w > px) y = max(y, py + ph);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 0; p.b = -1;\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        // U with reference to placed\n        for (int pi = 0; pi < (int)placed.size(); pi++) {\n            long long x = get<0>(placed[pi]) + get<2>(placed[pi]);\n            long long y = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (x < px + pw && x + w > px) y = max(y, py + ph);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 0; p.b = get<4>(placed[pi]);\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        // L with b=-1\n        {\n            long long y = 0, x = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (y < py + ph && y + h > py) x = max(x, px + pw);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 1; p.b = -1;\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        // L with reference to placed\n        for (int pi = 0; pi < (int)placed.size(); pi++) {\n            long long y = get<1>(placed[pi]) + get<3>(placed[pi]);\n            long long x = 0;\n            for (const auto& [px, py, pw, ph, pid] : placed) {\n                if (y < py + ph && y + h > py) x = max(x, px + pw);\n            }\n            Placement p;\n            p.p = idx; p.r = rot ? 1 : 0; p.d = 1; p.b = get<4>(placed[pi]);\n            auto opt = evaluate(p, x, y);\n            if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n        }\n        \n        placements.push_back(best.p);\n        placed.emplace_back(best.x, best.y, w, h, idx);\n        id_to_idx[idx] = (int)placed.size() - 1;\n    }\n    \n    return placements;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> T >> sigma;\n    rects.resize(N);\n    est_w.resize(N);\n    est_h.resize(N);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> rects[i].w >> rects[i].h;\n        rects[i].id = i;\n        est_w[i] = rects[i].w;\n        est_h[i] = rects[i].h;\n    }\n    \n    // Generate diverse strategies\n    vector<pair<vector<int>, vector<bool>>> strategies;\n    \n    // Different sortings\n    vector<pair<string, function<bool(int,int)>>> sortings = {\n        {\"area_desc\", [&](int a, int b) { return est_w[a]*est_h[a] > est_w[b]*est_h[b]; }},\n        {\"maxdim_desc\", [&](int a, int b) { return max(est_w[a],est_h[a]) > max(est_w[b],est_h[b]); }},\n        {\"sum_desc\", [&](int a, int b) { return est_w[a]+est_h[a] > est_w[b]+est_h[b]; }},\n        {\"width_desc\", [&](int a, int b) { return est_w[a] > est_w[b]; }},\n        {\"height_desc\", [&](int a, int b) { return est_h[a] > est_h[b]; }},\n        {\"mindim_desc\", [&](int a, int b) { return min(est_w[a],est_h[a]) > min(est_w[b],est_h[b]); }},\n    };\n    \n    // For each sorting, try two rotation strategies\n    for (auto& [name, cmp] : sortings) {\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), cmp);\n        \n        // Rotation: make width >= height (landscape)\n        {\n            vector<bool> rot(N, false);\n            for (int i = 0; i < N; i++) {\n                if (est_h[order[i]] > est_w[order[i]]) rot[i] = true;\n            }\n            strategies.push_back({order, rot});\n        }\n        \n        // Rotation: make height >= width (portrait)\n        {\n            vector<bool> rot(N, false);\n            for (int i = 0; i < N; i++) {\n                if (est_w[order[i]] > est_h[order[i]]) rot[i] = true;\n            }\n            strategies.push_back({order, rot});\n        }\n        \n        // No rotation\n        {\n            vector<bool> rot(N, false);\n            strategies.push_back({order, rot});\n        }\n        \n        // All rotated\n        {\n            vector<bool> rot(N, true);\n            strategies.push_back({order, rot});\n        }\n    }\n    \n    // Shuffle strategies for diversity\n    mt19937 rng(42);\n    shuffle(strategies.begin(), strategies.end(), rng);\n    \n    // Track best\n    long long best_score = LLONG_MAX;\n    \n    auto time_limit = chrono::milliseconds(2900);\n    \n    for (int turn = 0; turn < T; turn++) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time);\n        if (elapsed > time_limit) break;\n        \n        auto& [order, rot] = strategies[turn % strategies.size()];\n        \n        // Maybe add some perturbation in later turns\n        vector<int> perturbed_order = order;\n        vector<bool> perturbed_rot = rot;\n        \n        if (turn >= (int)strategies.size()) {\n            // Add small random perturbations\n            for (int i = 0; i < min(5, N); i++) {\n                int a = rng() % N;\n                int b = rng() % N;\n                swap(perturbed_order[a], perturbed_order[b]);\n            }\n            for (int i = 0; i < min(3, N); i++) {\n                perturbed_rot[rng() % N] = !perturbed_rot[rng() % N];\n            }\n        }\n        \n        vector<Placement> placements = greedy_packing(perturbed_order, perturbed_rot);\n        auto [W, H] = query(placements);\n        \n        long long score = W + H;\n        if (score < best_score) {\n            best_score = score;\n        }\n    }\n    \n    return 0;\n}","ahc041":"#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, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<pair<int,int>> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].first >> edges[i].second;\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n    }\n\n    vector<vector<int>> adj(N);\n    for (auto &e : edges) {\n        adj[e.first].push_back(e.second);\n        adj[e.second].push_back(e.first);\n    }\n\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n\n    // Function to compute depths from parent array, returns false if cycle or height > H\n    auto compute_depths = [&]() -> bool {\n        vector<int> indeg(N, 0);\n        for (int i = 0; i < N; ++i) if (parent[i] != -1) indeg[parent[i]]++;\n        queue<int> q;\n        for (int i = 0; i < N; ++i) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            } else {\n                depth[i] = -1;\n            }\n        }\n        int cnt = 0;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            cnt++;\n            if (depth[v] > H) return false;\n            for (int nb : adj[v]) {\n                if (parent[nb] == v) {\n                    depth[nb] = depth[v] + 1;\n                    q.push(nb);\n                }\n            }\n        }\n        return cnt == N; // if not all visited, there is a cycle\n    };\n\n    // Initially all roots, valid\n    // Try to increase depth greedily\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    mt19937 rng(random_device{}());\n\n    for (int iter = 0; iter < 10; ++iter) {\n        shuffle(order.begin(), order.end(), rng);\n        for (int u : order) {\n            int old_p = parent[u];\n            int old_d = depth[u];\n            long long best_gain = 0;\n            int best_p = old_p;\n            for (int p : adj[u]) {\n                if (p == u) continue;\n                if (depth[p] + 1 > H) continue;\n                // Temporarily set parent and check validity\n                parent[u] = p;\n                if (compute_depths()) {\n                    long long gain = (depth[u] - old_d) * 1LL * A[u];\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_p = p;\n                    }\n                }\n                // revert\n                parent[u] = old_p;\n                compute_depths(); // restore depths\n            }\n            if (best_p != old_p) {\n                parent[u] = best_p;\n                compute_depths();\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    int N;\n    cin >> N;\n    vector<string> board(N);\n    for (int i = 0; i < N; ++i) cin >> board[i];\n\n    vector<pair<int,int>> oni;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (board[i][j] == 'x') oni.push_back({i, j});\n\n    struct Move {\n        char d;\n        int p;\n        int steps;\n    };\n    vector<Move> moves;\n\n    // Process each Oni independently (simple + safe)\n    for (auto [i, j] : oni) {\n        // Check up\n        bool up_ok = true;\n        for (int k = 0; k < i; ++k) if (board[k][j] == 'o') up_ok = false;\n        // Check down\n        bool down_ok = true;\n        for (int k = i+1; k < N; ++k) if (board[k][j] == 'o') down_ok = false;\n        // Check left\n        bool left_ok = true;\n        for (int k = 0; k < j; ++k) if (board[i][k] == 'o') left_ok = false;\n        // Check right\n        bool right_ok = true;\n        for (int k = j+1; k < N; ++k) if (board[i][k] == 'o') right_ok = false;\n\n        int best_dist = 1e9;\n        char best_dir = 0;\n        if (up_ok && i+1 < best_dist) { best_dist = i+1; best_dir = 'U'; }\n        if (down_ok && N-i < best_dist) { best_dist = N-i; best_dir = 'D'; }\n        if (left_ok && j+1 < best_dist) { best_dist = j+1; best_dir = 'L'; }\n        if (right_ok && N-j < best_dist) { best_dist = N-j; best_dir = 'R'; }\n\n        // Perform removal\n        if (best_dir == 'U') {\n            for (int s = 0; s < i+1; ++s) {\n                moves.push_back({'U', j, 1});\n                // update board\n                char removed = board[0][j];\n                for (int r = 0; r < N-1; ++r) board[r][j] = board[r+1][j];\n                board[N-1][j] = removed;\n            }\n            for (int s = 0; s < i+1; ++s) {\n                moves.push_back({'D', j, 1});\n                char removed = board[N-1][j];\n                for (int r = N-1; r > 0; --r) board[r][j] = board[r-1][j];\n                board[0][j] = removed;\n            }\n        } else if (best_dir == 'D') {\n            for (int s = 0; s < N-i; ++s) {\n                moves.push_back({'D', j, 1});\n                char removed = board[N-1][j];\n                for (int r = N-1; r > 0; --r) board[r][j] = board[r-1][j];\n                board[0][j] = removed;\n            }\n            for (int s = 0; s < N-i; ++s) {\n                moves.push_back({'U', j, 1});\n                char removed = board[0][j];\n                for (int r = 0; r < N-1; ++r) board[r][j] = board[r+1][j];\n                board[N-1][j] = removed;\n            }\n        } else if (best_dir == 'L') {\n            for (int s = 0; s < j+1; ++s) {\n                moves.push_back({'L', i, 1});\n                char removed = board[i][0];\n                for (int c = 0; c < N-1; ++c) board[i][c] = board[i][c+1];\n                board[i][N-1] = removed;\n            }\n            for (int s = 0; s < j+1; ++s) {\n                moves.push_back({'R', i, 1});\n                char removed = board[i][N-1];\n                for (int c = N-1; c > 0; --c) board[i][c] = board[i][c-1];\n                board[i][0] = removed;\n            }\n        } else if (best_dir == 'R') {\n            for (int s = 0; s < N-j; ++s) {\n                moves.push_back({'R', i, 1});\n                char removed = board[i][N-1];\n                for (int c = N-1; c > 0; --c) board[i][c] = board[i][c-1];\n                board[i][0] = removed;\n            }\n            for (int s = 0; s < N-j; ++s) {\n                moves.push_back({'L', i, 1});\n                char removed = board[i][0];\n                for (int c = 0; c < N-1; ++c) board[i][c] = board[i][c+1];\n                board[i][N-1] = removed;\n            }\n        }\n    }\n\n    // Output moves\n    for (auto &mv : moves) {\n        cout << mv.d << ' ' << mv.p << '\\n';\n    }\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nint a[N], b[N];\nint best_a[N], best_b[N];\nint cnt[N];\nlong long best_error;\n\nvoid simulate() {\n    memset(cnt, 0, sizeof(cnt));\n    int cur = 0;\n    for (int week = 0; week < L; ++week) {\n        cnt[cur]++;\n        if (cnt[cur] % 2 == 1) {\n            cur = a[cur];\n        } else {\n            cur = b[cur];\n        }\n    }\n}\n\nlong long calc_error() {\n    long long 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    // Read input\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Initialize with round-robin\n    for (int i = 0; i < N; ++i) {\n        a[i] = (i + 1) % N;\n        b[i] = (i + 1) % N;\n    }\n\n    simulate();\n    best_error = calc_error();\n    memcpy(best_a, a, sizeof(a));\n    memcpy(best_b, b, sizeof(b));\n\n    auto start_time = steady_clock::now();\n    const double time_limit = 1.9; // seconds\n    mt19937 rng(42);\n    uniform_int_distribution<int> rand_emp(0, N-1);\n    uniform_real_distribution<double> rand_real(0.0, 1.0);\n\n    double temp = 1000.0;\n    long long current_error = best_error;\n    int iter = 0;\n\n    while (true) {\n        auto now = steady_clock::now();\n        double elapsed = duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n\n        // Save current state\n        int old_a[N], old_b[N];\n        memcpy(old_a, a, sizeof(a));\n        memcpy(old_b, b, sizeof(b));\n        int old_cnt[N];\n        memcpy(old_cnt, cnt, sizeof(cnt));\n\n        // Random modification\n        int i = rand_emp(rng);\n        if (rand_real(rng) < 0.5) {\n            a[i] = rand_emp(rng);\n        } else {\n            b[i] = rand_emp(rng);\n        }\n\n        simulate();\n        long long new_error = calc_error();\n\n        double prob = exp((current_error - new_error) / temp);\n        if (new_error < current_error || rand_real(rng) < prob) {\n            current_error = new_error;\n            if (new_error < best_error) {\n                best_error = new_error;\n                memcpy(best_a, a, sizeof(a));\n                memcpy(best_b, b, sizeof(b));\n            }\n        } else {\n            // Revert\n            memcpy(a, old_a, sizeof(a));\n            memcpy(b, old_b, sizeof(b));\n            memcpy(cnt, old_cnt, sizeof(cnt));\n        }\n\n        temp *= 0.99999;\n        ++iter;\n    }\n\n    // Output best found\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Union-Find\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        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    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    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // Compute rectangle centers as estimated positions\n    vector<long long> estX(N), estY(N);\n    for (int i = 0; i < N; i++) {\n        estX[i] = (lx[i] + rx[i]) / 2;\n        estY[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Sort city indices by center coordinates\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (estX[a] != estX[b]) return estX[a] < estX[b];\n        return estY[a] < estY[b];\n    });\n\n    // Partition into groups\n    vector<vector<int>> groups(M);\n    int idx = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < G[i]; j++) {\n            groups[i].push_back(order[idx++]);\n        }\n    }\n\n    // Store final edges per group\n    vector<vector<pair<int,int>>> final_edges(M);\n\n    // DSU per group for connectivity during construction\n    vector<DSU> dsu;\n    dsu.reserve(M);\n    for (int i = 0; i < M; i++) {\n        dsu.emplace_back(G[i]);\n    }\n\n    // Used queries counter\n    int queries_used = 0;\n\n    // For each group, use queries to get edges\n    for (int i = 0; i < M; i++) {\n        int sz = G[i];\n        if (sz <= 2) {\n            // Group size 2: no query possible or needed, just connect directly\n            if (sz == 2) {\n                final_edges[i].emplace_back(0, 1);\n                dsu[i].unite(0, 1);\n            }\n            continue;\n        }\n\n        // Sliding window queries of size up to L\n        int step = L - 1; // overlap 1 city between windows\n        for (int start = 0; start + 1 < sz && queries_used < Q; start += step) {\n            int end = min(start + L, sz);\n            if (end - start < 2) break; // need at least 2 cities\n\n            // Build query\n            vector<int> subset;\n            for (int j = start; j < end; j++) {\n                subset.push_back(groups[i][j]);\n            }\n            int l = subset.size();\n            cout << \"? \" << l;\n            for (int c : subset) cout << \" \" << c;\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n\n            // Read response\n            for (int j = 0; j < l - 1; j++) {\n                int a, b;\n                cin >> a >> b;\n                // Find local indices in group\n                auto ita = find(subset.begin(), subset.end(), a);\n                auto itb = find(subset.begin(), subset.end(), b);\n                int idx_a = start + distance(subset.begin(), ita);\n                int idx_b = start + distance(subset.begin(), itb);\n                // Add edge to final if it connects new components\n                if (dsu[i].unite(idx_a, idx_b)) {\n                    final_edges[i].emplace_back(idx_a, idx_b);\n                }\n            }\n        }\n    }\n\n    // End queries\n    cout << \"!\\n\";\n    cout.flush();\n\n    // For groups still not fully connected, add edges based on estimated distances\n    for (int i = 0; i < M; i++) {\n        int sz = G[i];\n        if (sz <= 1) continue;\n        // Collect components\n        unordered_map<int, vector<int>> comps;\n        for (int j = 0; j < sz; j++) {\n            comps[dsu[i].find(j)].push_back(j);\n        }\n        if (comps.size() == 1) continue; // already connected\n\n        // Build list of all possible edges between different components\n        vector<tuple<long long, int, int>> cand_edges;\n        vector<int> comp_keys;\n        for (auto &kv : comps) comp_keys.push_back(kv.first);\n        for (size_t ci = 0; ci < comp_keys.size(); ci++) {\n            for (size_t cj = ci + 1; cj < comp_keys.size(); cj++) {\n                for (int u : comps[comp_keys[ci]]) {\n                    for (int v : comps[comp_keys[cj]]) {\n                        long long dx = estX[groups[i][u]] - estX[groups[i][v]];\n                        long long dy = estY[groups[i][u]] - estY[groups[i][v]];\n                        long long dist = dx*dx + dy*dy; // squared distance for ordering\n                        cand_edges.emplace_back(dist, u, v);\n                    }\n                }\n            }\n        }\n        sort(cand_edges.begin(), cand_edges.end());\n\n        // Kruskal-like addition\n        for (auto &e : cand_edges) {\n            int u = get<1>(e), v = get<2>(e);\n            if (dsu[i].unite(u, v)) {\n                final_edges[i].emplace_back(u, v);\n            }\n            if (comps.size() == 1) break; // actually comps count won't update dynamically here; just loop til enough edges\n        }\n    }\n\n    // Output final answer\n    for (int i = 0; i < M; i++) {\n        // Print group cities\n        for (int j = 0; j < G[i]; j++) {\n            if (j) cout << \" \";\n            cout << groups[i][j];\n        }\n        cout << \"\\n\";\n        // Print edges\n        for (auto &e : final_edges[i]) {\n            cout << groups[i][e.first] << \" \" << groups[i][e.second] << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nvector<string> blocks;\nint cur_x, cur_y;\nvector<pair<int,int>> targets;\nvector<pair<char,char>> actions;\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar dirs[4] = {'U', 'D', 'L', 'R'};\n\nbool valid(int x, int y) { return x>=0 && x<N && y>=0 && y<N; }\n\nvoid add_action(char type, char dir) {\n    actions.push_back({type, dir});\n}\n\npair<int,int> slide_dest(int x, int y, char d) {\n    int dir_idx = string(\"UDLR\").find(d);\n    while (true) {\n        int nx = x + dx[dir_idx];\n        int ny = y + dy[dir_idx];\n        if (!valid(nx, ny)) break;\n        if (blocks[nx][ny] == '#') break;\n        x = nx; y = ny;\n    }\n    return {x, y};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    blocks.assign(N, string(N, '.'));\n    targets.resize(M);\n    for (int i=0;i<M;++i) cin >> targets[i].first >> targets[i].second;\n\n    cur_x = targets[0].first;\n    cur_y = targets[0].second;\n\n    // Place border blocks: we'll move to each border cell and place block inward? Actually we can alter from adjacent.\n    // But easier: we don't need to place border since sliding stops at invalid squares (outside grid) automatically!\n    // Yes: \"Continue sliding in the specified direction until you hit a block.\" and outside squares are blocks.\n    // So sliding stops at border without placing anything. Great!\n\n    for (int t=1; t<M; ++t) {\n        int tx = targets[t].first, ty = targets[t].second;\n        // Try to slide to align row or column\n        // If same row, slide horizontally\n        if (cur_x == tx) {\n            if (cur_y < ty) {\n                auto dest = slide_dest(cur_x, cur_y, 'R');\n                if (dest.second >= ty) {\n                    add_action('S', 'R');\n                    cur_y = dest.second;\n                }\n            } else if (cur_y > ty) {\n                auto dest = slide_dest(cur_x, cur_y, 'L');\n                if (dest.second <= ty) {\n                    add_action('S', 'L');\n                    cur_y = dest.second;\n                }\n            }\n        }\n        // If same col, slide vertically\n        if (cur_y == ty) {\n            if (cur_x < tx) {\n                auto dest = slide_dest(cur_x, cur_y, 'D');\n                if (dest.first >= tx) {\n                    add_action('S', 'D');\n                    cur_x = dest.first;\n                }\n            } else if (cur_x > tx) {\n                auto dest = slide_dest(cur_x, cur_y, 'U');\n                if (dest.first <= tx) {\n                    add_action('S', 'U');\n                    cur_x = dest.first;\n                }\n            }\n        }\n        // Move remaining distance\n        while (cur_x != tx || cur_y != ty) {\n            if (cur_x < tx) { add_action('M', 'D'); cur_x++; }\n            else if (cur_x > tx) { add_action('M', 'U'); cur_x--; }\n            else if (cur_y < ty) { add_action('M', 'R'); cur_y++; }\n            else if (cur_y > ty) { add_action('M', 'L'); cur_y--; }\n        }\n    }\n\n    for (auto &a : actions) cout << a.first << ' ' << a.second << '\\n';\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y, r, id;\n};\n\nint n;\nvector<Point> pts;\nvector<Rect> ans;\n\n// Recursive slicing with better splitting strategy\nvoid solve(int x1, int y1, int x2, int y2, vector<int> idxs) {\n    if (idxs.empty()) return;\n    if (idxs.size() == 1) {\n        ans[idxs[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    long long totalArea = 1LL * (x2 - x1) * (y2 - y1);\n    long long sumR = 0;\n    for (int i : idxs) sumR += pts[i].r;\n\n    // Try both dimensions with better scoring\n    struct Candidate {\n        double score;\n        int splitPos;\n        int dim; // 0 for x, 1 for y\n        vector<int> left, right;\n    };\n    vector<Candidate> cands;\n\n    // Split by x\n    sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n    for (int k = 0; k < (int)idxs.size() - 1; k++) {\n        // Split between k and k+1\n        int x_left_pt = pts[idxs[k]].x;\n        int x_right_pt = pts[idxs[k+1]].x;\n        // Ensure valid split\n        if (x_left_pt >= x_right_pt) continue;\n        // Try different split positions\n        for (int splitX = x_left_pt + 1; splitX <= x_right_pt && splitX < x2; splitX++) {\n            if (splitX <= x1) continue;\n            long long leftArea = 1LL * (splitX - x1) * (y2 - y1);\n            long long rightArea = 1LL * (x2 - splitX) * (y2 - y1);\n            long long leftR = 0;\n            for (int i = 0; i <= k; i++) leftR += pts[idxs[i]].r;\n            long long rightR = sumR - leftR;\n            \n            // Score: prefer proportional area allocation\n            double leftRatio = (double)leftArea / totalArea;\n            double targetRatio = (double)leftR / sumR;\n            double score = 1.0 - fabs(leftRatio - targetRatio) * 10.0;\n            \n            vector<int> left(idxs.begin(), idxs.begin() + k + 1);\n            vector<int> right(idxs.begin() + k + 1, idxs.end());\n            cands.push_back({score, splitX, 0, left, right});\n        }\n    }\n\n    // Split by y\n    sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n    for (int k = 0; k < (int)idxs.size() - 1; k++) {\n        int y_bottom_pt = pts[idxs[k]].y;\n        int y_top_pt = pts[idxs[k+1]].y;\n        if (y_bottom_pt >= y_top_pt) continue;\n        for (int splitY = y_bottom_pt + 1; splitY <= y_top_pt && splitY < y2; splitY++) {\n            if (splitY <= y1) continue;\n            long long bottomArea = 1LL * (x2 - x1) * (splitY - y1);\n            long long topArea = 1LL * (x2 - x1) * (y2 - splitY);\n            long long bottomR = 0;\n            for (int i = 0; i <= k; i++) bottomR += pts[idxs[i]].r;\n            long long topR = sumR - bottomR;\n            \n            double bottomRatio = (double)bottomArea / totalArea;\n            double targetRatio = (double)bottomR / sumR;\n            double score = 1.0 - fabs(bottomRatio - targetRatio) * 10.0;\n            \n            vector<int> bottom(idxs.begin(), idxs.begin() + k + 1);\n            vector<int> top(idxs.begin() + k + 1, idxs.end());\n            cands.push_back({score, splitY, 1, bottom, top});\n        }\n    }\n\n    if (cands.empty()) {\n        // Fallback: assign all to first point (shouldn't happen)\n        ans[idxs[0]] = {x1, y1, x2, y2};\n        return;\n    }\n\n    // Pick best candidate\n    sort(cands.begin(), cands.end(), [](const Candidate& a, const Candidate& b) {\n        return a.score > b.score;\n    });\n\n    // Try top few candidates and pick one that doesn't create degenerate rectangles\n    for (auto& cand : cands) {\n        if (cand.dim == 0) {\n            if (cand.splitPos - x1 < 1 || x2 - cand.splitPos < 1) continue;\n            solve(x1, y1, cand.splitPos, y2, cand.left);\n            solve(cand.splitPos, y1, x2, y2, cand.right);\n            return;\n        } else {\n            if (cand.splitPos - y1 < 1 || y2 - cand.splitPos < 1) continue;\n            solve(x1, y1, x2, cand.splitPos, cand.left);\n            solve(x1, cand.splitPos, x2, y2, cand.right);\n            return;\n        }\n    }\n    \n    // If all failed, use the first valid one\n    for (auto& cand : cands) {\n        if (cand.dim == 0) {\n            if (cand.splitPos > x1 && cand.splitPos < x2) {\n                solve(x1, y1, cand.splitPos, y2, cand.left);\n                solve(cand.splitPos, y1, x2, y2, cand.right);\n                return;\n            }\n        } else {\n            if (cand.splitPos > y1 && cand.splitPos < y2) {\n                solve(x1, y1, x2, cand.splitPos, cand.left);\n                solve(x1, cand.splitPos, x2, y2, cand.right);\n                return;\n            }\n        }\n    }\n    \n    // Ultimate fallback\n    ans[idxs[0]] = {x1, y1, x2, y2};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n;\n    pts.resize(n);\n    ans.resize(n);\n    for (int i = 0; i < n; i++) {\n        cin >> pts[i].x >> pts[i].y >> pts[i].r;\n        pts[i].id = i;\n    }\n    \n    vector<int> all(n);\n    iota(all.begin(), all.end(), 0);\n    solve(0, 0, 10000, 10000, all);\n    \n    for (int i = 0; i < n; i++) {\n        cout << ans[i].a << \" \" << ans[i].b << \" \" << ans[i].c << \" \" << ans[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <bitset>\n#include <queue>\n#include <chrono>\n\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_TILES = 2500;\nconst int BEAM_WIDTH = 200;\nconst int CAND_WIDTH = 1000;   // number of candidates for which we compute full potential\nconst int MAX_DEPTH = 2500;\n\nstruct State {\n    int score;\n    int est_score;          // final estimated score (score + full_potential)\n    short i, j;             // current square\n    bitset<MAX_TILES> visited;\n    int prev_idx;\n    char move_char;\n};\n\nint si, sj;\nint tile_id[N][N];\nint p[N][N];\nint M;\nint max_p[MAX_TILES];\nint tile_adj[MAX_TILES][4]; // at most 4 neighbours\nint tile_deg[MAX_TILES];\nint bfs_tag[MAX_TILES];\nint current_bfs_tag = 0;\n\n// Quick heuristic: sum of max_p of unvisited neighbouring tiles\nint quick_heuristic(const State& st) {\n    int t = tile_id[st.i][st.j];\n    int sum = 0;\n    for (int k = 0; k < tile_deg[t]; ++k) {\n        int v = tile_adj[t][k];\n        if (!st.visited[v]) sum += max_p[v];\n    }\n    return sum;\n}\n\n// Full heuristic: sum of max_p of all unvisited tiles reachable from current tile\nint full_potential(const State& st) {\n    current_bfs_tag++;\n    int start_tile = tile_id[st.i][st.j];\n    queue<int> q;\n    int pot = 0;\n    // start from unvisited neighbours\n    for (int k = 0; k < tile_deg[start_tile]; ++k) {\n        int v = tile_adj[start_tile][k];\n        if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n            bfs_tag[v] = current_bfs_tag;\n            q.push(v);\n            pot += max_p[v];\n        }\n    }\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (int k = 0; k < tile_deg[u]; ++k) {\n            int v = tile_adj[u][k];\n            if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n                bfs_tag[v] = current_bfs_tag;\n                q.push(v);\n                pot += max_p[v];\n            }\n        }\n    }\n    return pot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(1950);\n\n    cin >> si >> sj;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    // Number of tiles\n    M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (tile_id[i][j] >= M) M = tile_id[i][j] + 1;\n\n    // max_p for each tile\n    for (int t = 0; t < M; ++t) max_p[t] = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            if (p[i][j] > max_p[t]) max_p[t] = p[i][j];\n        }\n\n    // Build inter-tile adjacency (compact arrays)\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int nt = tile_id[ni][nj];\n                    if (nt != t) {\n                        // add if not already present\n                        bool exists = false;\n                        for (int idx = 0; idx < tile_deg[t]; ++idx) {\n                            if (tile_adj[t][idx] == nt) { exists = true; break; }\n                        }\n                        if (!exists) tile_adj[t][tile_deg[t]++] = nt;\n                    }\n                }\n            }\n        }\n    }\n\n    // Initial state\n    State init;\n    init.score = p[si][sj];\n    init.i = si; init.j = sj;\n    init.visited.reset();\n    init.visited[tile_id[si][sj]] = 1;\n    init.prev_idx = -1;\n    init.est_score = init.score + full_potential(init);\n\n    vector<State> beam;\n    beam.push_back(init);\n    vector<vector<State>> beam_history;\n    beam_history.push_back(beam);\n\n    int best_score = init.score;\n    int best_depth = 0;\n    int best_state_idx = 0;\n\n    // Beam search\n    for (int depth = 1; depth <= MAX_DEPTH; ++depth) {\n        if (chrono::steady_clock::now() - start_time > time_limit) break;\n\n        // 1. Expand all current beam states\n        vector<State> candidates;\n        for (int s_idx = 0; s_idx < (int)beam.size(); ++s_idx) {\n            const State& st = beam[s_idx];\n            short i = st.i, j = st.j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nt = tile_id[ni][nj];\n                if (nt == tile_id[i][j] || st.visited[nt]) continue;\n\n                State nxt = st;\n                nxt.i = ni; nxt.j = nj;\n                nxt.score += p[ni][nj];\n                nxt.visited[nt] = 1;\n                nxt.prev_idx = s_idx;\n                nxt.move_char = (k == 0 ? 'U' : (k == 1 ? 'D' : (k == 2 ? 'L' : 'R')));\n                nxt.est_score = nxt.score + quick_heuristic(nxt); // temporary\n                candidates.push_back(move(nxt));\n            }\n        }\n        if (candidates.empty()) break;\n\n        // 2. Sort by temporary est_score (quick heuristic) and keep top CAND_WIDTH\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)candidates.size() > CAND_WIDTH)\n            candidates.resize(CAND_WIDTH);\n\n        // 3. Compute full potential for the selected candidates\n        for (State& st : candidates) {\n            st.est_score = st.score + full_potential(st);\n        }\n\n        // 4. Final sorting and pruning to BEAM_WIDTH\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)candidates.size() > BEAM_WIDTH)\n            candidates.resize(BEAM_WIDTH);\n\n        if (candidates[0].score > best_score) {\n            best_score = candidates[0].score;\n            best_depth = depth;\n            best_state_idx = 0;\n        }\n\n        beam = move(candidates);\n        beam_history.push_back(beam);\n    }\n\n    // Global best\n    for (int d = 0; d < (int)beam_history.size(); ++d) {\n        for (int idx = 0; idx < (int)beam_history[d].size(); ++idx) {\n            if (beam_history[d][idx].score > best_score) {\n                best_score = beam_history[d][idx].score;\n                best_depth = d;\n                best_state_idx = idx;\n            }\n        }\n    }\n\n    // Reconstruct path\n    string path;\n    int cur_depth = best_depth;\n    int cur_idx = best_state_idx;\n    while (cur_depth > 0) {\n        const State& st = beam_history[cur_depth][cur_idx];\n        path.push_back(st.move_char);\n        cur_idx = st.prev_idx;\n        --cur_depth;\n    }\n    reverse(path.begin(), path.end());\n\n    // Simulate and then greedily extend\n    {\n        vector<bool> used_tile(M, false);\n        int ci = si, cj = sj;\n        used_tile[tile_id[ci][cj]] = true;\n        for (char c : path) {\n            int k = (c == 'U' ? 0 : (c == 'D' ? 1 : (c == 'L' ? 2 : 3)));\n            ci += di[k]; cj += dj[k];\n            used_tile[tile_id[ci][cj]] = true;\n        }\n        // Greedy extension from the end\n        string extra;\n        while (true) {\n            int best_ni = -1, best_nj = -1, best_val = -1;\n            char best_move = 0;\n            for (int k = 0; k < 4; ++k) {\n                int ni = ci + di[k], nj = cj + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nt = tile_id[ni][nj];\n                if (nt == tile_id[ci][cj] || used_tile[nt]) continue;\n                if (p[ni][nj] > best_val) {\n                    best_val = p[ni][nj];\n                    best_ni = ni; best_nj = nj;\n                    best_move = \"UDLR\"[k];\n                }\n            }\n            if (best_ni == -1) break;\n            extra.push_back(best_move);\n            used_tile[tile_id[best_ni][best_nj]] = true;\n            ci = best_ni; cj = best_nj;\n        }\n        path += extra;\n    }\n\n    cout << path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr double INF = 1e18;\n\nstruct EdgeModel {\n    // Horizontal edges: (i,j) - (i,j+1)\n    double row_base[N];\n    double row_split_val[N];\n    int row_split_idx[N];\n    double row_confidence[N]; // How confident in our estimates\n    \n    // Vertical edges: (i,j) - (i+1,j)\n    double col_base[N];\n    double col_split_val[N];\n    int col_split_idx[N];\n    double col_confidence[N];\n    \n    // Local variations\n    double local_H[N][N-1];\n    double local_V[N-1][N];\n    \n    // Statistics\n    int cnt_H[N][N-1];\n    int cnt_V[N-1][N];\n    \n    // For tracking variance per row/col\n    double sum_sq_H[N];\n    double sum_sq_V[N];\n    int n_samples_H[N];\n    int n_samples_V[N];\n    \n    // Track which rows/cols have been explored\n    bool row_explored[N];\n    bool col_explored[N];\n    \n    EdgeModel() {\n        for (int i = 0; i < N; i++) {\n            row_base[i] = 5000.0;\n            row_split_val[i] = 0.0;\n            row_split_idx[i] = -1;\n            row_confidence[i] = 0.0;\n            \n            col_base[i] = 5000.0;\n            col_split_val[i] = 0.0;\n            col_split_idx[i] = -1;\n            col_confidence[i] = 0.0;\n            \n            sum_sq_H[i] = 0.0;\n            sum_sq_V[i] = 0.0;\n            n_samples_H[i] = 0;\n            n_samples_V[i] = 0;\n            \n            row_explored[i] = false;\n            col_explored[i] = false;\n        }\n        \n        memset(local_H, 0, sizeof(local_H));\n        memset(local_V, 0, sizeof(local_V));\n        memset(cnt_H, 0, sizeof(cnt_H));\n        memset(cnt_V, 0, sizeof(cnt_V));\n    }\n    \n    inline double get_H(int i, int j) const {\n        double val = row_base[i] + local_H[i][j];\n        if (row_split_idx[i] >= 0 && j >= row_split_idx[i]) {\n            val += row_split_val[i];\n        }\n        return max(100.0, min(10000.0, val));\n    }\n    \n    inline double get_V(int i, int j) const {\n        double val = col_base[j] + local_V[i][j];\n        if (col_split_idx[j] >= 0 && i >= col_split_idx[j]) {\n            val += col_split_val[j];\n        }\n        return max(100.0, min(10000.0, val));\n    }\n    \n    double get_H_uncertainty(int i) const {\n        if (n_samples_H[i] < 2) return 2000.0;\n        return sqrt(sum_sq_H[i] / n_samples_H[i]);\n    }\n    \n    double get_V_uncertainty(int j) const {\n        if (n_samples_V[j] < 2) return 2000.0;\n        return sqrt(sum_sq_V[j] / n_samples_V[j]);\n    }\n    \n    int total_visited_H() const {\n        int total = 0;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N-1; j++)\n                total += cnt_H[i][j];\n        return total;\n    }\n    \n    int total_visited_V() const {\n        int total = 0;\n        for (int i = 0; i < N-1; i++)\n            for (int j = 0; j < N; j++)\n                total += cnt_V[i][j];\n        return total;\n    }\n};\n\nstruct PathFinder {\n    double dist[N][N];\n    pair<int,int> prev[N][N];\n    \n    vector<pair<int,int>> find_path(int si, int sj, int ti, int tj,\n                                     EdgeModel& model, double explore_bonus,\n                                     int query_idx) {\n        // Reset\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                dist[i][j] = INF;\n        \n        dist[si][sj] = 0;\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({0.0, si, sj});\n        \n        int di[] = {-1, 1, 0, 0};\n        int dj[] = {0, 0, -1, 1};\n        \n        while (!pq.empty()) {\n            auto [d, i, j] = pq.top(); pq.pop();\n            if (d > dist[i][j]) continue;\n            if (i == ti && j == tj) break;\n            \n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double edge_est, edge_uncertainty;\n                bool is_vertical = (k == 0 || k == 1);\n                \n                if (k == 0) { // Up\n                    edge_est = model.get_V(ni, nj);\n                    edge_uncertainty = model.get_V_uncertainty(nj);\n                } else if (k == 1) { // Down\n                    edge_est = model.get_V(i, j);\n                    edge_uncertainty = model.get_V_uncertainty(j);\n                } else if (k == 2) { // Left\n                    edge_est = model.get_H(ni, nj);\n                    edge_uncertainty = model.get_H_uncertainty(ni);\n                } else { // Right\n                    edge_est = model.get_H(i, j);\n                    edge_uncertainty = model.get_H_uncertainty(i);\n                }\n                \n                // Exploration bonus: higher for uncertain edges\n                double bonus = explore_bonus * edge_uncertainty / 2000.0;\n                if (is_vertical) {\n                    bonus /= (1.0 + model.cnt_V[min(i,ni)][j]);\n                } else {\n                    bonus /= (1.0 + model.cnt_H[i][min(j,nj)]);\n                }\n                \n                double nd = d + edge_est + bonus;\n                if (nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i, j};\n                    pq.push({nd, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct\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 [pi, pj] = prev[ci][cj];\n            ci = pi; cj = pj;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n        \n        return path;\n    }\n    \n    double calc_path_length(const vector<pair<int,int>>& path, EdgeModel& model) {\n        double len = 0;\n        for (size_t i = 1; i < path.size(); i++) {\n            auto [a, b] = path[i-1];\n            auto [c, d] = path[i];\n            if (c == a-1) len += model.get_V(c, d);\n            else if (c == a+1) len += model.get_V(a, b);\n            else if (d == b-1) len += model.get_H(c, d);\n            else len += model.get_H(a, b);\n        }\n        return len;\n    }\n};\n\nstring path_to_string(const vector<pair<int,int>>& path) {\n    string s;\n    s.reserve(path.size());\n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        if (c == a-1) s += 'U';\n        else if (c == a+1) s += 'D';\n        else if (d == b-1) s += 'L';\n        else s += 'R';\n    }\n    return s;\n}\n\nvoid update_model(EdgeModel& model, const vector<pair<int,int>>& path,\n                  double observed, double estimated, int query_idx) {\n    if (estimated < 1.0) return;\n    \n    // De-bias: expected noise multiplier is 1.0 (uniform [0.9, 1.1])\n    // No bias correction needed if we assume symmetric noise\n    \n    double ratio = observed / estimated;\n    // Clamp ratio to reasonable bounds to prevent outliers\n    ratio = max(0.5, min(2.0, ratio));\n    \n    // Learning rate: start moderate, decay slowly\n    double lr = 0.4 / (1.0 + query_idx * 0.002);\n    \n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        \n        if (c == a-1) { // Up: vertical edge at (c,d)\n            int idx_i = c, idx_j = d;\n            model.cnt_V[idx_i][idx_j]++;\n            \n            double old_val = model.get_V(idx_i, idx_j);\n            double error = old_val * ratio - old_val;\n            \n            // Update local strongly, base moderately\n            model.local_V[idx_i][idx_j] += lr * 0.7 * error;\n            model.col_base[idx_j] += lr * 0.3 * error;\n            \n            // If split detected, also update split value\n            if (model.col_split_idx[idx_j] >= 0) {\n                if (idx_i >= model.col_split_idx[idx_j]) {\n                    model.col_split_val[idx_j] += lr * 0.1 * error;\n                }\n            }\n            \n            model.sum_sq_V[idx_j] += error * error;\n            model.n_samples_V[idx_j]++;\n        }\n        else if (c == a+1) { // Down: vertical edge at (a,b)\n            int idx_i = a, idx_j = b;\n            model.cnt_V[idx_i][idx_j]++;\n            \n            double old_val = model.get_V(idx_i, idx_j);\n            double error = old_val * ratio - old_val;\n            \n            model.local_V[idx_i][idx_j] += lr * 0.7 * error;\n            model.col_base[idx_j] += lr * 0.3 * error;\n            \n            if (model.col_split_idx[idx_j] >= 0 && idx_i >= model.col_split_idx[idx_j]) {\n                model.col_split_val[idx_j] += lr * 0.1 * error;\n            }\n            \n            model.sum_sq_V[idx_j] += error * error;\n            model.n_samples_V[idx_j]++;\n        }\n        else if (d == b-1) { // Left: horizontal edge at (c,d)\n            int idx_i = c, idx_j = d;\n            model.cnt_H[idx_i][idx_j]++;\n            \n            double old_val = model.get_H(idx_i, idx_j);\n            double error = old_val * ratio - old_val;\n            \n            model.local_H[idx_i][idx_j] += lr * 0.7 * error;\n            model.row_base[idx_i] += lr * 0.3 * error;\n            \n            if (model.row_split_idx[idx_i] >= 0 && idx_j >= model.row_split_idx[idx_i]) {\n                model.row_split_val[idx_i] += lr * 0.1 * error;\n            }\n            \n            model.sum_sq_H[idx_i] += error * error;\n            model.n_samples_H[idx_i]++;\n        }\n        else { // Right: horizontal edge at (a,b)\n            int idx_i = a, idx_j = b;\n            model.cnt_H[idx_i][idx_j]++;\n            \n            double old_val = model.get_H(idx_i, idx_j);\n            double error = old_val * ratio - old_val;\n            \n            model.local_H[idx_i][idx_j] += lr * 0.7 * error;\n            model.row_base[idx_i] += lr * 0.3 * error;\n            \n            if (model.row_split_idx[idx_i] >= 0 && idx_j >= model.row_split_idx[idx_i]) {\n                model.row_split_val[idx_i] += lr * 0.1 * error;\n            }\n            \n            model.sum_sq_H[idx_i] += error * error;\n            model.n_samples_H[idx_i]++;\n        }\n    }\n}\n\nvoid detect_splits(EdgeModel& model, int query_idx) {\n    if (query_idx < 25) return;\n    \n    // Only detect splits every 15 queries to save computation\n    if (query_idx % 15 != 0 && query_idx > 30) return;\n    \n    // Horizontal splits\n    for (int i = 0; i < N; i++) {\n        if (model.row_split_idx[i] >= 0) continue;\n        \n        int visited = 0;\n        for (int j = 0; j < N-1; j++) visited += (model.cnt_H[i][j] > 0);\n        if (visited < 12) continue;\n        \n        double best_t_stat = 2.0; // Minimum t-statistic for significance\n        int best_split = -1;\n        \n        for (int s = 3; s < N-4; s++) {\n            double left_mean = 0, right_mean = 0;\n            double left_var = 0, right_var = 0;\n            int left_n = 0, right_n = 0;\n            \n            for (int j = 0; j < s; j++) {\n                if (model.cnt_H[i][j] > 0) {\n                    double val = model.get_H(i, j);\n                    left_mean += val;\n                    left_var += val * val;\n                    left_n++;\n                }\n            }\n            for (int j = s; j < N-1; j++) {\n                if (model.cnt_H[i][j] > 0) {\n                    double val = model.get_H(i, j);\n                    right_mean += val;\n                    right_var += val * val;\n                    right_n++;\n                }\n            }\n            \n            if (left_n >= 4 && right_n >= 4) {\n                left_mean /= left_n;\n                right_mean /= right_n;\n                left_var = left_var/left_n - left_mean*left_mean;\n                right_var = right_var/right_n - right_mean*right_mean;\n                \n                double se = sqrt(left_var/left_n + right_var/right_n);\n                if (se < 1.0) se = 1.0;\n                double t_stat = fabs(left_mean - right_mean) / se;\n                \n                if (t_stat > best_t_stat) {\n                    best_t_stat = t_stat;\n                    best_split = s;\n                }\n            }\n        }\n        \n        if (best_split >= 0) {\n            model.row_split_idx[i] = best_split;\n            double left_avg = 0, right_avg = 0;\n            int lc = 0, rc = 0;\n            for (int j = 0; j < best_split; j++) {\n                if (model.cnt_H[i][j] > 0) {\n                    left_avg += model.get_H(i, j) - model.local_H[i][j];\n                    lc++;\n                }\n            }\n            for (int j = best_split; j < N-1; j++) {\n                if (model.cnt_H[i][j] > 0) {\n                    right_avg += model.get_H(i, j) - model.local_H[i][j];\n                    rc++;\n                }\n            }\n            if (lc > 0) left_avg /= lc;\n            if (rc > 0) right_avg /= rc;\n            model.row_split_val[i] = right_avg - left_avg;\n            \n            // Adjust local variations to be relative to new split\n            for (int j = 0; j < N-1; j++) {\n                if (model.cnt_H[i][j] > 0 && j >= best_split) {\n                    model.local_H[i][j] -= model.row_split_val[i];\n                }\n            }\n        }\n    }\n    \n    // Vertical splits\n    for (int j = 0; j < N; j++) {\n        if (model.col_split_idx[j] >= 0) continue;\n        \n        int visited = 0;\n        for (int i = 0; i < N-1; i++) visited += (model.cnt_V[i][j] > 0);\n        if (visited < 12) continue;\n        \n        double best_t_stat = 2.0;\n        int best_split = -1;\n        \n        for (int s = 3; s < N-4; s++) {\n            double top_mean = 0, bottom_mean = 0;\n            double top_var = 0, bottom_var = 0;\n            int top_n = 0, bottom_n = 0;\n            \n            for (int i = 0; i < s; i++) {\n                if (model.cnt_V[i][j] > 0) {\n                    double val = model.get_V(i, j);\n                    top_mean += val;\n                    top_var += val * val;\n                    top_n++;\n                }\n            }\n            for (int i = s; i < N-1; i++) {\n                if (model.cnt_V[i][j] > 0) {\n                    double val = model.get_V(i, j);\n                    bottom_mean += val;\n                    bottom_var += val * val;\n                    bottom_n++;\n                }\n            }\n            \n            if (top_n >= 4 && bottom_n >= 4) {\n                top_mean /= top_n;\n                bottom_mean /= bottom_n;\n                top_var = top_var/top_n - top_mean*top_mean;\n                bottom_var = bottom_var/bottom_n - bottom_mean*bottom_mean;\n                \n                double se = sqrt(top_var/top_n + bottom_var/bottom_n);\n                if (se < 1.0) se = 1.0;\n                double t_stat = fabs(top_mean - bottom_mean) / se;\n                \n                if (t_stat > best_t_stat) {\n                    best_t_stat = t_stat;\n                    best_split = s;\n                }\n            }\n        }\n        \n        if (best_split >= 0) {\n            model.col_split_idx[j] = best_split;\n            double top_avg = 0, bottom_avg = 0;\n            int tc = 0, bc = 0;\n            for (int i = 0; i < best_split; i++) {\n                if (model.cnt_V[i][j] > 0) {\n                    top_avg += model.get_V(i, j) - model.local_V[i][j];\n                    tc++;\n                }\n            }\n            for (int i = best_split; i < N-1; i++) {\n                if (model.cnt_V[i][j] > 0) {\n                    bottom_avg += model.get_V(i, j) - model.local_V[i][j];\n                    bc++;\n                }\n            }\n            if (tc > 0) top_avg /= tc;\n            if (bc > 0) bottom_avg /= bc;\n            model.col_split_val[j] = bottom_avg - top_avg;\n            \n            for (int i = 0; i < N-1; i++) {\n                if (model.cnt_V[i][j] > 0 && i >= best_split) {\n                    model.local_V[i][j] -= model.col_split_val[j];\n                }\n            }\n        }\n    }\n}\n\n// Generate a strategic exploration path for early queries\npair<pair<int,int>, pair<int,int>> get_strategic_targets(int query_idx) {\n    // First 30 queries: systematically explore different regions\n    int row = (query_idx / 6) % 30;\n    int col = (query_idx * 5) % 30;\n    \n    // Choose targets far from each other\n    int target_row = (row + 15) % 30;\n    int target_col = (col + 15) % 30;\n    \n    if (abs(target_row - row) + abs(target_col - col) < 10) {\n        target_row = 29 - row;\n        target_col = 29 - col;\n    }\n    \n    return {{min(row, 29), min(col, 29)}, {min(target_row, 29), min(target_col, 29)}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    EdgeModel model;\n    PathFinder finder;\n    \n    // Initial exploration bonus\n    double explore_bonus = 2500.0;\n    bool use_strategic = false; // Disable strategic exploration for now\n    \n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Detect splits early and often\n        if (k == 25 || k == 50 || k == 75 || k == 100 || \n            (k > 100 && k % 20 == 0)) {\n            detect_splits(model, k);\n        }\n        \n        // Find path\n        auto path = finder.find_path(si, sj, ti, tj, model, explore_bonus, k);\n        double est_len = finder.calc_path_length(path, model);\n        \n        // Output\n        cout << path_to_string(path) << '\\n';\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        // Update model\n        update_model(model, path, observed, est_len, k);\n        \n        // Adaptive exploration decay based on model confidence\n        double avg_uncertainty = 0;\n        int cnt_unc = 0;\n        for (int i = 0; i < N; i++) {\n            if (model.n_samples_H[i] > 0) {\n                avg_uncertainty += model.get_H_uncertainty(i);\n                cnt_unc++;\n            }\n            if (model.n_samples_V[i] > 0) {\n                avg_uncertainty += model.get_V_uncertainty(i);\n                cnt_unc++;\n            }\n        }\n        if (cnt_unc > 0) avg_uncertainty /= cnt_unc;\n        \n        // Decay faster when uncertainty is low\n        double decay = 0.997;\n        if (avg_uncertainty < 500) decay = 0.993;\n        else if (avg_uncertainty > 1500) decay = 0.999;\n        \n        explore_bonus *= decay;\n        explore_bonus = max(10.0, explore_bonus);\n    }\n    \n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nint N, M;\nvector<string> strings;\n\nchar grid[20][20];\n\n// Check if a placement is possible given current grid (excluding '.' matches anything)\nbool can_place(const string &s, int r, int c, int dir) {\n    int len = s.size();\n    if (dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            char g = grid[r][(c + p) % N];\n            if (g != '.' && g != s[p]) return false;\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            char g = grid[(r + p) % N][c];\n            if (g != '.' && g != s[p]) return false;\n        }\n    }\n    return true;\n}\n\nvoid place(const string &s, int r, int c, int dir) {\n    int len = s.size();\n    if (dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            grid[r][(c + p) % N] = s[p];\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            grid[(r + p) % N][c] = s[p];\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) cin >> strings[i];\n\n    // Initialize grid with '.'\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            grid[i][j] = '.';\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    // Sort strings by length descending to place longer strings first\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return strings[a].size() > strings[b].size();\n    });\n\n    mt19937 rng(42);\n    const char letters[] = {'A','B','C','D','E','F','G','H'};\n\n    for (int idx : order) {\n        const string &s = strings[idx];\n        bool placed = false;\n        vector<tuple<int,int,int>> candidates;\n        for (int r = 0; r < N; ++r)\n            for (int c = 0; c < N; ++c)\n                for (int dir = 0; dir < 2; ++dir)\n                    if (can_place(s, r, c, dir))\n                        candidates.emplace_back(r, c, dir);\n        if (!candidates.empty()) {\n            // Choose one randomly\n            auto [r, c, dir] = candidates[uniform_int_distribution<int>(0, candidates.size()-1)(rng)];\n            place(s, r, c, dir);\n        }\n    }\n\n    // Fill remaining '.' with random letters\n    uniform_int_distribution<int> letter_dist(0,7);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.')\n                grid[i][j] = letters[letter_dist(rng)];\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        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dir[4] = {'U', 'D', 'L', 'R'};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> cost;\nvector<vector<bool>> road;\nvector<vector<bitset<5000>>> visMask;\nint totalRoads = 0;\nvector<vector<int>> roadId;\n\nbool inside(int i, int j) {\n    return i>=0 && i<N && j>=0 && j<N;\n}\n\n// Returns distance and path\npair<int, vector<pair<int,int>>> shortestPath(int si, int sj, int ti, int tj) {\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    priority_queue<pair<int,pair<int,int>>, vector<pair<int,pair<int,int>>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, {si, sj}});\n    \n    while(!pq.empty()) {\n        auto [d, pos] = pq.top(); pq.pop();\n        auto [i, j] = pos;\n        if(d != dist[i][j]) continue;\n        if(i==ti && j==tj) break;\n        for(int k=0;k<4;k++) {\n            int ni = i+dx[k], nj = j+dy[k];\n            if(inside(ni,nj) && road[ni][nj]) {\n                int nd = d + cost[ni][nj];\n                if(nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i,j};\n                    pq.push({nd, {ni,nj}});\n                }\n            }\n        }\n    }\n    \n    vector<pair<int,int>> path;\n    if(dist[ti][tj] >= 1e8) {\n        // No path found - should not happen\n        return {1e9, path};\n    }\n    \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; cj = p.second;\n        if(ci == -1) break; // safety\n    }\n    path.push_back({si,sj});\n    reverse(path.begin(), path.end());\n    return {dist[ti][tj], path};\n}\n\nstring pathToDir(const vector<pair<int,int>>& path) {\n    string res;\n    for(int i=0;i+1<(int)path.size();i++) {\n        int di = path[i+1].first - path[i].first;\n        int dj = path[i+1].second - path[i].second;\n        if(di == -1) res += 'U';\n        else if(di == 1) res += 'D';\n        else if(dj == -1) res += 'L';\n        else if(dj == 1) res += 'R';\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    cost.assign(N, vector<int>(N,0));\n    road.assign(N, vector<bool>(N,false));\n    roadId.assign(N, vector<int>(N,-1));\n    \n    for(int i=0;i<N;i++) {\n        cin >> grid[i];\n        for(int j=0;j<N;j++) {\n            if(grid[i][j] != '#') {\n                road[i][j] = true;\n                cost[i][j] = grid[i][j] - '0';\n                roadId[i][j] = totalRoads++;\n            }\n        }\n    }\n    \n    // compute visibility masks\n    visMask.assign(N, vector<bitset<5000>>(N));\n    for(int i=0;i<N;i++) {\n        for(int j=0;j<N;j++) {\n            if(!road[i][j]) continue;\n            // horizontal\n            for(int jj=j; jj<N && road[i][jj]; jj++) \n                visMask[i][j].set(roadId[i][jj]);\n            for(int jj=j-1; jj>=0 && road[i][jj]; jj--) \n                visMask[i][j].set(roadId[i][jj]);\n            // vertical\n            for(int ii=i; ii<N && road[ii][j]; ii++) \n                visMask[i][j].set(roadId[ii][j]);\n            for(int ii=i-1; ii>=0 && road[ii][j]; ii--) \n                visMask[i][j].set(roadId[ii][j]);\n        }\n    }\n    \n    // Greedy set cover to choose points\n    bitset<5000> covered;\n    vector<pair<int,int>> chosen;\n    covered.set(roadId[si][sj]);\n    chosen.push_back({si,sj});\n    \n    while((int)covered.count() < totalRoads) {\n        int best = -1, bi = -1, bj = -1;\n        for(int i=0;i<N;i++) {\n            for(int j=0;j<N;j++) {\n                if(!road[i][j]) continue;\n                bitset<5000> newCov = visMask[i][j] | covered;\n                int gain = (int)newCov.count() - (int)covered.count();\n                if(gain > best) {\n                    best = gain;\n                    bi = i; bj = j;\n                }\n            }\n        }\n        if(best<=0) break;\n        covered |= visMask[bi][bj];\n        chosen.push_back({bi,bj});\n    }\n    \n    int M = (int)chosen.size();\n    \n    // Precompute all-pairs shortest paths\n    vector<vector<int>> dist(M, vector<int>(M));\n    vector<vector<vector<pair<int,int>>>> pathCache(M, vector<vector<pair<int,int>>>(M));\n    \n    for(int i=0;i<M;i++) {\n        for(int j=0;j<M;j++) {\n            if(i == j) {\n                dist[i][j] = 0;\n                pathCache[i][j] = {};\n                continue;\n            }\n            auto [d, path] = shortestPath(chosen[i].first, chosen[i].second,\n                                          chosen[j].first, chosen[j].second);\n            dist[i][j] = d;\n            pathCache[i][j] = path;\n        }\n    }\n    \n    // Nearest-neighbor tour (simpler and more reliable)\n    vector<int> tour;\n    vector<bool> used(M, false);\n    tour.push_back(0);\n    used[0] = true;\n    \n    for(int step=1; step<M; step++) {\n        int cur = tour.back();\n        int best = -1;\n        int bestD = 1e9;\n        for(int i=1;i<M;i++) {\n            if(!used[i] && dist[cur][i] < bestD) {\n                bestD = dist[cur][i];\n                best = i;\n            }\n        }\n        tour.push_back(best);\n        used[best] = true;\n    }\n    \n    // 2-opt improvement\n    bool improved = true;\n    while(improved) {\n        improved = false;\n        for(int i=0; i<M; i++) {\n            for(int j=i+2; j<M; j++) {\n                if(i==0 && j==M-1) continue; // would break the cycle\n                int a = tour[i];\n                int b = tour[(i+1)%M];\n                int c = tour[j];\n                int d = tour[(j+1)%M];\n                int oldCost = dist[a][b] + dist[c][d];\n                int newCost = dist[a][c] + dist[b][d];\n                if(newCost < oldCost) {\n                    reverse(tour.begin()+i+1, tour.begin()+j+1);\n                    improved = true;\n                }\n            }\n        }\n    }\n    \n    // Build full path by concatenating\n    vector<pair<int,int>> fullPath;\n    for(int i=0;i<M;i++) {\n        int cur = tour[i];\n        int nxt = tour[(i+1)%M];\n        const auto& pp = pathCache[cur][nxt];\n        \n        if(fullPath.empty()) {\n            fullPath = pp;\n        } else {\n            // The last point of fullPath should match the first point of pp\n            // Remove the duplicate start point of pp\n            for(int k=1; k<(int)pp.size(); k++) {\n                fullPath.push_back(pp[k]);\n            }\n        }\n    }\n    \n    // Remove consecutive duplicates (redundant steps)\n    vector<pair<int,int>> cleanPath;\n    for(const auto& p : fullPath) {\n        if(cleanPath.empty() || cleanPath.back() != p) {\n            cleanPath.push_back(p);\n        }\n    }\n    \n    // Verify the path is valid (starts and ends at correct position)\n    if(cleanPath.empty() || cleanPath.front() != make_pair(si, sj)) {\n        // Should not happen, but safety\n        cout << \"\\n\";\n        return 0;\n    }\n    \n    string ans = pathToDir(cleanPath);\n    \n    // Verify path does not go through obstacles\n    // (debug check - can be removed for speed)\n    int ci = si, cj = sj;\n    for(char c : ans) {\n        if(c == 'U') ci--;\n        else if(c == 'D') ci++;\n        else if(c == 'L') cj--;\n        else if(c == 'R') cj++;\n        if(!inside(ci, cj) || !road[ci][cj]) {\n            // Invalid move - fallback to simple BFS return\n            auto [d, path] = shortestPath(si, sj, si, sj);\n            cout << pathToDir(path) << \"\\n\";\n            return 0;\n        }\n    }\n    if(ci != si || cj != sj) {\n        auto [d, path] = shortestPath(si, sj, si, sj);\n        cout << pathToDir(path) << \"\\n\";\n        return 0;\n    }\n    \n    cout << ans << \"\\n\";\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, K, R;\nvector<vector<int>> d;\nvector<vector<int>> dep;\nvector<vector<int>> rev_dep;\nvector<int> in_degree;\n\nvector<vector<double>> s_est;\nvector<vector<int>> s_obs_count;\nvector<int> total_assigned;\nvector<vector<int>> completion_times; // observed completion times per (task, member)\n\nenum TaskStatus { NOT_STARTED = 0, IN_PROGRESS = 1, COMPLETED = 2 };\nvector<TaskStatus> task_status;\nvector<int> task_assigned_to;\nvector<int> task_start_day;\nvector<bool> member_busy;\nvector<int> member_current_task;\n\nvoid parse_input() {\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            cin >> d[i][k];\n        }\n    }\n    dep.resize(N);\n    rev_dep.resize(N);\n    in_degree.assign(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        dep[v].push_back(u);\n        rev_dep[u].push_back(v);\n        in_degree[v]++;\n    }\n}\n\nvoid init_estimation() {\n    s_est.assign(M, vector<double>(K, 0.0));\n    s_obs_count.assign(M, vector<int>(K, 0));\n    completion_times.assign(N, vector<int>(M, -1));\n    \n    // Initialize with reasonable defaults\n    for (int j = 0; j < M; j++) {\n        for (int k = 0; k < K; k++) {\n            s_est[j][k] = 25.0 + (j * 3) % 20; // spread initial estimates\n        }\n    }\n}\n\nvoid init_scheduling() {\n    task_status.assign(N, NOT_STARTED);\n    task_assigned_to.assign(N, -1);\n    task_start_day.assign(N, -1);\n    member_busy.assign(M, false);\n    member_current_task.assign(M, -1);\n    total_assigned.assign(M, 0);\n}\n\ndouble estimate_w(int i, int j) {\n    double w = 0;\n    for (int k = 0; k < K; k++) {\n        double gap = d[i][k] - s_est[j][k];\n        if (gap > 0) w += gap;\n    }\n    return w;\n}\n\nint estimate_t(int i, int j) {\n    double w = estimate_w(i, j);\n    if (w < 0.5) return 1;\n    return max(1, (int)round(w + 0.0)); // +0 for no bias, actual noise is \u00b13\n}\n\nvoid update_skill_estimate(int task, int member, int actual_t) {\n    completion_times[task][member] = actual_t;\n    \n    // If task completed in 1 day, member's skills are at least task requirements\n    if (actual_t == 1) {\n        for (int k = 0; k < K; k++) {\n            if (d[task][k] > 0) {\n                if (d[task][k] > s_est[member][k]) {\n                    s_est[member][k] = max(s_est[member][k], (double)d[task][k]);\n                }\n                s_obs_count[member][k]++;\n            }\n        }\n        return;\n    }\n    \n    // For longer tasks, actual_t \u2248 w_i,j + noise\n    // We want to adjust s_est to minimize (estimate_w - actual_t)^2\n    double current_w = estimate_w(task, member);\n    double target_w = actual_t; // actual_t is our best guess for w (noise cancels over time)\n    \n    // Compute gradient for each skill\n    double diff = target_w - current_w;\n    \n    if (abs(diff) < 0.1) return;\n    \n    // Find which skills are lacking\n    vector<int> lacking_skills;\n    double total_gap = 0;\n    vector<double> gaps(K, 0);\n    for (int k = 0; k < K; k++) {\n        gaps[k] = max(0.0, (double)d[task][k] - s_est[member][k]);\n        if (gaps[k] > 0.01) {\n            lacking_skills.push_back(k);\n            total_gap += gaps[k];\n        }\n    }\n    \n    if (total_gap < 0.01) return;\n    \n    // Distribute the adjustment proportionally\n    double lr = 0.4; // learning rate increased slightly\n    for (int k : lacking_skills) {\n        double adjustment = diff * gaps[k] / total_gap * lr;\n        s_est[member][k] -= adjustment;\n        if (s_est[member][k] < 0) s_est[member][k] = 0;\n        s_obs_count[member][k]++;\n    }\n    \n    // Also apply upper bound constraints from 1-day tasks we've seen\n    // If we've seen this member complete other tasks in 1 day,\n    // their skills must be at least those requirements\n    for (int i = 0; i < N; i++) {\n        if (completion_times[i][member] == 1 && i != task) {\n            for (int k = 0; k < K; k++) {\n                if (d[i][k] > s_est[member][k]) {\n                    s_est[member][k] = max(s_est[member][k], (double)d[i][k]);\n                }\n            }\n        }\n    }\n}\n\nbool is_task_ready(int task) {\n    if (task_status[task] != NOT_STARTED) return false;\n    for (int dep_task : dep[task]) {\n        if (task_status[dep_task] != COMPLETED) return false;\n    }\n    return true;\n}\n\n// Compute longest path from each task (critical path length)\nvector<int> compute_critical_paths() {\n    vector<int> est_remain(N, 0);\n    vector<int> out_degree(N, 0);\n    for (int i = 0; i < N; i++) {\n        out_degree[i] = rev_dep[i].size();\n    }\n    \n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (out_degree[i] == 0 && task_status[i] != COMPLETED) {\n            q.push(i);\n        }\n    }\n    \n    vector<int> topo;\n    vector<int> indeg = out_degree;\n    queue<int> q2;\n    for (int i = 0; i < N; i++) {\n        if (indeg[i] == 0 && task_status[i] != COMPLETED) {\n            q2.push(i);\n        }\n    }\n    while (!q2.empty()) {\n        int v = q2.front(); q2.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) q2.push(u);\n        }\n    }\n    \n    // Process in reverse topological order\n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        if (task_status[v] == COMPLETED) {\n            est_remain[v] = 0;\n        } else {\n            // Estimate minimum time for this task\n            int min_t = 1000000;\n            for (int j = 0; j < M; j++) {\n                min_t = min(min_t, estimate_t(v, j));\n            }\n            est_remain[v] = min_t;\n            int max_succ = 0;\n            for (int u : rev_dep[v]) {\n                max_succ = max(max_succ, est_remain[u]);\n            }\n            est_remain[v] += max_succ;\n        }\n    }\n    \n    return est_remain;\n}\n\n// Compute number of descendants (including self)\nvector<int> compute_descendants() {\n    vector<int> desc(N, 0);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < N; i++) {\n        for (int u : rev_dep[i]) indeg[u]++;\n    }\n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (indeg[i] == 0 && task_status[i] != COMPLETED) q.push(i);\n    }\n    vector<int> topo;\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) q.push(u);\n        }\n    }\n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        desc[v] = 1;\n        for (int u : rev_dep[v]) {\n            desc[v] += desc[u];\n        }\n    }\n    return desc;\n}\n\nvector<int> get_ready_tasks(int current_day) {\n    vector<int> ready;\n    for (int i = 0; i < N; i++) {\n        if (is_task_ready(i)) {\n            ready.push_back(i);\n        }\n    }\n    \n    if (ready.empty()) return ready;\n    \n    vector<int> crit = compute_critical_paths();\n    vector<int> desc = compute_descendants();\n    \n    // Sort by priority: combination of critical path length and descendants\n    sort(ready.begin(), ready.end(), [&](int a, int b) {\n        // Primary: longer critical path first\n        if (crit[a] != crit[b]) return crit[a] > crit[b];\n        // Secondary: more descendants first\n        if (desc[a] != desc[b]) return desc[a] > desc[b];\n        return a < b;\n    });\n    \n    return ready;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    parse_input();\n    init_estimation();\n    init_scheduling();\n    \n    int current_day = 0;\n    \n    while (true) {\n        current_day++;\n        \n        vector<int> ready_tasks = get_ready_tasks(current_day);\n        \n        vector<int> available;\n        for (int j = 0; j < M; j++) {\n            if (!member_busy[j]) {\n                available.push_back(j);\n            }\n        }\n        \n        vector<pair<int,int>> assignments;\n        vector<bool> used(M, false);\n        \n        // Phase 0: Strategic exploration in early days\n        bool explore_mode = (current_day <= 50);\n        \n        if (explore_mode && !available.empty() && !ready_tasks.empty()) {\n            // In exploration, assign diverse tasks to members with few observations\n            for (int j : available) {\n                if ((int)assignments.size() >= (int)available.size()) break;\n                if (used[j]) continue;\n                \n                // Find a task that tests under-explored skills for this member\n                int best_task = -1;\n                double best_explore_score = -1;\n                \n                for (int task : ready_tasks) {\n                    // Check if task is already assigned\n                    bool already = false;\n                    for (auto &p : assignments) {\n                        if (p.second == task) { already = true; break; }\n                    }\n                    if (already) continue;\n                    \n                    // Count how many needed skills are under-explored\n                    int unexplored = 0;\n                    int total_needed = 0;\n                    for (int k = 0; k < K; k++) {\n                        if (d[task][k] > 0) {\n                            total_needed++;\n                            if (s_obs_count[j][k] < 3) unexplored++;\n                        }\n                    }\n                    \n                    if (total_needed > 0) {\n                        double score = (double)unexplored / total_needed;\n                        // Prefer tasks that can be done faster\n                        score -= estimate_t(task, j) * 0.01;\n                        if (score > best_explore_score) {\n                            best_explore_score = score;\n                            best_task = task;\n                        }\n                    }\n                }\n                \n                if (best_task != -1 && best_explore_score > 0.3) {\n                    assignments.push_back({j, best_task});\n                    used[j] = true;\n                }\n            }\n        }\n        \n        // Phase 1: Assign tasks that can be done in 1 day (perfect matches)\n        for (int task : ready_tasks) {\n            if ((int)assignments.size() >= (int)available.size()) break;\n            \n            bool already = false;\n            for (auto &p : assignments) {\n                if (p.second == task) { already = true; break; }\n            }\n            if (already) continue;\n            \n            int best_member = -1;\n            double best_w = 1e18;\n            for (int j : available) {\n                if (used[j]) continue;\n                double w = estimate_w(task, j);\n                if (w < 0.5 && w < best_w) {\n                    best_w = w;\n                    best_member = j;\n                }\n            }\n            if (best_member != -1) {\n                assignments.push_back({best_member, task});\n                used[best_member] = true;\n            }\n        }\n        \n        // Phase 2: Assign remaining tasks optimally\n        for (int task : ready_tasks) {\n            if ((int)assignments.size() >= (int)available.size()) break;\n            \n            bool already = false;\n            for (auto &p : assignments) {\n                if (p.second == task) { already = true; break; }\n            }\n            if (already) continue;\n            \n            int best_member = -1;\n            double best_score = -1e18;\n            for (int j : available) {\n                if (used[j]) continue;\n                int est_t = estimate_t(task, j);\n                double score = -est_t * 100.0;\n                \n                // Exploration bonus: if we haven't tried this (member, task) combo\n                if (completion_times[task][j] == -1) {\n                    int unexplored = 0;\n                    for (int k = 0; k < K; k++) {\n                        if (d[task][k] > s_est[j][k] && s_obs_count[j][k] < 3) {\n                            unexplored++;\n                        }\n                    }\n                    score += unexplored * 15.0;\n                }\n                \n                // Slight load balancing\n                score -= total_assigned[j] * 0.1;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                assignments.push_back({best_member, task});\n                used[best_member] = true;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            int member = p.first;\n            int task = p.second;\n            cout << \" \" << (member + 1) << \" \" << (task + 1);\n            \n            task_status[task] = IN_PROGRESS;\n            task_assigned_to[task] = member;\n            task_start_day[task] = current_day;\n            member_busy[member] = true;\n            member_current_task[member] = task;\n            total_assigned[member]++;\n        }\n        cout << \"\\n\";\n        \n        // Output predictions as comments\n        for (int j = 0; j < M; j++) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << \" \" << (int)round(s_est[j][k]);\n            }\n            cout << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read completions\n        string line;\n        getline(cin, line);\n        while (line.empty()) {\n            if (!getline(cin, line)) break;\n        }\n        \n        istringstream iss(line);\n        vector<int> vals;\n        int x;\n        while (iss >> x) vals.push_back(x);\n        \n        if (vals.empty()) continue;\n        if (vals.size() == 1 && vals[0] == -1) {\n            break;\n        }\n        \n        int n_comp = vals[0];\n        for (int i = 0; i < n_comp; i++) {\n            int member = vals[i + 1] - 1;\n            member_busy[member] = false;\n            \n            int task = member_current_task[member];\n            if (task != -1 && task_status[task] == IN_PROGRESS) {\n                int actual_t = current_day - task_start_day[task] + 1;\n                update_skill_estimate(task, member, actual_t);\n                task_status[task] = COMPLETED;\n                task_assigned_to[task] = -1;\n                member_current_task[member] = -1;\n            }\n        }\n        \n        if (current_day >= 2000) break;\n    }\n    \n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <numeric>\n#include <cmath>\n#include <set>\n#include <map>\n#include <tuple>\n#include <cassert>\n#include <climits>\n\nusing namespace std;\n\n// ------------------------------------------------------------\n// geometry / distance\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\n// ------------------------------------------------------------\n// order structure\nstruct Order {\n    int id;\n    int ax, ay; // restaurant\n    int cx, cy; // destination\n};\n\n// ------------------------------------------------------------\n// route node kinds\nenum NodeType { PICKUP, DELIVERY, DEPOT };\n\nstruct Node {\n    NodeType type;\n    int order_id; // -1 for depot\n    int x, y;\n};\n\n// ------------------------------------------------------------\n// compute total Manhattan distance of a route\nint routeLength(const vector<Node>& route) {\n    int total = 0;\n    for (size_t i = 0; i + 1 < route.size(); ++i) {\n        total += manhattan(route[i].x, route[i].y, route[i+1].x, route[i+1].y);\n    }\n    return total;\n}\n\n// ------------------------------------------------------------\n// check if route satisfies pickup before delivery for all orders\nbool feasibleRoute(const vector<Node>& route) {\n    map<int, int> firstSeen;\n    for (size_t i = 0; i < route.size(); ++i) {\n        if (route[i].type == DEPOT) continue;\n        int oid = route[i].order_id;\n        if (route[i].type == PICKUP) {\n            if (firstSeen.find(oid) == firstSeen.end()) {\n                firstSeen[oid] = i;\n            }\n        } else { // DELIVERY\n            if (firstSeen.find(oid) == firstSeen.end()) return false;\n        }\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// insert one order (pickup then delivery) at best positions to minimize extra distance\npair<int,int> bestInsert(const vector<Node>& route, const Order& ord) {\n    int bestCost = INT_MAX;\n    int bestP = -1, bestD = -1;\n    // we cannot insert at pos 0 (depot) and pos N-1 (depot)\n    int n = (int)route.size();\n    // pickup can go after position i (0 <= i < n-1), delivery after position j (i+1 <= j < n-1)\n    for (int i = 0; i < n-1; ++i) {\n        // tentative pickup position after i\n        int pi = i+1;\n        int distPBefore = manhattan(route[i].x, route[i].y, ord.ax, ord.ay);\n        int distPAfter  = manhattan(ord.ax, ord.ay, route[pi].x, route[pi].y);\n        int extraP = distPBefore + distPAfter - manhattan(route[i].x, route[i].y, route[pi].x, route[pi].y);\n        for (int j = i; j < n-1; ++j) {\n            // delivery position after j, but after pickup inserted, indices shift\n            int dj = j+1;\n            int distDBefore = manhattan(route[j].x, route[j].y, ord.cx, ord.cy);\n            int distDAfter  = manhattan(ord.cx, ord.cy, route[dj].x, route[dj].y);\n            int extraD = distDBefore + distDAfter - manhattan(route[j].x, route[j].y, route[dj].x, route[dj].y);\n            int totalExtra = extraP + extraD;\n            if (totalExtra < bestCost) {\n                bestCost = totalExtra;\n                bestP = pi;\n                // delivery shift due to pickup inserted before j\n                bestD = (j >= i) ? dj + 1 : dj;\n            }\n        }\n    }\n    return {bestP, bestD};\n}\n\n// ------------------------------------------------------------\n// insert order at given positions (indices in the current route)\nvector<Node> insertOrder(const vector<Node>& route, const Order& ord, int posP, int posD) {\n    vector<Node> newRoute = route;\n    Node pNode = {PICKUP, ord.id, ord.ax, ord.ay};\n    Node dNode = {DELIVERY, ord.id, ord.cx, ord.cy};\n    if (posP < posD) {\n        newRoute.insert(newRoute.begin() + posD, dNode);\n        newRoute.insert(newRoute.begin() + posP, pNode);\n    } else {\n        newRoute.insert(newRoute.begin() + posP, pNode);\n        newRoute.insert(newRoute.begin() + posD, dNode);\n    }\n    return newRoute;\n}\n\n// ------------------------------------------------------------\n// build initial route with selected orders (simple greedy insertion)\nvector<Node> buildInitialRoute(const vector<Order>& orders, const vector<int>& selected) {\n    vector<Node> route;\n    route.push_back({DEPOT, -1, 400, 400});\n    route.push_back({DEPOT, -1, 400, 400});\n    \n    for (int id : selected) {\n        auto [p, d] = bestInsert(route, orders[id]);\n        route = insertOrder(route, orders[id], p, d);\n    }\n    return route;\n}\n\n// ------------------------------------------------------------\n// random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// main optimization\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    const int N = 1000;\n    const int K = 50;\n    const int DEPOT_X = 400, DEPOT_Y = 400;\n    \n    vector<Order> orders(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n        orders[i].id = i;\n    }\n    \n    // initial selection: first 50\n    vector<int> selected(K);\n    iota(selected.begin(), selected.end(), 0);\n    \n    // build initial route\n    vector<Node> route = buildInitialRoute(orders, selected);\n    int bestLen = routeLength(route);\n    vector<Node> bestRoute = route;\n    vector<int> bestSelected = selected;\n    \n    // set of available orders (not selected)\n    set<int> available;\n    for (int i = K; i < N; ++i) available.insert(i);\n    \n    // hill climbing with random restarts limited by time\n    auto startTime = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.8; // seconds\n    int iterations = 0;\n    \n    uniform_int_distribution<int> selDist(0, K-1);\n    uniform_int_distribution<int> availIdx(0, N-K-1);\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        iterations++;\n        \n        // Try to replace one selected order with an unchosen one\n        int idxRemove = selDist(rng);\n        int oldOrderId = selected[idxRemove];\n        \n        // pick a random available order\n        int pick = availIdx(rng) % (int)available.size();\n        auto it = available.begin();\n        advance(it, pick);\n        int newOrderId = *it;\n        \n        // new selection\n        vector<int> newSel = selected;\n        newSel[idxRemove] = newOrderId;\n        \n        // build route with new selection using greedy insertion from scratch\n        vector<Node> candRoute;\n        candRoute.push_back({DEPOT, -1, DEPOT_X, DEPOT_Y});\n        candRoute.push_back({DEPOT, -1, DEPOT_X, DEPOT_Y});\n        \n        for (int oid : newSel) {\n            auto [p, d] = bestInsert(candRoute, orders[oid]);\n            candRoute = insertOrder(candRoute, orders[oid], p, d);\n        }\n        \n        int candLen = routeLength(candRoute);\n        if (candLen < bestLen) {\n            bestLen = candLen;\n            bestRoute = candRoute;\n            bestSelected = newSel;\n            \n            // update available set\n            available.erase(newOrderId);\n            available.insert(oldOrderId);\n            selected = newSel;\n        }\n        \n        // also try some local search moves on the current best route\n        // for simplicity just 2-opt like relocation of single node\n        if (iterations % 10 == 0) {\n            int n = (int)bestRoute.size();\n            // try moving a node to another position maintaining feasibility\n            for (int i = 1; i < n-1; ++i) {\n                for (int j = 1; j < n-1; ++j) {\n                    if (i == j) continue;\n                    vector<Node> newRoute = bestRoute;\n                    Node moved = newRoute[i];\n                    newRoute.erase(newRoute.begin() + i);\n                    if (j > i) j--;\n                    newRoute.insert(newRoute.begin() + j, moved);\n                    if (feasibleRoute(newRoute)) {\n                        int len = routeLength(newRoute);\n                        if (len < bestLen) {\n                            bestLen = len;\n                            bestRoute = newRoute;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Output final\n    cout << K;\n    for (int id : bestSelected) cout << \" \" << id+1;\n    cout << \"\\n\";\n    cout << bestRoute.size();\n    for (const auto& node : bestRoute) {\n        cout << \" \" << node.x << \" \" << node.y;\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <queue>\n#include <cstring>\nusing namespace std;\n\nstruct Edge { int u, v, d; };\n\nclass UnionFind {\npublic:\n    vector<int> parent, rank;\n    int comps;\n    UnionFind(int n) : comps(n) {\n        parent.resize(n); rank.resize(n, 0);\n        for (int i = 0; i < n; i++) parent[i] = i;\n    }\n    int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); }\n    bool unite(int x, int y) {\n        int px = find(x), py = find(y);\n        if (px == py) return false;\n        if (rank[px] < rank[py]) parent[px] = py;\n        else if (rank[py] < rank[px]) parent[py] = px;\n        else { parent[py] = px; rank[px]++; }\n        comps--; return true;\n    }\n    bool connected(int x, int y) { return find(x) == find(y); }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(nullptr);\n    \n    const int N = 400, M = 1995;\n    \n    vector<pair<int,int>> coords(N);\n    for (int i = 0; i < N; i++) cin >> coords[i].first >> coords[i].second;\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        int dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = round(sqrt(dx*dx + dy*dy));\n    }\n    \n    UnionFind uf(N);\n    \n    for (int i = 0; i < M; i++) {\n        int li; cin >> li;\n        bool accept = false;\n        int stillNeed = uf.comps - 1;\n        \n        if (stillNeed > 0 && !uf.connected(edges[i].u, edges[i].v)) {\n            double ratio = (double)li / max(1.0, (double)edges[i].d);\n            int remaining = M - i - 1;\n            \n            // Check if remaining edges can connect all components\n            bool canFinish = false;\n            if (remaining >= stillNeed) {\n                int compToIdx[N];\n                memset(compToIdx, -1, sizeof(compToIdx));\n                int C = 0;\n                for (int j = 0; j < N; j++) {\n                    int c = uf.find(j);\n                    if (compToIdx[c] == -1) {\n                        compToIdx[c] = C++;\n                    }\n                }\n                \n                vector<vector<int>> compGraph(C);\n                for (int j = i + 1; j < M; j++) {\n                    int cu = compToIdx[uf.find(edges[j].u)];\n                    int cv = compToIdx[uf.find(edges[j].v)];\n                    if (cu != cv) {\n                        compGraph[cu].push_back(cv);\n                        compGraph[cv].push_back(cu);\n                    }\n                }\n                \n                vector<bool> vis(C, false);\n                queue<int> q;\n                q.push(0); vis[0] = true;\n                int cnt = 0;\n                while (!q.empty()) {\n                    int cur = q.front(); q.pop();\n                    cnt++;\n                    for (int nxt : compGraph[cur]) {\n                        if (!vis[nxt]) { vis[nxt] = true; q.push(nxt); }\n                    }\n                }\n                canFinish = (cnt == C);\n            }\n            \n            if (!canFinish) {\n                accept = true;\n            } else {\n                // Accept based on ratio and need\n                if (ratio <= 1.1) accept = true;\n                else if (ratio <= 1.3 && stillNeed > 200) accept = true;\n                else if (ratio <= 1.5 && stillNeed > 100) accept = true;\n                else if (ratio <= 1.8 && stillNeed > 50) accept = true;\n                else if (ratio <= 2.2 && stillNeed > 20) accept = true;\n                else if (ratio <= 2.8 && stillNeed > 3) accept = true;\n            }\n        }\n        \n        if (accept) uf.unite(edges[i].u, edges[i].v);\n        cout << (accept ? 1 : 0) << endl;\n        cout.flush();\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int TURNS = 300;\n\n// Directions\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dir_char[] = {'u', 'd', 'l', 'r'};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n    Pos(int x=0, int y=0) : x(x), y(y) {}\n    bool operator==(const Pos& o) const { return x==o.x && y==o.y; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n    bool valid() const { return x>=0 && x<GRID && y>=0 && y<GRID; }\n    Pos operator+(int d) const { return Pos(x+dx[d], y+dy[d]); }\n};\n\nstruct Pet {\n    Pos pos;\n    int type;\n};\n\n// Global state\nint N, M;\nvector<Pet> pets;\nvector<Pos> humans;\nvector<vector<bool>> impassable;\nvector<Pos> human_start;\n\n// BFS for reachable area\nint bfs_area(Pos start) {\n    vector<vector<bool>> vis(GRID, vector<bool>(GRID, false));\n    queue<Pos> q;\n    q.push(start);\n    vis[start.x][start.y] = true;\n    int area = 0;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        area++;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur + d;\n            if(nxt.valid() && !impassable[nxt.x][nxt.y] && !vis[nxt.x][nxt.y]) {\n                vis[nxt.x][nxt.y] = true;\n                q.push(nxt);\n            }\n        }\n    }\n    return area;\n}\n\n// Check if pet is adjacent to a position\nbool pet_adjacent(Pos p) {\n    for(const auto& pet : pets) {\n        if(abs(pet.pos.x - p.x) + abs(pet.pos.y - p.y) <= 1) return true;\n    }\n    return false;\n}\n\n// Check if human is at a position\nbool human_at(Pos p) {\n    for(const auto& h : humans) {\n        if(h == p) return true;\n    }\n    return false;\n}\n\n// Check if pet is at a position\nbool pet_at(Pos p) {\n    for(const auto& pet : pets) {\n        if(pet.pos == p) return true;\n    }\n    return false;\n}\n\n// Can build wall at position\nbool can_build(Pos p, int human_idx) {\n    if(!p.valid()) return false;\n    if(impassable[p.x][p.y]) return true; // already impassable\n    if(pet_at(p)) return false;\n    if(human_at(p)) return false;\n    if(pet_adjacent(p)) return false;\n    return true;\n}\n\n// Manhattan distance\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\n// Direction from a to b\nint dir_to(Pos from, Pos to) {\n    if(to.x < from.x) return 0; // up\n    if(to.x > from.x) return 1; // down\n    if(to.y < from.y) return 2; // left\n    if(to.y > from.y) return 3; // right\n    return -1;\n}\n\n// BFS path\nvector<int> find_path(Pos from, Pos to) {\n    vector<vector<int>> prev(GRID, vector<int>(GRID, -1));\n    vector<vector<int>> prev_dir(GRID, vector<int>(GRID, -1));\n    queue<Pos> q;\n    q.push(from);\n    prev[from.x][from.y] = -2;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        if(cur == to) break;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur + d;\n            if(nxt.valid() && !impassable[nxt.x][nxt.y] && prev[nxt.x][nxt.y] == -1) {\n                prev[nxt.x][nxt.y] = d;\n                prev_dir[nxt.x][nxt.y] = d;\n                q.push(nxt);\n            }\n        }\n    }\n    \n    if(prev[to.x][to.y] == -1) return {};\n    \n    vector<int> path;\n    Pos cur = to;\n    while(cur != from) {\n        int d = prev[cur.x][cur.y];\n        path.push_back(d);\n        cur = Pos(cur.x - dx[d], cur.y - dy[d]);\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    \n    // Read input\n    cin >> N;\n    pets.resize(N);\n    for(int i=0; i<N; i++) {\n        cin >> pets[i].pos.x >> pets[i].pos.y >> pets[i].type;\n        pets[i].pos.x--; pets[i].pos.y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    human_start.resize(M);\n    for(int i=0; i<M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n        human_start[i] = humans[i];\n    }\n    \n    // Initialize grid\n    impassable.assign(GRID, vector<bool>(GRID, false));\n    \n    // Strategy state\n    enum State { MOVING, BUILDING };\n    vector<State> state(M, MOVING);\n    vector<Pos> target(M);\n    vector<vector<Pos>> wall_plan(M);\n    vector<int> wall_idx(M, 0);\n    \n    // Assign targets: spread humans to different corners\n    vector<Pos> corners = {\n        Pos(0, 0), Pos(0, GRID-1), \n        Pos(GRID-1, 0), Pos(GRID-1, GRID-1),\n        Pos(0, GRID/2), Pos(GRID/2, 0),\n        Pos(GRID-1, GRID/2), Pos(GRID/2, GRID-1)\n    };\n    \n    // Assign each human to nearest unassigned corner\n    vector<bool> corner_used(corners.size(), false);\n    for(int i=0; i<M; i++) {\n        int best_c = -1;\n        int best_dist = 1e9;\n        for(int c=0; c<(int)corners.size(); c++) {\n            if(!corner_used[c]) {\n                int dist = manhattan(humans[i], corners[c]);\n                if(dist < best_dist) {\n                    best_dist = dist;\n                    best_c = c;\n                }\n            }\n        }\n        if(best_c != -1) {\n            target[i] = corners[best_c];\n            corner_used[best_c] = true;\n        }\n    }\n    \n    // Wall building plan: each human builds walls to create their region\n    // Simple plan: build walls extending from their target corner\n    for(int i=0; i<M; i++) {\n        Pos tgt = target[i];\n        // Build walls to create a rectangular area around their starting position\n        // For simplicity, build a wall along two edges from the corner\n        \n        if(tgt.x == 0 && tgt.y == 0) {\n            // Top-left corner: build right and down\n            for(int y=tgt.y; y<GRID; y++) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x+1; x<GRID; x++) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == 0 && tgt.y == GRID-1) {\n            // Top-right corner\n            for(int y=tgt.y; y>=0; y--) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x+1; x<GRID; x++) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == GRID-1 && tgt.y == 0) {\n            // Bottom-left corner\n            for(int y=tgt.y; y<GRID; y++) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x-1; x>=0; x--) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else if(tgt.x == GRID-1 && tgt.y == GRID-1) {\n            // Bottom-right corner\n            for(int y=tgt.y; y>=0; y--) wall_plan[i].push_back(Pos(tgt.x, y));\n            for(int x=tgt.x-1; x>=0; x--) wall_plan[i].push_back(Pos(x, tgt.y));\n        } else {\n            // Other positions - build a small enclosure\n            wall_plan[i].push_back(tgt);\n        }\n    }\n    \n    // Main game loop\n    for(int turn = 0; turn < TURNS; turn++) {\n        string actions(M, '.');\n        \n        for(int i=0; i<M; i++) {\n            if(state[i] == MOVING) {\n                // Move toward target\n                if(humans[i] == target[i]) {\n                    state[i] = BUILDING;\n                    wall_idx[i] = 0;\n                } else {\n                    auto path = find_path(humans[i], target[i]);\n                    if(!path.empty()) {\n                        int d = path[0];\n                        Pos next_pos = humans[i] + d;\n                        bool blocked = false;\n                        // Check if any other human is building there\n                        // (simplified check)\n                        actions[i] = move_char[d];\n                    } else {\n                        // Path blocked, try to build walls\n                        state[i] = BUILDING;\n                        wall_idx[i] = 0;\n                    }\n                }\n            }\n            \n            if(state[i] == BUILDING) {\n                if(wall_idx[i] < (int)wall_plan[i].size()) {\n                    Pos build_pos = wall_plan[i][wall_idx[i]];\n                    // Check if we can build here\n                    if(can_build(build_pos, i)) {\n                        int d = dir_to(humans[i], build_pos);\n                        if(d != -1 && manhattan(humans[i], build_pos) == 1) {\n                            actions[i] = dir_char[d];\n                            wall_idx[i]++;\n                        } else {\n                            // Need to move closer\n                            auto path = find_path(humans[i], build_pos);\n                            if(!path.empty() && path.size() == 1) {\n                                actions[i] = dir_char[path[0]];\n                                wall_idx[i]++;\n                            } else if(!path.empty()) {\n                                actions[i] = move_char[path[0]];\n                            }\n                        }\n                    } else {\n                        // Can't build here, skip this wall segment\n                        wall_idx[i]++;\n                    }\n                } else {\n                    // Done building, stay\n                    actions[i] = '.';\n                }\n            }\n        }\n        \n        // Output actions\n        cout << actions << endl;\n        cout.flush();\n        \n        // Read pet movements\n        for(int i=0; i<N; i++) {\n            string movement;\n            cin >> movement;\n            if(movement != \".\") {\n                for(char m : movement) {\n                    if(m == 'U') pets[i].pos.x--;\n                    else if(m == 'D') pets[i].pos.x++;\n                    else if(m == 'L') pets[i].pos.y--;\n                    else if(m == 'R') pets[i].pos.y++;\n                }\n            }\n        }\n        \n        // Update human positions and grid\n        for(int i=0; i<M; i++) {\n            char act = actions[i];\n            if(act == 'U') humans[i].x--;\n            else if(act == 'D') humans[i].x++;\n            else if(act == 'L') humans[i].y--;\n            else if(act == 'R') humans[i].y++;\n            else if(act == 'u') impassable[humans[i].x-1][humans[i].y] = true;\n            else if(act == 'd') impassable[humans[i].x+1][humans[i].y] = true;\n            else if(act == 'l') impassable[humans[i].x][humans[i].y-1] = true;\n            else if(act == 'r') impassable[humans[i].x][humans[i].y+1] = true;\n        }\n        \n        // Emergency: if human is trapped with many pets nearby, try to escape\n        // (simplified: just continue with plan)\n    }\n    \n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int MAXL = 200;\n\nint di[] = {-1, 1, 0, 0};\nint dj[] = {0, 0, -1, 1};\nchar dir[] = {'U', 'D', 'L', 'R'};\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), v(19);\n    for (int i = 0; i < 20; i++) cin >> h[i];\n    for (int i = 0; i < 19; i++) cin >> v[i];\n    \n    // Precompute valid moves\n    auto canMove = [&](int i, int j, int d) {\n        int ni = i + di[d], nj = j + dj[d];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n        if (d == 0 && i > 0 && v[i-1][j] == '1') return false;\n        if (d == 1 && i < N-1 && v[i][j] == '1') return false;\n        if (d == 2 && j > 0 && h[i][j-1] == '1') return false;\n        if (d == 3 && j < N-1 && h[i][j] == '1') return false;\n        return true;\n    };\n    \n    // BFS shortest path\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<char>> moveTo(N, vector<char>(N, ' '));\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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            if (!canMove(i, j, d)) continue;\n            int ni = i + di[d], nj = j + dj[d];\n            if (dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                prev[ni][nj] = {i, j};\n                moveTo[ni][nj] = dir[d];\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    string path;\n    {\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path.push_back(moveTo[ci][cj]);\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi; cj = pj;\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    // Initial sequence: repeat shortest path to fill 200\n    string bestSeq;\n    for (int i = 0; i < MAXL; i++) {\n        bestSeq.push_back(path[i % path.size()]);\n    }\n    \n    // Evaluate expected score for a sequence\n    auto eval = [&](const string &seq) {\n        int L = seq.size();\n        vector<vector<double>> prob(N, vector<double>(N, 0));\n        prob[si][sj] = 1.0;\n        double expScore = 0;\n        double probGoalBefore = 0;\n        for (int t = 0; t < L; t++) {\n            char c = seq[t];\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 d = 3;\n            \n            vector<vector<double>> nextProb(N, vector<double>(N, 0));\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (prob[i][j] == 0) continue;\n                    if (i == ti && j == tj) continue; // already absorbed\n                    // forget\n                    nextProb[i][j] += prob[i][j] * p;\n                    // move\n                    if (canMove(i, j, d)) {\n                        int ni = i + di[d], nj = j + dj[d];\n                        nextProb[ni][nj] += prob[i][j] * (1 - p);\n                    } else {\n                        nextProb[i][j] += prob[i][j] * (1 - p);\n                    }\n                }\n            }\n            prob = move(nextProb);\n            double probHere = prob[ti][tj];\n            double newlyReached = probHere - probGoalBefore;\n            expScore += newlyReached * (401 - (t + 1));\n            probGoalBefore = probHere;\n        }\n        return expScore;\n    };\n    \n    double bestScore = eval(bestSeq);\n    \n    // Local search: random modifications\n    mt19937 rng(42);\n    uniform_int_distribution<int> posDist(0, MAXL-1);\n    uniform_int_distribution<int> dirDist(0, 3);\n    \n    for (int iter = 0; iter < 500; iter++) {\n        string cand = bestSeq;\n        int changePos = posDist(rng);\n        char newC = dir[dirDist(rng)];\n        cand[changePos] = newC;\n        double candScore = eval(cand);\n        if (candScore > bestScore) {\n            bestScore = candScore;\n            bestSeq = cand;\n        }\n    }\n    \n    cout << bestSeq << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 30;\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int to[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1}\n};\n\nint tile_type[N][N];\nint rot[N][N];\n\n// Node per edge: node_id[i][j][dir]\nint node_id[N][N][4];\nint node_cnt;\n\n// Each node has 0 or 1 neighbor (degree <= 2 in cycle graph)\nint nxt[3600]; // next node in the cycle, -1 if none\nint prv[3600]; // previous node, for easy removal\n\n// For each node, which cycle it belongs to (index into cycles array)\nint cyc_id[3600];\nint cyc_len[3600];\nint cyc_cnt;\n\n// List of cycles by length (for quick top-2 retrieval)\nvector<int> cycle_lengths;\n\nvoid remove_edge(int u, int v) {\n    if (nxt[u] == v) nxt[u] = -1;\n    if (prv[v] == u) prv[v] = -1;\n    if (nxt[v] == u) nxt[v] = -1;\n    if (prv[u] == v) prv[u] = -1;\n}\n\nvoid add_edge(int u, int v) {\n    nxt[u] = v;\n    prv[v] = u;\n    nxt[v] = u;\n    prv[u] = v;\n}\n\n// Get exit direction for a tile given entry direction\nint get_exit(int type, int r, int entry_dir) {\n    if (to[type][entry_dir] == -1) return -1;\n    return (to[type][entry_dir] + r) % 4;\n}\n\n// Find the connected component (cycle or path) containing a node\n// Returns: cycle length if it's a cycle, 0 if it's a path/dead end\nint trace_component(int start_node, int id_to_assign) {\n    if (nxt[start_node] == -1) {\n        cyc_id[start_node] = -2; // dead end\n        return 0;\n    }\n    \n    // Check if this is part of a cycle\n    // Follow in one direction\n    vector<int> nodes;\n    int cur = start_node;\n    set<int> seen;\n    \n    while (cur != -1 && seen.find(cur) == seen.end()) {\n        seen.insert(cur);\n        nodes.push_back(cur);\n        cur = nxt[cur];\n    }\n    \n    if (cur == start_node) {\n        // It's a cycle\n        int len = nodes.size();\n        for (int x : nodes) {\n            cyc_id[x] = id_to_assign;\n        }\n        return len;\n    }\n    \n    // Check if start is in a cycle by following prv\n    cur = start_node;\n    seen.clear();\n    nodes.clear();\n    while (cur != -1 && seen.find(cur) == seen.end()) {\n        seen.insert(cur);\n        nodes.push_back(cur);\n        cur = prv[cur];\n    }\n    \n    if (cur != -1 && seen.find(cur) != seen.end()) {\n        // Found a cycle from the other direction\n        // Find the cycle node and build the cycle\n        int cycle_start = cur;\n        vector<int> cyc_nodes;\n        int p = cycle_start;\n        do {\n            cyc_nodes.push_back(p);\n            p = nxt[p];\n        } while (p != cycle_start && p != -1);\n        \n        int len = cyc_nodes.size();\n        for (int x : cyc_nodes) cyc_id[x] = id_to_assign;\n        return len;\n    }\n    \n    // It's a path/dead end\n    for (int x : nodes) cyc_id[x] = -2;\n    return 0;\n}\n\n// Recompute all cycles fully (used initially and when incremental becomes messy)\nvoid full_recompute() {\n    fill(cyc_id, cyc_id + node_cnt, -1);\n    fill(cyc_len, cyc_len + node_cnt, 0);\n    cyc_cnt = 0;\n    cycle_lengths.clear();\n    \n    for (int i = 0; i < node_cnt; i++) {\n        if (cyc_id[i] == -1 && nxt[i] != -1) {\n            int len = trace_component(i, cyc_cnt);\n            if (len > 0) {\n                cyc_len[cyc_cnt] = len;\n                cycle_lengths.push_back(len);\n                cyc_cnt++;\n            }\n        }\n    }\n    sort(cycle_lengths.rbegin(), cycle_lengths.rend());\n}\n\nvoid init_graph() {\n    node_cnt = 0;\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                node_id[i][j][d] = node_cnt++;\n    \n    fill(nxt, nxt + node_cnt, -1);\n    fill(prv, prv + node_cnt, -1);\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 exit_dir = get_exit(tile_type[i][j], rot[i][j], d);\n                if (exit_dir == -1) continue;\n                int ni = i + di[exit_dir];\n                int nj = j + dj[exit_dir];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nd = (exit_dir + 2) % 4;\n                int exit2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                if (exit2 == d) {\n                    int u = node_id[i][j][d];\n                    int v = node_id[ni][nj][exit_dir];\n                    if (nxt[u] == -1 && nxt[v] == -1) {\n                        add_edge(u, v);\n                    }\n                }\n            }\n        }\n    }\n}\n\nint get_score_from_lengths() {\n    if (cycle_lengths.empty()) return 0;\n    if (cycle_lengths.size() == 1) return 0;\n    return cycle_lengths[0] * cycle_lengths[1];\n}\n\n// Update cycles after changing tile (i,j)\nvoid update_after_change(int i, int j) {\n    // The edges of this tile may have changed, but we do full recompute for simplicity\n    // since incremental is complex to maintain correctly\n    full_recompute();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start_time = high_resolution_clock::now();\n    \n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++) {\n            tile_type[i][j] = s[j] - '0';\n        }\n    }\n    \n    mt19937 rng(42);\n    \n    // Initialize to maximize local connections\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            rot[i][j] = rng() % 4;\n    \n    // Greedy local optimization\n    auto count_connections_at = [&](int i, int j, int r) {\n        int cnt = 0;\n        for (int d = 0; d < 4; d++) {\n            int ex = get_exit(tile_type[i][j], r, d);\n            if (ex == -1) continue;\n            int ni = i + di[ex], nj = j + dj[ex];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            int nd = (ex + 2) % 4;\n            int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n            if (ex2 == d) cnt++;\n        }\n        return cnt;\n    };\n    \n    for (int iter = 0; iter < 10; iter++) {\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int best_r = rot[i][j];\n                int best_c = count_connections_at(i, j, rot[i][j]);\n                for (int r = 0; r < 4; r++) {\n                    int c = count_connections_at(i, j, r);\n                    if (c > best_c) {\n                        best_c = c; best_r = r;\n                    }\n                }\n                rot[i][j] = best_r;\n            }\n        }\n    }\n    \n    init_graph();\n    full_recompute();\n    int best_score = get_score_from_lengths();\n    int cur_score = best_score;\n    int best_rot[N][N];\n    memcpy(best_rot, rot, sizeof(rot));\n    \n    uniform_real_distribution<> prob(0, 1);\n    uniform_int_distribution<> pos(0, N-1);\n    uniform_int_distribution<> rdelta(1, 3);\n    \n    double temp = 20.0;\n    double alpha = 0.9999;\n    int iter_cnt = 0;\n    const int MAX_ITER = 300000;\n    \n    while (true) {\n        auto now = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(now - start_time).count() > 1950) break;\n        if (iter_cnt >= MAX_ITER) break;\n        \n        int i = pos(rng), j = pos(rng);\n        int old_r = rot[i][j];\n        int new_r = (old_r + rdelta(rng)) % 4;\n        rot[i][j] = new_r;\n        \n        // Rebuild affected parts and compute new score\n        // For efficiency, we just rebuild the whole graph but skip if we can\n        // Actually, let's do incremental rebuild of just this tile's edges\n        \n        // Remove old edges of tile (i,j)\n        for (int d = 0; d < 4; d++) {\n            int ex = get_exit(tile_type[i][j], old_r, d);\n            if (ex != -1) {\n                int ni = i + di[ex], nj = j + dj[ex];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int nd = (ex + 2) % 4;\n                    int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                    if (ex2 == d) {\n                        int u = node_id[i][j][d];\n                        int v = node_id[ni][nj][ex];\n                        if (nxt[u] == v) remove_edge(u, v);\n                    }\n                }\n            }\n        }\n        \n        // Add new edges\n        for (int d = 0; d < 4; d++) {\n            int ex = get_exit(tile_type[i][j], new_r, d);\n            if (ex != -1) {\n                int ni = i + di[ex], nj = j + dj[ex];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int nd = (ex + 2) % 4;\n                    int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                    if (ex2 == d) {\n                        int u = node_id[i][j][d];\n                        int v = node_id[ni][nj][ex];\n                        if (nxt[u] == -1 && nxt[v] == -1) {\n                            add_edge(u, v);\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Need to recompute cycles that were affected\n        // For simplicity, do full recompute (but this is expensive)\n        // Actually, let's identify affected nodes and only recompute their components\n        // But for now, do full to ensure correctness\n        full_recompute();\n        int new_score = get_score_from_lengths();\n        \n        if (new_score > best_score) {\n            best_score = new_score;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n        \n        if (new_score >= cur_score || prob(rng) < exp((new_score - cur_score) / temp)) {\n            cur_score = new_score;\n            // keep changes\n        } else {\n            // revert\n            rot[i][j] = old_r;\n            // remove new edges\n            for (int d = 0; d < 4; d++) {\n                int ex = get_exit(tile_type[i][j], new_r, d);\n                if (ex != -1) {\n                    int ni = i + di[ex], nj = j + dj[ex];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        int nd = (ex + 2) % 4;\n                        int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                        if (ex2 == d) {\n                            int u = node_id[i][j][d];\n                            int v = node_id[ni][nj][ex];\n                            if (nxt[u] == v) remove_edge(u, v);\n                        }\n                    }\n                }\n            }\n            // add back old edges\n            for (int d = 0; d < 4; d++) {\n                int ex = get_exit(tile_type[i][j], old_r, d);\n                if (ex != -1) {\n                    int ni = i + di[ex], nj = j + dj[ex];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        int nd = (ex + 2) % 4;\n                        int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                        if (ex2 == d) {\n                            int u = node_id[i][j][d];\n                            int v = node_id[ni][nj][ex];\n                            if (nxt[u] == -1 && nxt[v] == -1) {\n                                add_edge(u, v);\n                            }\n                        }\n                    }\n                }\n            }\n            full_recompute();\n            cur_score = get_score_from_lengths(); // should be same as before\n        }\n        \n        temp *= alpha;\n        iter_cnt++;\n    }\n    \n    // Output best found\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cout << best_rot[i][j];\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 10;\nint N, T;\nint empty_r, empty_c;\nvector<string> board;\n\nconst int dr[] = {0, -1, 0, 1};\nconst int dc[] = {-1, 0, 1, 0};\nconst char dir_char[] = {'L', 'U', 'R', 'D'};\nconst int bit[] = {1, 2, 4, 8};\nconst int opp_dir[] = {2, 3, 0, 1};\n\nauto start_time = chrono::steady_clock::now();\n\nbool in_board(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nint tile_val(char c) {\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return c - '0';\n}\n\nchar val_to_char(int v) {\n    if (v < 10) return '0' + v;\n    return 'a' + (v - 10);\n}\n\nbool has_line(char tile, int d) {\n    return (tile_val(tile) & bit[d]) != 0;\n}\n\nbool is_connected(const vector<string>& b, int r1, int c1, int r2, int c2) {\n    if (!in_board(r1, c1) || !in_board(r2, c2)) return false;\n    if (b[r1][c1] == '0' || b[r2][c2] == '0') return false;\n    if (r1 == r2 && c1 + 1 == c2) {\n        return has_line(b[r1][c1], 2) && has_line(b[r2][c2], 0);\n    }\n    if (r1 == r2 && c1 - 1 == c2) {\n        return has_line(b[r1][c1], 0) && has_line(b[r2][c2], 2);\n    }\n    if (r1 + 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 3) && has_line(b[r2][c2], 1);\n    }\n    if (r1 - 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 1) && has_line(b[r2][c2], 3);\n    }\n    return false;\n}\n\n// Detailed evaluation: returns max tree size, total trees, potential connections\ntuple<int, int, int> analyze(const vector<string>& b) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    int max_tree = 0;\n    int total_trees = 0;\n    int potential = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] == '0' || vis[i][j]) continue;\n            \n            queue<pair<int,int>> q;\n            q.push({i, j});\n            vis[i][j] = true;\n            int edges = 0;\n            int nodes = 0;\n            set<pair<int,int>> comp;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front(); q.pop();\n                nodes++;\n                comp.insert({r, c});\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (in_board(nr, nc) && b[nr][nc] != '0') {\n                        if (is_connected(b, r, c, nr, nc)) {\n                            edges++;\n                            if (!vis[nr][nc]) {\n                                vis[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        } else {\n                            // Check if connection is one-sided (potential)\n                            if (has_line(b[r][c], d) || \n                                (in_board(nr, nc) && has_line(b[nr][nc], opp_dir[d]))) {\n                                potential++;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            edges /= 2;\n            if (edges == nodes - 1) {\n                max_tree = max(max_tree, nodes);\n                total_trees++;\n            } else if (nodes > edges + 1) {\n                // Has cycles, but we count nodes anyway for potential\n                max_tree = max(max_tree, nodes);\n            }\n        }\n    }\n    \n    return {max_tree, total_trees, potential};\n}\n\nint evaluate(const vector<string>& b) {\n    auto [max_tree, total_trees, potential] = analyze(b);\n    // Heavily reward large trees\n    return max_tree * 10000 + total_trees * 100 + potential;\n}\n\n// Apply moves to a board\nvoid apply_moves(vector<string>& b, int& er, int& ec, const string& moves) {\n    for (char c : moves) {\n        int d;\n        if (c == 'L') d = 0;\n        else if (c == 'U') d = 1;\n        else if (c == 'R') d = 2;\n        else d = 3;\n        \n        int nr = er + dr[d];\n        int nc = ec + dc[d];\n        swap(b[er][ec], b[nr][nc]);\n        er = nr;\n        ec = nc;\n    }\n}\n\n// Beam search from a given state, returns best moves found\nstring beam_search(vector<string> b, int er, int ec, int max_depth, int beam_width, \n                   int& best_eval, string current_moves = \"\") {\n    struct State {\n        vector<string> b;\n        int er, ec;\n        string moves;\n        int eval;\n    };\n    \n    vector<State> beam;\n    beam.push_back({b, er, ec, current_moves, evaluate(b)});\n    best_eval = beam[0].eval;\n    string best_moves = current_moves;\n    \n    unordered_set<string> seen;\n    string init_hash;\n    for (int i = 0; i < N; i++) init_hash += b[i];\n    seen.insert(init_hash);\n    \n    for (int depth = 0; depth < max_depth; depth++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2800) break;\n        \n        vector<State> next_states;\n        \n        for (const auto& s : beam) {\n            for (int d = 0; d < 4; d++) {\n                int nr = s.er + dr[d];\n                int nc = s.ec + dc[d];\n                if (!in_board(nr, nc)) continue;\n                \n                // Avoid direct undos\n                if (!s.moves.empty()) {\n                    char last = s.moves.back();\n                    if ((last == 'L' && d == 2) || (last == 'R' && d == 0) ||\n                        (last == 'U' && d == 3) || (last == 'D' && d == 1)) {\n                        continue;\n                    }\n                }\n                \n                State ns = s;\n                swap(ns.b[ns.er][ns.ec], ns.b[nr][nc]);\n                ns.er = nr;\n                ns.ec = nc;\n                ns.moves += dir_char[d];\n                \n                string h;\n                for (int i = 0; i < N; i++) h += ns.b[i];\n                \n                if (seen.count(h)) continue;\n                seen.insert(h);\n                \n                ns.eval = evaluate(ns.b);\n                if (ns.eval > best_eval) {\n                    best_eval = ns.eval;\n                    best_moves = ns.moves;\n                }\n                \n                next_states.push_back(move(ns));\n            }\n        }\n        \n        if (next_states.empty()) break;\n        \n        sort(next_states.begin(), next_states.end(),\n             [](const State& a, const State& b) { return a.eval > b.eval; });\n        \n        beam.clear();\n        for (int i = 0; i < min((int)next_states.size(), beam_width); i++) {\n            beam.push_back(move(next_states[i]));\n        }\n    }\n    \n    return best_moves;\n}\n\n// Find disconnected components and try to merge them\nvector<vector<pair<int,int>>> find_components(const vector<string>& b) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> components;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] == '0' || vis[i][j]) continue;\n            \n            vector<pair<int,int>> comp;\n            queue<pair<int,int>> q;\n            q.push({i, j});\n            vis[i][j] = true;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front(); q.pop();\n                comp.push_back({r, c});\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (in_board(nr, nc) && b[nr][nc] != '0' && !vis[nr][nc]) {\n                        if (is_connected(b, r, c, nr, nc)) {\n                            vis[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n            }\n            \n            // Check if this component is a tree\n            int edges = 0;\n            for (auto [r, c] : comp) {\n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (in_board(nr, nc) && b[nr][nc] != '0') {\n                        if (is_connected(b, r, c, nr, nc)) edges++;\n                    }\n                }\n            }\n            edges /= 2;\n            \n            if (edges == (int)comp.size() - 1) {\n                components.push_back(comp);\n            }\n        }\n    }\n    \n    sort(components.begin(), components.end(), \n         [](const auto& a, const auto& b) { return a.size() > b.size(); });\n    \n    return components;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0') {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    start_time = chrono::steady_clock::now();\n    \n    string all_moves;\n    \n    // Phase 1: Initial beam search to improve tree size\n    int current_eval = evaluate(board);\n    \n    // Do multiple rounds of beam search with increasing depth\n    for (int round = 0; round < 5; round++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2500) break;\n        \n        int best_eval;\n        int search_depth = min(200, T - (int)all_moves.length());\n        if (search_depth <= 0) break;\n        \n        string new_moves = beam_search(board, empty_r, empty_c, search_depth, 80, best_eval, \"\");\n        \n        if (!new_moves.empty() && best_eval > current_eval) {\n            apply_moves(board, empty_r, empty_c, new_moves);\n            all_moves += new_moves;\n            current_eval = best_eval;\n        } else {\n            break; // No improvement\n        }\n    }\n    \n    // Phase 2: Try to connect components\n    while ((int)all_moves.length() < T) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2800) break;\n        \n        auto components = find_components(board);\n        if (components.size() <= 1) break; // Already one tree\n        \n        // Find two largest components\n        auto& comp1 = components[0];\n        auto& comp2 = components[1];\n        \n        // Find closest pair of tiles between components\n        int min_dist = N * N;\n        pair<int,int> t1, t2;\n        \n        for (auto [r1, c1] : comp1) {\n            for (auto [r2, c2] : comp2) {\n                int dist = abs(r1 - r2) + abs(c1 - c2);\n                if (dist < min_dist) {\n                    min_dist = dist;\n                    t1 = {r1, c1};\n                    t2 = {r2, c2};\n                }\n            }\n        }\n        \n        // Try beam search to bring them together\n        int remaining = T - all_moves.length();\n        int search_depth = min(150, remaining);\n        if (search_depth <= 0) break;\n        \n        int best_eval;\n        string new_moves = beam_search(board, empty_r, empty_c, search_depth, 50, best_eval, \"\");\n        \n        if (!new_moves.empty() && best_eval > current_eval) {\n            apply_moves(board, empty_r, empty_c, new_moves);\n            all_moves += new_moves;\n            current_eval = best_eval;\n        } else {\n            break;\n        }\n    }\n    \n    // Phase 3: Final improvement pass\n    if ((int)all_moves.length() < T) {\n        int remaining = T - all_moves.length();\n        int search_depth = min(remaining, 300);\n        \n        int best_eval;\n        string new_moves = beam_search(board, empty_r, empty_c, search_depth, 120, best_eval, \"\");\n        \n        if (!new_moves.empty() && best_eval >= current_eval) {\n            all_moves += new_moves;\n        }\n    }\n    \n    cout << all_moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n    Point(long long x = 0, long long y = 0) : x(x), y(y) {}\n    \n    Point operator-(const Point& other) const {\n        return Point(x - other.x, y - other.y);\n    }\n    \n    long long dot(const Point& other) const {\n        return x * other.x + y * other.y;\n    }\n    \n    long long cross(const Point& other) const {\n        return x * other.y - y * other.x;\n    }\n    \n    long long dist2() const {\n        return x * x + y * y;\n    }\n    \n    double dist() const {\n        return sqrt(dist2());\n    }\n    \n    double angle() const {\n        return atan2(y, x);\n    }\n    \n    bool operator<(const Point& other) const {\n        return angle() < other.angle();\n    }\n};\n\nstruct Strawberry {\n    double x, y;\n    int id;\n    Strawberry(double x = 0, double y = 0, int id = 0) : x(x), y(y), id(id) {}\n};\n\n// Generate a line that separates two points\npair<pair<long long, long long>, pair<long long, long long>> \nseparatingLine(const Point& p1, const Point& p2) {\n    // Midpoint\n    double mx = (p1.x + p2.x) / 2.0;\n    double my = (p1.y + p2.y) / 2.0;\n    \n    // Direction perpendicular to the line connecting p1 and p2\n    double dx = p2.y - p1.y;\n    double dy = p1.x - p2.x;\n    \n    // Scale to get integer coordinates within range\n    double scale = 1e9 / max(abs(dx), abs(dy));\n    dx *= scale;\n    dy *= scale;\n    \n    long long px = (long long)(mx - dx);\n    long long py = (long long)(my - dy);\n    long long qx = (long long)(mx + dx);\n    long long qy = (long long)(my + dy);\n    \n    // Clamp to valid range\n    auto clamp = [](long long& v) {\n        v = max(-1000000000LL, min(1000000000LL, v));\n    };\n    clamp(px); clamp(py); clamp(qx); clamp(qy);\n    \n    return {{px, py}, {qx, qy}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> a(10);\n    for (int i = 0; i < 10; i++) {\n        cin >> a[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Strategy: Use angular partitioning + some additional cuts\n    vector<pair<double, int>> angles;\n    for (int i = 0; i < N; i++) {\n        angles.push_back({atan2(strawberries[i].y, strawberries[i].x), i});\n    }\n    sort(angles.begin(), angles.end());\n    \n    vector<pair<pair<long long, long long>, pair<long long, long long>>> lines;\n    \n    // Create pie-slice cuts from center\n    int num_cuts = min(K, N);\n    \n    // Try to make cuts that separate groups of strawberries\n    // Use lines through origin at specific angles\n    for (int i = 0; i < num_cuts; i++) {\n        double angle1 = 2.0 * M_PI * i / num_cuts;\n        double angle2 = angle1 + M_PI;\n        \n        long long x1 = (long long)(1000000000.0 * cos(angle1));\n        long long y1 = (long long)(1000000000.0 * sin(angle1));\n        long long x2 = (long long)(1000000000.0 * cos(angle2));\n        long long y2 = (long long)(1000000000.0 * sin(angle2));\n        \n        // Ensure points are distinct\n        if (abs(x1 - x2) < 2 && abs(y1 - y2) < 2) {\n            x2 = -x1;\n            y2 = -y1;\n        }\n        \n        lines.push_back({{x1, y1}, {x2, y2}});\n    }\n    \n    // Add some grid-like cuts to better isolate strawberries\n    int remaining_cuts = K - num_cuts;\n    if (remaining_cuts > 0) {\n        // Add horizontal and vertical cuts\n        for (int i = 0; i < min(remaining_cuts / 2, 20); i++) {\n            long long offset = (long long)((i + 1) * 5000);\n            // Horizontal line\n            lines.push_back({{-1000000000, offset}, {1000000000, offset}});\n            if (lines.size() >= K) break;\n            // Vertical line\n            lines.push_back({{offset, -1000000000}, {offset, 1000000000}});\n            if (lines.size() >= K) break;\n        }\n    }\n    \n    // Also add some diagonal cuts for better separation\n    remaining_cuts = K - lines.size();\n    if (remaining_cuts > 0) {\n        for (int i = 0; i < min(remaining_cuts, 10); i++) {\n            long long offset = (long long)((i + 1) * 3000);\n            lines.push_back({{-1000000000, -1000000000 + offset * 2}, \n                           {1000000000 - offset * 2, 1000000000}});\n        }\n    }\n    \n    // Ensure we don't exceed K\n    if (lines.size() > K) {\n        lines.resize(K);\n    }\n    \n    // Output\n    cout << lines.size() << '\\n';\n    for (const auto& line : lines) {\n        cout << line.first.first << ' ' << line.first.second << ' '\n             << line.second.first << ' ' << line.second.second << '\\n';\n    }\n    \n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing P = pair<int,int>;\n\nint N, M, C;\nset<P> dots;\nvector<array<P,4>> operations;\nvector<pair<P,P>> segment_list;\n\nll weight(int x, int y) {\n    return (ll)(x-C)*(x-C) + (ll)(y-C)*(y-C) + 1;\n}\n\nbool in_grid(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\nbool has_dot(int x, int y) {\n    return dots.count({x,y});\n}\n\n// Check if two collinear segments overlap\nbool segments_overlap(P a1, P a2, P b1, P b2) {\n    ll cross = (ll)(a2.first - a1.first) * (b2.second - b1.second) - \n               (ll)(a2.second - a1.second) * (b2.first - b1.first);\n    if (cross != 0) return false;\n    \n    ll cross2 = (ll)(b1.first - a1.first) * (a2.second - a1.second) - \n                (ll)(b1.second - a1.second) * (a2.first - a1.first);\n    if (cross2 != 0) return false;\n    \n    ll dir_x = a2.first - a1.first;\n    ll dir_y = a2.second - a1.second;\n    \n    auto project = [&](P p) -> ll {\n        return (ll)(p.first - a1.first) * dir_x + (ll)(p.second - a1.second) * dir_y;\n    };\n    \n    ll t1 = 0, t2 = project(a2);\n    ll s1 = project(b1), s2 = project(b2);\n    if (t1 > t2) swap(t1, t2);\n    if (s1 > s2) swap(s1, s2);\n    \n    return max(t1, s1) < min(t2, s2);\n}\n\nbool would_overlap(P a, P b) {\n    for (auto &seg : segment_list) {\n        if (segments_overlap(a, b, seg.first, seg.second))\n            return true;\n    }\n    return false;\n}\n\nbool clear_path(P a, P b, const set<P> &allowed) {\n    int dx = b.first - a.first;\n    int dy = b.second - a.second;\n    int g = __gcd(abs(dx), abs(dy));\n    int sx = dx / g;\n    int sy = dy / g;\n    for (int i = 1; i < g; i++) {\n        int cx = a.first + i * sx;\n        int cy = a.second + i * sy;\n        if (has_dot(cx, cy) && !allowed.count({cx, cy}))\n            return false;\n    }\n    return true;\n}\n\nbool is_valid_rect(P p1, P p2, P p3, P p4) {\n    if (has_dot(p1.first, p1.second)) return false;\n    if (!has_dot(p2.first, p2.second)) return false;\n    if (!has_dot(p3.first, p3.second)) return false;\n    if (!has_dot(p4.first, p4.second)) return false;\n    \n    set<P> allowed = {p2, p3, p4};\n    \n    if (!clear_path(p1, p2, allowed)) return false;\n    if (!clear_path(p2, p3, allowed)) return false;\n    if (!clear_path(p3, p4, allowed)) return false;\n    if (!clear_path(p4, p1, allowed)) return false;\n    \n    if (would_overlap(p1, p2)) return false;\n    if (would_overlap(p2, p3)) return false;\n    if (would_overlap(p3, p4)) return false;\n    if (would_overlap(p4, p1)) return false;\n    \n    return true;\n}\n\n// Try to find a valid rectangle for p1\nbool try_find_rect(P p1) {\n    int x = p1.first, y = p1.second;\n    \n    // Try axis-aligned rectangles with increasing size\n    for (int max_d = 1; max_d <= N; max_d++) {\n        for (int dx = 1; dx <= max_d; dx++) {\n            for (int dy = 1; dy <= max_d; dy++) {\n                if (dx != max_d && dy != max_d) continue;\n                \n                // p1 bottom-left\n                {\n                    P p2 = {x+dx, y};\n                    P p3 = {x+dx, y+dy};\n                    P p4 = {x, y+dy};\n                    if (in_grid(p2.first, p2.second) && in_grid(p3.first, p3.second) && in_grid(p4.first, p4.second))\n                        if (is_valid_rect(p1, p2, p3, p4)) {\n                            operations.push_back({p1, p2, p3, p4});\n                            return true;\n                        }\n                }\n                // p1 bottom-right\n                {\n                    P p2 = {x-dx, y};\n                    P p3 = {x-dx, y+dy};\n                    P p4 = {x, y+dy};\n                    if (in_grid(p2.first, p2.second) && in_grid(p3.first, p3.second) && in_grid(p4.first, p4.second))\n                        if (is_valid_rect(p1, p2, p3, p4)) {\n                            operations.push_back({p1, p2, p3, p4});\n                            return true;\n                        }\n                }\n                // p1 top-right\n                {\n                    P p2 = {x-dx, y};\n                    P p3 = {x-dx, y-dy};\n                    P p4 = {x, y-dy};\n                    if (in_grid(p2.first, p2.second) && in_grid(p3.first, p3.second) && in_grid(p4.first, p4.second))\n                        if (is_valid_rect(p1, p2, p3, p4)) {\n                            operations.push_back({p1, p2, p3, p4});\n                            return true;\n                        }\n                }\n                // p1 top-left\n                {\n                    P p2 = {x+dx, y};\n                    P p3 = {x+dx, y-dy};\n                    P p4 = {x, y-dy};\n                    if (in_grid(p2.first, p2.second) && in_grid(p3.first, p3.second) && in_grid(p4.first, p4.second))\n                        if (is_valid_rect(p1, p2, p3, p4)) {\n                            operations.push_back({p1, p2, p3, p4});\n                            return true;\n                        }\n                }\n            }\n        }\n    }\n    \n    // Try 45-degree rotated squares\n    for (int d = 1; d < N; d++) {\n        vector<array<P,4>> diags = {\n            {{{x,y}, {x+d, y+d}, {x, y+2*d}, {x-d, y+d}}},\n            {{{x,y}, {x+d, y-d}, {x+2*d, y}, {x+d, y+d}}},\n            {{{x,y}, {x-d, y-d}, {x, y-2*d}, {x+d, y-d}}},\n            {{{x,y}, {x-d, y+d}, {x-2*d, y}, {x-d, y-d}}}\n        };\n        for (auto &r : diags) {\n            bool ok = true;\n            for (auto &p : r) if (!in_grid(p.first, p.second)) { ok = false; break; }\n            if (!ok) continue;\n            if (is_valid_rect(r[0], r[1], r[2], r[3])) {\n                operations.push_back(r);\n                return true;\n            }\n        }\n    }\n    \n    return false;\n}\n\nvoid execute_move(const array<P,4> &r) {\n    dots.insert(r[0]);\n    segment_list.push_back({r[0], r[1]});\n    segment_list.push_back({r[1], r[2]});\n    segment_list.push_back({r[2], r[3]});\n    segment_list.push_back({r[3], r[0]});\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.8; // seconds\n    \n    cin >> N >> M;\n    C = (N-1)/2;\n    \n    for (int i = 0; i < M; i++) {\n        int x, y; cin >> x >> y;\n        dots.insert({x,y});\n    }\n    \n    // Generate candidate points sorted by weight (highest first)\n    vector<P> candidates;\n    for (int x = 0; x < N; x++)\n        for (int y = 0; y < N; y++)\n            if (!has_dot(x,y))\n                candidates.push_back({x,y});\n    \n    sort(candidates.begin(), candidates.end(), [](P a, P b) {\n        return weight(a.first, a.second) > weight(b.first, b.second);\n    });\n    \n    // Greedy with time limit\n    bool progress = true;\n    while (progress) {\n        progress = false;\n        \n        // Check time\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        for (auto &p1 : candidates) {\n            if (has_dot(p1.first, p1.second)) continue;\n            \n            // Check time periodically\n            if (rand() % 100 == 0) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - start_time).count();\n                if (elapsed > TIME_LIMIT) goto finish;\n            }\n            \n            if (try_find_rect(p1)) {\n                execute_move(operations.back());\n                progress = true;\n                break; // Restart from highest weight\n            }\n        }\n    }\n    \nfinish:\n    // Output\n    cout << operations.size() << \"\\n\";\n    for (auto &op : operations) {\n        for (int i = 0; i < 4; i++)\n            cout << op[i].first << \" \" << op[i].second << (i==3 ? \"\\n\" : \" \");\n    }\n    \n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\n\nint grid[N][N];\nint flavor[100];\nint total_count[4]; // total of each flavor\nint placed_count[4]; // placed so far\nint remaining[4]; // remaining\n\nchar dc[4] = {'L', 'R', 'F', 'B'};\n\nvoid tilt(int g[N][N], int d) {\n    if (d == 0) {\n        for (int i = 0; i < N; i++) {\n            int p = 0;\n            for (int j = 0; j < N; j++) if (g[i][j]) g[i][p++] = g[i][j];\n            while (p < N) g[i][p++] = 0;\n        }\n    } else if (d == 1) {\n        for (int i = 0; i < N; i++) {\n            int p = N-1;\n            for (int j = N-1; j >= 0; j--) if (g[i][j]) g[i][p--] = g[i][j];\n            while (p >= 0) g[i][p--] = 0;\n        }\n    } else if (d == 2) {\n        for (int j = 0; j < N; j++) {\n            int p = 0;\n            for (int i = 0; i < N; i++) if (g[i][j]) g[p++][j] = g[i][j];\n            while (p < N) g[p++][j] = 0;\n        }\n    } else {\n        for (int j = 0; j < N; j++) {\n            int p = N-1;\n            for (int i = N-1; i >= 0; i--) if (g[i][j]) g[p--][j] = g[i][j];\n            while (p >= 0) g[p--][j] = 0;\n        }\n    }\n}\n\nint64_t eval(int g[N][N]) {\n    bool vis[N][N] = {};\n    int64_t res = 0;\n    int qx[100], qy[100];\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!g[i][j] || vis[i][j]) continue;\n            int f = g[i][j], cnt = 0;\n            int h = 0, t = 0;\n            qx[0] = i; qy[0] = j;\n            vis[i][j] = 1;\n            while (h <= t) {\n                int x = qx[h], y = qy[h]; h++; cnt++;\n                if (x>0 && !vis[x-1][y] && g[x-1][y]==f) \n                    vis[x-1][y]=1, qx[++t]=x-1, qy[t]=y;\n                if (x<N-1 && !vis[x+1][y] && g[x+1][y]==f) \n                    vis[x+1][y]=1, qx[++t]=x+1, qy[t]=y;\n                if (y>0 && !vis[x][y-1] && g[x][y-1]==f) \n                    vis[x][y-1]=1, qx[++t]=x, qy[t]=y-1;\n                if (y<N-1 && !vis[x][y+1] && g[x][y+1]==f) \n                    vis[x][y+1]=1, qx[++t]=x, qy[t]=y+1;\n            }\n            res += 1LL * cnt * cnt;\n        }\n    }\n    return res;\n}\n\n// Quick simulation: simulate just a few steps and return estimated score\nint64_t quick_sim(int g[N][N], int step, int sims) {\n    int64_t total = 0;\n    \n    // Precompute list of empty cells for each simulation\n    for (int s = 0; s < sims; s++) {\n        int tmp[N][N];\n        memcpy(tmp, g, sizeof(tmp));\n        \n        // Simulate next moves with a simple greedy heuristic\n        int look = min(10, 100 - step);  // Look ahead at most 10 steps\n        for (int k = 0; k < look; k++) {\n            int f = flavor[step + k];\n            \n            // Find all empty positions\n            vector<pair<int,int>> empty;\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (!tmp[i][j]) empty.push_back({i,j});\n            \n            if (empty.empty()) break;\n            \n            // Pick random empty position (pseudo-random based on step+k+s)\n            int idx = (step * 7 + k * 13 + s * 3) % empty.size();\n            tmp[empty[idx].first][empty[idx].second] = f;\n            \n            // Greedily tilt\n            int best_d = 0;\n            int64_t best_sc = -1;\n            for (int d = 0; d < 4; d++) {\n                int tmp2[N][N];\n                memcpy(tmp2, tmp, sizeof(tmp));\n                tilt(tmp2, d);\n                int64_t sc = eval(tmp2);\n                if (sc > best_sc) { best_sc = sc; best_d = d; }\n            }\n            tilt(tmp, best_d);\n        }\n        \n        total += eval(tmp);\n    }\n    return total / sims;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    memset(total_count, 0, sizeof(total_count));\n    for (int i = 0; i < 100; i++) {\n        cin >> flavor[i];\n        total_count[flavor[i]]++;\n    }\n    \n    memset(grid, 0, sizeof(grid));\n    memset(placed_count, 0, sizeof(placed_count));\n    \n    for (int step = 0; step < 100; step++) {\n        int p; cin >> p;\n        \n        // Find p-th empty cell\n        int cnt = 0, r = 0, c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (!grid[i][j] && ++cnt == p) {\n                    r = i; c = j;\n                    i = N; break;\n                }\n            }\n        }\n        \n        int f = flavor[step];\n        placed_count[f]++;\n        grid[r][c] = f;\n        \n        // Try all directions\n        int best_d = 0;\n        int64_t best_score = -1;\n        \n        for (int d = 0; d < 4; d++) {\n            int tmp[N][N];\n            memcpy(tmp, grid, sizeof(grid));\n            tilt(tmp, d);\n            \n            int64_t base = eval(tmp);\n            \n            // Add small simulation bonus if we have time (only early steps need it)\n            int64_t bonus = 0;\n            if (step < 80) { // Only simulate when enough remaining steps\n                bonus = quick_sim(tmp, step + 1, 3); // Just 3 quick sims\n            }\n            \n            int64_t score = base * 10 + bonus; // Weight base heavily\n            \n            if (score > best_score) {\n                best_score = score;\n                best_d = d;\n            }\n        }\n        \n        tilt(grid, best_d);\n        cout << dc[best_d] << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\n// Random number generator\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n// Compute degree sequence from graph string\nvector<int> get_degrees(const string& g, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute feature vector for a graph\nvector<double> compute_features(const string& g, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    int edges = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n                edges++;\n            }\n            idx++;\n        }\n    }\n    \n    // Feature 1: Number of edges (normalized)\n    double max_edges = N * (N - 1) / 2.0;\n    double edge_ratio = edges / max_edges;\n    \n    // Feature 2: Degree statistics\n    sort(deg.begin(), deg.end());\n    double mean_deg = 0, var_deg = 0;\n    for (int d : deg) mean_deg += d;\n    mean_deg /= N;\n    for (int d : deg) var_deg += (d - mean_deg) * (d - mean_deg);\n    var_deg /= N;\n    \n    // Feature 3: Degree distribution quantiles\n    vector<double> features;\n    features.push_back(edge_ratio);\n    features.push_back(mean_deg / (N - 1));\n    features.push_back(sqrt(var_deg) / (N - 1));\n    \n    // Quantiles of degree distribution\n    for (int p : {10, 25, 50, 75, 90}) {\n        features.push_back(deg[min(N-1, N * p / 100)] / (double)(N - 1));\n    }\n    \n    return features;\n}\n\n// Generate a graph with specified edge probability\nstring generate_random_graph(int N, double p) {\n    string g;\n    int m = N * (N - 1) / 2;\n    uniform_real_distribution<> dis(0.0, 1.0);\n    for (int i = 0; i < m; i++) {\n        g += (dis(rng) < p) ? '1' : '0';\n    }\n    return g;\n}\n\n// Generate M distinctive graphs\nvector<string> generate_graphs(int N, int M, double eps) {\n    vector<string> graphs;\n    set<string> used;\n    \n    // Strategy: Generate graphs with different edge densities\n    // Use multiple rounds to ensure diversity\n    double base_p = 0.1;\n    double step = 0.8 / max(1, M - 1);\n    \n    for (int k = 0; k < M; k++) {\n        double p = base_p + k * step;\n        p = min(0.9, max(0.05, p));\n        \n        string best_g;\n        double best_dist = -1;\n        \n        // Try multiple times to get well-separated features\n        for (int trial = 0; trial < 20; trial++) {\n            string g = generate_random_graph(N, p);\n            if (used.count(g)) continue;\n            \n            auto feat = compute_features(g, N);\n            \n            // Calculate minimum distance to existing graphs\n            double min_dist = 1e9;\n            for (const auto& existing : graphs) {\n                auto feat2 = compute_features(existing, N);\n                double dist = 0;\n                for (size_t i = 0; i < feat.size(); i++) {\n                    dist += (feat[i] - feat2[i]) * (feat[i] - feat2[i]);\n                }\n                min_dist = min(min_dist, sqrt(dist));\n            }\n            \n            if (graphs.empty() || min_dist > best_dist) {\n                best_dist = min_dist;\n                best_g = g;\n            }\n        }\n        \n        if (best_dist < 0) {\n            best_g = generate_random_graph(N, p);\n        }\n        \n        graphs.push_back(best_g);\n        used.insert(best_g);\n    }\n    \n    return graphs;\n}\n\n// Predict which original graph generated H\nint predict(const string& H, const vector<string>& graphs, int N, double eps) {\n    auto feat_H = compute_features(H, N);\n    \n    int best_idx = 0;\n    double best_score = -1e9;\n    \n    // Calculate expected noise variance\n    double noise_std = sqrt(eps * (1 - eps));\n    \n    for (int k = 0; k < (int)graphs.size(); k++) {\n        auto feat_G = compute_features(graphs[k], N);\n        \n        // Compute weighted distance\n        double score = 0;\n        for (size_t i = 0; i < feat_H.size(); i++) {\n            double diff = feat_H[i] - feat_G[i];\n            // Weight by feature importance and noise sensitivity\n            double weight = 1.0;\n            if (i == 0) weight = 5.0;  // Edge ratio is very informative\n            score -= weight * diff * diff / (noise_std * noise_std + 0.01);\n        }\n        \n        if (score > best_score) {\n            best_score = score;\n            best_idx = k;\n        }\n    }\n    \n    return best_idx;\n}\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 N based on M and eps\n    // Smaller N for easier cases, larger N for harder cases\n    int N;\n    if (eps <= 0.05 && M <= 30) {\n        N = max(10, min(20, M + 5));\n    } else if (eps <= 0.15 && M <= 50) {\n        N = max(15, min(40, M + 10));\n    } else if (eps <= 0.25) {\n        N = max(20, min(60, M * 2 / 3 + 20));\n    } else {\n        N = max(30, min(80, M + 20));\n    }\n    N = min(N, 100);\n    N = max(N, 4);\n    \n    // Generate graphs\n    auto graphs = generate_graphs(N, M, eps);\n    \n    // Output graphs\n    cout << N << endl;\n    for (const auto& g : graphs) {\n        cout << g << endl;\n    }\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n        \n        int t = predict(H, graphs, N, eps);\n        cout << t << endl;\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = 1e18;\nconst long long PENALTY = 1e9;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nchrono::steady_clock::time_point start_time;\n\nlong long elapsed_ms() {\n    return chrono::duration_cast<chrono::milliseconds>(\n        chrono::steady_clock::now() - start_time).count();\n}\n\nbool time_left(long long limit = 5800) {\n    return elapsed_ms() < limit;\n}\n\nclass DSU {\n    vector<int> parent, size;\npublic:\n    DSU(int n) : parent(n), size(n, 1) {\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 (size[x] < size[y]) swap(x, y);\n        parent[y] = x;\n        size[x] += size[y];\n        return true;\n    }\n};\n\nbool check_connected(int N, const vector<Edge>& edges, const vector<bool>& removed) {\n    DSU dsu(N);\n    int comps = N;\n    for (const auto& e : edges) {\n        if (!removed[e.id]) {\n            if (dsu.unite(e.u, e.v)) comps--;\n        }\n    }\n    return comps == 1;\n}\n\nvector<long long> dijkstra(int src, int N, const vector<vector<pair<int,int>>>& adj,\n                            const vector<Edge>& edges) {\n    vector<long long> dist(N, INF);\n    dist[src] = 0;\n    priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n    pq.push({0, src});\n    \n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, eid] : adj[u]) {\n            long long nd = d + edges[eid].w;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                pq.push({nd, v});\n            }\n        }\n    }\n    return dist;\n}\n\n// Build adjacency for a specific day\nvector<vector<pair<int,int>>> build_day_adj(int N, const vector<Edge>& edges, \n                                              const vector<bool>& day_removed) {\n    vector<vector<pair<int,int>>> adj(N);\n    for (const auto& e : edges) {\n        if (!day_removed[e.id]) {\n            adj[e.u].push_back({e.v, e.id});\n            adj[e.v].push_back({e.u, e.id});\n        }\n    }\n    return adj;\n}\n\n// Compute frustration for a day with sampling\ndouble compute_frustration(int N, const vector<vector<pair<int,int>>>& day_adj,\n                           const vector<Edge>& edges,\n                           const vector<vector<long long>>& orig_dist,\n                           int step) {\n    double total_inc = 0;\n    long long cnt = 0;\n    \n    for (int src = 0; src < N; src += step) {\n        auto dist = dijkstra(src, N, day_adj, edges);\n        for (int dst = src + 1; dst < N; dst += step) {\n            long long dk = min(PENALTY, dist[dst]);\n            long long inc = max(0LL, dk - orig_dist[src][dst]);\n            total_inc += inc;\n            cnt++;\n        }\n    }\n    \n    return cnt > 0 ? total_inc / cnt : 0;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::steady_clock::now();\n    srand(12345);\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>>> full_adj(N);\n    \n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        full_adj[edges[i].u].push_back({edges[i].v, i});\n        full_adj[edges[i].v].push_back({edges[i].u, i});\n    }\n    \n    // Skip coordinates\n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n    }\n    \n    // Compute original all-pairs shortest paths\n    vector<vector<long long>> orig_dist(N, vector<long long>(N, INF));\n    for (int src = 0; src < N; src++) {\n        orig_dist[src] = dijkstra(src, N, full_adj, edges);\n    }\n    \n    // Compute edge criticality/importance\n    // Use betweenness centrality\n    vector<double> importance(M, 0.0);\n    int num_samples = min(N, 200);\n    \n    for (int si = 0; si < num_samples; si++) {\n        int src = (si * N) / num_samples;\n        \n        vector<long long> dist(N, INF);\n        vector<long long> cnt(N, 0);\n        vector<vector<int>> incoming(N);\n        \n        dist[src] = 0;\n        cnt[src] = 1;\n        \n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            \n            for (auto [v, eid] : full_adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    cnt[v] = cnt[u];\n                    incoming[v] = {eid};\n                    pq.push({nd, v});\n                } else if (nd == dist[v]) {\n                    cnt[v] += cnt[u];\n                    incoming[v].push_back(eid);\n                }\n            }\n        }\n        \n        vector<double> score(N, 1.0);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        \n        for (int u : order) {\n            if (dist[u] >= INF) continue;\n            for (int eid : incoming[u]) {\n                int v = (edges[eid].u == u) ? edges[eid].v : edges[eid].u;\n                if (dist[v] + edges[eid].w == dist[u]) {\n                    double contrib = score[u] * (double)cnt[v] / cnt[u];\n                    importance[eid] += contrib;\n                    score[v] += contrib;\n                }\n            }\n        }\n    }\n    \n    // Normalize importance\n    double max_imp = *max_element(importance.begin(), importance.end());\n    if (max_imp > 0) {\n        for (auto& imp : importance) imp /= max_imp;\n    }\n    \n    // Also compute a secondary metric: weight / degree\n    vector<int> degree(N, 0);\n    for (const auto& e : edges) {\n        degree[e.u]++;\n        degree[e.v]++;\n    }\n    \n    vector<double> importance2(M);\n    for (const auto& e : edges) {\n        importance2[e.id] = (double)e.w / sqrt((double)degree[e.u] * degree[e.v]);\n    }\n    max_imp = *max_element(importance2.begin(), importance2.end());\n    if (max_imp > 0) {\n        for (auto& imp : importance2) imp /= max_imp;\n    }\n    \n    vector<double> combined_imp(M);\n    for (int i = 0; i < M; i++) {\n        combined_imp[i] = 0.7 * importance[i] + 0.3 * importance2[i];\n    }\n    \n    // Sort edges by importance for initial assignment\n    vector<int> edge_order(M);\n    iota(edge_order.begin(), edge_order.end(), 0);\n    sort(edge_order.begin(), edge_order.end(), [&](int a, int b) {\n        return combined_imp[a] > combined_imp[b];\n    });\n    \n    // Initial assignment: greedy with connectivity check\n    vector<int> assignment(M);\n    vector<int> day_count(D, 0);\n    vector<vector<bool>> day_removed(D, vector<bool>(M, false));\n    vector<double> day_imp_sum(D, 0.0);\n    \n    int target = (M + D - 1) / D;\n    \n    for (int eid : edge_order) {\n        int best_d = -1;\n        double best_score = -1e18;\n        \n        // Try each day\n        for (int d = 0; d < D; d++) {\n            if (day_count[d] >= K) continue;\n            \n            // Temporarily add to this day and check connectivity\n            day_removed[d][eid] = true;\n            bool ok = check_connected(N, edges, day_removed[d]);\n            day_removed[d][eid] = false;\n            \n            if (!ok) continue;\n            \n            // Score: balance importance load and edge count\n            double overload = max(0, day_count[d] + 1 - target);\n            double score = -(day_imp_sum[d] + combined_imp[eid]) - overload * 100;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_d = d;\n            }\n        }\n        \n        if (best_d == -1) {\n            // Shouldn't happen if there's capacity, but fallback\n            for (int d = 0; d < D; d++) {\n                if (day_count[d] < K) {\n                    best_d = d;\n                    break;\n                }\n            }\n        }\n        \n        assignment[eid] = best_d;\n        day_removed[best_d][eid] = true;\n        day_count[best_d]++;\n        day_imp_sum[best_d] += combined_imp[eid];\n    }\n    \n    // Verify all days are connected, fix if not\n    for (int d = 0; d < D; d++) {\n        if (!check_connected(N, edges, day_removed[d])) {\n            // Find edges to move out\n            vector<int> day_edges;\n            for (int i = 0; i < M; i++) {\n                if (assignment[i] == d) day_edges.push_back(i);\n            }\n            sort(day_edges.begin(), day_edges.end(), [&](int a, int b) {\n                return combined_imp[a] < combined_imp[b];\n            });\n            \n            bool fixed = false;\n            for (int eid : day_edges) {\n                for (int d2 = 0; d2 < D && !fixed; d2++) {\n                    if (d2 == d || day_count[d2] >= K) continue;\n                    \n                    day_removed[d][eid] = false;\n                    day_removed[d2][eid] = true;\n                    \n                    bool ok1 = check_connected(N, edges, day_removed[d]);\n                    bool ok2 = check_connected(N, edges, day_removed[d2]);\n                    \n                    if (ok1 && ok2) {\n                        assignment[eid] = d2;\n                        day_count[d]--;\n                        day_count[d2]++;\n                        day_imp_sum[d] -= combined_imp[eid];\n                        day_imp_sum[d2] += combined_imp[eid];\n                        fixed = true;\n                    } else {\n                        day_removed[d][eid] = true;\n                        day_removed[d2][eid] = false;\n                    }\n                }\n                if (check_connected(N, edges, day_removed[d])) break;\n            }\n        }\n    }\n    \n    // Build day adjacencies\n    vector<vector<vector<pair<int,int>>>> day_adj(D);\n    for (int d = 0; d < D; d++) {\n        day_adj[d] = build_day_adj(N, edges, day_removed[d]);\n    }\n    \n    // Compute initial frustrations\n    int step = (N <= 600) ? 2 : (N <= 800) ? 3 : 4;\n    vector<double> frustrations(D);\n    for (int d = 0; d < D; d++) {\n        frustrations[d] = compute_frustration(N, day_adj[d], edges, orig_dist, step);\n    }\n    \n    double current_avg = accumulate(frustrations.begin(), frustrations.end(), 0.0) / D;\n    double best_avg = current_avg;\n    vector<int> best_assignment = assignment;\n    \n    // Simulated annealing\n    double temp = 200.0;\n    long long iter = 0;\n    \n    while (time_left()) {\n        for (int batch = 0; batch < 50 && time_left(); batch++) {\n            iter++;\n            \n            // Cool temperature\n            if (iter % 500 == 0) {\n                temp *= 0.9995;\n                if (temp < 0.01) temp = 0.01;\n            }\n            \n            // Choose operation\n            int op = rand() % 10;\n            \n            if (op < 7) {\n                // Swap two edges between different days\n                int e1 = rand() % M;\n                int e2 = rand() % M;\n                int d1 = assignment[e1];\n                int d2 = assignment[e2];\n                \n                if (d1 == d2) continue;\n                \n                // Test swap\n                // Remove e1 from d1, add e2 to d1\n                day_removed[d1][e1] = false;\n                day_removed[d1][e2] = true;\n                // Remove e2 from d2, add e1 to d2\n                day_removed[d2][e2] = false;\n                day_removed[d2][e1] = true;\n                \n                bool ok1 = check_connected(N, edges, day_removed[d1]);\n                bool ok2 = check_connected(N, edges, day_removed[d2]);\n                \n                if (!ok1 || !ok2) {\n                    // Revert\n                    day_removed[d1][e1] = true;\n                    day_removed[d1][e2] = false;\n                    day_removed[d2][e2] = true;\n                    day_removed[d2][e1] = false;\n                    continue;\n                }\n                \n                // Build new adjacencies\n                auto new_adj1 = build_day_adj(N, edges, day_removed[d1]);\n                auto new_adj2 = build_day_adj(N, edges, day_removed[d2]);\n                \n                double new_f1 = compute_frustration(N, new_adj1, edges, orig_dist, step);\n                double new_f2 = compute_frustration(N, new_adj2, edges, orig_dist, step);\n                \n                double new_avg = current_avg + (new_f1 - frustrations[d1] + new_f2 - frustrations[d2]) / D;\n                double delta = new_avg - current_avg;\n                \n                bool accept = (delta < 0) || \n                             (temp > 0 && exp(-delta / temp) > (double)rand() / RAND_MAX);\n                \n                if (accept) {\n                    assignment[e1] = d2;\n                    assignment[e2] = d1;\n                    frustrations[d1] = new_f1;\n                    frustrations[d2] = new_f2;\n                    current_avg = new_avg;\n                    day_adj[d1] = move(new_adj1);\n                    day_adj[d2] = move(new_adj2);\n                    \n                    if (current_avg < best_avg) {\n                        best_avg = current_avg;\n                        best_assignment = assignment;\n                    }\n                } else {\n                    // Revert\n                    day_removed[d1][e1] = true;\n                    day_removed[d1][e2] = false;\n                    day_removed[d2][e2] = true;\n                    day_removed[d2][e1] = false;\n                }\n            } else if (op < 9) {\n                // Move a single edge\n                int e = rand() % M;\n                int d1 = assignment[e];\n                \n                if (day_count[d1] <= target) continue; // Don't make sparse days sparser\n                \n                int d2 = rand() % D;\n                if (d1 == d2 || day_count[d2] >= K) continue;\n                \n                // Test move\n                day_removed[d1][e] = false;\n                day_removed[d2][e] = true;\n                \n                bool ok1 = check_connected(N, edges, day_removed[d1]);\n                bool ok2 = check_connected(N, edges, day_removed[d2]);\n                \n                if (!ok1 || !ok2) {\n                    day_removed[d1][e] = true;\n                    day_removed[d2][e] = false;\n                    continue;\n                }\n                \n                auto new_adj1 = build_day_adj(N, edges, day_removed[d1]);\n                auto new_adj2 = build_day_adj(N, edges, day_removed[d2]);\n                \n                double new_f1 = compute_frustration(N, new_adj1, edges, orig_dist, step);\n                double new_f2 = compute_frustration(N, new_adj2, edges, orig_dist, step);\n                \n                double new_avg = current_avg + (new_f1 - frustrations[d1] + new_f2 - frustrations[d2]) / D;\n                double delta = new_avg - current_avg;\n                \n                bool accept = (delta < 0) || \n                             (temp > 0 && exp(-delta / temp) > (double)rand() / RAND_MAX);\n                \n                if (accept) {\n                    assignment[e] = d2;\n                    frustrations[d1] = new_f1;\n                    frustrations[d2] = new_f2;\n                    current_avg = new_avg;\n                    day_count[d1]--;\n                    day_count[d2]++;\n                    day_adj[d1] = move(new_adj1);\n                    day_adj[d2] = move(new_adj2);\n                    \n                    if (current_avg < best_avg) {\n                        best_avg = current_avg;\n                        best_assignment = assignment;\n                    }\n                } else {\n                    day_removed[d1][e] = true;\n                    day_removed[d2][e] = false;\n                }\n            } else {\n                // 2-opt: swap two edges on the same pair of days\n                int d1 = rand() % D;\n                int d2 = rand() % D;\n                if (d1 == d2) continue;\n                \n                // Pick an edge from each day\n                vector<int> edges_d1, edges_d2;\n                for (int i = 0; i < M; i++) {\n                    if (assignment[i] == d1) edges_d1.push_back(i);\n                    if (assignment[i] == d2) edges_d2.push_back(i);\n                }\n                \n                if (edges_d1.empty() || edges_d2.empty()) continue;\n                \n                int e1 = edges_d1[rand() % edges_d1.size()];\n                int e2 = edges_d2[rand() % edges_d2.size()];\n                \n                // Test swap\n                day_removed[d1][e1] = false;\n                day_removed[d1][e2] = true;\n                day_removed[d2][e2] = false;\n                day_removed[d2][e1] = true;\n                \n                bool ok1 = check_connected(N, edges, day_removed[d1]);\n                bool ok2 = check_connected(N, edges, day_removed[d2]);\n                \n                if (!ok1 || !ok2) {\n                    day_removed[d1][e1] = true;\n                    day_removed[d1][e2] = false;\n                    day_removed[d2][e2] = true;\n                    day_removed[d2][e1] = false;\n                    continue;\n                }\n                \n                auto new_adj1 = build_day_adj(N, edges, day_removed[d1]);\n                auto new_adj2 = build_day_adj(N, edges, day_removed[d2]);\n                \n                double new_f1 = compute_frustration(N, new_adj1, edges, orig_dist, step);\n                double new_f2 = compute_frustration(N, new_adj2, edges, orig_dist, step);\n                \n                double new_avg = current_avg + (new_f1 - frustrations[d1] + new_f2 - frustrations[d2]) / D;\n                double delta = new_avg - current_avg;\n                \n                if (delta < 0 || (temp > 0 && exp(-delta / temp) > (double)rand() / RAND_MAX)) {\n                    assignment[e1] = d2;\n                    assignment[e2] = d1;\n                    frustrations[d1] = new_f1;\n                    frustrations[d2] = new_f2;\n                    current_avg = new_avg;\n                    day_adj[d1] = move(new_adj1);\n                    day_adj[d2] = move(new_adj2);\n                    \n                    if (current_avg < best_avg) {\n                        best_avg = current_avg;\n                        best_assignment = assignment;\n                    }\n                } else {\n                    day_removed[d1][e1] = true;\n                    day_removed[d1][e2] = false;\n                    day_removed[d2][e2] = true;\n                    day_removed[d2][e1] = false;\n                }\n            }\n        }\n    }\n    \n    // Use best assignment found\n    assignment = best_assignment;\n    \n    // Output\n    for (int i = 0; i < M; i++) {\n        if (i > 0) cout << \" \";\n        cout << assignment[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct FastBitset {\n    static constexpr int N = 2744;\n    static constexpr int CHUNKS = (N + 63) / 64;\n    uint64_t bits[CHUNKS]{};\n    FastBitset() { clear(); }\n    void clear() { memset(bits, 0, sizeof bits); }\n    void set(int i) { bits[i>>6] |= 1ULL << (i&63); }\n    void reset(int i) { bits[i>>6] &= ~(1ULL << (i&63)); }\n    bool test(int i) const { return (bits[i>>6] >> (i&63)) & 1ULL; }\n    int count() const {\n        int c = 0;\n        for (int i = 0; i < CHUNKS; ++i) c += __builtin_popcountll(bits[i]);\n        return c;\n    }\n    FastBitset operator&(const FastBitset& o) const {\n        FastBitset r;\n        for (int i = 0; i < CHUNKS; ++i) r.bits[i] = bits[i] & o.bits[i];\n        return r;\n    }\n    template<typename F>\n    void forEachSetBit(F f) const {\n        for (int i = 0; i < CHUNKS; ++i) {\n            uint64_t w = bits[i];\n            while (w) {\n                int j = __builtin_ctzll(w);\n                f((i << 6) | j);\n                w &= w - 1;\n            }\n        }\n    }\n};\n\nint D, D2, D3;\nvector<vector<int>> adj;\nvector<vector<int>> f1_voxels, r1_voxels, f2_voxels, r2_voxels;\n\ninline int encode(int x, int y, int z) { return x*D2 + y*D + z; }\ninline tuple<int,int,int> decode(int idx) {\n    int z = idx % D;\n    int y = (idx / D) % D;\n    int x = idx / D2;\n    return {x,y,z};\n}\n\nvector<array<array<int,3>,3>> rots;\nvector<array<array<int,3>,3>> inv_rots;\n\nvoid generate_rotations() {\n    int perm[3] = {0,1,2};\n    do {\n        for (int s0 = -1; s0 <= 1; s0+=2)\n        for (int s1 = -1; s1 <= 1; s1+=2)\n        for (int s2 = -1; s2 <= 1; s2+=2) {\n            int sign = 1;\n            for (int i=0;i<3;i++) for (int j=i+1;j<3;j++) if (perm[i]>perm[j]) sign = -sign;\n            if (sign * s0 * s1 * s2 != 1) continue;\n            array<array<int,3>,3> mat = {{{0}}};\n            mat[0][perm[0]] = s0;\n            mat[1][perm[1]] = s1;\n            mat[2][perm[2]] = s2;\n            rots.push_back(mat);\n        }\n    } while (next_permutation(perm, perm+3));\n    for (auto& mat : rots) {\n        array<array<int,3>,3> inv = {{{0}}};\n        for (int i=0;i<3;i++) for (int j=0;j<3;j++) inv[j][i] = mat[i][j];\n        inv_rots.push_back(inv);\n    }\n}\n\nFastBitset rotate_bitset(const FastBitset& src, const array<array<int,3>,3>& mat) {\n    FastBitset dst;\n    src.forEachSetBit([&](int idx) {\n        auto [x,y,z] = decode(idx);\n        int nx = mat[0][0]*x + mat[0][1]*y + mat[0][2]*z;\n        int ny = mat[1][0]*x + mat[1][1]*y + mat[1][2]*z;\n        int nz = mat[2][0]*x + mat[2][1]*y + mat[2][2]*z;\n        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n            dst.set(encode(nx,ny,nz));\n        }\n    });\n    return dst;\n}\n\nint main() {\n    auto start_time = steady_clock::now();\n    auto get_ms = [&]() {\n        return duration_cast<milliseconds>(steady_clock::now() - start_time).count();\n    };\n\n    generate_rotations();\n\n    cin >> D;\n    D2 = D*D;\n    D3 = D*D*D;\n\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i=0; i<D; i++) cin >> f1[i];\n    for (int i=0; i<D; i++) cin >> r1[i];\n    for (int i=0; i<D; i++) cin >> f2[i];\n    for (int i=0; i<D; i++) cin >> r2[i];\n\n    adj.resize(D3);\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        int idx = encode(x,y,z);\n        if (x>0)   adj[idx].push_back(encode(x-1, y, z));\n        if (x<D-1) adj[idx].push_back(encode(x+1, y, z));\n        if (y>0)   adj[idx].push_back(encode(x, y-1, z));\n        if (y<D-1) adj[idx].push_back(encode(x, y+1, z));\n        if (z>0)   adj[idx].push_back(encode(x, y, z-1));\n        if (z<D-1) adj[idx].push_back(encode(x, y, z+1));\n    }\n\n    FastBitset A1, A2;\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        if (f1[z][x]=='1' && r1[z][y]=='1') A1.set(encode(x,y,z));\n        if (f2[z][x]=='1' && r2[z][y]=='1') A2.set(encode(x,y,z));\n    }\n\n    FastBitset available1 = A1, available2 = A2;\n    vector<int> b1(D3, 0), b2(D3, 0);\n    int block_id = 1;\n\n    vector unc1_f(D, vector<bool>(D, false));\n    vector unc1_r(D, vector<bool>(D, false));\n    vector unc2_f(D, vector<bool>(D, false));\n    vector unc2_r(D, vector<bool>(D, false));\n\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f1[z][x]=='1') unc1_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r1[z][y]=='1') unc1_r[z][y] = true;\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f2[z][x]=='1') unc2_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r2[z][y]=='1') unc2_r[z][y] = true;\n\n    auto count_new_lines = [&](const FastBitset& voxels, bool is_obj1) -> int {\n        int cnt = 0;\n        voxels.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            if (is_obj1) {\n                if (unc1_f[z][x]) cnt++;\n                if (unc1_r[z][y]) cnt++;\n            } else {\n                if (unc2_f[z][x]) cnt++;\n                if (unc2_r[z][y]) cnt++;\n            }\n        });\n        return cnt;\n    };\n\n    while (get_ms() < 4000) {\n        int best_gain = 0;\n        int best_vol = 0;\n        FastBitset best_comp2, best_preimage1;\n        int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n        for (int r = 0; r < 24; ++r) {\n            FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n            int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n            bool any = false;\n            rot_avail1.forEachSetBit([&](int idx) {\n                auto [x,y,z] = decode(idx);\n                any = true;\n                min_x = std::min(min_x, x); max_x = std::max(max_x, x);\n                min_y = std::min(min_y, y); max_y = std::max(max_y, y);\n                min_z = std::min(min_z, z); max_z = std::max(max_z, z);\n            });\n            if (!any) continue;\n\n            int dx_min = -min_x, dx_max = D-1 - max_x;\n            int dy_min = -min_y, dy_max = D-1 - max_y;\n            int dz_min = -min_z, dz_max = D-1 - max_z;\n\n            for (int dx = dx_min; dx <= dx_max; ++dx) {\n                for (int dy = dy_min; dy <= dy_max; ++dy) {\n                    for (int dz = dz_min; dz <= dz_max; ++dz) {\n                        FastBitset overlap;\n                        rot_avail1.forEachSetBit([&](int idx) {\n                            auto [x,y,z] = decode(idx);\n                            int nx = x+dx, ny = y+dy, nz = z+dz;\n                            if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                int idx2 = encode(nx,ny,nz);\n                                if (available2.test(idx2)) overlap.set(idx2);\n                            }\n                        });\n                        if (overlap.count() <= best_vol) continue;\n\n                        FastBitset visited;\n                        overlap.forEachSetBit([&](int seed) {\n                            if (visited.test(seed)) return;\n                            queue<int> q;\n                            q.push(seed);\n                            visited.set(seed);\n                            FastBitset comp;\n                            comp.set(seed);\n                            int sz = 1;\n                            while (!q.empty()) {\n                                int cur = q.front(); q.pop();\n                                for (int nb : adj[cur]) {\n                                    if (overlap.test(nb) && !visited.test(nb)) {\n                                        visited.set(nb);\n                                        comp.set(nb);\n                                        sz++;\n                                        q.push(nb);\n                                    }\n                                }\n                            }\n                            if (sz > best_vol) {\n                                FastBitset preimage;\n                                comp.forEachSetBit([&](int idx2) {\n                                    auto [x2,y2,z2] = decode(idx2);\n                                    int sx = x2 - dx, sy = y2 - dy, sz2 = z2 - dz;\n                                    int ox = inv_rots[r][0][0]*sx + inv_rots[r][0][1]*sy + inv_rots[r][0][2]*sz2;\n                                    int oy = inv_rots[r][1][0]*sx + inv_rots[r][1][1]*sy + inv_rots[r][1][2]*sz2;\n                                    int oz = inv_rots[r][2][0]*sx + inv_rots[r][2][1]*sy + inv_rots[r][2][2]*sz2;\n                                    preimage.set(encode(ox,oy,oz));\n                                });\n                                int new_lines = count_new_lines(preimage, true) + count_new_lines(comp, false);\n                                int gain = sz + 100 * new_lines;\n                                if (gain > best_gain) {\n                                    best_gain = gain;\n                                    best_vol = sz;\n                                    best_comp2 = comp;\n                                    best_preimage1 = preimage;\n                                    best_r = r;\n                                    best_dx = dx; best_dy = dy; best_dz = dz;\n                                }\n                            }\n                        });\n                    }\n                }\n            }\n        }\n        if (best_vol == 0 || best_vol <= 2) break;\n\n        // Expand the block\n        {\n            FastBitset &preimage1 = best_preimage1;\n            FastBitset &comp2 = best_comp2;\n            int r = best_r, dx = best_dx, dy = best_dy, dz = best_dz;\n            queue<int> q1, q2;\n            preimage1.forEachSetBit([&](int v) { q1.push(v); });\n            comp2.forEachSetBit([&](int v) { q2.push(v); });\n            while (!q1.empty()) {\n                int v1 = q1.front(); q1.pop();\n                int v2 = q2.front(); q2.pop();\n                for (int nb1 : adj[v1]) {\n                    if (available1.test(nb1) && !preimage1.test(nb1)) {\n                        auto [x,y,z] = decode(nb1);\n                        int nx = rots[r][0][0]*x + rots[r][0][1]*y + rots[r][0][2]*z + dx;\n                        int ny = rots[r][1][0]*x + rots[r][1][1]*y + rots[r][1][2]*z + dy;\n                        int nz = rots[r][2][0]*x + rots[r][2][1]*y + rots[r][2][2]*z + dz;\n                        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                            int nb2 = encode(nx,ny,nz);\n                            if (available2.test(nb2) && !comp2.test(nb2)) {\n                                preimage1.set(nb1);\n                                comp2.set(nb2);\n                                available1.reset(nb1);\n                                available2.reset(nb2);\n                                q1.push(nb1);\n                                q2.push(nb2);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        int bid = block_id++;\n        best_preimage1.forEachSetBit([&](int idx) {\n            b1[idx] = bid;\n            available1.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc1_f[z][x] = false;\n            unc1_r[z][y] = false;\n        });\n        best_comp2.forEachSetBit([&](int idx) {\n            b2[idx] = bid;\n            available2.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc2_f[z][x] = false;\n            unc2_r[z][y] = false;\n        });\n    }\n\n    // Collect remaining voxels covering uncovered lines\n    vector<int> remaining_voxels1, remaining_voxels2;\n\n    auto pick_best_voxel = [&](FastBitset& avail, \n                                const vector<vector<bool>>& unc_f, \n                                const vector<vector<bool>>& unc_r) -> int {\n        int best_idx = -1, best_cnt = -1;\n        avail.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            int cnt = 0;\n            if (unc_f[z][x]) cnt++;\n            if (unc_r[z][y]) cnt++;\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_idx = idx;\n            }\n        });\n        return best_idx;\n    };\n\n    FastBitset avail1_copy = available1;\n    vector unc1_f_copy = unc1_f, unc1_r_copy = unc1_r;\n    while (true) {\n        int v = pick_best_voxel(avail1_copy, unc1_f_copy, unc1_r_copy);\n        if (v == -1) break;\n        auto [x,y,z] = decode(v);\n        if (!unc1_f_copy[z][x] && !unc1_r_copy[z][y]) break;\n        remaining_voxels1.push_back(v);\n        avail1_copy.reset(v);\n        unc1_f_copy[z][x] = false;\n        unc1_r_copy[z][y] = false;\n    }\n\n    FastBitset avail2_copy = available2;\n    vector unc2_f_copy = unc2_f, unc2_r_copy = unc2_r;\n    while (true) {\n        int v = pick_best_voxel(avail2_copy, unc2_f_copy, unc2_r_copy);\n        if (v == -1) break;\n        auto [x,y,z] = decode(v);\n        if (!unc2_f_copy[z][x] && !unc2_r_copy[z][y]) break;\n        remaining_voxels2.push_back(v);\n        avail2_copy.reset(v);\n        unc2_f_copy[z][x] = false;\n        unc2_r_copy[z][y] = false;\n    }\n\n    // Share 1x1 blocks\n    while (!remaining_voxels1.empty() && !remaining_voxels2.empty()) {\n        int v1 = remaining_voxels1.back(); remaining_voxels1.pop_back();\n        int v2 = remaining_voxels2.back(); remaining_voxels2.pop_back();\n        int bid = block_id++;\n        b1[v1] = bid;\n        b2[v2] = bid;\n    }\n    for (int v : remaining_voxels1) {\n        int bid = block_id++;\n        b1[v] = bid;\n    }\n    for (int v : remaining_voxels2) {\n        int bid = block_id++;\n        b2[v] = bid;\n    }\n\n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    for (int i=0; i<D3; i++) cout << b1[i] << \" \\n\"[i==D3-1];\n    for (int i=0; i<D3; i++) cout << b2[i] << \" \\n\"[i==D3-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\n#define rep(i, a, b) for (int i = (a); i < (b); i++)\n#define all(x) begin(x), end(x)\n\nusing ll = long long;\nconst ll INF = 1e18;\n\nstruct Edge {\n    int u, v;\n    ll w;\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    vector<pair<int, int>> pos(N);\n    rep(i, 0, N) cin >> pos[i].first >> pos[i].second;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, ll>>> adj(N);\n    rep(j, 0, M) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n\n    vector<pair<int, int>> residents(K);\n    rep(k, 0, K) cin >> residents[k].first >> residents[k].second;\n\n    // All-pairs shortest paths\n    vector<vector<ll>> dist(N, vector<ll>(N, INF));\n    rep(s, 0, N) {\n        dist[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[s][u]) continue;\n            for (auto [v, w] : adj[u]) {\n                if (dist[s][v] > d + w) {\n                    dist[s][v] = d + w;\n                    pq.push({dist[s][v], v});\n                }\n            }\n        }\n    }\n\n    // Precompute squared distances from stations to residents\n    vector<vector<ll>> stationToRes(N, vector<ll>(K));\n    vector<int> nearestStation(K, 0);\n    rep(i, 0, N) rep(k, 0, K) {\n        ll dx = pos[i].first - residents[k].first;\n        ll dy = pos[i].second - residents[k].second;\n        stationToRes[i][k] = dx * dx + dy * dy;\n    }\n    rep(k, 0, K) {\n        ll best = stationToRes[0][k];\n        nearestStation[k] = 0;\n        rep(i, 1, N) {\n            if (stationToRes[i][k] < best) {\n                best = stationToRes[i][k];\n                nearestStation[k] = i;\n            }\n        }\n    }\n\n    // Phase 1: Start with all stations that are nearest to at least one resident\n    vector<bool> active(N, false);\n    active[0] = true;\n    rep(k, 0, K) active[nearestStation[k]] = true;\n\n    vector<int> assign(K);\n    rep(k, 0, K) assign[k] = nearestStation[k];\n\n    // Compute P_i for each active station\n    auto computeP = [&]() {\n        vector<int> P(N, 0);\n        rep(i, 0, N) {\n            if (!active[i]) continue;\n            ll maxDistSq = 0;\n            rep(k, 0, K) if (assign[k] == i) {\n                maxDistSq = max(maxDistSq, stationToRes[i][k]);\n            }\n            ll Pi = (ll)ceil(sqrt(maxDistSq));\n            if (Pi > 5000) Pi = 5000;\n            P[i] = (int)Pi;\n        }\n        return P;\n    };\n\n    // Compute edge cost for active stations (Steiner tree via MST on metric closure)\n    auto computeEdgeCost = [&]() {\n        vector<int> act;\n        rep(i, 0, N) if (active[i]) act.push_back(i);\n        if (act.empty()) return 0LL;\n        int sz = act.size();\n        vector<bool> inTree(sz, false);\n        vector<ll> minDist(sz, INF);\n        minDist[0] = 0;\n        ll total = 0;\n        rep(iter, 0, sz) {\n            int u = -1;\n            ll best = INF;\n            rep(i, 0, sz) if (!inTree[i] && minDist[i] < best) {\n                best = minDist[i];\n                u = i;\n            }\n            if (u == -1) break;\n            inTree[u] = true;\n            total += best;\n            rep(v, 0, sz) if (!inTree[v]) {\n                minDist[v] = min(minDist[v], dist[act[u]][act[v]]);\n            }\n        }\n        return total;\n    };\n\n    auto totalCost = [&]() {\n        auto P = computeP();\n        ll powerCost = 0;\n        rep(i, 0, N) powerCost += (ll)P[i] * P[i];\n        return powerCost + computeEdgeCost();\n    };\n\n    ll currentCost = totalCost();\n\n    // Phase 2: Try to remove stations\n    for (int iter = 0; iter < 100; iter++) {\n        bool improved = false;\n        // Try removing each active station (except 0)\n        vector<int> actList;\n        rep(i, 1, N) if (active[i]) actList.push_back(i);\n        // Shuffle for variety\n        random_shuffle(all(actList));\n        \n        for (int i : actList) {\n            if (!active[i]) continue;\n            \n            // Save state\n            vector<bool> savedActive = active;\n            vector<int> savedAssign = assign;\n            \n            // Remove i\n            active[i] = false;\n            // Reassign residents from i to nearest remaining active station\n            rep(k, 0, K) {\n                if (assign[k] == i) {\n                    ll bestDist = INF;\n                    int bestSt = 0;\n                    rep(j, 0, N) {\n                        if (active[j] && stationToRes[j][k] < bestDist) {\n                            bestDist = stationToRes[j][k];\n                            bestSt = j;\n                        }\n                    }\n                    assign[k] = bestSt;\n                }\n            }\n            \n            ll newCost = totalCost();\n            if (newCost < currentCost) {\n                currentCost = newCost;\n                improved = true;\n            } else {\n                // Restore\n                active = savedActive;\n                assign = savedAssign;\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Phase 3: Try pairwise merges\n    for (int iter = 0; iter < 50; iter++) {\n        bool improved = false;\n        vector<int> actList;\n        rep(i, 1, N) if (active[i]) actList.push_back(i);\n        if (actList.size() < 2) break;\n        \n        random_shuffle(all(actList));\n        rep(idx1, 0, (int)actList.size()) {\n            int i = actList[idx1];\n            if (!active[i]) continue;\n            rep(idx2, idx1+1, (int)actList.size()) {\n                int j = actList[idx2];\n                if (!active[j]) continue;\n                \n                // Try i covers j's residents\n                vector<bool> savedActive = active;\n                vector<int> savedAssign = assign;\n                \n                active[j] = false;\n                rep(k, 0, K) if (assign[k] == j) assign[k] = i;\n                \n                ll newCost = totalCost();\n                if (newCost < currentCost) {\n                    currentCost = newCost;\n                    improved = true;\n                    goto next_merge_iter;\n                }\n                \n                // Restore and try j covers i's residents\n                active = savedActive;\n                assign = savedAssign;\n                \n                active[i] = false;\n                rep(k, 0, K) if (assign[k] == i) assign[k] = j;\n                \n                newCost = totalCost();\n                if (newCost < currentCost) {\n                    currentCost = newCost;\n                    improved = true;\n                    goto next_merge_iter;\n                }\n                \n                // Restore\n                active = savedActive;\n                assign = savedAssign;\n            }\n        }\n        next_merge_iter:\n        if (!improved) break;\n    }\n\n    // Phase 4: Try adjusting assignments (move residents to nearby active stations if it reduces P_i)\n    for (int iter = 0; iter < 30; iter++) {\n        bool improved = false;\n        rep(k, 0, K) {\n            int cur = assign[k];\n            ll curDist = stationToRes[cur][k];\n            rep(i, 0, N) {\n                if (!active[i] || i == cur) continue;\n                if (stationToRes[i][k] >= curDist) continue; // only consider closer stations\n                \n                vector<int> savedAssign = assign;\n                assign[k] = i;\n                ll newCost = totalCost();\n                if (newCost < currentCost) {\n                    currentCost = newCost;\n                    improved = true;\n                } else {\n                    assign = savedAssign;\n                }\n            }\n        }\n        if (!improved) break;\n    }\n\n    // Final computation of P and edges\n    auto P = computeP();\n    \n    // Build the Steiner tree edges\n    // First, compute MST on active stations using metric closure\n    vector<int> actList;\n    rep(i, 0, N) if (active[i]) actList.push_back(i);\n    int sz = actList.size();\n    vector<int> onEdge(M, 0);\n    \n    if (sz > 0) {\n        // Map station index to position in actList\n        vector<int> posInList(N, -1);\n        rep(i, 0, sz) posInList[actList[i]] = i;\n        \n        vector<bool> inTree(sz, false);\n        vector<int> treeParent(sz, -1);\n        vector<ll> minDist(sz, INF);\n        minDist[0] = 0; // Start from vertex 1 (should be first if active)\n        \n        rep(iter, 0, sz) {\n            int u = -1;\n            ll best = INF;\n            rep(i, 0, sz) if (!inTree[i] && minDist[i] < best) {\n                best = minDist[i];\n                u = i;\n            }\n            if (u == -1) break;\n            inTree[u] = true;\n            \n            if (treeParent[u] != -1) {\n                // Need to add edges on shortest path between actList[u] and actList[treeParent[u]]\n                int from = actList[u];\n                int to = actList[treeParent[u]];\n                \n                // Reconstruct path from 'from' to 'to'\n                int cur = from;\n                while (cur != to) {\n                    // Find next step on shortest path from cur to to\n                    int nxt = -1;\n                    ll bestDist = INF;\n                    for (auto [v, w] : adj[cur]) {\n                        if (dist[v][to] + w == dist[cur][to]) {\n                            nxt = v;\n                            break;\n                        }\n                    }\n                    if (nxt == -1) break;\n                    // Enable edge between cur and nxt\n                    for (int j = 0; j < M; j++) {\n                        if ((edges[j].u == cur && edges[j].v == nxt) ||\n                            (edges[j].u == nxt && edges[j].v == cur)) {\n                            onEdge[j] = 1;\n                            break;\n                        }\n                    }\n                    cur = nxt;\n                }\n            }\n            \n            rep(v, 0, sz) if (!inTree[v]) {\n                ll d = dist[actList[u]][actList[v]];\n                if (d < minDist[v]) {\n                    minDist[v] = d;\n                    treeParent[v] = u;\n                }\n            }\n        }\n    }\n\n    // Output\n    rep(i, 0, N) cout << P[i] << (i + 1 < N ? ' ' : '\\n');\n    rep(j, 0, M) cout << onEdge[j] << (j + 1 < M ? ' ' : '\\n');\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL = N * (N + 1) / 2;\n\nint board[N][N];\npair<int,int> pos[TOTAL];\nvector<array<int,4>> moves;\n\nint dx[6] = {-1, -1, 0, 0, 1, 1};\nint dy[6] = {-1, 0, -1, 1, 0, 1};\n\nbool valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvoid swap_balls(int x1, int y1, int x2, int y2) {\n    if (moves.size() >= 10000) return;\n    moves.push_back({x1, y1, x2, y2});\n    int v1 = board[x1][y1], v2 = board[x2][y2];\n    swap(board[x1][y1], board[x2][y2]);\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n}\n\n// BFS to find shortest path\nvector<pair<int,int>> bfs(int sx, int sy, int tx, int ty) {\n    vector dist(N, vector<int>(N, -1));\n    vector prev_x(N, vector<int>(N, -1));\n    vector prev_y(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    dist[sx][sy] = 0;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        if (x == tx && y == ty) break;\n        for (int d = 0; d < 6; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (valid(nx, ny) && dist[nx][ny] == -1) {\n                dist[nx][ny] = dist[x][y] + 1;\n                prev_x[nx][ny] = x;\n                prev_y[nx][ny] = y;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    vector<pair<int,int>> path;\n    int x = tx, y = ty;\n    while (x != -1) {\n        path.push_back({x, y});\n        int px = prev_x[x][y];\n        int py = prev_y[x][y];\n        x = px; y = py;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Move ball from source to target along path\nvoid move_along(vector<pair<int,int>>& path) {\n    for (size_t i = 1; i < path.size() && moves.size() < 10000; i++) {\n        swap_balls(path[i-1].first, path[i-1].second,\n                   path[i].first, path[i].second);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < N; i++)\n        for (int j = 0; j <= i; j++) {\n            cin >> board[i][j];\n            pos[board[i][j]] = {i, j};\n        }\n\n    // Calculate target layer for each value\n    // Value v should be in layer L where L is determined by triangular numbers\n    vector<int> target_layer(TOTAL);\n    int idx = 0;\n    for (int L = 0; L < N; L++) {\n        for (int j = 0; j <= L; j++) {\n            target_layer[idx++] = L;\n        }\n    }\n    \n    // Phase 1: Move small values to upper layers\n    // Process values in order, moving each to its target layer\n    for (int val = 0; val < TOTAL && moves.size() < 10000; val++) {\n        int target_l = target_layer[val];\n        auto [cur_x, cur_y] = pos[val];\n        \n        if (cur_x <= target_l) continue; // Already in correct or higher layer\n        \n        // Find a position in target layer to move to\n        int best_x = -1, best_y = -1;\n        int best_dist = 1e9;\n        \n        for (int y = 0; y <= target_l; y++) {\n            int d = abs(cur_x - target_l) + abs(cur_y - y);\n            if (d < best_dist && board[target_l][y] > val) {\n                best_dist = d;\n                best_x = target_l;\n                best_y = y;\n            }\n        }\n        \n        if (best_x != -1) {\n            auto path = bfs(cur_x, cur_y, best_x, best_y);\n            if (path.size() > 1) {\n                move_along(path);\n            }\n        }\n    }\n    \n    // Phase 2: Bottom-up heapify to fix heap property\n    for (int x = N-2; x >= 0 && moves.size() < 10000; x--) {\n        for (int y = 0; y <= x && moves.size() < 10000; y++) {\n            int cur_x = x, cur_y = y;\n            while (cur_x < N-1 && moves.size() < 10000) {\n                int c1 = board[cur_x+1][cur_y];\n                int c2 = board[cur_x+1][cur_y+1];\n                int p = board[cur_x][cur_y];\n                \n                if (c1 < p && c1 <= c2) {\n                    swap_balls(cur_x, cur_y, cur_x+1, cur_y);\n                    cur_x++;\n                } else if (c2 < p) {\n                    swap_balls(cur_x, cur_y, cur_x+1, cur_y+1);\n                    cur_x++;\n                    cur_y++;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Fine-tuning - fix remaining violations with greedy swaps\n    bool changed = true;\n    while (changed && moves.size() < 10000) {\n        changed = false;\n        for (int x = 0; x < N-1 && !changed; x++) {\n            for (int y = 0; y <= x && !changed; y++) {\n                int p = board[x][y];\n                int c1 = board[x+1][y];\n                int c2 = board[x+1][y+1];\n                \n                if (c1 < p || c2 < p) {\n                    if (c1 <= c2 && c1 < p) {\n                        swap_balls(x, y, x+1, y);\n                    } else {\n                        swap_balls(x, y, x+1, y+1);\n                    }\n                    changed = true;\n                }\n            }\n        }\n    }\n\n    if (moves.size() > 10000) moves.resize(10000);\n\n    cout << moves.size() << '\\n';\n    for (auto &[x1,y1,x2,y2] : moves)\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0, ENTRANCE_J = 4;\nint max_id;\n\nvector<string> grid(D, string(D, '.'));\nvector<vector<int>> dist(D, vector<int>(D, -1));\nvector<vector<bool>> obstacle(D, vector<bool>(D, false));\nvector<vector<bool>> occupied(D, vector<bool>(D, false));\n\nint dx[4] = {1, -1, 0, 0};\nint dy[4] = {0, 0, 1, -1};\n\nvoid bfs_distance(int si, int sj) {\n    for (int i = 0; i < D; i++)\n        fill(dist[i].begin(), dist[i].end(), -1);\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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 (nx >= 0 && nx < D && ny >= 0 && ny < D &&\n                dist[nx][ny] == -1 && !obstacle[nx][ny] && !occupied[nx][ny]) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n}\n\nbool reachable(int i, int j) {\n    return dist[i][j] != -1;\n}\n\nint count_reachable_empty() {\n    int cnt = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !occupied[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J) && reachable(i, j))\n                cnt++;\n    return cnt;\n}\n\npair<int,int> find_best_cell(int target_dist, int remaining) {\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int best_i = -1, best_j = -1, best_score = 1e9;\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_I && j == ENTRANCE_J) continue;\n            if (!reachable(i, j)) continue;\n            // temporarily place\n            occupied[i][j] = true;\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            int reachable_after = count_reachable_empty();\n            occupied[i][j] = false;\n            if (reachable_after < remaining - 1) continue; // would block future\n            int score = abs(dist[i][j] - target_dist);\n            if (score < best_score) {\n                best_score = score;\n                best_i = i; best_j = j;\n            }\n        }\n    }\n    return {best_i, best_j};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    for (int i = 0; i < N; i++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n\n    max_id = D*D - 1 - N;\n    int total_containers = max_id;\n    vector<pair<int,int>> placements(total_containers);\n\n    // Compute max distance\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int max_dist = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J))\n                max_dist = max(max_dist, dist[i][j]);\n\n    for (int d = 0; d < total_containers; d++) {\n        int tid;\n        cin >> tid;\n        int remaining = total_containers - d;\n        int target_dist = (int)((double)tid / max_id * max_dist);\n        auto [pi, pj] = find_best_cell(target_dist, remaining);\n        if (pi == -1) {\n            // fallback: any reachable\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            for (int i = 0; i < D && pi==-1; i++)\n                for (int j = 0; j < D && pi==-1; j++)\n                    if (!obstacle[i][j] && !occupied[i][j] && reachable(i,j) && !(i==ENTRANCE_I && j==ENTRANCE_J)) {\n                        pi = i; pj = j;\n                    }\n        }\n        occupied[pi][pj] = true;\n        placements[tid] = {pi, pj};\n        cout << pi << \" \" << pj << \"\\n\";\n        cout.flush();\n    }\n\n    // Removal: try sorted order, pick accessible with smallest ID\n    vector<bool> removed(total_containers, false);\n    for (int step = 0; step < total_containers; step++) {\n        bfs_distance(ENTRANCE_I, ENTRANCE_J);\n        int chosen = -1;\n        for (int id = 0; id < total_containers; id++) {\n            if (!removed[id]) {\n                auto [i, j] = placements[id];\n                if (reachable(i, j)) {\n                    chosen = id;\n                    break;\n                }\n            }\n        }\n        removed[chosen] = true;\n        occupied[placements[chosen].first][placements[chosen].second] = false;\n        cout << placements[chosen].first << \" \" << placements[chosen].second << \"\\n\";\n    }\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nvector<vector<int>> input(N, vector<int>(N));\nbool adj[M+1][M+1];\nbool needs_zero[M+1];\nvector<int> graph[M+1];\n\nint dx[4] = {-1, 0, 1, 0};\nint dy[4] = {0, 1, 0, -1};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> input[i][j];\n    \n    // Build adjacency matrix\n    memset(adj, 0, sizeof(adj));\n    memset(needs_zero, 0, sizeof(needs_zero));\n    \n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = input[i][j];\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                needs_zero[c] = true;\n            for (int d = 0; d < 4; d++) {\n                int ni = i + dx[d], nj = j + dy[d];\n                int nc = 0;\n                if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n                    nc = input[ni][nj];\n                if (c != nc)\n                    adj[c][nc] = adj[nc][c] = true;\n            }\n        }\n    }\n    \n    for (int c = 1; c <= m; c++)\n        for (int d = 0; d <= m; d++)\n            if (adj[c][d] && c != d)\n                graph[c].push_back(d);\n    \n    // Output: all 0 initially\n    vector<vector<int>> output(N, vector<int>(N, 0));\n    \n    // For each color, we'll assign a \"seed\" cell\n    // Then expand to satisfy adjacencies\n    \n    // Build spanning tree for ordering\n    vector<bool> visited(M+1, false);\n    vector<int> order;\n    queue<int> q;\n    \n    // Start with colors that need color 0\n    for (int c = 1; c <= m; c++) {\n        if (needs_zero[c] && !visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; c++) {\n        if (!visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    \n    // Place colors in a compact region\n    // Use a rectangular block in the center, starting from row 2, col 2\n    // Place each color as a small connected region (1 cell for now)\n    \n    map<int, vector<pair<int,int>>> cells; // cells for each color\n    \n    int cur_r = 2, cur_c = 2;\n    int max_r = N-3, max_c = N-3;\n    \n    for (int c : order) {\n        // Find free cell\n        while (cur_r <= max_r && output[cur_r][cur_c] != 0) {\n            cur_c++;\n            if (cur_c > max_c) { cur_c = 2; cur_r++; }\n        }\n        if (cur_r > max_r) break;\n        \n        output[cur_r][cur_c] = c;\n        cells[c].push_back({cur_r, cur_c});\n    }\n    \n    // Now ensure all required adjacencies are satisfied\n    // For each adjacency pair, if not adjacent, add cells\n    \n    bool changed = true;\n    int iterations = 0;\n    while (changed && iterations < 100) {\n        changed = false;\n        iterations++;\n        \n        for (int c = 1; c <= m; c++) {\n            for (int d : graph[c]) {\n                if (d == 0 || c >= d) continue; // process each pair once\n                \n                // Check if c and d are adjacent in output\n                bool adj_found = false;\n                for (auto [r1, c1] : cells[c]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r1 + dx[k], nc = c1 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == d) {\n                            adj_found = true;\n                            break;\n                        }\n                    }\n                    if (adj_found) break;\n                }\n                if (adj_found) continue;\n                \n                // Try to add a cell of c adjacent to some cell of d\n                bool placed = false;\n                for (auto [r2, c2] : cells[d]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r2 + dx[k], nc = c2 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                            output[nr][nc] = c;\n                            cells[c].push_back({nr, nc});\n                            placed = true;\n                            changed = true;\n                            break;\n                        }\n                    }\n                    if (placed) break;\n                }\n                \n                if (!placed) {\n                    // Try adding a cell of d adjacent to c\n                    for (auto [r1, c1] : cells[c]) {\n                        for (int k = 0; k < 4; k++) {\n                            int nr = r1 + dx[k], nc = c1 + dy[k];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                                output[nr][nc] = d;\n                                cells[d].push_back({nr, nc});\n                                placed = true;\n                                changed = true;\n                                break;\n                            }\n                        }\n                        if (placed) break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Check if any color needs color-0 adjacency but doesn't have it\n    for (int c = 1; c <= m; c++) {\n        if (!needs_zero[c]) continue;\n        if (cells[c].empty()) continue;\n        \n        bool touches_zero = false;\n        for (auto [r, col] : cells[c]) {\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dx[k], nc = col + dy[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || output[nr][nc] == 0) {\n                    touches_zero = true;\n                    break;\n                }\n            }\n            if (touches_zero) break;\n        }\n        \n        if (!touches_zero) {\n            // Expand c towards the border\n            // Find path to border through color 0\n            for (auto [r, col] : cells[c]) {\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dx[k], nc = col + dy[k];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                        output[nr][nc] = c;\n                        cells[c].push_back({nr, nc});\n                        break;\n                    }\n                }\n                break;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << output[i][j] << (j == N-1 ? '\\n' : ' ');\n        }\n    }\n    \n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nint query_count = 0;\n\nchar compare_sets(const vector<int>& L, const vector<int>& R) {\n    query_count++;\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res;\n    cin >> res;\n    return res;\n}\n\nchar compare_items(int a, int b) {\n    return compare_sets({a}, {b});\n}\n\n// Full merge sort (will use queries until done or out of queries)\nvector<int> merge_sort(const vector<int>& arr, int l, int r) {\n    if (l == r) return {arr[l]};\n    int m = (l + r) / 2;\n    auto left = merge_sort(arr, l, m);\n    auto right = merge_sort(arr, m + 1, r);\n    vector<int> res;\n    int i = 0, j = 0;\n    while (i < (int)left.size() && j < (int)right.size()) {\n        if (query_count >= Q) {\n            // Out of queries, just concatenate rest\n            while (i < (int)left.size()) res.push_back(left[i++]);\n            while (j < (int)right.size()) res.push_back(right[j++]);\n            return res;\n        }\n        char cmp = compare_items(left[i], right[j]);\n        if (cmp == '>') {\n            res.push_back(left[i++]);\n        } else if (cmp == '<') {\n            res.push_back(right[j++]);\n        } else {\n            res.push_back(left[i++]);\n            res.push_back(right[j++]);\n        }\n    }\n    while (i < (int)left.size()) res.push_back(left[i++]);\n    while (j < (int)right.size()) res.push_back(right[j++]);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> D >> Q;\n    \n    query_count = 0;\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n\n    // Phase 1: Sort items by weight (heaviest first)\n    vector<int> sorted = merge_sort(items, 0, N - 1);\n\n    // Phase 2: Estimate weights using exponential order statistics\n    // For \u03bb = 1e-5, scale = 1e5\n    double scale = 100000.0;\n    vector<double> harmonic(N + 1, 0.0);\n    for (int i = 1; i <= N; i++) {\n        harmonic[i] = harmonic[i - 1] + 1.0 / i;\n    }\n    \n    vector<double> est_weight(N);\n    // Map item index to its position in sorted array\n    vector<int> pos_of(N);\n    for (int i = 0; i < N; i++) {\n        pos_of[sorted[i]] = i;\n    }\n    \n    // sorted[0] is heaviest = N-th smallest (k = N)\n    // sorted[N-1] is lightest = 1st smallest (k = 1)\n    for (int idx = 0; idx < N; idx++) {\n        int k = N - idx;  // 1-indexed: 1=lightest, N=heaviest\n        // E = scale * sum_{i=1}^k 1/(N-i+1) = scale * (H_N - H_{N-k})\n        double expected = scale * (harmonic[N] - harmonic[N - k]);\n        est_weight[idx] = max(1.0, expected);\n    }\n\n    // Phase 3: Greedy assignment\n    vector<vector<int>> groups(D);\n    vector<double> group_sum(D, 0.0);\n    \n    for (int idx = 0; idx < N; idx++) {\n        int item = sorted[idx];\n        double w = est_weight[idx];\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_sum[g] < group_sum[best]) best = g;\n        }\n        groups[best].push_back(item);\n        group_sum[best] += w;\n    }\n\n    // Phase 4: Refinement using remaining queries\n    mt19937 rng(12345);\n    uniform_int_distribution<int> group_dist(0, D - 1);\n    \n    int no_progress = 0;\n    while (query_count + 2 <= Q && no_progress < 200) {\n        // Find groups with max and min estimated sum\n        int max_g = 0, min_g = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_sum[g] > group_sum[max_g]) max_g = g;\n            if (group_sum[g] < group_sum[min_g]) min_g = g;\n        }\n        \n        if (max_g == min_g) {\n            // All groups appear balanced by our estimates\n            // Try comparing two random groups to verify\n            int a = group_dist(rng);\n            int b = group_dist(rng);\n            if (a == b || groups[a].empty() || groups[b].empty()) {\n                no_progress++;\n                continue;\n            }\n            char cmp = compare_sets(groups[a], groups[b]);\n            if (cmp == '>') {\n                group_sum[a] *= 1.1;  // a is heavier than expected\n                group_sum[b] *= 0.9;\n            } else if (cmp == '<') {\n                group_sum[a] *= 0.9;\n                group_sum[b] *= 1.1;\n            } else {\n                // Equal, estimates are correct\n            }\n            no_progress = 0;\n            continue;\n        }\n        \n        if (groups[max_g].size() <= 1 || groups[min_g].empty()) {\n            no_progress++;\n            continue;\n        }\n        \n        char cmp = compare_sets(groups[max_g], groups[min_g]);\n        \n        if (cmp == '=') {\n            // They are equal despite our estimates saying otherwise\n            // Update estimates to match reality\n            double avg = (group_sum[max_g] + group_sum[min_g]) / 2.0;\n            group_sum[max_g] = avg;\n            group_sum[min_g] = avg;\n            no_progress = 0;\n            continue;\n        }\n        \n        if (cmp == '<') {\n            // Our estimates are wrong: min_g is actually heavier\n            // Move estimates closer to reality\n            double avg = (group_sum[max_g] + group_sum[min_g]) / 2.0;\n            group_sum[max_g] = avg * 0.9;\n            group_sum[min_g] = avg * 1.1;\n            no_progress++;\n            continue;\n        }\n        \n        // cmp == '>': max_g is indeed heavier, try to move lightest item\n        int best_item = -1;\n        double min_w = 1e18;\n        for (int item : groups[max_g]) {\n            int pos = pos_of[item];\n            double w = est_weight[pos];\n            if (w < min_w) {\n                min_w = w;\n                best_item = item;\n            }\n        }\n        \n        if (best_item == -1) {\n            no_progress++;\n            continue;\n        }\n        \n        // Move the item\n        auto& v = groups[max_g];\n        v.erase(remove(v.begin(), v.end(), best_item), v.end());\n        groups[min_g].push_back(best_item);\n        group_sum[max_g] -= min_w;\n        group_sum[min_g] += min_w;\n        no_progress = 0;\n    }\n\n    // Phase 5: Burn remaining queries with meaningful comparisons\n    while (query_count < Q) {\n        int a = group_dist(rng);\n        int b = group_dist(rng);\n        if (a != b && !groups[a].empty() && !groups[b].empty() && groups[a].size() + groups[b].size() <= N) {\n            compare_sets(groups[a], groups[b]);\n        } else {\n            // Fallback: compare two items\n            int x = uniform_int_distribution<int>(0, N-1)(rng);\n            int y = uniform_int_distribution<int>(0, N-1)(rng);\n            if (x != y) compare_items(x, y);\n            else compare_items(0, 1);\n        }\n    }\n\n    // Build final assignment\n    vector<int> assignment(N);\n    for (int g = 0; g < D; g++) {\n        for (int item : groups[g]) {\n            assignment[item] = g;\n        }\n    }\n\n    cout << \"#c\";\n    for (int i = 0; i < N; i++) cout << \" \" << assignment[i];\n    cout << endl;\n\n    for (int i = 0; i < N; i++) {\n        if (i > 0) cout << \" \";\n        cout << assignment[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 200, M = 10, H = N / M;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    vector<vector<int>> stacks(m, vector<int>(n / m));\n    for (int i = 0; i < m; ++i) {\n        for (int j = 0; j < n / m; ++j) {\n            cin >> stacks[i][j];\n        }\n    }\n\n    vector<pair<int, int>> moves; // (v, i) where i=0 means carry out, else move to stack i-1\n    auto move_op = [&](int v, int dest) {\n        moves.emplace_back(v, dest + 1);\n    };\n    auto carry_out = [&](int v) {\n        moves.emplace_back(v, 0);\n    };\n\n    int next_target = 1;\n    while (next_target <= n) {\n        // find stack and position of next_target\n        int si = -1, pos = -1;\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < (int)stacks[i].size(); ++j) {\n                if (stacks[i][j] == next_target) {\n                    si = i;\n                    pos = j;\n                    break;\n                }\n            }\n            if (si != -1) break;\n        }\n\n        if (pos == (int)stacks[si].size() - 1) {\n            // on top, carry out\n            carry_out(next_target);\n            stacks[si].pop_back();\n            ++next_target;\n            continue;\n        }\n\n        // need to move boxes above\n        int k = (int)stacks[si].size() - pos;\n        // choose destination: prefer an empty stack or one with top > next_target\n        int dest = -1;\n        // first look for empty\n        for (int i = 0; i < m; ++i) {\n            if (i != si && stacks[i].empty()) {\n                dest = i;\n                break;\n            }\n        }\n        if (dest == -1) {\n            // pick stack with minimum top number (to keep sorted)\n            int min_top = INT_MAX;\n            for (int i = 0; i < m; ++i) {\n                if (i != si && !stacks[i].empty() && stacks[i].back() < min_top) {\n                    min_top = stacks[i].back();\n                    dest = i;\n                }\n            }\n            if (dest == -1) dest = (si + 1) % m; // fallback\n        }\n\n        // move\n        move_op(next_target, dest);\n        vector<int> moving(stacks[si].begin() + pos, stacks[si].end());\n        stacks[si].resize(pos);\n        stacks[dest].insert(stacks[dest].end(), moving.begin(), moving.end());\n    }\n\n    // output\n    for (auto &[v, i] : moves) {\n        cout << v << \" \" << i << \"\\n\";\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\nconst char dir_char[4] = {'R', 'D', 'L', 'U'};\n\nbool can_move(int i, int j, int ni, int nj) {\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    // Check if there's no wall between (i,j) and (ni,nj)\n    if (i == ni) {\n        // Horizontal move: check vertical walls\n        int min_j = min(j, nj);\n        return v[i][min_j] == '0';\n    } else {\n        // Vertical move: check horizontal walls\n        int min_i = min(i, ni);\n        return h[min_i][j] == '0';\n    }\n}\n\n// BFS to compute shortest path distances\nvector<vector<int>> compute_distances(int si, int sj) {\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int k = 0; k < 4; k++) {\n            int ni = i + dx[k], nj = j + dy[k];\n            if (can_move(i, j, ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return dist;\n}\n\n// Generate route string from coordinate sequence\nstring route_to_string(const vector<pair<int,int>>& route) {\n    string s;\n    for (size_t t = 1; t < route.size(); t++) {\n        int ci = route[t-1].first, cj = route[t-1].second;\n        int ni = route[t].first, nj = route[t].second;\n        \n        bool found = false;\n        for (int k = 0; k < 4; k++) {\n            if (ci + dx[k] == ni && cj + dy[k] == nj) {\n                if (can_move(ci, cj, ni, nj)) {\n                    s += dir_char[k];\n                    found = true;\n                    break;\n                }\n            }\n        }\n        if (!found) {\n            // This should not happen if route is valid\n            return \"\";\n        }\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    \n    vector<pair<int,pair<int,int>>> dirt_cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n            dirt_cells.push_back({-d[i][j], {i, j}});\n        }\n    }\n    sort(dirt_cells.begin(), dirt_cells.end());\n    \n    // Step 1: Build base route using priority-based DFS\n    vector<pair<int,int>> base_route;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    \n    function<void(int,int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        base_route.push_back({i, j});\n        \n        // Collect reachable unvisited neighbors with priority\n        vector<pair<int,pair<int,int>>> neighbors;\n        for (int k = 0; k < 4; k++) {\n            int ni = i + dx[k], nj = j + dy[k];\n            if (can_move(i, j, ni, nj) && !visited[ni][nj]) {\n                neighbors.push_back({-d[ni][nj], {ni, nj}});\n            }\n        }\n        sort(neighbors.begin(), neighbors.end());\n        \n        for (auto& [_, next] : neighbors) {\n            auto [ni, nj] = next;\n            dfs(ni, nj);\n            base_route.push_back({i, j}); // Return to current node\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Step 2: Create working route\n    vector<pair<int,int>> current_route = base_route;\n    int MAX_LENGTH = 100000;\n    \n    // Step 3: Insert extra visits for high-dirt cells\n    // We'll insert additional visits to top priority cells\n    \n    // Build map of cell positions in route\n    map<pair<int,int>, vector<int>> pos_map;\n    for (size_t pos = 0; pos < current_route.size(); pos++) {\n        pos_map[current_route[pos]].push_back(pos);\n    }\n    \n    int insertions = 0;\n    int max_insertions = min(200, N * N / 2);\n    \n    for (auto& [neg_d, cell] : dirt_cells) {\n        if (insertions >= max_insertions) break;\n        if (current_route.size() >= MAX_LENGTH - 200) break;\n        \n        int di = cell.first, dj = cell.second;\n        int dirt_val = -neg_d;\n        \n        // Only add extra visits for cells with high dirt value\n        if (dirt_val < 300) continue;\n        \n        auto& positions = pos_map[{di, dj}];\n        if (positions.size() < 1) continue;\n        \n        // Calculate average gap between visits\n        int L = current_route.size();\n        int num_visits = positions.size();\n        double avg_gap = (double)L / num_visits;\n        \n        // If average gap is large, add extra visit\n        if (avg_gap > 80 && L < MAX_LENGTH - 100) {\n            // Find the largest gap\n            int max_gap = 0;\n            int insert_after = -1;\n            \n            for (size_t p = 0; p < positions.size(); p++) {\n                int curr = positions[p];\n                int next = positions[(p + 1) % positions.size()];\n                int gap;\n                if (next > curr) {\n                    gap = next - curr;\n                } else {\n                    gap = L - curr + next;\n                }\n                \n                if (gap > max_gap) {\n                    max_gap = gap;\n                    // We'll insert near the midpoint of this gap\n                    int midpoint = (curr + gap / 2) % L;\n                    \n                    // Find a point near midpoint that's close to target cell\n                    for (int delta = 0; delta <= 10; delta++) {\n                        int check_pos = (midpoint - delta + L) % L;\n                        auto [ci, cj] = current_route[check_pos];\n                        \n                        vector<vector<int>> dist = compute_distances(ci, cj);\n                        if (dist[di][dj] != -1 && dist[di][dj] <= 10) {\n                            insert_after = check_pos;\n                            break;\n                        }\n                    }\n                    \n                    if (insert_after >= 0) break;\n                }\n            }\n            \n            if (insert_after >= 0 && max_gap > 50) {\n                // Get insertion point\n                auto [si, sj] = current_route[insert_after];\n                \n                // Find path from insertion point to target cell and back\n                // We'll use BFS to find shortest paths\n                vector<vector<int>> dist_to = compute_distances(si, sj);\n                \n                if (dist_to[di][dj] != -1 && dist_to[di][dj] <= 15) {\n                    // Build path from si,sj to di,dj\n                    vector<pair<int,int>> path_to;\n                    int ci = di, cj = dj;\n                    while (ci != si || cj != sj) {\n                        path_to.push_back({ci, cj});\n                        // Find predecessor\n                        for (int k = 0; k < 4; k++) {\n                            int pi = ci - dx[k], pj = cj - dy[k];\n                            if (pi >= 0 && pi < N && pj >= 0 && pj < N && \n                                can_move(pi, pj, ci, cj) && \n                                dist_to[pi][pj] == dist_to[ci][cj] - 1) {\n                                ci = pi; cj = pj;\n                                break;\n                            }\n                        }\n                    }\n                    path_to.push_back({si, sj});\n                    reverse(path_to.begin(), path_to.end());\n                    \n                    // Build path back (reverse of path_to)\n                    vector<pair<int,int>> path_back = path_to;\n                    reverse(path_back.begin(), path_back.end());\n                    \n                    // Remove duplicate endpoints\n                    if (path_to.size() > 1) path_to.erase(path_to.begin()); // Remove start (already in route)\n                    if (path_back.size() > 1) path_back.pop_back(); // Remove end (will continue from there)\n                    \n                    int additional_moves = path_to.size() + path_back.size();\n                    if (current_route.size() + additional_moves <= MAX_LENGTH) {\n                        // Insert into route\n                        vector<pair<int,int>> new_route;\n                        for (int i = 0; i <= insert_after; i++) {\n                            new_route.push_back(current_route[i]);\n                        }\n                        for (auto& p : path_to) new_route.push_back(p);\n                        for (auto& p : path_back) new_route.push_back(p);\n                        for (size_t i = insert_after + 1; i < current_route.size(); i++) {\n                            new_route.push_back(current_route[i]);\n                        }\n                        \n                        current_route = new_route;\n                        insertions++;\n                        \n                        // Rebuild position map\n                        pos_map.clear();\n                        for (size_t pos = 0; pos < current_route.size(); pos++) {\n                            pos_map[current_route[pos]].push_back(pos);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Step 4: Ensure route ends at (0,0)\n    if (current_route.back().first != 0 || current_route.back().second != 0) {\n        int ci = current_route.back().first, cj = current_route.back().second;\n        vector<vector<int>> dist = compute_distances(ci, cj);\n        \n        if (dist[0][0] != -1) {\n            vector<pair<int,int>> return_path;\n            int x = 0, y = 0;\n            vector<pair<int,int>> rev_path;\n            while (x != ci || y != cj) {\n                rev_path.push_back({x, y});\n                for (int k = 0; k < 4; k++) {\n                    int px = x - dx[k], py = y - dy[k];\n                    if (px >= 0 && px < N && py >= 0 && py < N &&\n                        can_move(px, py, x, y) &&\n                        dist[px][py] == dist[x][y] - 1) {\n                        x = px; y = py;\n                        break;\n                    }\n                }\n            }\n            rev_path.push_back({ci, cj});\n            reverse(rev_path.begin(), rev_path.end());\n            \n            // Skip first element (already in route)\n            for (size_t i = 1; i < rev_path.size(); i++) {\n                current_route.push_back(rev_path[i]);\n            }\n        }\n    }\n    \n    // Step 5: Generate output string\n    string ans = route_to_string(current_route);\n    \n    // Validate and truncate if needed\n    if (ans.empty() || ans.size() > MAX_LENGTH) {\n        // Fallback: use simple DFS route\n        vector<pair<int,int>> fallback;\n        vector<vector<bool>> vis(N, vector<bool>(N, false));\n        \n        function<void(int,int)> simple_dfs = [&](int i, int j) {\n            vis[i][j] = true;\n            fallback.push_back({i, j});\n            for (int k = 0; k < 4; k++) {\n                int ni = i + dx[k], nj = j + dy[k];\n                if (can_move(i, j, ni, nj) && !vis[ni][nj]) {\n                    simple_dfs(ni, nj);\n                    fallback.push_back({i, j});\n                }\n            }\n        };\n        simple_dfs(0, 0);\n        ans = route_to_string(fallback);\n    }\n    \n    if (ans.size() > MAX_LENGTH) {\n        ans = ans.substr(0, MAX_LENGTH);\n    }\n    \n    cout << ans << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint si, sj;\nchar grid[15][15];\nvector<pair<int,int>> pos[26];\nvector<string> targets;\nint dist[225][225];\n\nvector<vector<pair<int,int>>> target_info; // [i][start] = {cost, end}\nvector<vector<vector<int>>> target_path;\n\nint cell_id(int i, int j) { return i*N + j; }\n\nvoid bfs_dist() {\n    int di[] = {1,-1,0,0};\n    int dj[] = {0,0,1,-1};\n    for (int i = 0; i < N*N; i++)\n        for (int j = 0; j < N*N; j++)\n            dist[i][j] = 1e9;\n    \n    for (int i = 0; i < N*N; i++) {\n        int si = i/N, sj = i%N;\n        dist[i][i] = 0;\n        queue<pair<int,int>> q;\n        q.push({si,sj});\n        while (!q.empty()) {\n            auto [ci, cj] = q.front(); q.pop();\n            int cid = cell_id(ci,cj);\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nid = cell_id(ni,nj);\n                if (dist[i][nid] > dist[i][cid] + 1) {\n                    dist[i][nid] = dist[i][cid] + 1;\n                    q.push({ni,nj});\n                }\n            }\n        }\n    }\n}\n\nvoid precompute_targets() {\n    target_info.assign(M, vector<pair<int,int>>(N*N, {1e9, -1}));\n    target_path.assign(M, vector<vector<int>>(N*N));\n    \n    for (int idx = 0; idx < M; idx++) {\n        const string& t = targets[idx];\n        int L = t.size();\n        \n        for (int start_cell = 0; start_cell < N*N; start_cell++) {\n            vector<int> dp_cur(225, 1e9);\n            vector<vector<int>> prev(L, vector<int>(225, -1));\n            \n            for (auto [i, j] : pos[t[0]-'A']) {\n                int cid = cell_id(i,j);\n                dp_cur[cid] = dist[start_cell][cid] + 1;\n                prev[0][cid] = -2;\n            }\n            \n            for (int k = 1; k < L; k++) {\n                vector<int> dp_next(225, 1e9);\n                for (auto [i, j] : pos[t[k]-'A']) {\n                    int cid = cell_id(i,j);\n                    for (auto [pi, pj] : pos[t[k-1]-'A']) {\n                        int pid = cell_id(pi,pj);\n                        if (dp_cur[pid] == 1e9) continue;\n                        int nd = dp_cur[pid] + dist[pid][cid] + 1;\n                        if (nd < dp_next[cid]) {\n                            dp_next[cid] = nd;\n                            prev[k][cid] = pid;\n                        }\n                    }\n                }\n                dp_cur = dp_next;\n            }\n            \n            int best_end = -1, best_cost = 1e9;\n            for (auto [i, j] : pos[t.back()-'A']) {\n                int cid = cell_id(i,j);\n                if (dp_cur[cid] < best_cost) {\n                    best_cost = dp_cur[cid];\n                    best_end = cid;\n                }\n            }\n            \n            target_info[idx][start_cell] = {best_cost, best_end};\n            \n            if (best_end != -1) {\n                vector<int> path(L);\n                int cur = best_end;\n                for (int k = L-1; k >= 0; k--) {\n                    path[k] = cur;\n                    if (k > 0) cur = prev[k][cur];\n                }\n                target_path[idx][start_cell] = path;\n            }\n        }\n    }\n}\n\n// Compute total cost of an order\nint compute_cost(const vector<int>& order, int start_cell) {\n    int cur = start_cell;\n    int total = 0;\n    for (int idx : order) {\n        total += target_info[idx][cur].first;\n        cur = target_info[idx][cur].second;\n    }\n    return total;\n}\n\n// Build output from order\nvector<int> build_output(const vector<int>& order, int start_cell) {\n    vector<int> out;\n    int cur = start_cell;\n    for (int idx : order) {\n        const auto& path = target_path[idx][cur];\n        for (int c : path) out.push_back(c);\n        cur = path.back();\n    }\n    return out;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = s[j];\n            pos[s[j]-'A'].push_back({i,j});\n        }\n    }\n    \n    targets.resize(M);\n    for (int i = 0; i < M; i++) cin >> targets[i];\n    \n    bfs_dist();\n    precompute_targets();\n    \n    int start_cell = cell_id(si, sj);\n    \n    // Try multiple initial orders\n    vector<int> best_order;\n    int best_cost = 1e9;\n    \n    // Helper for greedy: picks nearest unused target\n    auto greedy_order = [&](int first_target) -> vector<int> {\n        vector<bool> used(M, false);\n        vector<int> order;\n        int cur = start_cell;\n        \n        if (first_target != -1) {\n            order.push_back(first_target);\n            used[first_target] = true;\n            cur = target_info[first_target][cur].second;\n        }\n        \n        for (int step = (first_target!=-1?1:0); step < M; step++) {\n            int best_idx = -1, best_cst = 1e9;\n            for (int i = 0; i < M; i++) {\n                if (used[i]) continue;\n                int cst = target_info[i][cur].first;\n                if (cst < best_cst) {\n                    best_cst = cst;\n                    best_idx = i;\n                }\n            }\n            order.push_back(best_idx);\n            used[best_idx] = true;\n            cur = target_info[best_idx][cur].second;\n        }\n        return order;\n    };\n    \n    // Try starting with each of the first few cheapest targets as first\n    vector<pair<int,int>> initial_costs;\n    for (int i = 0; i < M; i++) {\n        initial_costs.push_back({target_info[i][start_cell].first, i});\n    }\n    sort(initial_costs.begin(), initial_costs.end());\n    \n    int num_trials = min(10, M);\n    for (int t = 0; t < num_trials; t++) {\n        vector<int> order;\n        if (t == 0) {\n            // Pure greedy\n            order = greedy_order(-1);\n        } else {\n            // Start with the t-th cheapest target\n            order = greedy_order(initial_costs[t].second);\n        }\n        \n        // 2-opt improvement\n        bool improved = true;\n        int iter = 0;\n        while (improved && iter < 100) {\n            improved = false;\n            iter++;\n            \n            // Precompute prefix states for quick delta evaluation\n            // Actually, just recompute cost for each candidate reversal\n            for (int i = 0; i < M; i++) {\n                for (int j = i+2; j < min(M, i+50); j++) {\n                    // Compute cost of segment before reversal\n                    int seg_start = (i == 0) ? start_cell : target_info[order[i-1]][(i==0?start_cell:target_info[order[i-2]][seg_start].second)].second;\n                    // This is wrong, let's just recompute the whole cost for the reversed segment.\n                    // Actually, we can compute the change in cost:\n                    // Old: cost(i-1 -> i) + cost(i..j) + cost(j -> j+1)\n                    // New: cost(i-1 -> j) + cost(reversed(i..j)) + cost(i -> j+1)\n                    \n                    // Let's just do a full evaluation of the reversed order for now\n                    int cur_start = start_cell;\n                    int old_cost = 0;\n                    for (int k = 0; k < M; k++) {\n                        old_cost += target_info[order[k]][cur_start].first;\n                        cur_start = target_info[order[k]][cur_start].second;\n                    }\n                    \n                    // Try reversed\n                    reverse(order.begin()+i, order.begin()+j+1);\n                    cur_start = start_cell;\n                    int new_cost = 0;\n                    for (int k = 0; k < M; k++) {\n                        new_cost += target_info[order[k]][cur_start].first;\n                        cur_start = target_info[order[k]][cur_start].second;\n                    }\n                    \n                    if (new_cost < old_cost) {\n                        improved = true;\n                    } else {\n                        // Revert\n                        reverse(order.begin()+i, order.begin()+j+1);\n                    }\n                }\n            }\n        }\n        \n        int cost = compute_cost(order, start_cell);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_order = order;\n        }\n    }\n    \n    // Output best order\n    vector<int> output = build_output(best_order, start_cell);\n    for (int c : output) {\n        cout << c/N << \" \" << c%N << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <cassert>\n#include <numeric>\nusing namespace std;\n\nstruct OilField {\n    int d;\n    vector<pair<int,int>> cells; // relative coordinates\n    int h, w; // height and width\n};\n\nint N, M;\ndouble eps;\nvector<OilField> fields;\nvector<vector<int>> true_v; // unknown to us, but for local testing only; in real, we'll build estimate\n\n// Our belief of v: double matrix\nvector<vector<double>> belief;\n\n// placed shapes tracking\nvector<vector<bool>> occupied_by_shape; // to avoid double counting\n\n// Helper: get sum of belief over a set of cells\ndouble belief_sum(const vector<pair<int,int>> &cells) {\n    double s = 0.0;\n    for (auto &p : cells) {\n        s += belief[p.first][p.second];\n    }\n    return s;\n}\n\n// Divination function (in real usage, we output query and read response)\ndouble divine(const vector<pair<int,int>> &cells) {\n    int k = (int)cells.size();\n    // Output query\n    cout << \"q \" << k;\n    for (auto &p : cells) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    double o;\n    cin >> o;\n    return o;\n}\n\n// Drill function\nint drill(int i, int j) {\n    cout << \"q 1 \" << i << \" \" << j << endl;\n    int v;\n    cin >> v;\n    return v;\n}\n\n// Answer function\nvoid answer(const vector<pair<int,int>> &pos) {\n    cout << \"a \" << pos.size();\n    for (auto &p : pos) {\n        cout << \" \" << p.first << \" \" << p.second;\n    }\n    cout << endl;\n    int res;\n    cin >> res;\n    if (res == 1) exit(0);\n}\n\nint main() {\n    // Read initial info\n    cin >> N >> M >> eps;\n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        fields[k].d = d;\n        fields[k].cells.resize(d);\n        int min_i = N, min_j = N, max_i = 0, max_j = 0;\n        for (int t = 0; t < d; ++t) {\n            int i, j;\n            cin >> i >> j;\n            fields[k].cells[t] = {i, j};\n            min_i = min(min_i, i);\n            min_j = min(min_j, j);\n            max_i = max(max_i, i);\n            max_j = max(max_j, j);\n        }\n        fields[k].h = max_i - min_i + 1;\n        fields[k].w = max_j - min_j + 1;\n        // normalize to (0,0)\n        for (auto &p : fields[k].cells) {\n            p.first -= min_i;\n            p.second -= min_j;\n        }\n    }\n\n    // Initialize belief to 0\n    belief.assign(N, vector<double>(N, 0.0));\n    occupied_by_shape.assign(N, vector<bool>(N, false));\n    vector<pair<int,int>> positive_cells;\n\n    // Phase 1: large set divinations to get rough estimate\n    // Example: divination on all cells (cost ~1/sqrt(N^2) very small)\n    {\n        vector<pair<int,int>> all;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                all.push_back({i, j});\n        double o = divine(all);\n        double k = (double)all.size();\n        double v_total = (o - k * eps) / (1 - 2*eps);\n        double avg = v_total / k;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                belief[i][j] = avg;\n    }\n\n    // Phase 2: row and column divinations for better localization\n    for (int i = 0; i < N; ++i) {\n        vector<pair<int,int>> row;\n        for (int j = 0; j < N; ++j) row.push_back({i, j});\n        double o = divine(row);\n        double k = (double)row.size();\n        double v_row = (o - k * eps) / (1 - 2*eps);\n        double avg = v_row / k;\n        for (int j = 0; j < N; ++j) belief[i][j] = (belief[i][j] + avg) / 2.0;\n    }\n    for (int j = 0; j < N; ++j) {\n        vector<pair<int,int>> col;\n        for (int i = 0; i < N; ++i) col.push_back({i, j});\n        double o = divine(col);\n        double k = (double)col.size();\n        double v_col = (o - k * eps) / (1 - 2*eps);\n        double avg = v_col / k;\n        for (int i = 0; i < N; ++i) belief[i][j] = (belief[i][j] + avg) / 2.0;\n    }\n\n    // Phase 3: Place shapes using belief\n    vector<bool> placed(M, false);\n    for (int k = 0; k < M; ++k) {\n        if (placed[k]) continue;\n        double best_score = -1e9;\n        int best_i = -1, best_j = -1;\n        // Slide shape\n        for (int di = 0; di + fields[k].h <= N; ++di) {\n            for (int dj = 0; dj + fields[k].w <= N; ++dj) {\n                vector<pair<int,int>> cand;\n                bool overlap_occupied = false;\n                for (auto &p : fields[k].cells) {\n                    int ni = di + p.first, nj = dj + p.second;\n                    cand.push_back({ni, nj});\n                    if (occupied_by_shape[ni][nj]) overlap_occupied = true;\n                }\n                if (overlap_occupied) continue;\n                double sum_belief = belief_sum(cand);\n                if (sum_belief > best_score) {\n                    best_score = sum_belief;\n                    best_i = di;\n                    best_j = dj;\n                }\n            }\n        }\n        if (best_i == -1) continue; // no place found\n        // Verify by divination\n        vector<pair<int,int>> verify_cells;\n        for (auto &p : fields[k].cells) verify_cells.push_back({best_i + p.first, best_j + p.second});\n        double o = divine(verify_cells);\n        double expected = fields[k].d; // if exactly one shape there, but could be more\n        double var = verify_cells.size() * eps * (1 - eps);\n        double stddev = sqrt(var);\n        // accept if within 2 sigma\n        if (fabs(o - expected) <= 2 * stddev + 1e-6) {\n            // place shape\n            placed[k] = true;\n            for (auto &p : verify_cells) {\n                occupied_by_shape[p.first][p.second] = true;\n                belief[p.first][p.second] += 1.0; // adjust belief\n            }\n        }\n    }\n\n    // Phase 4: Drill uncertain positive cells\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (belief[i][j] > 0.5 && !occupied_by_shape[i][j]) {\n                int v = drill(i, j);\n                if (v > 0) occupied_by_shape[i][j] = true;\n                belief[i][j] = v;\n            }\n        }\n    }\n\n    // Collect all positive cells\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (occupied_by_shape[i][j] || belief[i][j] > 0.5)\n                positive_cells.push_back({i, j});\n\n    answer(positive_cells);\n\n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <cstring>\n#include <functional>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nlong long area(const Rect& r) {\n    return (long long)(r.i1 - r.i0) * (r.j1 - r.j0);\n}\n\n// Compute L_d cost between prev and curr layouts\nlong long partition_change_cost(const vector<Rect>& prev, const vector<Rect>& curr, int W) {\n    static vector<char> H_prev, H_curr, V_prev, V_curr;\n    H_prev.assign(W * W, 0);\n    H_curr.assign(W * W, 0);\n    V_prev.assign(W * W, 0);\n    V_curr.assign(W * W, 0);\n    \n    auto mark_rect = [W](vector<char>& H, vector<char>& V, const Rect& r) {\n        if (r.i0 > 0 && r.i0 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H[r.i0 * W + j] = 1;\n            }\n        }\n        if (r.i1 > 0 && r.i1 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H[r.i1 * W + j] = 1;\n            }\n        }\n        if (r.j0 > 0 && r.j0 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V[i * W + r.j0] = 1;\n            }\n        }\n        if (r.j1 > 0 && r.j1 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V[i * W + r.j1] = 1;\n            }\n        }\n    };\n    \n    if (!prev.empty()) {\n        for (const auto& r : prev) {\n            mark_rect(H_prev, V_prev, r);\n        }\n    }\n    for (const auto& r : curr) {\n        mark_rect(H_curr, V_curr, r);\n    }\n    \n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (H_prev[i * W + j] != H_curr[i * W + j]) cost++;\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            if (V_prev[i * W + j] != V_curr[i * W + j]) cost++;\n        }\n    }\n    return cost;\n}\n\n// Compute area deficit penalty\nlong long area_penalty(const vector<Rect>& rects, const vector<int>& demands) {\n    long long penalty = 0;\n    for (size_t k = 0; k < demands.size(); ++k) {\n        long long rect_area = area(rects[k]);\n        if (rect_area < demands[k]) {\n            penalty += 100 * (demands[k] - rect_area);\n        }\n    }\n    return penalty;\n}\n\n// Create layout for given demands using recursive bisection\n// Ensures each rectangle gets at least its demanded area\nvector<Rect> create_layout(const vector<int>& demands) {\n    int N = demands.size();\n    vector<Rect> rects(N);\n    \n    // Pair (demand, original_index) sorted by demand descending\n    vector<pair<long long, int>> slots;\n    for (int k = 0; k < N; ++k) {\n        slots.emplace_back(demands[k], k);\n    }\n    sort(slots.begin(), slots.end(), greater<pair<long long, int>>());\n    \n    function<void(int, int, int, int, int, int)> assign;\n    assign = [&](int start, int end, int i0, int j0, int i1, int j1) {\n        if (start >= end) return;\n        if (start + 1 == end) {\n            int idx = slots[start].second;\n            rects[idx] = {i0, j0, i1, j1};\n            return;\n        }\n        \n        // Total demand for this group\n        long long total_demand = 0;\n        for (int i = start; i < end; ++i) {\n            total_demand += slots[i].first;\n        }\n        \n        int height = i1 - i0;\n        int width = j1 - j0;\n        long long region_area = (long long)height * width;\n        \n        // Split along longer dimension\n        if (height >= width) {\n            // Horizontal split\n            // Find best split point that balances areas\n            long long best_penalty = 1LL << 60;\n            int best_split = start + 1;\n            \n            for (int split = start + 1; split < end; ++split) {\n                long long area_above = 0;\n                for (int i = start; i < split; ++i) area_above += slots[i].first;\n                long long area_below = total_demand - area_above;\n                \n                // Compute ideal split position\n                int ideal_split_i = i0 + (int)((area_above * height + total_demand/2) / total_demand);\n                if (ideal_split_i <= i0) ideal_split_i = i0 + 1;\n                if (ideal_split_i >= i1) ideal_split_i = i1 - 1;\n                \n                long long actual_above = (long long)(ideal_split_i - i0) * width;\n                long long actual_below = region_area - actual_above;\n                \n                long long penalty = 0;\n                if (actual_above < area_above) penalty += 100 * (area_above - actual_above);\n                if (actual_below < area_below) penalty += 100 * (area_below - actual_below);\n                \n                // Also prefer splits that make rectangles closer to square\n                double aspect_above = (double)(ideal_split_i - i0) / width;\n                double aspect_below = (double)(i1 - ideal_split_i) / width;\n                if (aspect_above < 1) aspect_above = 1.0 / aspect_above;\n                if (aspect_below < 1) aspect_below = 1.0 / aspect_below;\n                long long aspect_penalty = (long long)((aspect_above + aspect_below) * 10);\n                \n                if (penalty + aspect_penalty < best_penalty) {\n                    best_penalty = penalty + aspect_penalty;\n                    best_split = split;\n                }\n            }\n            \n            // Compute actual split position\n            long long area_above = 0;\n            for (int i = start; i < best_split; ++i) area_above += slots[i].first;\n            int split_i = i0 + (int)((area_above * height + total_demand/2) / total_demand);\n            if (split_i <= i0) split_i = i0 + 1;\n            if (split_i >= i1) split_i = i1 - 1;\n            \n            assign(start, best_split, i0, j0, split_i, j1);\n            assign(best_split, end, split_i, j0, i1, j1);\n        } else {\n            // Vertical split\n            long long best_penalty = 1LL << 60;\n            int best_split = start + 1;\n            \n            for (int split = start + 1; split < end; ++split) {\n                long long area_left = 0;\n                for (int i = start; i < split; ++i) area_left += slots[i].first;\n                long long area_right = total_demand - area_left;\n                \n                int ideal_split_j = j0 + (int)((area_left * width + total_demand/2) / total_demand);\n                if (ideal_split_j <= j0) ideal_split_j = j0 + 1;\n                if (ideal_split_j >= j1) ideal_split_j = j1 - 1;\n                \n                long long actual_left = (long long)height * (ideal_split_j - j0);\n                long long actual_right = region_area - actual_left;\n                \n                long long penalty = 0;\n                if (actual_left < area_left) penalty += 100 * (area_left - actual_left);\n                if (actual_right < area_right) penalty += 100 * (area_right - actual_right);\n                \n                double aspect_left = (double)height / (ideal_split_j - j0);\n                double aspect_right = (double)height / (j1 - ideal_split_j);\n                if (aspect_left < 1) aspect_left = 1.0 / aspect_left;\n                if (aspect_right < 1) aspect_right = 1.0 / aspect_right;\n                long long aspect_penalty = (long long)((aspect_left + aspect_right) * 10);\n                \n                if (penalty + aspect_penalty < best_penalty) {\n                    best_penalty = penalty + aspect_penalty;\n                    best_split = split;\n                }\n            }\n            \n            long long area_left = 0;\n            for (int i = start; i < best_split; ++i) area_left += slots[i].first;\n            int split_j = j0 + (int)((area_left * width + total_demand/2) / total_demand);\n            if (split_j <= j0) split_j = j0 + 1;\n            if (split_j >= j1) split_j = j1 - 1;\n            \n            assign(start, best_split, i0, j0, i1, split_j);\n            assign(best_split, end, i0, split_j, i1, j1);\n        }\n    };\n    \n    assign(0, N, 0, 0, 1000, 1000);\n    return rects;\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    // Precompute optimal layout for each day\n    vector<vector<Rect>> day_layouts(D);\n    for (int d = 0; d < D; ++d) {\n        day_layouts[d] = create_layout(a[d]);\n    }\n    \n    // Use DP-like approach: for each day, decide whether to keep previous layout or switch\n    vector<vector<Rect>> output_layouts(D);\n    output_layouts[0] = day_layouts[0];\n    \n    for (int d = 1; d < D; ++d) {\n        // Cost to keep previous layout\n        long long penalty_keep = area_penalty(output_layouts[d-1], a[d]);\n        \n        // Cost to switch to new optimal layout\n        long long change_cost = partition_change_cost(output_layouts[d-1], day_layouts[d], W);\n        long long penalty_new = area_penalty(day_layouts[d], a[d]);\n        \n        // Also consider switching to this day's layout might help future days\n        // Simple heuristic: look ahead one day\n        long long future_benefit = 0;\n        if (d + 1 < D) {\n            // If we switch now, estimate cost for day d+1\n            long long change_next_if_switch = partition_change_cost(day_layouts[d], day_layouts[d+1], W);\n            long long penalty_next_if_switch = area_penalty(day_layouts[d+1], a[d+1]);\n            long long cost_next_if_switch = change_next_if_switch + penalty_next_if_switch;\n            \n            // If we keep current, estimate cost for day d+1\n            long long change_next_if_keep = partition_change_cost(output_layouts[d-1], day_layouts[d+1], W);\n            long long penalty_next_if_keep = area_penalty(day_layouts[d+1], a[d+1]);\n            long long cost_next_if_keep = change_next_if_keep + penalty_next_if_keep;\n            \n            future_benefit = cost_next_if_keep - cost_next_if_switch;\n        }\n        \n        long long cost_keep = penalty_keep;\n        long long cost_switch = change_cost + penalty_new - future_benefit;\n        \n        if (cost_switch < cost_keep) {\n            output_layouts[d] = day_layouts[d];\n        } else {\n            output_layouts[d] = output_layouts[d-1];\n        }\n    }\n\n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cout << output_layouts[d][k].i0 << \" \" << output_layouts[d][k].j0 << \" \"\n                 << output_layouts[d][k].i1 << \" \" << output_layouts[d][k].j1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\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<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> a[i][j];\n\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int s = 0; s < M; s++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> stamps[s][i][j];\n\n    vector<vector<int>> board = a;\n    vector<tuple<int,int,int>> ops;\n\n    // Greedy selection\n    for (int step = 0; step < K; step++) {\n        int best_m = -1, best_p = -1, best_q = -1;\n        long long best_gain = -1;\n\n        for (int m_idx = 0; m_idx < M; m_idx++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    long long gain = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            int old_val = board[p+i][q+j];\n                            int new_val = old_val + stamps[m_idx][i][j];\n                            gain += (new_val % MOD) - (old_val % MOD);\n                        }\n                    }\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_m = m_idx;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_m == -1) break;\n        ops.emplace_back(best_m, best_p, best_q);\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                board[best_p+i][best_q+j] += stamps[best_m][i][j];\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &[m_idx, p, q] : ops)\n        cout << m_idx << ' ' << p << ' ' << q << '\\n';\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\n// Direction mappings\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char dc[] = {'U', 'D', 'L', 'R'};\n\nstruct Position {\n    int x, y;\n    bool operator==(const Position& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Position& o) const { return !(*this == o); }\n};\n\n// BFS to find shortest path with obstacle avoidance\nvector<Position> bfs(const vector<vector<int>>& grid, \n                     Position start, Position goal,\n                     const set<pair<int,int>>& crane_positions,\n                     int exclude_idx = -1) {\n    vector<vector<Position>> parent(N, vector<Position>(N, {-1, -1}));\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<Position> q;\n    \n    q.push(start);\n    dist[start.x][start.y] = 0;\n    \n    while (!q.empty()) {\n        Position cur = q.front(); q.pop();\n        if (cur == goal) break;\n        \n        for (int d = 0; d < 4; d++) {\n            int nx = cur.x + dx[d], ny = cur.y + dy[d];\n            if (nx < 0 || nx >= N || ny < 0 || ny >= N) continue;\n            if (dist[nx][ny] != -1) continue;\n            \n            // Check if occupied by another crane\n            bool occupied = false;\n            for (auto& cp : crane_positions) {\n                if (cp.first == nx && cp.second == ny) {\n                    occupied = true;\n                    break;\n                }\n            }\n            if (occupied) continue;\n            \n            dist[nx][ny] = dist[cur.x][cur.y] + 1;\n            parent[nx][ny] = cur;\n            q.push({nx, ny});\n        }\n    }\n    \n    if (dist[goal.x][goal.y] == -1) return {};\n    \n    vector<Position> path;\n    Position cur = goal;\n    while (!(cur == start)) {\n        path.push_back(cur);\n        cur = parent[cur.x][cur.y];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nchar get_move_dir(Position from, Position to) {\n    if (to.x == from.x - 1) return 'U';\n    if (to.x == from.x + 1) return 'D';\n    if (to.y == from.y - 1) return 'L';\n    if (to.y == from.y + 1) return 'R';\n    return '.';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> A[i][j];\n    \n    // Grid: -1 = empty, otherwise container ID\n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    \n    // Receiving queues per gate row\n    vector<queue<int>> recv_queue(N);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            recv_queue[i].push(A[i][j]);\n    \n    // Crane state\n    struct Crane {\n        int x, y;\n        bool holding;\n        int container;\n        bool bombed;\n        bool large; // large crane can move over containers while carrying\n    };\n    vector<Crane> cranes(N);\n    for (int i = 0; i < N; i++) {\n        cranes[i] = {i, 0, false, -1, false, i == 0};\n    }\n    \n    // Which containers have been dispatched\n    vector<bool> dispatched(N * N, false);\n    int dispatched_count = 0;\n    \n    // Dispatch log per gate\n    vector<vector<int>> dispatch_log(N);\n    \n    // Next expected container per gate\n    vector<int> next_expected(N);\n    for (int i = 0; i < N; i++) next_expected[i] = i * N;\n    \n    vector<string> output(N);\n    \n    // Helper: get target gate for a container\n    auto target_gate = [](int cid) { return cid / N; };\n    \n    // Main loop\n    for (int turn = 0; turn < MAX_TURNS && dispatched_count < N * N; turn++) {\n        // Step 1: Spawn containers at empty receiving gates\n        for (int i = 0; i < N; i++) {\n            if (!recv_queue[i].empty() && grid[i][0] == -1) {\n                bool crane_holding_at_gate = false;\n                for (auto& cr : cranes) {\n                    if (!cr.bombed && cr.x == i && cr.y == 0 && cr.holding)\n                        crane_holding_at_gate = true;\n                }\n                if (!crane_holding_at_gate) {\n                    int cid = recv_queue[i].front(); recv_queue[i].pop();\n                    grid[i][0] = cid;\n                }\n            }\n        }\n        \n        // Step 2: Dispatch containers at gates (dispatch ALL containers at gates)\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N-1] != -1) {\n                int cid = grid[i][N-1];\n                dispatch_log[i].push_back(cid);\n                dispatched[cid] = true;\n                dispatched_count++;\n                grid[i][N-1] = -1;\n            }\n        }\n        \n        if (dispatched_count == N * N) break;\n        \n        // Step 3: Plan actions for each crane\n        vector<char> actions(N, '.');\n        vector<Position> new_pos(N);\n        for (int i = 0; i < N; i++) {\n            new_pos[i] = {cranes[i].x, cranes[i].y};\n        }\n        \n        // Build set of occupied positions for pathfinding\n        set<pair<int,int>> occupied;\n        for (int i = 0; i < N; i++) {\n            if (!cranes[i].bombed) {\n                occupied.insert({cranes[i].x, cranes[i].y});\n            }\n        }\n        \n        // Process cranes in order: large crane first\n        vector<int> crane_order;\n        for (int i = 0; i < N; i++) if (cranes[i].large) crane_order.push_back(i);\n        for (int i = 0; i < N; i++) if (!cranes[i].large) crane_order.push_back(i);\n        \n        for (int ci : crane_order) {\n            if (cranes[ci].bombed) continue;\n            auto& cr = cranes[ci];\n            \n            if (cr.large) {\n                // LARGE CRANE: Main transporter\n                if (cr.holding) {\n                    int tgt = target_gate(cr.container);\n                    // Deliver to target dispatch gate\n                    if (cr.y == N-1 && cr.x == tgt) {\n                        // At correct dispatch gate, release\n                        if (grid[cr.x][cr.y] == -1) {\n                            actions[ci] = 'Q';\n                        }\n                    } else {\n                        // Move towards target gate\n                        Position goal = {tgt, N-1};\n                        auto path = bfs(grid, {cr.x, cr.y}, goal, occupied, ci);\n                        if (!path.empty()) {\n                            Position next = path[0];\n                            // Check if we can move there (large crane can move over containers)\n                            // But need to ensure no crane is there\n                            bool other_crane_there = false;\n                            for (int j = 0; j < N; j++) {\n                                if (j != ci && !cranes[j].bombed && \n                                    new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                    other_crane_there = true;\n                                }\n                            }\n                            if (!other_crane_there) {\n                                actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                            }\n                        }\n                    }\n                } else {\n                    // Find a container to pick up\n                    // Priority: containers that belong to correct gates\n                    // Check all grid positions\n                    bool found_target = false;\n                    Position pickup_target;\n                    \n                    // First priority: containers at receiving gates\n                    for (int i = 0; i < N && !found_target; i++) {\n                        if (grid[i][0] != -1 && !dispatched[grid[i][0]]) {\n                            pickup_target = {i, 0};\n                            found_target = true;\n                        }\n                    }\n                    \n                    // Second: containers in buffer area\n                    if (!found_target) {\n                        for (int i = 0; i < N && !found_target; i++) {\n                            for (int j = 1; j < N-1 && !found_target; j++) {\n                                if (grid[i][j] != -1 && !dispatched[grid[i][j]]) {\n                                    pickup_target = {i, j};\n                                    found_target = true;\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (found_target) {\n                        if (cr.x == pickup_target.x && cr.y == pickup_target.y) {\n                            if (grid[cr.x][cr.y] != -1) {\n                                actions[ci] = 'P';\n                            }\n                        } else {\n                            auto path = bfs(grid, {cr.x, cr.y}, pickup_target, occupied, ci);\n                            if (!path.empty()) {\n                                Position next = path[0];\n                                bool other_crane_there = false;\n                                for (int j = 0; j < N; j++) {\n                                    if (j != ci && !cranes[j].bombed && \n                                        new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                        other_crane_there = true;\n                                    }\n                                }\n                                if (!other_crane_there) {\n                                    actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                                }\n                            }\n                        }\n                    }\n                }\n            } else {\n                // SMALL CRANE: Help move containers from receiving gate to buffer\n                if (cr.holding) {\n                    // Move to nearest empty buffer spot and drop\n                    Position buffer_target = {-1, -1};\n                    // Try column 2 first (middle buffer)\n                    for (int col = 1; col <= 3 && buffer_target.x == -1; col++) {\n                        for (int row = 0; row < N && buffer_target.x == -1; row++) {\n                            if (grid[row][col] == -1) {\n                                // Check if no crane plans to go there\n                                bool taken = false;\n                                for (int j = 0; j < N; j++) {\n                                    if (j != ci && !cranes[j].bombed && \n                                        new_pos[j].x == row && new_pos[j].y == col) {\n                                        taken = true;\n                                    }\n                                }\n                                if (!taken) {\n                                    buffer_target = {row, col};\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (buffer_target.x != -1) {\n                        if (cr.x == buffer_target.x && cr.y == buffer_target.y) {\n                            if (grid[cr.x][cr.y] == -1) {\n                                actions[ci] = 'Q';\n                            }\n                        } else {\n                            auto path = bfs(grid, {cr.x, cr.y}, buffer_target, occupied, ci);\n                            if (!path.empty()) {\n                                Position next = path[0];\n                                // Check if next position has a container (small crane can't move there while carrying)\n                                if (grid[next.x][next.y] != -1) continue;\n                                bool other_crane_there = false;\n                                for (int j = 0; j < N; j++) {\n                                    if (j != ci && !cranes[j].bombed && \n                                        new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                        other_crane_there = true;\n                                    }\n                                }\n                                if (!other_crane_there) {\n                                    actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                                }\n                            }\n                        }\n                    }\n                } else {\n                    // Pick up from receiving gate (own row)\n                    if (cr.y == 0 && grid[cr.x][0] != -1) {\n                        actions[ci] = 'P';\n                    } else if (cr.y > 0 && grid[cr.x][0] != -1) {\n                        // Move to receiving gate\n                        Position goal = {cr.x, 0};\n                        auto path = bfs(grid, {cr.x, cr.y}, goal, occupied, ci);\n                        if (!path.empty()) {\n                            Position next = path[0];\n                            if (grid[next.x][next.y] != -1) continue;\n                            bool other_crane_there = false;\n                            for (int j = 0; j < N; j++) {\n                                if (j != ci && !cranes[j].bombed && \n                                    new_pos[j].x == next.x && new_pos[j].y == next.y) {\n                                    other_crane_there = true;\n                                }\n                            }\n                            if (!other_crane_there) {\n                                actions[ci] = get_move_dir({cr.x, cr.y}, next);\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Update new_pos for this crane based on action\n            if (actions[ci] == 'U') new_pos[ci] = {cr.x-1, cr.y};\n            else if (actions[ci] == 'D') new_pos[ci] = {cr.x+1, cr.y};\n            else if (actions[ci] == 'L') new_pos[ci] = {cr.x, cr.y-1};\n            else if (actions[ci] == 'R') new_pos[ci] = {cr.x, cr.y+1};\n            // For P, Q, B, . position stays same\n        }\n        \n        // Step 4: Resolve conflicts\n        bool has_conflict = false;\n        \n        // Check for position conflicts\n        for (int i = 0; i < N && !has_conflict; i++) {\n            if (cranes[i].bombed) continue;\n            for (int j = i+1; j < N && !has_conflict; j++) {\n                if (cranes[j].bombed) continue;\n                if (new_pos[i] == new_pos[j]) {\n                    has_conflict = true;\n                }\n                // Swap conflict\n                if (new_pos[i].x == cranes[j].x && new_pos[i].y == cranes[j].y &&\n                    new_pos[j].x == cranes[i].x && new_pos[j].y == cranes[i].y) {\n                    has_conflict = true;\n                }\n            }\n        }\n        \n        // Check small cranes moving onto containers while carrying\n        for (int i = 0; i < N && !has_conflict; i++) {\n            if (cranes[i].bombed || cranes[i].large) continue;\n            if (cranes[i].holding && actions[i] != 'P' && actions[i] != 'Q' && actions[i] != 'B' && actions[i] != '.') {\n                if (grid[new_pos[i].x][new_pos[i].y] != -1) {\n                    has_conflict = true;\n                }\n            }\n        }\n        \n        // If conflict, cancel all non-P/Q movements (keep P/Q if valid)\n        if (has_conflict) {\n            for (int i = 0; i < N; i++) {\n                if (actions[i] != 'P' && actions[i] != 'Q' && actions[i] != 'B') {\n                    actions[i] = '.';\n                }\n                new_pos[i] = {cranes[i].x, cranes[i].y};\n            }\n            \n            // Re-check P/Q actions\n            for (int i = 0; i < N; i++) {\n                if (actions[i] == 'P') {\n                    if (cranes[i].holding || grid[cranes[i].x][cranes[i].y] == -1) {\n                        actions[i] = '.';\n                    }\n                }\n                if (actions[i] == 'Q') {\n                    if (!cranes[i].holding || grid[cranes[i].x][cranes[i].y] != -1) {\n                        actions[i] = '.';\n                    }\n                }\n            }\n        }\n        \n        // Step 5: Apply actions\n        for (int i = 0; i < N; i++) {\n            if (cranes[i].bombed) continue;\n            \n            if (actions[i] == 'P') {\n                if (!cranes[i].holding && grid[cranes[i].x][cranes[i].y] != -1) {\n                    cranes[i].holding = true;\n                    cranes[i].container = grid[cranes[i].x][cranes[i].y];\n                    grid[cranes[i].x][cranes[i].y] = -1;\n                }\n            } else if (actions[i] == 'Q') {\n                if (cranes[i].holding && grid[cranes[i].x][cranes[i].y] == -1) {\n                    grid[cranes[i].x][cranes[i].y] = cranes[i].container;\n                    cranes[i].holding = false;\n                    cranes[i].container = -1;\n                }\n            } else if (actions[i] == 'B') {\n                if (!cranes[i].holding) {\n                    cranes[i].bombed = true;\n                }\n            } else {\n                cranes[i].x = new_pos[i].x;\n                cranes[i].y = new_pos[i].y;\n            }\n        }\n        \n        // Record actions\n        for (int i = 0; i < N; i++) {\n            output[i] += actions[i];\n        }\n    }\n    \n    // Pad to equal length\n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)output[i].size());\n    for (int i = 0; i < N; i++) {\n        while ((int)output[i].size() < max_len) output[i] += '.';\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << output[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> h[i][j];\n\n    const int MOVE_COST_BASE = 100;\n    int x = 0, y = 0, load = 0;\n    vector<string> ops;\n\n    auto dist = [&](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_to = [&](int tx, int ty) {\n        while (x < tx) { ops.push_back(\"D\"); x++; }\n        while (x > tx) { ops.push_back(\"U\"); x--; }\n        while (y < ty) { ops.push_back(\"R\"); y++; }\n        while (y > ty) { ops.push_back(\"L\"); y--; }\n    };\n\n    while (true) {\n        // Check if any positive remains\n        bool has_pos = false;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (h[i][j] > 0) { has_pos = true; break; }\n        if (!has_pos) break;\n\n        if (load == 0) {\n            // Find best positive-negative pair\n            int best_cost = 1e9;\n            int best_px = -1, best_py = -1, best_nx = -1, best_ny = -1;\n            \n            for (int pi = 0; pi < N; pi++) {\n                for (int pj = 0; pj < N; pj++) {\n                    if (h[pi][pj] <= 0) continue;\n                    // Find nearest negative for this positive\n                    int near_ni = -1, near_nj = -1, near_dist = 1e9;\n                    for (int ni = 0; ni < N; ni++) {\n                        for (int nj = 0; nj < N; nj++) {\n                            if (h[ni][nj] >= 0) continue;\n                            int d = dist(pi, pj, ni, nj);\n                            if (d < near_dist) {\n                                near_dist = d;\n                                near_ni = ni;\n                                near_nj = nj;\n                            }\n                        }\n                    }\n                    if (near_ni == -1) continue;\n                    // Cost: move to positive (empty) + move to negative (loaded with h[pi][pj])\n                    int amount = h[pi][pj];\n                    int cost = dist(x, y, pi, pj) * MOVE_COST_BASE \n                             + near_dist * (MOVE_COST_BASE + amount);\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_px = pi;\n                        best_py = pj;\n                        best_nx = near_ni;\n                        best_ny = near_nj;\n                    }\n                }\n            }\n            \n            if (best_px == -1) break;\n            \n            // Move to positive, load\n            move_to(best_px, best_py);\n            int amount = h[best_px][best_py];\n            ops.push_back(\"+\" + to_string(amount));\n            load += amount;\n            h[best_px][best_py] = 0;\n            \n            // Move to negative, unload\n            move_to(best_nx, best_ny);\n            int need = -h[best_nx][best_ny];\n            int unload = min(load, need);\n            ops.push_back(\"-\" + to_string(unload));\n            h[best_nx][best_ny] += unload;\n            load -= unload;\n            \n        } else {\n            // We have remaining load, find nearest negative\n            int best_dist = 1e9, best_nx = -1, best_ny = -1;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (h[i][j] >= 0) continue;\n                    int d = dist(x, y, i, j);\n                    if (d < best_dist) {\n                        best_dist = d;\n                        best_nx = i;\n                        best_ny = j;\n                    }\n                }\n            }\n            if (best_nx == -1) {\n                // No more negatives? Should not happen if sum is zero\n                break;\n            }\n            move_to(best_nx, best_ny);\n            int need = -h[best_nx][best_ny];\n            int unload = min(load, need);\n            ops.push_back(\"-\" + to_string(unload));\n            h[best_nx][best_ny] += unload;\n            load -= unload;\n        }\n    }\n\n    for (const auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <set>\n#include <tuple>\n#include <cmath>\n#include <queue>\n#include <map>\n#include <cstring>\n#include <iomanip>\n#include <cassert>\n\nusing namespace std;\n\nint main() {\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1); // 60\n    vector<vector<int>> X(seed_count, vector<int>(M, 0));\n\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    // Precompute initial per-dimension maximums\n    vector<int> dimension_max(M, 0);\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            dimension_max[j] = max(dimension_max[j], X[i][j]);\n        }\n    }\n    int theoretical_max = accumulate(dimension_max.begin(), dimension_max.end(), 0);\n\n    // For each turn\n    for (int t = 0; t < T; t++) {\n        // Compute value and per-dimension contribution for each seed\n        vector<int> seed_val(seed_count);\n        vector<vector<int>> seed_dim_scores(seed_count, vector<int>(M));\n        \n        for (int i = 0; i < seed_count; i++) {\n            int sum = 0;\n            for (int j = 0; j < M; j++) {\n                sum += X[i][j];\n                // Score: how close to max for each dimension\n                seed_dim_scores[i][j] = X[i][j];\n            }\n            seed_val[i] = sum;\n        }\n        \n        // Selection strategy varies by turn\n        vector<int> selected;\n        set<int> selected_set;\n        \n        if (t < 2) {\n            // Early turns: Select diverse seeds that cover maximums well\n            // First, select top seeds by total value\n            vector<pair<int, int>> by_val;\n            for (int i = 0; i < seed_count; i++) {\n                by_val.push_back({seed_val[i], i});\n            }\n            sort(by_val.begin(), by_val.end(), greater<pair<int, int>>());\n            \n            // Take top 20 by value\n            for (int i = 0; i < 20 && i < seed_count; i++) {\n                selected.push_back(by_val[i].second);\n                selected_set.insert(by_val[i].second);\n            }\n            \n            // Then add seeds that have high values in dimensions not well-covered\n            vector<int> dim_coverage(M, 0);\n            for (int idx : selected) {\n                for (int j = 0; j < M; j++) {\n                    dim_coverage[j] = max(dim_coverage[j], X[idx][j]);\n                }\n            }\n            \n            // Find seeds that improve coverage\n            vector<pair<int, int>> improvement_scores;\n            for (int i = 0; i < seed_count; i++) {\n                if (selected_set.find(i) != selected_set.end()) continue;\n                int improvement = 0;\n                for (int j = 0; j < M; j++) {\n                    if (X[i][j] > dim_coverage[j]) {\n                        improvement += X[i][j] - dim_coverage[j];\n                    }\n                }\n                improvement_scores.push_back({improvement, i});\n            }\n            sort(improvement_scores.begin(), improvement_scores.end(), greater<pair<int, int>>());\n            \n            for (int i = 0; (int)selected.size() < N * N && i < (int)improvement_scores.size(); i++) {\n                selected.push_back(improvement_scores[i].second);\n                selected_set.insert(improvement_scores[i].second);\n            }\n            \n            // Fill remaining with best by value\n            for (int i = 0; (int)selected.size() < N * N && i < seed_count; i++) {\n                if (selected_set.find(by_val[i].second) == selected_set.end()) {\n                    selected.push_back(by_val[i].second);\n                    selected_set.insert(by_val[i].second);\n                }\n            }\n        } else if (t < 5) {\n            // Middle turns: Focus on seeds that have good combinations\n            // Select top seeds by value, but with some diversity preservation\n            vector<pair<int, int>> by_val;\n            for (int i = 0; i < seed_count; i++) {\n                by_val.push_back({seed_val[i], i});\n            }\n            sort(by_val.begin(), by_val.end(), greater<pair<int, int>>());\n            \n            // Take top 30 by value\n            for (int i = 0; i < 30 && i < seed_count; i++) {\n                selected.push_back(by_val[i].second);\n                selected_set.insert(by_val[i].second);\n            }\n            \n            // Add seeds that contribute to dimensions not at max yet\n            vector<int> current_dim_max(M, 0);\n            for (int idx : selected) {\n                for (int j = 0; j < M; j++) {\n                    current_dim_max[j] = max(current_dim_max[j], X[idx][j]);\n                }\n            }\n            \n            vector<pair<int, int>> improvement_scores;\n            for (int i = 0; i < seed_count; i++) {\n                if (selected_set.find(i) != selected_set.end()) continue;\n                int improvement = 0;\n                for (int j = 0; j < M; j++) {\n                    if (X[i][j] > current_dim_max[j]) {\n                        improvement += X[i][j] - current_dim_max[j];\n                    }\n                }\n                improvement_scores.push_back({improvement, i});\n            }\n            sort(improvement_scores.begin(), improvement_scores.end(), greater<pair<int, int>>());\n            \n            for (int i = 0; (int)selected.size() < N * N && i < (int)improvement_scores.size(); i++) {\n                if (selected_set.find(improvement_scores[i].second) == selected_set.end()) {\n                    selected.push_back(improvement_scores[i].second);\n                    selected_set.insert(improvement_scores[i].second);\n                }\n            }\n            \n            // Fill with best by value\n            for (int i = 0; (int)selected.size() < N * N && i < seed_count; i++) {\n                if (selected_set.find(by_val[i].second) == selected_set.end()) {\n                    selected.push_back(by_val[i].second);\n                    selected_set.insert(by_val[i].second);\n                }\n            }\n        } else {\n            // Late turns: Pure elitism - select absolute best seeds\n            vector<pair<int, int>> by_val;\n            for (int i = 0; i < seed_count; i++) {\n                by_val.push_back({seed_val[i], i});\n            }\n            sort(by_val.begin(), by_val.end(), greater<pair<int, int>>());\n            \n            for (int i = 0; i < N * N && i < seed_count; i++) {\n                selected.push_back(by_val[i].second);\n                selected_set.insert(by_val[i].second);\n            }\n        }\n        \n        // Ensure we have exactly N*N seeds\n        while ((int)selected.size() < N * N) {\n            for (int i = 0; i < seed_count && (int)selected.size() < N * N; i++) {\n                if (selected_set.find(i) == selected_set.end()) {\n                    selected.push_back(i);\n                    selected_set.insert(i);\n                }\n            }\n        }\n        \n        // Compute values for selected seeds\n        vector<pair<int, int>> sel_vals;\n        for (int idx : selected) {\n            sel_vals.push_back({seed_val[idx], idx});\n        }\n        sort(sel_vals.begin(), sel_vals.end(), greater<pair<int, int>>());\n        \n        // Grid arrangement\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        \n        if (t < 2) {\n            // Early turns: Interleave diverse seeds to maximize mixing\n            // Sort by total value\n            vector<int> sorted;\n            for (auto& p : sel_vals) sorted.push_back(p.second);\n            \n            // Snake pattern for good mixing\n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                if (i % 2 == 0) {\n                    for (int j = 0; j < N; j++) {\n                        A[i][j] = sorted[pos++];\n                    }\n                } else {\n                    for (int j = N - 1; j >= 0; j--) {\n                        A[i][j] = sorted[pos++];\n                    }\n                }\n            }\n        } else if (t < 5) {\n            // Middle turns: Concentrate good seeds but allow mixing\n            vector<int> sorted;\n            for (auto& p : sel_vals) sorted.push_back(p.second);\n            \n            // Place in a modified snake that keeps the very best seeds in center\n            // First, identify center positions\n            vector<pair<int, int>> positions;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    positions.push_back({i, j});\n                }\n            }\n            // Sort by distance from center (closest first)\n            double cx = (N - 1) / 2.0;\n            double cy = (N - 1) / 2.0;\n            sort(positions.begin(), positions.end(), \n                 [cx, cy](const pair<int,int>& a, const pair<int,int>& b) {\n                     double da = pow(a.first - cx, 2) + pow(a.second - cy, 2);\n                     double db = pow(b.first - cx, 2) + pow(b.second - cy, 2);\n                     return da < db;\n                 });\n            \n            // Place best seeds in center positions\n            for (int idx = 0; idx < (int)sorted.size() && idx < (int)positions.size(); idx++) {\n                A[positions[idx].first][positions[idx].second] = sorted[idx];\n            }\n        } else {\n            // Late turns: Maximize adjacency between top seeds\n            // Use a BFS from center to place best seeds as neighbors\n            vector<int> sorted;\n            for (auto& p : sel_vals) sorted.push_back(p.second);\n            \n            // Place absolute best seed in center\n            int ci = N / 2, cj = N / 2;\n            A[ci][cj] = sorted[0];\n            set<int> placed_pos;\n            placed_pos.insert(ci * N + cj);\n            \n            // BFS queue\n            queue<pair<int, int>> q;\n            q.push({ci, cj});\n            int seed_idx = 1;\n            \n            const int di[] = {-1, 1, 0, 0};\n            const int dj[] = {0, 0, -1, 1};\n            \n            while (!q.empty() && seed_idx < (int)sorted.size()) {\n                auto [i, j] = q.front();\n                q.pop();\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = i + di[d];\n                    int nj = j + dj[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N && \n                        placed_pos.find(ni * N + nj) == placed_pos.end()) {\n                        A[ni][nj] = sorted[seed_idx++];\n                        placed_pos.insert(ni * N + nj);\n                        q.push({ni, nj});\n                    }\n                }\n            }\n            \n            // Fill remaining (should not happen often)\n            for (int i = 0; i < N && seed_idx < (int)sorted.size(); i++) {\n                for (int j = 0; j < N && seed_idx < (int)sorted.size(); j++) {\n                    if (A[i][j] == -1) {\n                        A[i][j] = sorted[seed_idx++];\n                    }\n                }\n            }\n        }\n        \n        // Output 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 << endl;\n        }\n        cout.flush();\n        \n        // Read new 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 <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <cassert>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\nusing namespace std;\n\n// ---------- Constants ----------\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char MOVE_CHAR[4] = {'R', 'D', 'L', 'U'};\n\n// ---------- Types ----------\nstruct Point {\n    int x, y;\n    Point operator+(Point o) const { return {x+o.x, y+o.y}; }\n    bool operator==(Point o) const { return x==o.x && y==o.y; }\n};\n\n// ---------- Global state ----------\nint N, M, V;\nvector<string> start_grid, target_grid;\nvector<pair<int,int>> start_positions, target_positions;\nvector<int> parent;\nvector<int> length_to_parent;\nvector<int> leaf_order; // leaves index\nint root_x, root_y;\nvector<int> angles; // direction index (0: right, 1: down, 2: left, 3: up)\nvector<bool> holding; // true if fingertip carrying takoyaki\nvector<Point> fingertip_positions;\nvector<vector<int>> children;\n\n// ---------- Function declarations ----------\nvoid design_tree();\nvoid compute_fingertip_positions();\nvoid simulate_turn(vector<string>& commands, int& turn);\nbool pick_if_possible(int leaf_idx);\nbool place_if_possible(int leaf_idx);\nvoid move_root_to_target(Point target, vector<string>& commands);\nvoid set_angle(int node, int desired_angle, vector<string>& commands);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N >> M >> V;\n    start_grid.resize(N);\n    target_grid.resize(N);\n    for (int i = 0; i < N; i++) cin >> start_grid[i];\n    for (int i = 0; i < N; i++) cin >> target_grid[i];\n\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (start_grid[i][j] == '1')\n                start_positions.emplace_back(i, j);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (target_grid[i][j] == '1')\n                target_positions.emplace_back(i, j);\n\n    // Design tree\n    design_tree();\n\n    // Set initial root near center of start positions\n    int sumx = 0, sumy = 0;\n    for (auto& p : start_positions) { sumx += p.first; sumy += p.second; }\n    root_x = sumx / M;\n    root_y = sumy / M;\n    root_x = min(max(root_x, 0), N-1);\n    root_y = min(max(root_y, 0), N-1);\n\n    // Output tree info\n    int Vp = parent.size();\n    cout << Vp << \"\\n\";\n    for (int i = 1; i < Vp; i++)\n        cout << parent[i] << \" \" << length_to_parent[i] << \"\\n\";\n    cout << root_x << \" \" << root_y << \"\\n\";\n\n    angles.assign(Vp, 0); // all edges initially to the right\n    holding.assign(Vp, false);\n\n    // Identify leaves\n    vector<bool> is_leaf(Vp, false);\n    for (int i = 0; i < Vp; i++) {\n        if (children[i].empty()) {\n            is_leaf[i] = true;\n            leaf_order.push_back(i);\n        }\n    }\n\n    // Simulation\n    vector<string> commands;\n    int turn = 0;\n    const int MAX_TURNS = 100000;\n\n    // Simple greedy assignment: for each leaf, find nearest start->target pair\n    vector<tuple<int,int,int>> tasks; // (dist, start_idx, target_idx)\n    for (size_t si = 0; si < start_positions.size(); si++) {\n        int best_ti = -1;\n        int best_dist = 1e9;\n        for (size_t ti = 0; ti < target_positions.size(); ti++) {\n            int d = abs(start_positions[si].first - target_positions[ti].first)\n                   + abs(start_positions[si].second - target_positions[ti].second);\n            if (d < best_dist) {\n                best_dist = d;\n                best_ti = ti;\n            }\n        }\n        tasks.emplace_back(best_dist, si, best_ti);\n    }\n    sort(tasks.begin(), tasks.end());\n\n    vector<bool> start_done(start_positions.size(), false);\n    vector<bool> target_done(target_positions.size(), false);\n    int placed = 0;\n\n    auto try_move_leaf_to = [&](int leaf, Point target) {\n        // move root toward target, then set leaf angle\n        while (turn < MAX_TURNS) {\n            Point cur = fingertip_positions[leaf];\n            if (cur.x == target.x && cur.y == target.y) break;\n            // move root greedily\n            int dx = target.x - cur.x;\n            int dy = target.y - cur.y;\n            int mx = (dx > 0) - (dx < 0);\n            int my = (dy > 0) - (dy < 0);\n            if (mx != 0 || my != 0) {\n                int dir = -1;\n                if (mx == 1 && my == 0) dir = 1; // down\n                else if (mx == -1 && my == 0) dir = 3; // up\n                else if (mx == 0 && my == 1) dir = 0; // right\n                else if (mx == 0 && my == -1) dir = 2; // left\n                else if (mx == 1 && my == 1) dir = (rand()%2) ? 1 : 0;\n                else if (mx == -1 && my == 1) dir = (rand()%2) ? 3 : 0;\n                else if (mx == 1 && my == -1) dir = (rand()%2) ? 1 : 2;\n                else if (mx == -1 && my == -1) dir = (rand()%2) ? 3 : 2;\n                if (dir >= 0) {\n                    int nx = root_x + DX[dir];\n                    int ny = root_y + DY[dir];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        root_x = nx; root_y = ny;\n                        string cmd(2*Vp, '.');\n                        cmd[0] = MOVE_CHAR[dir];\n                        commands.push_back(cmd);\n                        turn++;\n                        compute_fingertip_positions();\n                        continue;\n                    }\n                }\n            }\n            // rotation to adjust fingertip if close\n            if (abs(cur.x - target.x) <= 1 && abs(cur.y - target.y) <= 1) {\n                for (int a = 0; a < 4; a++) {\n                    angles[leaf] = a;\n                    compute_fingertip_positions();\n                    if (fingertip_positions[leaf].x == target.x && fingertip_positions[leaf].y == target.y) {\n                        string cmd(2*Vp, '.');\n                        cmd[leaf] = (a == (angles[leaf]+3)%4) ? 'L' : ((a == (angles[leaf]+1)%4) ? 'R' : '.');\n                        commands.push_back(cmd);\n                        turn++;\n                        return;\n                    }\n                }\n            }\n        }\n    };\n\n    for (auto& [dist, si, ti] : tasks) {\n        if (start_done[si] || target_done[ti]) continue;\n        Point sp = {start_positions[si].first, start_positions[si].second};\n        Point tp = {target_positions[ti].first, target_positions[ti].second};\n\n        int leaf = leaf_order[0]; // simple: use first leaf for everything\n\n        // go to start\n        try_move_leaf_to(leaf, sp);\n        // pick\n        if (fingertip_positions[leaf] == sp && !holding[leaf] && start_grid[sp.x][sp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = true;\n            start_grid[sp.x][sp.y] = '0';\n            turn++;\n        }\n        // go to target\n        try_move_leaf_to(leaf, tp);\n        // place\n        if (fingertip_positions[leaf] == tp && holding[leaf] && target_grid[tp.x][tp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = false;\n            target_grid[tp.x][tp.y] = '0';\n            placed++;\n            turn++;\n        }\n        start_done[si] = true;\n        target_done[ti] = true;\n    }\n\n    for (auto& s : commands) cout << s << \"\\n\";\n    return 0;\n}\n\nvoid design_tree() {\n    // simple star-like: root + V-1 leaves with length 1..N-1\n    parent.push_back(-1);\n    length_to_parent.push_back(0);\n    children.resize(1);\n    for (int i = 1; i < V; i++) {\n        parent.push_back(0);\n        length_to_parent.push_back(1);\n        children[0].push_back(i);\n        children.push_back({});\n    }\n}\n\nvoid compute_fingertip_positions() {\n    fingertip_positions.resize(parent.size());\n    fingertip_positions[0] = {root_x, root_y};\n    for (int i = 1; i < (int)parent.size(); i++) {\n        int p = parent[i];\n        int len = length_to_parent[i];\n        int dir = angles[i];\n        Point offset = {DX[dir]*len, DY[dir]*len};\n        fingertip_positions[i] = fingertip_positions[p] + offset;\n    }\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_COORD = 100000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<int> mx(N), my(N), sx(N), sy(N);\n    for (int i = 0; i < N; i++) cin >> mx[i] >> my[i];\n    for (int i = 0; i < N; i++) cin >> sx[i] >> sy[i];\n    \n    // Use a coarse grid for initial approximation\n    const int G = 50;\n    int cellW = (MAX_COORD + G - 1) / G;\n    int cellH = (MAX_COORD + G - 1) / G;\n    \n    vector<vector<int>> mGrid(G, vector<int>(G, 0));\n    vector<vector<int>> sGrid(G, vector<int>(G, 0));\n    \n    for (int i = 0; i < N; i++) {\n        mGrid[min(my[i]/cellH, G-1)][min(mx[i]/cellW, G-1)]++;\n        sGrid[min(sy[i]/cellH, G-1)][min(sx[i]/cellW, G-1)]++;\n    }\n    \n    // Value grid\n    vector<vector<int>> val(G, vector<int>(G, 0));\n    for (int i = 0; i < G; i++)\n        for (int j = 0; j < G; j++)\n            val[i][j] = mGrid[i][j] - sGrid[i][j];\n    \n    // 2D prefix sum\n    vector<vector<int>> pref(G + 1, vector<int>(G + 1, 0));\n    for (int i = 0; i < G; i++)\n        for (int j = 0; j < G; j++)\n            pref[i + 1][j + 1] = val[i][j] + pref[i][j + 1] + \n                                 pref[i + 1][j] - pref[i][j];\n    \n    auto getSum = [&](int r1, int c1, int r2, int c2) {\n        return pref[r2 + 1][c2 + 1] - pref[r1][c2 + 1] - \n               pref[r2 + 1][c1] + pref[r1][c1];\n    };\n    \n    // Find best rectangle using 2D maximum subarray\n    int bestVal = -1e9;\n    int br1 = 0, bc1 = 0, br2 = 0, bc2 = 0;\n    \n    for (int r1 = 0; r1 < G; r1++) {\n        vector<int> rowSum(G, 0);\n        for (int r2 = r1; r2 < G; r2++) {\n            for (int c = 0; c < G; c++) rowSum[c] += val[r2][c];\n            \n            int curr = 0, maxSum = -1e9;\n            int cStart = 0, cBest = 0, cEnd = 0;\n            for (int c = 0; c < G; c++) {\n                if (curr <= 0) { curr = rowSum[c]; cStart = c; }\n                else curr += rowSum[c];\n                if (curr > maxSum) { maxSum = curr; cBest = cStart; cEnd = c; }\n            }\n            if (maxSum > bestVal) {\n                bestVal = maxSum;\n                br1 = r1; br2 = r2; bc1 = cBest; bc2 = cEnd;\n            }\n        }\n    }\n    \n    // Convert to coordinates\n    int x1 = bc1 * cellW;\n    int y1 = br1 * cellH;\n    int x2 = min(MAX_COORD, (bc2 + 1) * cellW);\n    int y2 = min(MAX_COORD, (br2 + 1) * cellH);\n    \n    // Simple count function (avoid building large data structures)\n    auto countInRect = [&](int xl, int xr, int yl, int yr) -> pair<int,int> {\n        int m = 0, s = 0;\n        for (int i = 0; i < N; i++) {\n            if (mx[i] >= xl && mx[i] <= xr && my[i] >= yl && my[i] <= yr) m++;\n            if (sx[i] >= xl && sx[i] <= xr && sy[i] >= yl && sy[i] <= yr) s++;\n        }\n        return {m, s};\n    };\n    \n    // Refine boundaries using binary search on sorted coordinates\n    vector<int> uniqX, uniqY;\n    uniqX.push_back(0); uniqX.push_back(MAX_COORD);\n    uniqY.push_back(0); uniqY.push_back(MAX_COORD);\n    for (int i = 0; i < N; i++) {\n        uniqX.push_back(mx[i]); uniqX.push_back(sx[i]);\n        uniqY.push_back(my[i]); uniqY.push_back(sy[i]);\n    }\n    sort(uniqX.begin(), uniqX.end());\n    uniqX.erase(unique(uniqX.begin(), uniqX.end()), uniqX.end());\n    sort(uniqY.begin(), uniqY.end());\n    uniqY.erase(unique(uniqY.begin(), uniqY.end()), uniqY.end());\n    \n    // Limit the number of candidate coordinates for refinement\n    if (uniqX.size() > 1000) {\n        // Keep only a subset: start, end, and every k-th element\n        vector<int> newX;\n        int step = uniqX.size() / 500;\n        for (int i = 0; i < (int)uniqX.size(); i += step) newX.push_back(uniqX[i]);\n        if (newX.back() != uniqX.back()) newX.push_back(uniqX.back());\n        uniqX = newX;\n    }\n    if (uniqY.size() > 1000) {\n        vector<int> newY;\n        int step = uniqY.size() / 500;\n        for (int i = 0; i < (int)uniqY.size(); i += step) newY.push_back(uniqY[i]);\n        if (newY.back() != uniqY.back()) newY.push_back(uniqY.back());\n        uniqY = newY;\n    }\n    \n    auto [curM, curS] = countInRect(x1, x2, y1, y2);\n    int curScore = curM - curS;\n    \n    // Refinement with limited iterations\n    for (int iter = 0; iter < 3; iter++) {\n        bool improved = false;\n        \n        // Left boundary\n        for (int nx : uniqX) {\n            if (nx >= x2) continue;\n            auto [m, s] = countInRect(nx, x2, y1, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                x1 = nx;\n                improved = true;\n                break;\n            }\n        }\n        \n        // Right boundary\n        for (int nx : uniqX) {\n            if (nx <= x1) continue;\n            auto [m, s] = countInRect(x1, nx, y1, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                x2 = nx;\n                improved = true;\n                break;\n            }\n        }\n        \n        // Bottom boundary\n        for (int ny : uniqY) {\n            if (ny >= y2) continue;\n            auto [m, s] = countInRect(x1, x2, ny, y2);\n            if (m - s > curScore) {\n                curScore = m - s;\n                y1 = ny;\n                improved = true;\n                break;\n            }\n        }\n        \n        // Top boundary\n        for (int ny : uniqY) {\n            if (ny <= y1) continue;\n            auto [m, s] = countInRect(x1, x2, y1, ny);\n            if (m - s > curScore) {\n                curScore = m - s;\n                y2 = ny;\n                improved = true;\n                break;\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Try L-shaped polygons with limited candidate points\n    // Sample a subset of inner corner positions\n    vector<pair<int,int>> innerPoints;\n    int stepX = max(1, (int)uniqX.size() / 30);\n    int stepY = max(1, (int)uniqY.size() / 30);\n    \n    for (int ix = 0; ix < (int)uniqX.size(); ix += stepX) {\n        int cx = uniqX[ix];\n        if (cx <= x1 || cx >= x2) continue;\n        for (int iy = 0; iy < (int)uniqY.size(); iy += stepY) {\n            int cy = uniqY[iy];\n            if (cy <= y1 || cy >= y2) continue;\n            innerPoints.push_back({cx, cy});\n        }\n    }\n    \n    struct Candidate {\n        vector<pair<int,int>> verts;\n        int score;\n    };\n    \n    vector<Candidate> candidates;\n    \n    // Rectangle\n    {\n        Candidate c;\n        c.verts = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n        c.score = curScore;\n        candidates.push_back(c);\n    }\n    \n    // L-shapes\n    for (auto [cx, cy] : innerPoints) {\n        // Bottom-left cut\n        {\n            auto [m1, s1] = countInRect(cx, x2, y1, y2);\n            auto [m2, s2] = countInRect(x1, cx - 1, cy, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x2, cy}, {x2, y2}, {x1, y2}, {x1, y1}, {cx, y1}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n        \n        // Bottom-right cut\n        {\n            auto [m1, s1] = countInRect(x1, cx, y1, y2);\n            auto [m2, s2] = countInRect(cx + 1, x2, cy, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x1, cy}, {x1, y2}, {x2, y2}, {x2, y1}, {cx, y1}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n        \n        // Top-right cut\n        {\n            auto [m1, s1] = countInRect(x1, x2, y1, cy);\n            auto [m2, s2] = countInRect(x1, cx, cy + 1, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x1, cy}, {x1, y1}, {x2, y1}, {x2, y2}, {cx, y2}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n        \n        // Top-left cut\n        {\n            auto [m1, s1] = countInRect(x1, x2, y1, cy);\n            auto [m2, s2] = countInRect(cx, x2, cy + 1, y2);\n            int score = (m1 + m2) - (s1 + s2);\n            if (score > 0) {\n                Candidate c;\n                c.verts = {{cx, cy}, {x2, cy}, {x2, y1}, {x1, y1}, {x1, y2}, {cx, y2}};\n                c.score = score;\n                candidates.push_back(c);\n            }\n        }\n    }\n    \n    // Sort by score\n    sort(candidates.begin(), candidates.end(), \n         [](const Candidate& a, const Candidate& b) { return a.score > b.score; });\n    \n    // Pick best valid candidate\n    vector<pair<int,int>> bestVerts;\n    for (auto& cand : candidates) {\n        // Check perimeter\n        long long perim = 0;\n        int sz = cand.verts.size();\n        for (int i = 0; i < sz; i++) {\n            int j = (i + 1) % sz;\n            perim += abs(cand.verts[i].first - cand.verts[j].first) + \n                     abs(cand.verts[i].second - cand.verts[j].second);\n        }\n        if (sz <= 1000 && perim <= 400000) {\n            // Simplify collinear vertices\n            vector<pair<int,int>> simp;\n            for (int i = 0; i < sz; i++) {\n                int prev = (i - 1 + sz) % sz;\n                int next = (i + 1) % sz;\n                bool col = false;\n                if (cand.verts[prev].first == cand.verts[i].first && \n                    cand.verts[i].first == cand.verts[next].first) col = true;\n                if (cand.verts[prev].second == cand.verts[i].second && \n                    cand.verts[i].second == cand.verts[next].second) col = true;\n                if (!col) simp.push_back(cand.verts[i]);\n            }\n            if (simp.size() >= 4) {\n                bestVerts = simp;\n            } else {\n                bestVerts = cand.verts;\n            }\n            break;\n        }\n    }\n    \n    if (bestVerts.empty()) {\n        bestVerts = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n    }\n    \n    // Output\n    cout << bestVerts.size() << \"\\n\";\n    for (auto [x, y] : bestVerts) {\n        cout << x << \" \" << y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T, sigma;\nvector<long long> est_w, est_h;\n\nstruct Placement {\n    int p, r, d;\n    int b;\n};\n\npair<long long, long long> query(const vector<Placement>& placements) {\n    cout << placements.size() << \"\\n\";\n    for (const auto& pl : placements) {\n        cout << pl.p << \" \" << pl.r << \" \" << (pl.d == 0 ? \"U\" : \"L\") << \" \" << pl.b << \"\\n\";\n    }\n    cout.flush();\n    long long W, H;\n    cin >> W >> H;\n    return {W, H};\n}\n\n// Core greedy packing with configurable parameters\nvector<Placement> pack(double skip_mult, bool prefer_U, bool rotate_all, bool rotate_none) {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long, int>> placed; // x, y, w, h, id\n    \n    for (int idx = 0; idx < N; idx++) {\n        long long w_orig = est_w[idx];\n        long long h_orig = est_h[idx];\n        \n        struct Option {\n            Placement p;\n            long long x, y, w, h, new_W, new_H;\n            bool skip;\n        };\n        const long long INF = 1LL << 60;\n        Option best;\n        best.new_W = INF; best.new_H = INF; best.skip = true;\n        \n        // Determine which rotations to try\n        vector<int> rots;\n        if (rotate_all) rots = {1};\n        else if (rotate_none) rots = {0};\n        else rots = {0, 1};\n        \n        for (int rot_flag : rots) {\n            long long w = w_orig, h = h_orig;\n            if (rot_flag == 1) swap(w, h);\n            \n            // Try U and L\n            vector<int> dirs;\n            if (prefer_U) dirs = {0, 1};\n            else dirs = {1, 0};\n            \n            for (int dir : dirs) {\n                // b = -1\n                {\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        for (const auto& [px, py, pw, ph, pid] : placed) {\n                            if (x < px + pw && x + w > px) y = max(y, py + ph);\n                        }\n                    } else {\n                        for (const auto& [px, py, pw, ph, pid] : placed) {\n                            if (y < py + ph && y + h > py) x = max(x, px + pw);\n                        }\n                    }\n                    Placement p;\n                    p.p = idx; p.r = rot_flag; p.d = dir; p.b = -1;\n                    Option opt;\n                    opt.p = p; opt.x = x; opt.y = y; opt.w = w; opt.h = h; opt.skip = false;\n                    opt.new_W = x + w; opt.new_H = y + h;\n                    for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                        opt.new_W = max(opt.new_W, px2 + pw2);\n                        opt.new_H = max(opt.new_H, py2 + ph2);\n                    }\n                    if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n                }\n                \n                // b = each placed rectangle\n                int n_placed = (int)placed.size();\n                int step = max(1, n_placed / 20); // limit to ~20 references\n                for (int pi = 0; pi < n_placed; pi += step) {\n                    auto& [px, py, pw, ph, pid] = placed[pi];\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        x = px + pw;\n                        for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                            if (x < px2 + pw2 && x + w > px2) y = max(y, py2 + ph2);\n                        }\n                    } else {\n                        y = py + ph;\n                        for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                            if (y < py2 + ph2 && y + h > py2) x = max(x, px2 + pw2);\n                        }\n                    }\n                    Placement p;\n                    p.p = idx; p.r = rot_flag; p.d = dir; p.b = pid;\n                    Option opt;\n                    opt.p = p; opt.x = x; opt.y = y; opt.w = w; opt.h = h; opt.skip = false;\n                    opt.new_W = x + w; opt.new_H = y + h;\n                    for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                        opt.new_W = max(opt.new_W, px2 + pw2);\n                        opt.new_H = max(opt.new_H, py2 + ph2);\n                    }\n                    if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n                }\n            }\n        }\n        \n        // Skip decision\n        long long current_W = 0, current_H = 0;\n        for (const auto& [px, py, pw, ph, pid] : placed) {\n            current_W = max(current_W, px + pw);\n            current_H = max(current_H, py + ph);\n        }\n        long long current_sum = current_W + current_H;\n        long long skip_cost = w_orig + h_orig;\n        \n        if (!best.skip && best.new_W + best.new_H <= current_sum + skip_cost * skip_mult) {\n            placements.push_back(best.p);\n            placed.emplace_back(best.x, best.y, best.w, best.h, idx);\n        }\n    }\n    \n    return placements;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> T >> sigma;\n    est_w.resize(N);\n    est_h.resize(N);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> est_w[i] >> est_h[i];\n    }\n    \n    auto time_limit = chrono::milliseconds(2900);\n    long long best_score = LLONG_MAX;\n    \n    // Generate diverse parameter combinations\n    struct Config {\n        double skip_mult;\n        bool prefer_U;\n        bool rotate_all;\n        bool rotate_none;\n    };\n    \n    vector<Config> configs;\n    for (double mult : {1.0, 0.6, 0.8, 1.2, 1.5, 2.0, 0.4, 0.9, 1.1, 1.8}) {\n        for (bool pref_U : {true, false}) {\n            configs.push_back({mult, pref_U, false, false});\n        }\n    }\n    // Add forced rotation configs\n    for (double mult : {1.0, 0.8, 1.2}) {\n        for (bool pref_U : {true, false}) {\n            configs.push_back({mult, pref_U, true, false}); // all rotated\n            configs.push_back({mult, pref_U, false, true}); // none rotated\n        }\n    }\n    \n    // Shuffle for diversity\n    mt19937 rng(42);\n    shuffle(configs.begin(), configs.end(), rng);\n    \n    for (int turn = 0; turn < T; turn++) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time);\n        if (elapsed > time_limit) break;\n        \n        Config cfg = configs[turn % configs.size()];\n        vector<Placement> placements = pack(cfg.skip_mult, cfg.prefer_U, cfg.rotate_all, cfg.rotate_none);\n        \n        auto [W, H] = query(placements);\n        \n        vector<bool> used(N, false);\n        for (const auto& pl : placements) used[pl.p] = true;\n        long long penalty = 0;\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) penalty += est_w[i] + est_h[i];\n        }\n        long long score = W + H + penalty;\n        \n        if (score < best_score) best_score = score;\n    }\n    \n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Xor128 {\n    unsigned x, y, z, w;\n    Xor128(unsigned seed = 123456789) : x(seed), y(362436069), z(521288629), w(88675123) {}\n    unsigned next() {\n        unsigned t = x ^ (x << 11);\n        x = y; y = z; z = w;\n        return w = w ^ (w >> 19) ^ t ^ (t >> 8);\n    }\n    double prob() { return next() / 4294967295.0; }\n};\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<pair<int,int>> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].first >> edges[i].second;\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n    }\n\n    vector<vector<int>> adj(N);\n    for (auto &e : edges) {\n        adj[e.first].push_back(e.second);\n        adj[e.second].push_back(e.first);\n    }\n\n    vector<int> parent(N, -1);\n    vector<int> depth(N, 0);\n    vector<int> subtree_size(N, 1);\n    vector<vector<int>> children(N);\n    \n    // Build tree structures from parent array\n    auto build_tree = [&]() {\n        for (int i = 0; i < N; ++i) children[i].clear();\n        for (int i = 0; i < N; ++i) {\n            if (parent[i] != -1) children[parent[i]].push_back(i);\n        }\n    };\n    \n    // Compute depths and subtree sizes via DFS\n    auto compute_depths_sizes = [&]() -> bool {\n        vector<int> indeg(N, 0);\n        for (int i = 0; i < N; ++i) if (parent[i] != -1) indeg[parent[i]]++;\n        queue<int> q;\n        for (int i = 0; i < N; ++i) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            } else {\n                depth[i] = -1;\n            }\n        }\n        int cnt = 0;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            cnt++;\n            if (depth[v] > H) return false;\n            for (int nb : adj[v]) {\n                if (parent[nb] == v) {\n                    depth[nb] = depth[v] + 1;\n                    q.push(nb);\n                }\n            }\n        }\n        if (cnt != N) return false;\n        \n        // Compute subtree sizes bottom-up\n        fill(subtree_size.begin(), subtree_size.end(), 1);\n        vector<int> order;\n        for (int i = 0; i < N; ++i) if (parent[i] == -1) {\n            order.push_back(i);\n        }\n        // topological order\n        queue<int> q2;\n        for (int i = 0; i < N; ++i) if (parent[i] == -1) q2.push(i);\n        vector<int> topo;\n        while (!q2.empty()) {\n            int v = q2.front(); q2.pop();\n            topo.push_back(v);\n            for (int nb : adj[v]) {\n                if (parent[nb] == v) {\n                    q2.push(nb);\n                }\n            }\n        }\n        reverse(topo.begin(), topo.end());\n        for (int v : topo) {\n            if (parent[v] != -1) {\n                subtree_size[parent[v]] += subtree_size[v];\n            }\n        }\n        return true;\n    };\n\n    // Compute total attractiveness\n    auto total_score = [&]() {\n        long long sc = 1;\n        for (int v = 0; v < N; ++v) sc += (depth[v] + 1LL) * A[v];\n        return sc;\n    };\n\n    // Initial: all roots\n    parent.assign(N, -1);\n    depth.assign(N, 0);\n    compute_depths_sizes();\n    long long current_score = total_score();\n    \n    vector<int> best_parent = parent;\n    long long best_score = current_score;\n    \n    Xor128 rng(123456789);\n    \n    // Simulated Annealing parameters\n    double temp_start = 500.0;\n    double temp_end = 1.0;\n    int max_iter = 50000;\n    \n    auto elapsed = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(1800);\n    \n    for (int iter = 0; iter < max_iter; ++iter) {\n        if (chrono::steady_clock::now() - elapsed > time_limit) break;\n        \n        double progress = (double)iter / max_iter;\n        double temp = temp_start * pow(temp_end / temp_start, progress);\n        \n        // Pick random vertex u\n        int u = rng.next() % N;\n        int old_p = parent[u];\n        int old_d = depth[u];\n        \n        // Try random neighbor as new parent\n        if (adj[u].empty()) continue;\n        int p = adj[u][rng.next() % adj[u].size()];\n        if (p == u || p == old_p) continue;\n        if (depth[p] + 1 > H) continue;\n        \n        // Temporarily change\n        parent[u] = p;\n        if (compute_depths_sizes()) {\n            long long new_score = total_score();\n            long long delta = new_score - current_score;\n            if (delta >= 0 || rng.prob() < exp(delta / temp)) {\n                current_score = new_score;\n                if (current_score > best_score) {\n                    best_score = current_score;\n                    best_parent = parent;\n                }\n                continue;\n            }\n        }\n        // Revert\n        parent[u] = old_p;\n        compute_depths_sizes();\n    }\n    \n    // Output best found\n    parent = best_parent;\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\nusing pii = pair<int,int>;\n\nint N;\nvector<string> board;\nvector<pair<char,int>> answer;\n\nvoid shiftRowLeft(int i) {\n    answer.push_back({'L', i});\n    for (int j = 0; j < N-1; j++)\n        board[i][j] = board[i][j+1];\n    board[i][N-1] = '.';\n}\n\nvoid shiftRowRight(int i) {\n    answer.push_back({'R', i});\n    for (int j = N-1; j > 0; j--)\n        board[i][j] = board[i][j-1];\n    board[i][0] = '.';\n}\n\nvoid shiftColUp(int j) {\n    answer.push_back({'U', j});\n    for (int i = 0; i < N-1; i++)\n        board[i][j] = board[i+1][j];\n    board[N-1][j] = '.';\n}\n\nvoid shiftColDown(int j) {\n    answer.push_back({'D', j});\n    for (int i = N-1; i > 0; i--)\n        board[i][j] = board[i-1][j];\n    board[0][j] = '.';\n}\n\n// Check if Oni at (i,j) can be removed in given direction\nbool canRemoveUp(int i, int j) {\n    for (int k = 0; k < i; k++)\n        if (board[k][j] == 'o') return false;\n    return true;\n}\nbool canRemoveDown(int i, int j) {\n    for (int k = i+1; k < N; k++)\n        if (board[k][j] == 'o') return false;\n    return true;\n}\nbool canRemoveLeft(int i, int j) {\n    for (int k = 0; k < j; k++)\n        if (board[i][k] == 'o') return false;\n    return true;\n}\nbool canRemoveRight(int i, int j) {\n    for (int k = j+1; k < N; k++)\n        if (board[i][k] == 'o') return false;\n    return true;\n}\n\n// Count Oni in a row that can be removed in a direction, and find farthest\nint countRemovableInRowLeft(int i, int& farthest_j) {\n    int count = 0;\n    farthest_j = -1;\n    for (int j = 0; j < N; j++) {\n        if (board[i][j] == 'x' && canRemoveLeft(i, j)) {\n            count++;\n            farthest_j = max(farthest_j, j);\n        }\n    }\n    return count;\n}\n\nint countRemovableInRowRight(int i, int& nearest_j) {\n    int count = 0;\n    nearest_j = N;\n    for (int j = 0; j < N; j++) {\n        if (board[i][j] == 'x' && canRemoveRight(i, j)) {\n            count++;\n            nearest_j = min(nearest_j, j);\n        }\n    }\n    return count;\n}\n\nint countRemovableInColUp(int j, int& farthest_i) {\n    int count = 0;\n    farthest_i = -1;\n    for (int i = 0; i < N; i++) {\n        if (board[i][j] == 'x' && canRemoveUp(i, j)) {\n            count++;\n            farthest_i = max(farthest_i, i);\n        }\n    }\n    return count;\n}\n\nint countRemovableInColDown(int j, int& nearest_i) {\n    int count = 0;\n    nearest_i = N;\n    for (int i = 0; i < N; i++) {\n        if (board[i][j] == 'x' && canRemoveDown(i, j)) {\n            count++;\n            nearest_i = min(nearest_i, i);\n        }\n    }\n    return count;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    board.resize(N);\n    for (int i = 0; i < N; i++) cin >> board[i];\n\n    // Main loop: repeatedly find and execute best batch removal\n    while (true) {\n        // Count remaining Oni\n        int remaining = 0;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (board[i][j] == 'x') remaining++;\n        if (remaining == 0) break;\n\n        double best_efficiency = -1.0;\n        char best_dir = 0;\n        int best_idx = -1;\n        int best_dist = 0;\n        int best_count = 0;\n\n        // Check all rows - LEFT\n        for (int i = 0; i < N; i++) {\n            int farthest_j;\n            int count = countRemovableInRowLeft(i, farthest_j);\n            if (count > 0) {\n                int dist = farthest_j + 1;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'L';\n                    best_idx = i;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        // Check all rows - RIGHT\n        for (int i = 0; i < N; i++) {\n            int nearest_j;\n            int count = countRemovableInRowRight(i, nearest_j);\n            if (count > 0) {\n                int dist = N - nearest_j;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'R';\n                    best_idx = i;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        // Check all columns - UP\n        for (int j = 0; j < N; j++) {\n            int farthest_i;\n            int count = countRemovableInColUp(j, farthest_i);\n            if (count > 0) {\n                int dist = farthest_i + 1;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'U';\n                    best_idx = j;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        // Check all columns - DOWN\n        for (int j = 0; j < N; j++) {\n            int nearest_i;\n            int count = countRemovableInColDown(j, nearest_i);\n            if (count > 0) {\n                int dist = N - nearest_i;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'D';\n                    best_idx = j;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        if (best_dir == 0) break; // No removable Oni found (should not happen)\n\n        // Execute the batch removal\n        if (best_dir == 'L') {\n            for (int s = 0; s < best_dist; s++) shiftRowLeft(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftRowRight(best_idx);\n        } else if (best_dir == 'R') {\n            for (int s = 0; s < best_dist; s++) shiftRowRight(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftRowLeft(best_idx);\n        } else if (best_dir == 'U') {\n            for (int s = 0; s < best_dist; s++) shiftColUp(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftColDown(best_idx);\n        } else if (best_dir == 'D') {\n            for (int s = 0; s < best_dist; s++) shiftColDown(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftColUp(best_idx);\n        }\n    }\n\n    // Output\n    for (auto [d, p] : answer)\n        cout << d << ' ' << p << '\\n';\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nint a[N], b[N];\nint best_a[N], best_b[N];\nint cnt[N];\nlong long best_error;\n\nvoid simulate() {\n    memset(cnt, 0, sizeof(cnt));\n    int cur = 0;\n    for (int week = 0; week < L; ++week) {\n        cnt[cur]++;\n        if (cnt[cur] & 1) cur = a[cur];\n        else cur = b[cur];\n    }\n}\n\nlong long calc_error() {\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += abs(cnt[i] - T[i]);\n    return err;\n}\n\n// Fast incremental error update when only one node's transitions change\n// (Not used in final version, but keeping simulation for correctness)\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    int n, l;\n    cin >> n >> l;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n    \n    auto start_time = steady_clock::now();\n    const double time_limit = 1.95;\n    mt19937 rng(12345);  // Different seed\n    uniform_int_distribution<int> rand_emp(0, N-1);\n    uniform_real_distribution<double> rand_real(0.0, 1.0);\n    \n    best_error = 1e18;\n    \n    // Try multiple restarts with different initializations\n    for (int restart = 0; restart < 100; ++restart) {\n        auto now = steady_clock::now();\n        if (duration<double>(now - start_time).count() > time_limit) break;\n        \n        // Initialize (a,b) smartly\n        if (restart == 0) {\n            // Simple round-robin\n            for (int i = 0; i < N; ++i) {\n                a[i] = (i + 1) % N;\n                b[i] = (i + 2) % N;\n            }\n        } else if (restart == 1) {\n            // Point to high-target nodes\n            vector<pair<int,int>> order;\n            for (int i = 0; i < N; ++i) order.push_back({T[i], i});\n            sort(order.rbegin(), order.rend());\n            for (int i = 0; i < N; ++i) {\n                a[i] = order[rand() % min(10, N)].second;\n                b[i] = order[rand() % min(10, N)].second;\n            }\n        } else {\n            // Random initialization biased towards high T\n            for (int i = 0; i < N; ++i) {\n                // Pick a random target with probability proportional to T\n                int r = rand() % L;\n                int sum = 0;\n                int target = 0;\n                for (int j = 0; j < N; ++j) {\n                    sum += T[j];\n                    if (r < sum) { target = j; break; }\n                }\n                a[i] = target;\n                r = rand() % L;\n                sum = 0;\n                target = 0;\n                for (int j = 0; j < N; ++j) {\n                    sum += T[j];\n                    if (r < sum) { target = j; break; }\n                }\n                b[i] = target;\n            }\n        }\n        \n        simulate();\n        long long current_error = calc_error();\n        \n        if (current_error < best_error) {\n            best_error = current_error;\n            memcpy(best_a, a, sizeof(a));\n            memcpy(best_b, b, sizeof(b));\n        }\n        \n        // Simulated annealing for this restart\n        double temp = 2000.0;\n        int iterations_without_improvement = 0;\n        \n        for (int iter = 0; iter < 5000; ++iter) {\n            auto now2 = steady_clock::now();\n            if (duration<double>(now2 - start_time).count() > time_limit) break;\n            \n            // Save state\n            int old_a[N], old_b[N], old_cnt[N];\n            memcpy(old_a, a, sizeof(a));\n            memcpy(old_b, b, sizeof(b));\n            memcpy(old_cnt, cnt, sizeof(cnt));\n            \n            // Targeted mutation: prefer changing nodes with high error\n            int i;\n            if (rand_real(rng) < 0.7) {\n                // Pick node proportional to its error contribution\n                vector<int> candidates;\n                for (int j = 0; j < N; ++j) {\n                    int err_j = abs(cnt[j] - T[j]);\n                    for (int k = 0; k < err_j + 1; ++k) candidates.push_back(j);\n                }\n                i = candidates[rand() % candidates.size()];\n            } else {\n                i = rand_emp(rng);\n            }\n            \n            // Change one transition\n            if (rand_real(rng) < 0.5) {\n                a[i] = rand_emp(rng);\n            } else {\n                b[i] = rand_emp(rng);\n            }\n            \n            simulate();\n            long long new_error = calc_error();\n            \n            double prob = exp((current_error - new_error) / temp);\n            if (new_error < current_error || rand_real(rng) < prob) {\n                current_error = new_error;\n                if (new_error < best_error) {\n                    best_error = new_error;\n                    memcpy(best_a, a, sizeof(a));\n                    memcpy(best_b, b, sizeof(b));\n                    iterations_without_improvement = 0;\n                }\n            } else {\n                memcpy(a, old_a, sizeof(a));\n                memcpy(b, old_b, sizeof(b));\n                memcpy(cnt, old_cnt, sizeof(cnt));\n                iterations_without_improvement++;\n            }\n            \n            temp *= 0.998;\n            if (temp < 0.1) break;\n            if (iterations_without_improvement > 1000) break;\n        }\n    }\n    \n    // Output best found\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#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        return parent[x] == x ? x : parent[x] = find(parent[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]) 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    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<long long> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n\n    // Estimated positions (rectangle centers)\n    vector<long long> estX(N), estY(N);\n    for (int i = 0; i < N; ++i) {\n        estX[i] = (lx[i] + rx[i]) / 2;\n        estY[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    // Morton code for better spatial ordering\n    auto morton = [](long long x, long long y) -> unsigned long long {\n        auto interleave = [](unsigned int a) -> unsigned long long {\n            unsigned long long b = a;\n            b = (b | (b << 16)) & 0x0000FFFF0000FFFFULL;\n            b = (b | (b << 8))  & 0x00FF00FF00FF00FFULL;\n            b = (b | (b << 4))  & 0x0F0F0F0F0F0F0F0FULL;\n            b = (b | (b << 2))  & 0x3333333333333333ULL;\n            b = (b | (b << 1))  & 0x5555555555555555ULL;\n            return b;\n        };\n        unsigned int ix = (unsigned int)max(0LL, min(10000LL, x));\n        unsigned int iy = (unsigned int)max(0LL, min(10000LL, y));\n        return interleave(ix) | (interleave(iy) << 1);\n    };\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return morton(estX[a], estY[a]) < morton(estX[b], estY[b]);\n    });\n\n    // Assign groups\n    vector<vector<int>> groups(M);\n    vector<int> group_of(N, -1), pos_in_group(N, -1);\n    int idx = 0;\n    for (int g = 0; g < M; ++g) {\n        groups[g].reserve(G[g]);\n        for (int j = 0; j < G[g]; ++j) {\n            int city = order[idx++];\n            groups[g].push_back(city);\n            group_of[city] = g;\n            pos_in_group[city] = j;\n        }\n    }\n\n    vector<vector<pair<int,int>>> final_edges(M);\n    vector<DSU> dsu;\n    dsu.reserve(M);\n    for (int g = 0; g < M; ++g) dsu.emplace_back(G[g]);\n\n    int queries_used = 0;\n\n    // Phase 1: Query sliding windows for each group\n    for (int g = 0; g < M && queries_used < Q; ++g) {\n        int sz = G[g];\n        if (sz <= 2) {\n            if (sz == 2) {\n                final_edges[g].emplace_back(0, 1);\n                dsu[g].unite(0, 1);\n            }\n            continue;\n        }\n\n        int step = L - 2;\n        if (step < 1) step = 1;\n        for (int start = 0; start + 1 < sz && queries_used < Q; start += step) {\n            int end = min(start + L, sz);\n            if (end - start < 2) break;\n\n            cout << \"? \" << end - start;\n            for (int j = start; j < end; ++j) cout << \" \" << groups[g][j];\n            cout << \"\\n\";\n            cout.flush();\n            ++queries_used;\n\n            for (int j = 0; j < (end - start) - 1; ++j) {\n                int a, b;\n                cin >> a >> b;\n                int pa = pos_in_group[a];\n                int pb = pos_in_group[b];\n                if (pa < start || pa >= end || pb < start || pb >= end) continue; // safety\n                if (dsu[g].unite(pa, pb))\n                    final_edges[g].emplace_back(pa, pb);\n            }\n        }\n    }\n\n    // Phase 2: Use remaining queries to connect components inside groups\n    for (int g = 0; g < M && queries_used < Q; ++g) {\n        int sz = G[g];\n        if (sz <= 2) continue;\n\n        // Find components\n        unordered_map<int, vector<int>> comps;\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        while (comps.size() > 1 && queries_used < Q) {\n            // Gather one representative from each component (up to L)\n            vector<int> reps;\n            for (auto &kv : comps) {\n                reps.push_back(kv.second.front());\n                if ((int)reps.size() == L) break;\n            }\n            if (reps.size() < 2) break;\n\n            cout << \"? \" << reps.size();\n            for (int r : reps) cout << \" \" << groups[g][r];\n            cout << \"\\n\";\n            cout.flush();\n            ++queries_used;\n\n            int nedges = reps.size() - 1;\n            for (int j = 0; j < nedges; ++j) {\n                int a, b;\n                cin >> a >> b;\n                int pa = pos_in_group[a];\n                int pb = pos_in_group[b];\n                if (dsu[g].unite(pa, pb))\n                    final_edges[g].emplace_back(pa, pb);\n            }\n            // Recompute components\n            comps.clear();\n            for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        }\n    }\n\n    // End queries\n    cout << \"!\\n\";\n    cout.flush();\n\n    // Phase 3: Complete connectivity by estimated distances\n    for (int g = 0; g < M; ++g) {\n        if (G[g] <= 1) continue;\n        const auto &cities = groups[g];\n        int sz = cities.size();\n\n        unordered_map<int, vector<int>> comps;\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        if (comps.size() == 1) continue;\n\n        // Compute centroids\n        vector<int> comp_ids;\n        vector<pair<long long, long long>> centroids;\n        for (auto &kv : comps) {\n            long long sx = 0, sy = 0;\n            for (int idx : kv.second) {\n                sx += estX[cities[idx]];\n                sy += estY[cities[idx]];\n            }\n            int cnt = kv.second.size();\n            centroids.emplace_back(sx / cnt, sy / cnt);\n            comp_ids.push_back(kv.first);\n        }\n\n        // Nearest-neighbor connections\n        int ccount = centroids.size();\n        DSU comp_dsu(ccount);\n        vector<tuple<long long, int, int>> inter_edges;\n        for (int i = 0; i < ccount; ++i) {\n            long long best_dist2 = LLONG_MAX;\n            int best_j = -1;\n            for (int j = 0; j < ccount; ++j) {\n                if (i == j) continue;\n                long long dx = centroids[i].first - centroids[j].first;\n                long long dy = centroids[i].second - centroids[j].second;\n                long long d2 = dx*dx + dy*dy;\n                if (d2 < best_dist2) {\n                    best_dist2 = d2;\n                    best_j = j;\n                }\n            }\n            if (best_j != -1) {\n                inter_edges.emplace_back(best_dist2, i, best_j);\n            }\n        }\n        sort(inter_edges.begin(), inter_edges.end());\n        for (auto &e : inter_edges) {\n            int i = get<1>(e), j = get<2>(e);\n            if (comp_dsu.unite(i, j)) {\n                // Find actual closest pair between component i and j\n                int u = -1, v = -1;\n                long long min_d2 = LLONG_MAX;\n                for (int a : comps[comp_ids[i]]) {\n                    long long xa = estX[cities[a]], ya = estY[cities[a]];\n                    for (int b : comps[comp_ids[j]]) {\n                        long long dx = xa - estX[cities[b]];\n                        long long dy = ya - estY[cities[b]];\n                        long long d2 = dx*dx + dy*dy;\n                        if (d2 < min_d2) {\n                            min_d2 = d2;\n                            u = a; v = b;\n                        }\n                    }\n                }\n                if (u != -1 && v != -1) {\n                    dsu[g].unite(u, v);\n                    final_edges[g].emplace_back(u, v);\n                }\n            }\n        }\n\n        // If still not fully connected, full Kruskal fallback\n        comps.clear();\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        if (comps.size() > 1) {\n            vector<tuple<long long, int, int>> cand;\n            vector<int> comp_keys;\n            for (auto &kv : comps) comp_keys.push_back(kv.first);\n            for (size_t ci = 0; ci < comp_keys.size(); ++ci) {\n                for (size_t cj = ci+1; cj < comp_keys.size(); ++cj) {\n                    for (int u : comps[comp_keys[ci]]) {\n                        for (int v : comps[comp_keys[cj]]) {\n                            long long dx = estX[cities[u]] - estX[cities[v]];\n                            long long dy = estY[cities[u]] - estY[cities[v]];\n                            long long d2 = dx*dx + dy*dy;\n                            cand.emplace_back(d2, u, v);\n                        }\n                    }\n                }\n            }\n            sort(cand.begin(), cand.end());\n            for (auto &e : cand) {\n                int u = get<1>(e), v = get<2>(e);\n                if (dsu[g].unite(u, v)) {\n                    final_edges[g].emplace_back(u, v);\n                }\n            }\n        }\n    }\n\n    // Output answer\n    for (int g = 0; g < M; ++g) {\n        for (int i = 0; i < G[g]; ++i) {\n            if (i) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << \"\\n\";\n        for (auto &e : final_edges[g]) {\n            cout << groups[g][e.first] << \" \" << groups[g][e.second] << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nvector<string> blocks;\nint cur_x, cur_y;\nvector<pair<int,int>> targets;\nvector<pair<char,char>> actions;\n\nbool valid(int x, int y) { return x>=0 && x<N && y>=0 && y<N; }\n\nvoid add(char t, char d) {\n    actions.push_back({t, d});\n    if (t == 'M') {\n        if (d == 'U') cur_x--; else if (d == 'D') cur_x++;\n        else if (d == 'L') cur_y--; else if (d == 'R') cur_y++;\n    } else if (t == 'S') {\n        while (true) {\n            int nx = cur_x, ny = cur_y;\n            if (d == 'U') nx--; else if (d == 'D') nx++;\n            else if (d == 'L') ny--; else if (d == 'R') ny++;\n            if (!valid(nx, ny) || blocks[nx][ny] == '#') break;\n            cur_x = nx; cur_y = ny;\n        }\n    } else if (t == 'A') {\n        int bx = cur_x, by = cur_y;\n        if (d == 'U') bx--; else if (d == 'D') bx++;\n        else if (d == 'L') by--; else if (d == 'R') by++;\n        if (valid(bx, by)) {\n            blocks[bx][by] = (blocks[bx][by] == '.') ? '#' : '.';\n        }\n    }\n}\n\nvoid move_to(int tx, int ty) {\n    while (cur_x != tx || cur_y != ty) {\n        if (cur_x < tx) {\n            if (blocks[cur_x+1][cur_y] == '#') { add('A', 'D'); continue; }\n            add('M', 'D');\n        } else if (cur_x > tx) {\n            if (blocks[cur_x-1][cur_y] == '#') { add('A', 'U'); continue; }\n            add('M', 'U');\n        } else if (cur_y < ty) {\n            if (blocks[cur_x][cur_y+1] == '#') { add('A', 'R'); continue; }\n            add('M', 'R');\n        } else if (cur_y > ty) {\n            if (blocks[cur_x][cur_y-1] == '#') { add('A', 'L'); continue; }\n            add('M', 'L');\n        }\n    }\n}\n\npair<int,int> slide_dest(int x, int y, char d) {\n    while (true) {\n        int nx = x, ny = y;\n        if (d == 'U') nx--; else if (d == 'D') nx++;\n        else if (d == 'L') ny--; else if (d == 'R') ny++;\n        if (!valid(nx, ny) || blocks[nx][ny] == '#') break;\n        x = nx; y = ny;\n    }\n    return {x, y};\n}\n\nint dist(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    cin >> N >> M;\n    blocks.assign(N, string(N, '.'));\n    targets.resize(M);\n    for (int i=0;i<M;++i) cin >> targets[i].first >> targets[i].second;\n\n    cur_x = targets[0].first;\n    cur_y = targets[0].second;\n\n    for (int t=1; t<M; ++t) {\n        int tx = targets[t].first, ty = targets[t].second;\n        while (cur_x != tx || cur_y != ty) {\n            // if aligned, try direct slide with temp block\n            if (cur_x == tx) {\n                if (cur_y < ty) {\n                    auto dest = slide_dest(cur_x, cur_y, 'R');\n                    if (dest.second == ty) { add('S', 'R'); continue; }\n                    else if (dest.second > ty) {\n                        if (ty+1 < N && blocks[tx][ty+1] != '#') {\n                            bool was_block = (blocks[tx][ty+1] == '#');\n                            move_to(tx, ty);\n                            if (!was_block) add('A', 'R'); // place block\n                            move_to(cur_x, ty-1); // move back left\n                            add('S', 'R');\n                            if (!was_block) add('A', 'R'); // remove\n                            continue;\n                        }\n                    }\n                } else if (cur_y > ty) {\n                    auto dest = slide_dest(cur_x, cur_y, 'L');\n                    if (dest.second == ty) { add('S', 'L'); continue; }\n                    else if (dest.second < ty) {\n                        if (ty-1 >= 0 && blocks[tx][ty-1] != '#') {\n                            bool was_block = (blocks[tx][ty-1] == '#');\n                            move_to(tx, ty);\n                            if (!was_block) add('A', 'L');\n                            move_to(cur_x, ty+1);\n                            add('S', 'L');\n                            if (!was_block) add('A', 'L');\n                            continue;\n                        }\n                    }\n                }\n                move_to(tx, ty);\n            } else if (cur_y == ty) {\n                if (cur_x < tx) {\n                    auto dest = slide_dest(cur_x, cur_y, 'D');\n                    if (dest.first == tx) { add('S', 'D'); continue; }\n                    else if (dest.first > tx) {\n                        if (tx+1 < N && blocks[tx+1][ty] != '#') {\n                            bool was_block = (blocks[tx+1][ty] == '#');\n                            move_to(tx, ty);\n                            if (!was_block) add('A', 'D');\n                            move_to(tx-1, cur_y);\n                            add('S', 'D');\n                            if (!was_block) add('A', 'D');\n                            continue;\n                        }\n                    }\n                } else if (cur_x > tx) {\n                    auto dest = slide_dest(cur_x, cur_y, 'U');\n                    if (dest.first == tx) { add('S', 'U'); continue; }\n                    else if (dest.first < tx) {\n                        if (tx-1 >= 0 && blocks[tx-1][ty] != '#') {\n                            bool was_block = (blocks[tx-1][ty] == '#');\n                            move_to(tx, ty);\n                            if (!was_block) add('A', 'U');\n                            move_to(tx+1, cur_y);\n                            add('S', 'U');\n                            if (!was_block) add('A', 'U');\n                            continue;\n                        }\n                    }\n                }\n                move_to(tx, ty);\n            } else {\n                // not aligned: try to slide to align\n                // Check slides that reduce distance to target\n                char best_slide = 0;\n                int best_dist = dist(cur_x, cur_y, tx, ty);\n                for (char d : {'U','D','L','R'}) {\n                    auto dest = slide_dest(cur_x, cur_y, d);\n                    int d2 = dist(dest.first, dest.second, tx, ty);\n                    if (d2 < best_dist) {\n                        best_dist = d2;\n                        best_slide = d;\n                    }\n                }\n                if (best_slide) {\n                    add('S', best_slide);\n                } else {\n                    // move one step toward target\n                    if (cur_x < tx) add('M', 'D');\n                    else if (cur_x > tx) add('M', 'U');\n                    else if (cur_y < ty) add('M', 'R');\n                    else if (cur_y > ty) add('M', 'L');\n                }\n            }\n        }\n    }\n\n    for (auto &a : actions) cout << a.first << ' ' << a.second << '\\n';\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y, r, id;\n};\n\nstruct Node {\n    int x1, y1, x2, y2;\n    int split_dim; // 0: x, 1: y, -1: leaf\n    int split_pos;\n    vector<int> indices;\n    Node* left;\n    Node* right;\n    Node* parent;\n    \n    Node() : left(nullptr), right(nullptr), parent(nullptr), split_dim(-1), split_pos(0) {}\n    ~Node() { delete left; delete right; }\n};\n\nint n;\nvector<Point> pts;\nvector<Rect> best_ans;\ndouble best_score = -1;\nmt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\nlong long area(int x1, int y1, int x2, int y2) {\n    return 1LL * (x2 - x1) * (y2 - y1);\n}\n\ndouble calcSat(long long s, long long r) {\n    if (s == 0) return 0;\n    double ratio = (double)min(r, s) / max(r, s);\n    double t = 1.0 - ratio;\n    return 1.0 - t * t;\n}\n\nNode* buildTree(int x1, int y1, int x2, int y2, vector<int> idxs, bool randomize) {\n    Node* node = new Node();\n    node->x1 = x1; node->y1 = y1; node->x2 = x2; node->y2 = y2;\n    node->indices = idxs;\n    \n    if (idxs.size() == 1) {\n        return node;\n    }\n    \n    long long totalArea = area(x1, y1, x2, y2);\n    long long sumR = 0;\n    for (int i : idxs) sumR += pts[i].r;\n    \n    struct Candidate {\n        double score;\n        int splitPos;\n        int dim;\n        vector<int> left, right;\n        int k;\n    };\n    vector<Candidate> cands;\n    \n    // Try x splits\n    vector<int> sorted_by_x = idxs;\n    sort(sorted_by_x.begin(), sorted_by_x.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n    for (int k = 0; k < (int)sorted_by_x.size() - 1; k++) {\n        int x_l = pts[sorted_by_x[k]].x;\n        int x_r = pts[sorted_by_x[k+1]].x;\n        if (x_l >= x_r) continue;\n        \n        long long leftR = 0;\n        for (int i = 0; i <= k; i++) leftR += pts[sorted_by_x[i]].r;\n        \n        double targetRatio = (double)leftR / sumR;\n        int minSplit = max(x1 + 1, x_l + 1);\n        int maxSplit = min(x2 - 1, x_r);\n        \n        if (minSplit <= maxSplit) {\n            int idealSplit = x1 + (int)((x2 - x1) * targetRatio);\n            int splitX = max(minSplit, min(maxSplit, idealSplit));\n            \n            double leftRatio = (double)area(x1, y1, splitX, y2) / totalArea;\n            double score = -fabs(leftRatio - targetRatio);\n            \n            vector<int> left(sorted_by_x.begin(), sorted_by_x.begin() + k + 1);\n            vector<int> right(sorted_by_x.begin() + k + 1, sorted_by_x.end());\n            cands.push_back({score, splitX, 0, left, right, k});\n            \n            // Also consider impact on final satisfaction\n            // Prefer splits that don't trap points with large area requests in small regions\n            double leftAreaRatio = (double)area(x1, y1, splitX, y2) / totalArea;\n            double leftNeedRatio = (double)leftR / sumR;\n            // Penalty if a side gets too little space relative to needs\n            double balancePenalty = max(0.0, leftNeedRatio - leftAreaRatio) + max(0.0, (1-leftNeedRatio) - (1-leftAreaRatio));\n            score -= balancePenalty * 0.5;\n            cands.back().score = score;\n        }\n    }\n    \n    // Try y splits\n    vector<int> sorted_by_y = idxs;\n    sort(sorted_by_y.begin(), sorted_by_y.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n    for (int k = 0; k < (int)sorted_by_y.size() - 1; k++) {\n        int y_b = pts[sorted_by_y[k]].y;\n        int y_t = pts[sorted_by_y[k+1]].y;\n        if (y_b >= y_t) continue;\n        \n        long long bottomR = 0;\n        for (int i = 0; i <= k; i++) bottomR += pts[sorted_by_y[i]].r;\n        \n        double targetRatio = (double)bottomR / sumR;\n        int minSplit = max(y1 + 1, y_b + 1);\n        int maxSplit = min(y2 - 1, y_t);\n        \n        if (minSplit <= maxSplit) {\n            int idealSplit = y1 + (int)((y2 - y1) * targetRatio);\n            int splitY = max(minSplit, min(maxSplit, idealSplit));\n            \n            double bottomRatio = (double)area(x1, y1, x2, splitY) / totalArea;\n            double score = -fabs(bottomRatio - targetRatio);\n            \n            vector<int> bottom(sorted_by_y.begin(), sorted_by_y.begin() + k + 1);\n            vector<int> top(sorted_by_y.begin() + k + 1, sorted_by_y.end());\n            \n            double bottomAreaRatio = (double)area(x1, y1, x2, splitY) / totalArea;\n            double bottomNeedRatio = (double)bottomR / sumR;\n            double balancePenalty = max(0.0, bottomNeedRatio - bottomAreaRatio) + max(0.0, (1-bottomNeedRatio) - (1-bottomAreaRatio));\n            score -= balancePenalty * 0.5;\n            \n            cands.push_back({score, splitY, 1, bottom, top, k});\n        }\n    }\n    \n    if (cands.empty()) {\n        return node;\n    }\n    \n    if (randomize && cands.size() > 1) {\n        // Pick from top candidates with probability proportional to score\n        sort(cands.begin(), cands.end(), [](const Candidate& a, const Candidate& b) {\n            return a.score > b.score;\n        });\n        int top_k = min(10, (int)cands.size());\n        // Use exponential distribution over ranks\n        vector<double> weights(top_k);\n        for (int i = 0; i < top_k; i++) {\n            weights[i] = exp(-i * 0.5);\n        }\n        discrete_distribution<int> dist(weights.begin(), weights.end());\n        int pick = dist(rng);\n        swap(cands[0], cands[pick]);\n    } else {\n        sort(cands.begin(), cands.end(), [](const Candidate& a, const Candidate& b) {\n            return a.score > b.score;\n        });\n    }\n    \n    for (auto& cand : cands) {\n        if (cand.dim == 0) {\n            if (cand.splitPos - x1 < 1 || x2 - cand.splitPos < 1) continue;\n            node->split_dim = 0;\n            node->split_pos = cand.splitPos;\n            node->left = buildTree(x1, y1, cand.splitPos, y2, cand.left, randomize);\n            node->right = buildTree(cand.splitPos, y1, x2, y2, cand.right, randomize);\n            if (node->left) node->left->parent = node;\n            if (node->right) node->right->parent = node;\n            return node;\n        } else {\n            if (cand.splitPos - y1 < 1 || y2 - cand.splitPos < 1) continue;\n            node->split_dim = 1;\n            node->split_pos = cand.splitPos;\n            node->left = buildTree(x1, y1, x2, cand.splitPos, cand.left, randomize);\n            node->right = buildTree(x1, cand.splitPos, x2, y2, cand.right, randomize);\n            if (node->left) node->left->parent = node;\n            if (node->right) node->right->parent = node;\n            return node;\n        }\n    }\n    \n    return node;\n}\n\n// Extract rectangles from tree\nvoid extractRects(Node* node, vector<Rect>& ans) {\n    if (node->split_dim == -1) {\n        if (!node->indices.empty()) {\n            ans[node->indices[0]] = {node->x1, node->y1, node->x2, node->y2};\n        }\n        return;\n    }\n    // Boundaries should already be set, but ensure they're propagated\n    if (node->split_dim == 0) {\n        node->left->x1 = node->x1; node->left->y1 = node->y1;\n        node->left->x2 = node->split_pos; node->left->y2 = node->y2;\n        node->right->x1 = node->split_pos; node->right->y1 = node->y1;\n        node->right->x2 = node->x2; node->right->y2 = node->y2;\n    } else {\n        node->left->x1 = node->x1; node->left->y1 = node->y1;\n        node->left->x2 = node->x2; node->left->y2 = node->split_pos;\n        node->right->x1 = node->x1; node->right->y1 = node->split_pos;\n        node->right->x2 = node->x2; node->right->y2 = node->y2;\n    }\n    extractRects(node->left, ans);\n    extractRects(node->right, ans);\n}\n\n// Compute total requested area for a subtree\nlong long totalR(Node* node) {\n    long long sum = 0;\n    for (int i : node->indices) sum += pts[i].r;\n    return sum;\n}\n\n// Optimize splits bottom-up with area balancing\nvoid optimizeSplits(Node* node) {\n    if (node->split_dim == -1) return;\n    \n    optimizeSplits(node->left);\n    optimizeSplits(node->right);\n    \n    int minPos, maxPos;\n    if (node->split_dim == 0) {\n        int maxLeftX = -1;\n        for (int i : node->left->indices) maxLeftX = max(maxLeftX, pts[i].x);\n        int minRightX = 10001;\n        for (int i : node->right->indices) minRightX = min(minRightX, pts[i].x);\n        minPos = max(node->x1 + 1, maxLeftX + 1);\n        maxPos = min(node->x2 - 1, minRightX);\n    } else {\n        int maxLeftY = -1;\n        for (int i : node->left->indices) maxLeftY = max(maxLeftY, pts[i].y);\n        int minRightY = 10001;\n        for (int i : node->right->indices) minRightY = min(minRightY, pts[i].y);\n        minPos = max(node->y1 + 1, maxLeftY + 1);\n        maxPos = min(node->y2 - 1, minRightY);\n    }\n    \n    if (maxPos < minPos) return;\n    \n    long long leftR = totalR(node->left);\n    long long rightR = totalR(node->right);\n    long long total_R = leftR + rightR;\n    \n    int idealSplit;\n    if (node->split_dim == 0) {\n        idealSplit = node->x1 + (int)((long long)(node->x2 - node->x1) * leftR / total_R);\n    } else {\n        idealSplit = node->y1 + (int)((long long)(node->y2 - node->y1) * leftR / total_R);\n    }\n    idealSplit = max(minPos, min(maxPos, idealSplit));\n    \n    node->split_pos = idealSplit;\n    \n    // Update children\n    if (node->split_dim == 0) {\n        node->left->x2 = node->split_pos;\n        node->right->x1 = node->split_pos;\n        node->left->y2 = node->y2;\n        node->right->y2 = node->y2;\n    } else {\n        node->left->y2 = node->split_pos;\n        node->right->y1 = node->split_pos;\n        node->left->x2 = node->x2;\n        node->right->x2 = node->x2;\n    }\n}\n\n// Try to flip split dimensions randomly and see if it improves\nvoid tryFlipSplits(Node* node, vector<Rect>& cur_ans) {\n    if (node->split_dim == -1) return;\n    \n    // Try flipping this node's split\n    int orig_dim = node->split_dim;\n    int orig_pos = node->split_pos;\n    \n    // Check if flipping is possible\n    if (node->split_dim == 0) {\n        // Currently x-split, try y-split\n        vector<int> sorted_by_y = node->indices;\n        sort(sorted_by_y.begin(), sorted_by_y.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n        // Find a k that gives same partition? No, we need to re-partition.\n        // This is complex to do while maintaining valid children.\n        // Instead, we'll skip flipping and just rely on multi-start.\n    }\n    \n    tryFlipSplits(node->left, cur_ans);\n    tryFlipSplits(node->right, cur_ans);\n}\n\n// Evaluate a solution\ndouble evaluateSolution(const vector<Rect>& ans) {\n    double total = 0;\n    for (int i = 0; i < n; i++) {\n        if (ans[i].a > pts[i].x || ans[i].c <= pts[i].x ||\n            ans[i].b > pts[i].y || ans[i].d <= pts[i].y) {\n            continue;\n        }\n        long long s = area(ans[i].a, ans[i].b, ans[i].c, ans[i].d);\n        total += calcSat(s, pts[i].r);\n    }\n    return total * 1e9 / n;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> n;\n    pts.resize(n);\n    best_ans.resize(n);\n    for (int i = 0; i < n; i++) {\n        cin >> pts[i].x >> pts[i].y >> pts[i].r;\n        pts[i].id = i;\n    }\n    \n    vector<int> all(n);\n    iota(all.begin(), all.end(), 0);\n    \n    int trial = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - start_time).count();\n        if (elapsed > 4500) break; // Use 4.5 sec max\n        \n        Node* root = buildTree(0, 0, 10000, 10000, all, trial > 0);\n        optimizeSplits(root);\n        \n        vector<Rect> cur_ans(n);\n        extractRects(root, cur_ans);\n        \n        double score = evaluateSolution(cur_ans);\n        if (score > best_score) {\n            best_score = score;\n            best_ans = cur_ans;\n        }\n        \n        delete root;\n        trial++;\n    }\n    \n    for (int i = 0; i < n; i++) {\n        cout << best_ans[i].a << \" \" << best_ans[i].b << \" \" \n             << best_ans[i].c << \" \" << best_ans[i].d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <bitset>\n#include <queue>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_TILES = 2500;\nconst int BEAM_WIDTH = 200;\nconst int CAND_WIDTH = 1000;\nconst int MAX_DEPTH = 2500;\nconst int FULL_BFS_DEPTH = 8;   // depth limit for the full potential BFS\n\nstruct State {\n    int score;\n    int est_score;          // score + full_potential + tiny noise\n    short i, j;\n    bitset<MAX_TILES> visited;\n    int prev_idx;\n    char move_char;\n};\n\nint si, sj;\nint tile_id[N][N];\nint p[N][N];\nint M;\nint max_p[MAX_TILES];\nint tile_adj[MAX_TILES][4];\nint tile_deg[MAX_TILES];\nint bfs_tag[MAX_TILES];\nint current_bfs_tag = 0;\n\n// Quick heuristic: immediate neighbour value + sum of max_p of other unvisited neighbours\nint quick_heuristic(const State& st, int ni, int nj) {\n    int nt = tile_id[ni][nj];\n    int sum = p[ni][nj];\n    int cur_t = tile_id[st.i][st.j];\n    for (int k = 0; k < tile_deg[cur_t]; ++k) {\n        int v = tile_adj[cur_t][k];\n        if (v != nt && !st.visited[v]) sum += max_p[v];\n    }\n    return sum;\n}\n\n// Depth-limited full potential\nint full_potential(const State& st) {\n    current_bfs_tag++;\n    int start_tile = tile_id[st.i][st.j];\n    queue<pair<int,int>> q; // tile, depth\n    int pot = 0;\n    for (int k = 0; k < tile_deg[start_tile]; ++k) {\n        int v = tile_adj[start_tile][k];\n        if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n            bfs_tag[v] = current_bfs_tag;\n            q.push({v, 1});\n            pot += max_p[v];\n        }\n    }\n    while (!q.empty()) {\n        auto [u, d] = q.front(); q.pop();\n        if (d == FULL_BFS_DEPTH) continue;\n        for (int k = 0; k < tile_deg[u]; ++k) {\n            int v = tile_adj[u][k];\n            if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n                bfs_tag[v] = current_bfs_tag;\n                q.push({v, d + 1});\n                pot += max_p[v];\n            }\n        }\n    }\n    return pot;\n}\n\nint path_score(const string& path) {\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    vector<bool> used(M, false);\n    int ci = si, cj = sj;\n    used[tile_id[ci][cj]] = true;\n    int score = p[ci][cj];\n    for (char c : path) {\n        int k = (c == 'U' ? 0 : (c == 'D' ? 1 : (c == 'L' ? 2 : 3)));\n        ci += di[k]; cj += dj[k];\n        int t = tile_id[ci][cj];\n        if (used[t]) return -1;\n        used[t] = true;\n        score += p[ci][cj];\n    }\n    return score;\n}\n\npair<int, string> run_beam_search(int seed, const chrono::steady_clock::time_point& start_time, const chrono::milliseconds& time_limit) {\n    mt19937 rng(seed);\n    uniform_int_distribution<int> dist(0, 100);\n\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n\n    State init;\n    init.score = p[si][sj];\n    init.i = si; init.j = sj;\n    init.visited.reset();\n    init.visited[tile_id[si][sj]] = 1;\n    init.prev_idx = -1;\n    init.est_score = init.score + full_potential(init);\n\n    vector<State> beam;\n    beam.push_back(init);\n    vector<vector<State>> beam_history;\n    beam_history.push_back(beam);\n\n    int best_score = init.score;\n    int best_depth = 0;\n    int best_state_idx = 0;\n\n    for (int depth = 1; depth <= MAX_DEPTH; ++depth) {\n        if (chrono::steady_clock::now() - start_time > time_limit) break;\n\n        vector<State> candidates;\n        for (int s_idx = 0; s_idx < (int)beam.size(); ++s_idx) {\n            const State& st = beam[s_idx];\n            short i = st.i, j = st.j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nt = tile_id[ni][nj];\n                if (nt == tile_id[i][j] || st.visited[nt]) continue;\n\n                State nxt = st;\n                nxt.i = ni; nxt.j = nj;\n                nxt.score += p[ni][nj];\n                nxt.visited[nt] = 1;\n                nxt.prev_idx = s_idx;\n                nxt.move_char = (k == 0 ? 'U' : (k == 1 ? 'D' : (k == 2 ? 'L' : 'R')));\n                nxt.est_score = nxt.score + quick_heuristic(nxt, ni, nj);\n                candidates.push_back(move(nxt));\n            }\n        }\n        if (candidates.empty()) break;\n\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)candidates.size() > CAND_WIDTH) candidates.resize(CAND_WIDTH);\n\n        for (State& st : candidates) {\n            st.est_score = st.score + full_potential(st) + dist(rng);\n        }\n\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)candidates.size() > BEAM_WIDTH) candidates.resize(BEAM_WIDTH);\n\n        if (candidates[0].score > best_score) {\n            best_score = candidates[0].score;\n            best_depth = depth;\n            best_state_idx = 0;\n        }\n\n        beam = move(candidates);\n        beam_history.push_back(beam);\n    }\n\n    for (int d = 0; d < (int)beam_history.size(); ++d) {\n        for (int idx = 0; idx < (int)beam_history[d].size(); ++idx) {\n            if (beam_history[d][idx].score > best_score) {\n                best_score = beam_history[d][idx].score;\n                best_depth = d;\n                best_state_idx = idx;\n            }\n        }\n    }\n\n    string path;\n    int cur_depth = best_depth;\n    int cur_idx = best_state_idx;\n    while (cur_depth > 0) {\n        const State& st = beam_history[cur_depth][cur_idx];\n        path.push_back(st.move_char);\n        cur_idx = st.prev_idx;\n        --cur_depth;\n    }\n    reverse(path.begin(), path.end());\n\n    // greedy extension\n    {\n        vector<bool> used_tile(M, false);\n        int ci = si, cj = sj;\n        used_tile[tile_id[ci][cj]] = true;\n        for (char c : path) {\n            int k = (c == 'U' ? 0 : (c == 'D' ? 1 : (c == 'L' ? 2 : 3)));\n            ci += di[k]; cj += dj[k];\n            used_tile[tile_id[ci][cj]] = true;\n        }\n        while (true) {\n            int best_ni = -1, best_nj = -1, best_val = -1;\n            char best_move = 0;\n            for (int k = 0; k < 4; ++k) {\n                int ni = ci + di[k], nj = cj + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nt = tile_id[ni][nj];\n                if (nt == tile_id[ci][cj] || used_tile[nt]) continue;\n                if (p[ni][nj] > best_val) {\n                    best_val = p[ni][nj];\n                    best_ni = ni; best_nj = nj;\n                    best_move = \"UDLR\"[k];\n                }\n            }\n            if (best_ni == -1) break;\n            path.push_back(best_move);\n            used_tile[tile_id[best_ni][best_nj]] = true;\n            ci = best_ni; cj = best_nj;\n        }\n    }\n\n    int real_score = path_score(path);\n    return {real_score, path};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(1950);\n\n    cin >> si >> sj;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (tile_id[i][j] >= M) M = tile_id[i][j] + 1;\n\n    for (int t = 0; t < M; ++t) max_p[t] = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            if (p[i][j] > max_p[t]) max_p[t] = p[i][j];\n        }\n\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int nt = tile_id[ni][nj];\n                    if (nt != t) {\n                        bool exists = false;\n                        for (int idx = 0; idx < tile_deg[t]; ++idx) {\n                            if (tile_adj[t][idx] == nt) { exists = true; break; }\n                        }\n                        if (!exists) tile_adj[t][tile_deg[t]++] = nt;\n                    }\n                }\n            }\n        }\n    }\n\n    string best_path;\n    int best_score = -1;\n\n    for (int run = 0; run < 2; ++run) {\n        if (chrono::steady_clock::now() - start_time > time_limit) break;\n        auto [score, path] = run_beam_search(42 + run * 100, start_time, time_limit);\n        if (score > best_score) {\n            best_score = score;\n            best_path = move(path);\n        }\n    }\n\n    cout << best_path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr double INF = 1e18;\n\n// Forward declarations\nstruct EdgeEstimator;\n\nstruct EdgeEstimator {\n    // We maintain a more explicit model:\n    // h[i][j] = H_row[i] + (j >= split_col[i] ? H_split[i] : 0) + delta[i][j]\n    // v[i][j] = V_col[j] + (i >= split_row[j] ? V_split[j] : 0) + gamma[i][j]\n    \n    double H_base[N];           // Row base for horizontal edges\n    double H_split[N];          // Split difference (could be 0)\n    int H_split_idx[N];         // Column where split occurs\n    double H_local[N][N-1];     // Local deviations\n    \n    double V_base[N];           // Column base for vertical edges  \n    double V_split[N];          // Split difference\n    int V_split_idx[N];         // Row where split occurs\n    double V_local[N-1][N];     // Local deviations\n    \n    // Counts\n    int H_cnt[N][N-1];\n    int V_cnt[N-1][N];\n    \n    // For tracking row/col statistics\n    double H_sum[N], H_sum2[N];\n    int H_n[N];\n    double V_sum[N], V_sum2[N];\n    int V_n[N];\n    \n    EdgeEstimator() {\n        // Initialize with better default (midpoint of [1000+D, 9000-D] for D~1000)\n        double init_val = 5000.0;\n        for (int i = 0; i < N; i++) {\n            H_base[i] = init_val;\n            H_split[i] = 0.0;\n            H_split_idx[i] = -1;\n            H_sum[i] = H_sum2[i] = 0.0;\n            H_n[i] = 0;\n            \n            V_base[i] = init_val;\n            V_split[i] = 0.0;\n            V_split_idx[i] = -1;\n            V_sum[i] = V_sum2[i] = 0.0;\n            V_n[i] = 0;\n        }\n        memset(H_local, 0, sizeof(H_local));\n        memset(V_local, 0, sizeof(V_local));\n        memset(H_cnt, 0, sizeof(H_cnt));\n        memset(V_cnt, 0, sizeof(V_cnt));\n    }\n    \n    inline double get_H(int i, int j) const {\n        double val = H_base[i] + H_local[i][j];\n        if (H_split_idx[i] >= 0 && j >= H_split_idx[i]) {\n            val += H_split[i];\n        }\n        return clamp(val, 100.0, 10000.0);\n    }\n    \n    inline double get_V(int i, int j) const {\n        double val = V_base[j] + V_local[i][j];\n        if (V_split_idx[j] >= 0 && i >= V_split_idx[j]) {\n            val += V_split[j];\n        }\n        return clamp(val, 100.0, 10000.0);\n    }\n    \n    double H_std(int i) const {\n        if (H_n[i] < 2) return 2000.0;\n        double mean = H_sum[i] / H_n[i];\n        double var = H_sum2[i] / H_n[i] - mean * mean;\n        return sqrt(max(0.0, var));\n    }\n    \n    double V_std(int j) const {\n        if (V_n[j] < 2) return 2000.0;\n        double mean = V_sum[j] / V_n[j];\n        double var = V_sum2[j] / V_n[j] - mean * mean;\n        return sqrt(max(0.0, var));\n    }\n};\n\nstruct Dijkstra {\n    double dist[N][N];\n    pair<int,int> prev[N][N];\n    \n    vector<pair<int,int>> find_path(int si, int sj, int ti, int tj,\n                                     EdgeEstimator& est, double bonus) {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                dist[i][j] = INF;\n        \n        dist[si][sj] = 0;\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({0.0, si, sj});\n        \n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n        \n        while (!pq.empty()) {\n            auto [d, i, j] = pq.top(); pq.pop();\n            if (d > dist[i][j]) continue;\n            if (i == ti && j == tj) break;\n            \n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double edge_w;\n                int edge_cnt;\n                \n                if (k == 0) { // Up\n                    edge_w = est.get_V(ni, nj);\n                    edge_cnt = est.V_cnt[ni][nj];\n                } else if (k == 1) { // Down\n                    edge_w = est.get_V(i, j);\n                    edge_cnt = est.V_cnt[i][j];\n                } else if (k == 2) { // Left\n                    edge_w = est.get_H(ni, nj);\n                    edge_cnt = est.H_cnt[ni][nj];\n                } else { // Right\n                    edge_w = est.get_H(i, j);\n                    edge_cnt = est.H_cnt[i][j];\n                }\n                \n                // UCB-style exploration\n                double exploration = bonus / sqrt(1.0 + edge_cnt);\n                double nd = d + edge_w + exploration;\n                \n                if (nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i, j};\n                    pq.push({nd, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct\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 [pi, pj] = prev[ci][cj];\n            ci = pi; cj = pj;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n        return path;\n    }\n};\n\nstring path_to_str(const vector<pair<int,int>>& path) {\n    string s;\n    s.reserve(path.size());\n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        if (c == a-1) s += 'U';\n        else if (c == a+1) s += 'D';\n        else if (d == b-1) s += 'L';\n        else s += 'R';\n    }\n    return s;\n}\n\ndouble calc_path_len(const vector<pair<int,int>>& path, EdgeEstimator& est) {\n    double len = 0;\n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        if (c == a-1) len += est.get_V(c, d);\n        else if (c == a+1) len += est.get_V(a, b);\n        else if (d == b-1) len += est.get_H(c, d);\n        else len += est.get_H(a, b);\n    }\n    return len;\n}\n\nvoid update_est(EdgeEstimator& est, const vector<pair<int,int>>& path,\n                double observed, double predicted, int qidx) {\n    if (predicted < 1.0) return;\n    \n    // Expected noise is 1.0, so use observed/predicted directly\n    double scale = observed / predicted;\n    scale = clamp(scale, 0.7, 1.4); // Tighter clamp for stability\n    \n    // Learning rate: decrease over time but stay substantial\n    double lr = 0.35 / pow(1.0 + qidx * 0.001, 0.6);\n    \n    // Collect edges and their current estimates\n    struct EdgeInfo {\n        int type; // 0=H, 1=V\n        int i, j;\n        double old_val;\n        double* local_ptr;\n        double* base_ptr;\n        double* split_ptr; // nullptr if no split\n        int* cnt_ptr;\n    };\n    \n    vector<EdgeInfo> edges;\n    edges.reserve(path.size());\n    \n    for (size_t k = 1; k < path.size(); k++) {\n        auto [a, b] = path[k-1];\n        auto [c, d] = path[k];\n        \n        EdgeInfo ei;\n        if (c == a-1) { // Up: V at (c,d)\n            ei.type = 1;\n            ei.i = c; ei.j = d;\n            ei.old_val = est.get_V(c, d);\n            ei.local_ptr = &est.V_local[c][d];\n            ei.base_ptr = &est.V_base[d];\n            ei.split_ptr = (est.V_split_idx[d] >= 0 && c >= est.V_split_idx[d]) ? &est.V_split[d] : nullptr;\n            ei.cnt_ptr = &est.V_cnt[c][d];\n        } else if (c == a+1) { // Down: V at (a,b)\n            ei.type = 1;\n            ei.i = a; ei.j = b;\n            ei.old_val = est.get_V(a, b);\n            ei.local_ptr = &est.V_local[a][b];\n            ei.base_ptr = &est.V_base[b];\n            ei.split_ptr = (est.V_split_idx[b] >= 0 && a >= est.V_split_idx[b]) ? &est.V_split[b] : nullptr;\n            ei.cnt_ptr = &est.V_cnt[a][b];\n        } else if (d == b-1) { // Left: H at (c,d)\n            ei.type = 0;\n            ei.i = c; ei.j = d;\n            ei.old_val = est.get_H(c, d);\n            ei.local_ptr = &est.H_local[c][d];\n            ei.base_ptr = &est.H_base[c];\n            ei.split_ptr = (est.H_split_idx[c] >= 0 && d >= est.H_split_idx[c]) ? &est.H_split[c] : nullptr;\n            ei.cnt_ptr = &est.H_cnt[c][d];\n        } else { // Right: H at (a,b)\n            ei.type = 0;\n            ei.i = a; ei.j = b;\n            ei.old_val = est.get_H(a, b);\n            ei.local_ptr = &est.H_local[a][b];\n            ei.base_ptr = &est.H_base[a];\n            ei.split_ptr = (est.H_split_idx[a] >= 0 && b >= est.H_split_idx[a]) ? &est.H_split[a] : nullptr;\n            ei.cnt_ptr = &est.H_cnt[a][b];\n        }\n        edges.push_back(ei);\n    }\n    \n    // Update each edge proportionally to its contribution\n    for (auto& ei : edges) {\n        (*ei.cnt_ptr)++;\n        \n        double target = ei.old_val * scale;\n        double err = target - ei.old_val;\n        \n        // Update local variation\n        *ei.local_ptr += lr * 0.6 * err;\n        *ei.base_ptr += lr * 0.3 * err;\n        if (ei.split_ptr) {\n            *ei.split_ptr += lr * 0.1 * err;\n        }\n        \n        // Track statistics\n        if (ei.type == 0) {\n            est.H_sum[ei.i] += err;\n            est.H_sum2[ei.i] += err * err;\n            est.H_n[ei.i]++;\n        } else {\n            est.V_sum[ei.j] += err;\n            est.V_sum2[ei.j] += err * err;\n            est.V_n[ei.j]++;\n        }\n    }\n}\n\nvoid find_splits(EdgeEstimator& est, int qidx) {\n    if (qidx < 20) return;\n    \n    // Horizontal splits\n    for (int i = 0; i < N; i++) {\n        if (est.H_split_idx[i] >= 0) continue;\n        \n        int visited = 0;\n        for (int j = 0; j < N-1; j++) visited += (est.H_cnt[i][j] > 0);\n        if (visited < 15) continue;\n        \n        // Try all possible split points\n        double best_diff = 0;\n        int best_s = -1;\n        \n        for (int s = 5; s < N-6; s++) {\n            double left_sum = 0, right_sum = 0;\n            double left_sum2 = 0, right_sum2 = 0;\n            int left_n = 0, right_n = 0;\n            \n            for (int j = 0; j < s; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    double v = est.get_H(i, j);\n                    left_sum += v;\n                    left_sum2 += v * v;\n                    left_n++;\n                }\n            }\n            for (int j = s; j < N-1; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    double v = est.get_H(i, j);\n                    right_sum += v;\n                    right_sum2 += v * v;\n                    right_n++;\n                }\n            }\n            \n            if (left_n >= 5 && right_n >= 5) {\n                double left_mean = left_sum / left_n;\n                double right_mean = right_sum / right_n;\n                \n                double left_var = left_sum2/left_n - left_mean*left_mean;\n                double right_var = right_sum2/right_n - right_mean*right_mean;\n                \n                double pooled_se = sqrt(left_var/left_n + right_var/right_n);\n                double diff = fabs(left_mean - right_mean);\n                \n                // Weight by statistical significance\n                double score = diff * diff / (pooled_se * pooled_se + 100.0);\n                \n                if (score > best_diff) {\n                    best_diff = score;\n                    best_s = s;\n                }\n            }\n        }\n        \n        if (best_diff > 4.0) { // Statistically significant\n            est.H_split_idx[i] = best_s;\n            \n            // Compute split value\n            double left_avg = 0, right_avg = 0;\n            int lc = 0, rc = 0;\n            for (int j = 0; j < best_s; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    left_avg += est.H_local[i][j];\n                    lc++;\n                }\n            }\n            for (int j = best_s; j < N-1; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    right_avg += est.H_local[i][j];\n                    rc++;\n                }\n            }\n            if (lc > 0) left_avg /= lc;\n            if (rc > 0) right_avg /= rc;\n            \n            double split_val = right_avg - left_avg;\n            est.H_split[i] = split_val;\n            \n            // Adjust locals to be zero-mean around their segments\n            for (int j = 0; j < best_s; j++) {\n                if (est.H_cnt[i][j] > 0) est.H_local[i][j] -= left_avg;\n            }\n            for (int j = best_s; j < N-1; j++) {\n                if (est.H_cnt[i][j] > 0) est.H_local[i][j] -= right_avg;\n            }\n            // Add back properly\n            for (int j = 0; j < N-1; j++) {\n                est.H_local[i][j] = 0; // Reset after split detection\n            }\n        }\n    }\n    \n    // Vertical splits (similar logic)\n    for (int j = 0; j < N; j++) {\n        if (est.V_split_idx[j] >= 0) continue;\n        \n        int visited = 0;\n        for (int i = 0; i < N-1; i++) visited += (est.V_cnt[i][j] > 0);\n        if (visited < 15) continue;\n        \n        double best_diff = 0;\n        int best_s = -1;\n        \n        for (int s = 5; s < N-6; s++) {\n            double top_sum = 0, bottom_sum = 0;\n            double top_sum2 = 0, bottom_sum2 = 0;\n            int top_n = 0, bottom_n = 0;\n            \n            for (int i = 0; i < s; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    double v = est.get_V(i, j);\n                    top_sum += v;\n                    top_sum2 += v * v;\n                    top_n++;\n                }\n            }\n            for (int i = s; i < N-1; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    double v = est.get_V(i, j);\n                    bottom_sum += v;\n                    bottom_sum2 += v * v;\n                    bottom_n++;\n                }\n            }\n            \n            if (top_n >= 5 && bottom_n >= 5) {\n                double top_mean = top_sum / top_n;\n                double bottom_mean = bottom_sum / bottom_n;\n                \n                double top_var = top_sum2/top_n - top_mean*top_mean;\n                double bottom_var = bottom_sum2/bottom_n - bottom_mean*bottom_mean;\n                \n                double pooled_se = sqrt(top_var/top_n + bottom_var/bottom_n);\n                double diff = fabs(top_mean - bottom_mean);\n                double score = diff * diff / (pooled_se * pooled_se + 100.0);\n                \n                if (score > best_diff) {\n                    best_diff = score;\n                    best_s = s;\n                }\n            }\n        }\n        \n        if (best_diff > 4.0) {\n            est.V_split_idx[j] = best_s;\n            \n            double top_avg = 0, bottom_avg = 0;\n            int tc = 0, bc = 0;\n            for (int i = 0; i < best_s; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    top_avg += est.V_local[i][j];\n                    tc++;\n                }\n            }\n            for (int i = best_s; i < N-1; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    bottom_avg += est.V_local[i][j];\n                    bc++;\n                }\n            }\n            if (tc > 0) top_avg /= tc;\n            if (bc > 0) bottom_avg /= bc;\n            \n            double split_val = bottom_avg - top_avg;\n            est.V_split[j] = split_val;\n            \n            for (int i = 0; i < N-1; i++) {\n                est.V_local[i][j] = 0; // Reset locals\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    EdgeEstimator est;\n    Dijkstra dij;\n    \n    double explore_bonus = 2000.0;\n    \n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Detect splits early and periodically\n        if (k == 20 || k == 40 || k == 60 || k == 80 || k == 100 || \n            (k > 100 && k % 25 == 0)) {\n            find_splits(est, k);\n        }\n        \n        auto path = dij.find_path(si, sj, ti, tj, est, explore_bonus);\n        double predicted = calc_path_len(path, est);\n        \n        cout << path_to_str(path) << '\\n';\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        update_est(est, path, observed, predicted, k);\n        \n        // Decay exploration\n        explore_bonus *= 0.997;\n        if (explore_bonus < 50) explore_bonus = 50;\n    }\n    \n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nint N, M;\nvector<string> strings;\n\nstruct Candidate {\n    int r, c, dir;\n};\nvector<vector<Candidate>> string_candidates;\n\nchar best_grid[20][20];\nint best_matched = 0;\nint best_empty = 0;\n\nbool compatible(const string &s, const Candidate &cand, const char grid[20][20]) {\n    int len = s.size();\n    if (cand.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            char g = grid[cand.r][(cand.c + p) % N];\n            if (g != '.' && g != s[p]) return false;\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            char g = grid[(cand.r + p) % N][cand.c];\n            if (g != '.' && g != s[p]) return false;\n        }\n    }\n    return true;\n}\n\nvoid place(const string &s, const Candidate &cand, char grid[20][20]) {\n    int len = s.size();\n    if (cand.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            grid[cand.r][(cand.c + p) % N] = s[p];\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            grid[(cand.r + p) % N][cand.c] = s[p];\n        }\n    }\n}\n\nbool check_match(const string &s, const Candidate &cand, const char grid[20][20]) {\n    int len = s.size();\n    if (cand.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            if (grid[cand.r][(cand.c + p) % N] != s[p]) return false;\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            if (grid[(cand.r + p) % N][cand.c] != s[p]) return false;\n        }\n    }\n    return true;\n}\n\nvoid evaluate_and_update(char grid[20][20]) {\n    int matched = 0, empty = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.') ++empty;\n    for (int i = 0; i < M; ++i) {\n        bool found = false;\n        for (auto &cand : string_candidates[i]) {\n            if (check_match(strings[i], cand, grid)) {\n                found = true;\n                break;\n            }\n        }\n        if (found) ++matched;\n    }\n    if (matched > best_matched || (matched == best_matched && empty < best_empty)) {\n        best_matched = matched;\n        best_empty = empty;\n        memcpy(best_grid, grid, sizeof(best_grid));\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) cin >> strings[i];\n\n    // Generate all candidates\n    string_candidates.resize(M);\n    for (int i = 0; i < M; ++i) {\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                string_candidates[i].push_back({r, c, 0});\n                string_candidates[i].push_back({r, c, 1});\n            }\n        }\n    }\n\n    const char letters[] = {'A','B','C','D','E','F','G','H'};\n    mt19937 rng(42);\n\n    // Order: length descending\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return strings[a].size() > strings[b].size();\n    });\n\n    auto start_time = high_resolution_clock::now();\n\n    while (true) {\n        auto now = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(now - start_time).count() > 2900) break;\n\n        char grid[20][20];\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                grid[i][j] = '.';\n\n        // shuffle within same length groups\n        vector<int> run_order = order;\n        int start_idx = 0;\n        while (start_idx < M) {\n            int cur_len = strings[run_order[start_idx]].size();\n            int end_idx = start_idx;\n            while (end_idx < M && strings[run_order[end_idx]].size() == cur_len) ++end_idx;\n            shuffle(run_order.begin() + start_idx, run_order.begin() + end_idx, rng);\n            start_idx = end_idx;\n        }\n\n        // Place strings\n        for (int idx : run_order) {\n            const string &s = strings[idx];\n            int valid_count = 0;\n            Candidate chosen;\n            for (auto &cand : string_candidates[idx]) {\n                if (compatible(s, cand, grid)) {\n                    ++valid_count;\n                    if (uniform_int_distribution<int>(1, valid_count)(rng) == 1) {\n                        chosen = cand;\n                    }\n                }\n            }\n            if (valid_count > 0) {\n                place(s, chosen, grid);\n            }\n        }\n\n        // Fill remaining '.' with random letters\n        uniform_int_distribution<int> letter_dist(0,7);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (grid[i][j] == '.')\n                    grid[i][j] = letters[letter_dist(rng)];\n\n        evaluate_and_update(grid);\n    }\n\n    // Output best\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dir[4] = {'U', 'D', 'L', 'R'};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> cost;\nvector<vector<bool>> road;\nvector<vector<bitset<5000>>> visMask;\nint totalRoads = 0;\nvector<vector<int>> roadId;\n\nbool inside(int i, int j) {\n    return i>=0 && i<N && j>=0 && j<N;\n}\n\npair<int, vector<pair<int,int>>> shortestPath(int si, int sj, int ti, int tj) {\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    priority_queue<pair<int,pair<int,int>>, vector<pair<int,pair<int,int>>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, {si, sj}});\n    \n    while(!pq.empty()) {\n        auto [d, pos] = pq.top(); pq.pop();\n        auto [i, j] = pos;\n        if(d != dist[i][j]) continue;\n        if(i==ti && j==tj) break;\n        for(int k=0;k<4;k++) {\n            int ni = i+dx[k], nj = j+dy[k];\n            if(inside(ni,nj) && road[ni][nj]) {\n                int nd = d + cost[ni][nj];\n                if(nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i,j};\n                    pq.push({nd, {ni,nj}});\n                }\n            }\n        }\n    }\n    \n    vector<pair<int,int>> path;\n    if(dist[ti][tj] >= 1e8) return {1e9, path};\n    \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; cj = p.second;\n        if(ci == -1) break;\n    }\n    path.push_back({si,sj});\n    reverse(path.begin(), path.end());\n    return {dist[ti][tj], path};\n}\n\nstring pathToDir(const vector<pair<int,int>>& path) {\n    string res;\n    for(int i=0;i+1<(int)path.size();i++) {\n        int di = path[i+1].first - path[i].first;\n        int dj = path[i+1].second - path[i].second;\n        if(di == -1) res += 'U';\n        else if(di == 1) res += 'D';\n        else if(dj == -1) res += 'L';\n        else if(dj == 1) res += 'R';\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    cost.assign(N, vector<int>(N,0));\n    road.assign(N, vector<bool>(N,false));\n    roadId.assign(N, vector<int>(N,-1));\n    \n    for(int i=0;i<N;i++) {\n        cin >> grid[i];\n        for(int j=0;j<N;j++) {\n            if(grid[i][j] != '#') {\n                road[i][j] = true;\n                cost[i][j] = grid[i][j] - '0';\n                roadId[i][j] = totalRoads++;\n            }\n        }\n    }\n    \n    // Compute visibility masks\n    visMask.assign(N, vector<bitset<5000>>(N));\n    for(int i=0;i<N;i++) {\n        for(int j=0;j<N;j++) {\n            if(!road[i][j]) continue;\n            for(int jj=j; jj<N && road[i][jj]; jj++) \n                visMask[i][j].set(roadId[i][jj]);\n            for(int jj=j-1; jj>=0 && road[i][jj]; jj--) \n                visMask[i][j].set(roadId[i][jj]);\n            for(int ii=i; ii<N && road[ii][j]; ii++) \n                visMask[i][j].set(roadId[ii][j]);\n            for(int ii=i-1; ii>=0 && road[ii][j]; ii--) \n                visMask[i][j].set(roadId[ii][j]);\n        }\n    }\n    \n    // Greedy set cover\n    bitset<5000> covered;\n    vector<pair<int,int>> chosen;\n    covered.set(roadId[si][sj]);\n    chosen.push_back({si,sj});\n    \n    while((int)covered.count() < totalRoads) {\n        int best = -1, bi = -1, bj = -1;\n        for(int i=0;i<N;i++) {\n            for(int j=0;j<N;j++) {\n                if(!road[i][j]) continue;\n                bitset<5000> newCov = visMask[i][j] | covered;\n                int gain = (int)newCov.count() - (int)covered.count();\n                if(gain > best) {\n                    best = gain;\n                    bi = i; bj = j;\n                }\n            }\n        }\n        if(best<=0) break;\n        covered |= visMask[bi][bj];\n        chosen.push_back({bi,bj});\n    }\n    \n    int M = (int)chosen.size();\n    \n    // Precompute all-pairs shortest paths\n    vector<vector<int>> dist(M, vector<int>(M));\n    vector<vector<vector<pair<int,int>>>> pathCache(M, vector<vector<pair<int,int>>>(M));\n    \n    for(int i=0;i<M;i++) {\n        for(int j=0;j<M;j++) {\n            if(i == j) {\n                dist[i][j] = 0;\n                pathCache[i][j] = {{chosen[i].first, chosen[i].second}};\n                continue;\n            }\n            if(i > j) {\n                dist[i][j] = dist[j][i];\n                auto rev = pathCache[j][i];\n                reverse(rev.begin(), rev.end());\n                pathCache[i][j] = rev;\n                continue;\n            }\n            auto [d, path] = shortestPath(chosen[i].first, chosen[i].second,\n                                          chosen[j].first, chosen[j].second);\n            dist[i][j] = d;\n            pathCache[i][j] = path;\n        }\n    }\n    \n    // Build initial tour: Nearest neighbor from start (0)\n    vector<int> tour;\n    vector<bool> used(M, false);\n    tour.push_back(0);\n    used[0] = true;\n    \n    for(int step=1; step<M; step++) {\n        int cur = tour.back();\n        int best = -1;\n        int bestD = 1e9;\n        for(int i=1;i<M;i++) {\n            if(!used[i] && dist[cur][i] < bestD) {\n                bestD = dist[cur][i];\n                best = i;\n            }\n        }\n        if(best == -1) {\n            for(int i=0;i<M;i++) {\n                if(!used[i]) {\n                    best = i;\n                    break;\n                }\n            }\n        }\n        tour.push_back(best);\n        used[best] = true;\n    }\n    \n    // 2-opt improvement\n    {\n        bool improved = true;\n        while(improved) {\n            improved = false;\n            for(int i=0; i<M; i++) {\n                for(int j=i+2; j<M; j++) {\n                    if(i==0 && j==M-1) continue;\n                    int a = tour[i], b = tour[(i+1)%M];\n                    int c = tour[j], d = tour[(j+1)%M];\n                    int oldCost = dist[a][b] + dist[c][d];\n                    int newCost = dist[a][c] + dist[b][d];\n                    if(newCost < oldCost) {\n                        reverse(tour.begin()+i+1, tour.begin()+j+1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Build full path\n    vector<pair<int,int>> fullPath;\n    for(int i=0;i<M;i++) {\n        int cur = tour[i];\n        int nxt = tour[(i+1)%M];\n        const auto& pp = pathCache[cur][nxt];\n        \n        if(fullPath.empty()) {\n            fullPath = pp;\n        } else {\n            for(int k=1; k<(int)pp.size(); k++) {\n                fullPath.push_back(pp[k]);\n            }\n        }\n    }\n    \n    // Remove consecutive duplicates only\n    vector<pair<int,int>> cleanPath;\n    for(const auto& p : fullPath) {\n        if(cleanPath.empty() || cleanPath.back() != p) {\n            cleanPath.push_back(p);\n        }\n    }\n    \n    string ans = pathToDir(cleanPath);\n    cout << ans << \"\\n\";\n    \n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, K, R;\nvector<vector<int>> d;\nvector<vector<int>> dep;\nvector<vector<int>> rev_dep;\nvector<int> in_degree;\nvector<int> descendants;\n\nvector<vector<double>> s_est;\nvector<vector<double>> s_sum_obs;\nvector<vector<int>> s_obs_count;\nvector<int> total_assigned;\nvector<vector<int>> completion_times;\nvector<vector<int>> completion_count;\n\nenum TaskStatus { NOT_STARTED = 0, IN_PROGRESS = 1, COMPLETED = 2 };\nvector<TaskStatus> task_status;\nvector<int> task_assigned_to;\nvector<int> task_start_day;\nvector<bool> member_busy;\nvector<int> member_current_task;\n\nvoid parse_input() {\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            cin >> d[i][k];\n        }\n    }\n    dep.resize(N);\n    rev_dep.resize(N);\n    in_degree.assign(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        dep[v].push_back(u);\n        rev_dep[u].push_back(v);\n        in_degree[v]++;\n    }\n}\n\nvoid init_estimation() {\n    s_est.assign(M, vector<double>(K, 0.0));\n    s_sum_obs.assign(M, vector<double>(K, 0.0));\n    s_obs_count.assign(M, vector<int>(K, 0));\n    completion_times.assign(N, vector<int>(M, -1));\n    completion_count.assign(N, vector<int>(M, 0));\n    \n    for (int j = 0; j < M; j++) {\n        for (int k = 0; k < K; k++) {\n            s_est[j][k] = 20.0 + (j * 2.0) + (k % 3) * 3.0;\n        }\n    }\n}\n\nvoid init_scheduling() {\n    task_status.assign(N, NOT_STARTED);\n    task_assigned_to.assign(N, -1);\n    task_start_day.assign(N, -1);\n    member_busy.assign(M, false);\n    member_current_task.assign(M, -1);\n    total_assigned.assign(M, 0);\n}\n\nvoid precompute_descendants() {\n    descendants.assign(N, 0);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < N; i++) {\n        for (int u : rev_dep[i]) indeg[u]++;\n    }\n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (indeg[i] == 0) q.push(i);\n    }\n    vector<int> topo;\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) q.push(u);\n        }\n    }\n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        descendants[v] = 1;\n        for (int u : rev_dep[v]) {\n            descendants[v] += descendants[u];\n        }\n    }\n}\n\ndouble estimate_w(int i, int j) {\n    double w = 0;\n    for (int k = 0; k < K; k++) {\n        double gap = d[i][k] - s_est[j][k];\n        if (gap > 0) w += gap;\n    }\n    return w;\n}\n\nint estimate_t(int i, int j) {\n    double w = estimate_w(i, j);\n    if (w < 0.5) return 1;\n    return max(1, (int)round(w));\n}\n\nvoid update_skill_estimate(int task, int member, int actual_t) {\n    completion_times[task][member] = actual_t;\n    completion_count[task][member]++;\n    \n    if (actual_t == 1) {\n        for (int k = 0; k < K; k++) {\n            if (d[task][k] > 0) {\n                double implied = d[task][k];\n                s_sum_obs[member][k] += implied;\n                s_obs_count[member][k]++;\n                s_est[member][k] = max(s_est[member][k], implied);\n            }\n        }\n        return;\n    }\n    \n    double current_w = estimate_w(task, member);\n    double target_w = actual_t;\n    double diff = target_w - current_w;\n    \n    if (abs(diff) < 0.05) return;\n    \n    vector<int> lacking;\n    vector<double> gaps(K, 0);\n    double total_gap = 0;\n    for (int k = 0; k < K; k++) {\n        gaps[k] = max(0.0, (double)d[task][k] - s_est[member][k]);\n        if (gaps[k] > 0.01) {\n            lacking.push_back(k);\n            total_gap += gaps[k];\n        }\n    }\n    \n    if (lacking.empty() || total_gap < 0.01) return;\n    \n    double base_lr = 0.5;\n    \n    for (int k : lacking) {\n        double lr = base_lr / (1.0 + 0.1 * s_obs_count[member][k]);\n        double adjustment = diff * (gaps[k] / total_gap) * lr;\n        s_est[member][k] -= adjustment;\n        s_est[member][k] = max(0.0, s_est[member][k]);\n        \n        double implied = d[task][k] - gaps[k] * (1.0 - adjustment / max(0.001, gaps[k]));\n        if (implied > 0) {\n            s_sum_obs[member][k] += implied;\n            if (s_obs_count[member][k] < 20) s_obs_count[member][k]++;\n        }\n    }\n}\n\nbool is_task_ready(int task) {\n    if (task_status[task] != NOT_STARTED) return false;\n    for (int dep_task : dep[task]) {\n        if (task_status[dep_task] != COMPLETED) return false;\n    }\n    return true;\n}\n\nint count_blocked(int task) {\n    if (task_status[task] == COMPLETED) return 0;\n    return descendants[task];\n}\n\n// Compute critical path lengths for all incomplete tasks\nvector<int> compute_critical_path() {\n    vector<int> longest(N, 0);\n    \n    vector<int> indeg(N, 0);\n    for (int i = 0; i < N; i++) {\n        if (task_status[i] == COMPLETED) continue;\n        for (int u : rev_dep[i]) indeg[u]++;\n    }\n    \n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (task_status[i] != COMPLETED && indeg[i] == 0) q.push(i);\n    }\n    \n    vector<int> topo;\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) q.push(u);\n        }\n    }\n    \n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        if (task_status[v] == COMPLETED) {\n            longest[v] = 0;\n        } else {\n            int min_est = 1000000;\n            for (int j = 0; j < M; j++) {\n                min_est = min(min_est, estimate_t(v, j));\n            }\n            min_est = max(1, min_est);\n            \n            int max_succ = 0;\n            for (int u : rev_dep[v]) {\n                max_succ = max(max_succ, longest[u]);\n            }\n            longest[v] = min_est + max_succ;\n        }\n    }\n    \n    return longest;\n}\n\nvector<int> get_ready_tasks() {\n    vector<int> ready;\n    for (int i = 0; i < N; i++) {\n        if (is_task_ready(i)) {\n            ready.push_back(i);\n        }\n    }\n    \n    if (ready.empty()) return ready;\n    \n    vector<int> crit = compute_critical_path();\n    \n    sort(ready.begin(), ready.end(), [&](int a, int b) {\n        if (crit[a] != crit[b]) return crit[a] > crit[b];\n        if (descendants[a] != descendants[b]) return descendants[a] > descendants[b];\n        return a < b;\n    });\n    \n    return ready;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    parse_input();\n    init_estimation();\n    init_scheduling();\n    precompute_descendants();\n    \n    int current_day = 0;\n    \n    while (true) {\n        current_day++;\n        \n        // Check exploration status\n        int total_skill_obs = 0;\n        for (int j = 0; j < M; j++) {\n            for (int k = 0; k < K; k++) {\n                total_skill_obs += min(10, s_obs_count[j][k]);\n            }\n        }\n        int max_possible = M * K * 10;\n        bool exploration_phase = (total_skill_obs < max_possible * 0.5);\n        \n        vector<int> ready_tasks = get_ready_tasks();\n        vector<int> crit = compute_critical_path();\n        \n        vector<int> available;\n        for (int j = 0; j < M; j++) {\n            if (!member_busy[j]) {\n                available.push_back(j);\n            }\n        }\n        \n        vector<pair<int,int>> assignments;\n        vector<bool> used(M, false);\n        \n        // Phase 1: Assign 1-day tasks by urgency\n        if (!ready_tasks.empty() && !available.empty()) {\n            vector<tuple<int,int,int>> one_day_options; // (urgency, member, task) - urgency is negative crit\n            for (int task : ready_tasks) {\n                for (int j : available) {\n                    if (used[j]) continue;\n                    double w = estimate_w(task, j);\n                    if (w < 0.5) {\n                        one_day_options.push_back({-crit[task], j, task});\n                    }\n                }\n            }\n            \n            sort(one_day_options.begin(), one_day_options.end());\n            \n            for (auto &opt : one_day_options) {\n                int j = get<1>(opt);\n                int task = get<2>(opt);\n                if (!used[j]) {\n                    bool already = false;\n                    for (auto &p : assignments) {\n                        if (p.second == task) { already = true; break; }\n                    }\n                    if (!already) {\n                        assignments.push_back({j, task});\n                        used[j] = true;\n                    }\n                }\n            }\n        }\n        \n        // Phase 2: Assign remaining tasks\n        for (int task : ready_tasks) {\n            if ((int)assignments.size() >= (int)available.size()) break;\n            \n            bool already = false;\n            for (auto &p : assignments) {\n                if (p.second == task) { already = true; break; }\n            }\n            if (already) continue;\n            \n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int j : available) {\n                if (used[j]) continue;\n                \n                int est_t = estimate_t(task, j);\n                double score = -est_t * 100.0;\n                \n                // Urgency based on critical path and blocked tasks\n                score += crit[task] * 3.0;\n                score += count_blocked(task) * 0.5;\n                \n                // Exploration bonus\n                if (exploration_phase) {\n                    int unexplored = 0;\n                    for (int k = 0; k < K; k++) {\n                        if (d[task][k] > s_est[j][k] && s_obs_count[j][k] < 3) {\n                            unexplored++;\n                        }\n                    }\n                    score += unexplored * 20.0;\n                }\n                \n                // Load balancing\n                score -= total_assigned[j] * 0.3;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                assignments.push_back({best_member, task});\n                used[best_member] = true;\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            int member = p.first;\n            int task = p.second;\n            cout << \" \" << (member + 1) << \" \" << (task + 1);\n            \n            task_status[task] = IN_PROGRESS;\n            task_assigned_to[task] = member;\n            task_start_day[task] = current_day;\n            member_busy[member] = true;\n            member_current_task[member] = task;\n            total_assigned[member]++;\n        }\n        cout << \"\\n\";\n        \n        // Output predictions\n        for (int j = 0; j < M; j++) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << \" \" << max(0, (int)round(s_est[j][k]));\n            }\n            cout << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read completions\n        string line;\n        getline(cin, line);\n        while (line.empty()) {\n            if (!getline(cin, line)) break;\n        }\n        \n        istringstream iss(line);\n        vector<int> vals;\n        int x;\n        while (iss >> x) vals.push_back(x);\n        \n        if (vals.empty()) continue;\n        if (vals.size() == 1 && vals[0] == -1) {\n            break;\n        }\n        \n        int n_comp = vals[0];\n        for (int i = 0; i < n_comp; i++) {\n            int member = vals[i + 1] - 1;\n            member_busy[member] = false;\n            \n            int task = member_current_task[member];\n            if (task != -1 && task_status[task] == IN_PROGRESS) {\n                int actual_t = current_day - task_start_day[task] + 1;\n                update_skill_estimate(task, member, actual_t);\n                task_status[task] = COMPLETED;\n                task_assigned_to[task] = -1;\n                member_current_task[member] = -1;\n            }\n        }\n        \n        if (current_day >= 2000) break;\n    }\n    \n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <tuple>\n#include <cmath>\nusing namespace std;\n\nstruct Order {\n    int ax, ay, cx, cy;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    const int N = 1000, K = 50, DEPOT = 0, MAXN = 2*N+1;\n    vector<int> x(MAXN), y(MAXN);\n    x[DEPOT] = y[DEPOT] = 400;\n    for (int i = 0; i < N; ++i) {\n        cin >> x[2*i+1] >> y[2*i+1] >> x[2*i+2] >> y[2*i+2];\n    }\n    // Precompute distances\n    vector<vector<int>> dist(MAXN, vector<int>(MAXN));\n    for (int i = 0; i < MAXN; ++i)\n        for (int j = 0; j <= i; ++j)\n            dist[i][j] = dist[j][i] = abs(x[i]-x[j]) + abs(y[i]-y[j]);\n    \n    auto routeLen = [&](const vector<int>& r){\n        int len=0;\n        for(size_t i=0;i+1<r.size();++i) len += dist[r[i]][r[i+1]];\n        return len;\n    };\n    \n    auto insertTwo = [&](vector<int> r, int p, int d, int posP, int posD){\n        if (posP <= posD) {\n            r.insert(r.begin() + posP, p);\n            r.insert(r.begin() + posD + 1, d);\n        } else {\n            r.insert(r.begin() + posD, d);\n            r.insert(r.begin() + posP + 1, p);\n        }\n        return r;\n    };\n    \n    // fast best insertion with limited candidates (W = 12)\n    const int W = 12;\n    auto bestInsertFast = [&](const vector<int>& r, int pNode, int dNode) -> tuple<int,int,int> {\n        int bestExtra = INT_MAX;\n        int bestP = -1, bestD = -1;\n        int m = (int)r.size();\n        vector<pair<int,int>> candP;\n        candP.reserve(W);\n        for (int i = 0; i < m-1; ++i) {\n            int pi = i+1;\n            int extraP = dist[r[i]][pNode] + dist[pNode][r[pi]] - dist[r[i]][r[pi]];\n            auto it = lower_bound(candP.begin(), candP.end(), make_pair(extraP, i),\n                                   [](auto& a, auto& b){ return a.first < b.first; });\n            if ((int)candP.size() < W) {\n                candP.insert(it, {extraP, i});\n            } else if (it != candP.end()) {\n                candP.insert(it, {extraP, i});\n                candP.pop_back();\n            }\n        }\n        for (auto& p : candP) {\n            int i = p.second;\n            int pi = i+1;\n            int extraP = p.first;\n            if (extraP >= bestExtra) continue;\n            for (int j = i; j < m-1; ++j) {\n                int dj = j+1;\n                int extraD = dist[r[j]][dNode] + dist[dNode][r[dj]] - dist[r[j]][r[dj]];\n                int total = extraP + extraD;\n                if (total < bestExtra) {\n                    bestExtra = total;\n                    bestP = pi;\n                    bestD = dj;\n                }\n            }\n        }\n        return {bestP, bestD, bestExtra};\n    };\n    \n    // full best insertion for initial construction\n    auto bestInsertFull = [&](const vector<int>& r, int pNode, int dNode) -> tuple<int,int,int> {\n        int bestExtra = INT_MAX, bestP = -1, bestD = -1;\n        int m = (int)r.size();\n        for (int i = 0; i < m-1; ++i) {\n            int pi = i+1;\n            int extraP = dist[r[i]][pNode] + dist[pNode][r[pi]] - dist[r[i]][r[pi]];\n            for (int j = i; j < m-1; ++j) {\n                int dj = j+1;\n                int extraD = dist[r[j]][dNode] + dist[dNode][r[dj]] - dist[r[j]][r[dj]];\n                int total = extraP + extraD;\n                if (total < bestExtra) {\n                    bestExtra = total;\n                    bestP = pi;\n                    bestD = dj;\n                }\n            }\n        }\n        return {bestP, bestD, bestExtra};\n    };\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> realDist(0.0, 1.0);\n    \n    // Multiple initial attempts\n    vector<int> bestSelected;\n    vector<int> bestRouteVec;\n    int bestLenGlobal = INT_MAX;\n    \n    auto startTime = chrono::steady_clock::now();\n    const double TIME_INIT = 0.15;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - startTime).count() > TIME_INIT) break;\n        vector<int> sel(N);\n        iota(sel.begin(), sel.end(), 0);\n        shuffle(sel.begin(), sel.end(), rng);\n        sel.resize(K);\n        vector<int> rte = {DEPOT, DEPOT};\n        for (int id : sel) {\n            int p = 2*id+1, d = 2*id+2;\n            auto [bp, bd, _] = bestInsertFull(rte, p, d);\n            rte = insertTwo(rte, p, d, bp, bd);\n        }\n        int len = routeLen(rte);\n        if (len < bestLenGlobal) {\n            bestLenGlobal = len;\n            bestRouteVec = rte;\n            bestSelected = sel;\n        }\n    }\n    \n    // SA state\n    vector<int> curSelected = bestSelected;\n    vector<int> curRoute = bestRouteVec;\n    int curLen = bestLenGlobal;\n    \n    vector<bool> chosen(N, false);\n    for (int id : curSelected) chosen[id] = true;\n    vector<int> avail;\n    for (int i = 0; i < N; ++i) if (!chosen[i]) avail.push_back(i);\n    \n    uniform_int_distribution<int> selDist(0, K-1);\n    uniform_int_distribution<int> availDist(0, (int)avail.size()-1);\n    \n    double temperature = 200.0;\n    double cool = 0.999995;\n    int saIter = 0;\n    const double TIME_END = 1.95;\n    \n    while (true) {\n        if (saIter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - startTime).count() > TIME_END) break;\n        }\n        saIter++;\n        \n        int idxR = selDist(rng), oldId = curSelected[idxR];\n        int idxA = availDist(rng), newId = avail[idxA];\n        int oldP = 2*oldId+1, oldD = 2*oldId+2;\n        int newP = 2*newId+1, newD = 2*newId+2;\n        \n        vector<int> tempRoute;\n        tempRoute.reserve(curRoute.size()-2);\n        for (int node : curRoute) if (node != oldP && node != oldD) tempRoute.push_back(node);\n        \n        auto [bp, bd, extra] = bestInsertFast(tempRoute, newP, newD);\n        vector<int> cand = insertTwo(tempRoute, newP, newD, bp, bd);\n        int candLen = routeLen(cand);\n        \n        int delta = candLen - curLen;\n        if (delta < 0 || realDist(rng) < exp(-delta / temperature)) {\n            curRoute = move(cand);\n            curLen = candLen;\n            curSelected[idxR] = newId;\n            chosen[oldId] = false; chosen[newId] = true;\n            avail[idxA] = avail.back();\n            avail.pop_back();\n            avail.push_back(oldId);\n            availDist = uniform_int_distribution<int>(0, max(0,(int)avail.size()-1));\n            \n            if (curLen < bestLenGlobal) {\n                bestLenGlobal = curLen;\n                bestRouteVec = curRoute;\n                bestSelected = curSelected;\n            }\n        }\n        temperature *= cool;\n    }\n    \n    // Output\n    cout << K;\n    for (int id : bestSelected) cout << \" \" << id+1;\n    cout << \"\\n\" << bestRouteVec.size();\n    for (int node : bestRouteVec) cout << \" \" << x[node] << \" \" << y[node];\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <queue>\n#include <cstring>\nusing namespace std;\n\nstruct Edge { int u, v, d; };\n\nclass UnionFind {\npublic:\n    vector<int> parent, rank;\n    int comps;\n    UnionFind(int n) : comps(n) {\n        parent.resize(n); rank.resize(n, 0);\n        for (int i = 0; i < n; i++) parent[i] = i;\n    }\n    int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); }\n    bool unite(int x, int y) {\n        int px = find(x), py = find(y);\n        if (px == py) return false;\n        if (rank[px] < rank[py]) parent[px] = py;\n        else if (rank[py] < rank[px]) parent[py] = px;\n        else { parent[py] = px; rank[px]++; }\n        comps--; return true;\n    }\n    bool connected(int x, int y) { return find(x) == find(y); }\n};\n\n// Check if remaining edges can connect all current components\nbool canFinish(const vector<Edge>& edges, int startIdx, int M, UnionFind& uf) {\n    int compToIdx[400];\n    memset(compToIdx, -1, sizeof(compToIdx));\n    int C = 0;\n    for (int j = 0; j < 400; j++) {\n        int c = uf.find(j);\n        if (compToIdx[c] == -1) compToIdx[c] = C++;\n    }\n    if (C <= 1) return true;\n    \n    vector<vector<int>> compGraph(C);\n    for (int j = startIdx; j < M; j++) {\n        int cu = compToIdx[uf.find(edges[j].u)];\n        int cv = compToIdx[uf.find(edges[j].v)];\n        if (cu != cv) {\n            compGraph[cu].push_back(cv);\n            compGraph[cv].push_back(cu);\n        }\n    }\n    \n    vector<bool> vis(C, false);\n    queue<int> q;\n    q.push(0); vis[0] = true;\n    int cnt = 0;\n    while (!q.empty()) {\n        int cur = q.front(); q.pop();\n        cnt++;\n        for (int nxt : compGraph[cur]) {\n            if (!vis[nxt]) { vis[nxt] = true; q.push(nxt); }\n        }\n    }\n    return cnt == C;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(nullptr);\n    \n    const int N = 400, M = 1995, TARGET = 399;\n    \n    vector<pair<int,int>> coords(N);\n    for (int i = 0; i < N; i++) cin >> coords[i].first >> coords[i].second;\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        int dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = round(sqrt(dx*dx + dy*dy));\n    }\n    \n    // Simulate 5 rounds of MST extraction for edge importance\n    vector<bool> usedInRounds(M, false);\n    vector<int> edgeRound(M, 5);\n    for (int round = 0; round < 5; round++) {\n        vector<pair<double,int>> remaining;\n        for (int i = 0; i < M; i++) {\n            if (!usedInRounds[i]) remaining.push_back({(double)edges[i].d, i});\n        }\n        sort(remaining.begin(), remaining.end());\n        UnionFind tmpUf(N);\n        for (auto& [d, idx] : remaining) {\n            if (tmpUf.unite(edges[idx].u, edges[idx].v)) {\n                usedInRounds[idx] = true;\n                edgeRound[idx] = round;\n            }\n        }\n    }\n    \n    UnionFind uf(N);\n    int accepted = 0;\n    \n    for (int i = 0; i < M; i++) {\n        int li; cin >> li;\n        bool accept = false;\n        int stillNeed = uf.comps - 1;\n        \n        if (stillNeed > 0 && !uf.connected(edges[i].u, edges[i].v)) {\n            double ratio = (double)li / max(1.0, (double)edges[i].d);\n            int remaining = M - i - 1;\n            \n            // ALWAYS check connectivity safety first\n            bool finishable = canFinish(edges, i + 1, M, uf);\n            \n            if (!finishable) {\n                // Must accept to have any chance of connecting all components\n                accept = true;\n            } else {\n                // Safe to potentially reject. Now use quality heuristics.\n                \n                // Determine threshold based on edge importance and progress\n                double threshold;\n                int imp = edgeRound[i];\n                \n                // Base threshold by importance\n                if (imp == 0) threshold = 2.0;      // Most structurally important\n                else if (imp == 1) threshold = 1.7;\n                else if (imp == 2) threshold = 1.4;\n                else if (imp == 3) threshold = 1.2;\n                else threshold = 1.1;                // Least important\n                \n                // Adjust for stillNeed\n                if (stillNeed > 300) threshold += 0.2;\n                else if (stillNeed > 200) threshold += 0.1;\n                else if (stillNeed < 50) threshold += 0.3;\n                else if (stillNeed < 20) threshold += 0.5;\n                else if (stillNeed < 5) threshold = 3.0;  // Almost done, accept anything\n                \n                // Adjust for remaining edges buffer\n                if (remaining < stillNeed * 3) threshold = 3.0;  // Desperate\n                else if (remaining < stillNeed * 6) threshold += 0.5;\n                \n                if (ratio <= threshold) accept = true;\n            }\n        }\n        \n        if (accept) {\n            uf.unite(edges[i].u, edges[i].v);\n            accepted++;\n        }\n        \n        cout << (accept ? 1 : 0) << endl;\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int TURNS = 300;\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char wall_char[] = {'u', 'd', 'l', 'r'};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\nconst int rev_dir[] = {1, 0, 3, 2};\n\nstruct Pos {\n    int x, y;\n    Pos() : x(0), y(0) {}\n    Pos(int x, int y) : x(x), y(y) {}\n    bool operator==(const Pos& o) const { return x==o.x && y==o.y; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n    bool operator<(const Pos& o) const { return tie(x,y) < tie(o.x,o.y); }\n    bool valid() const { return x>=0 && x<GRID && y>=0 && y<GRID; }\n    Pos move(int d) const { return Pos(x+dx[d], y+dy[d]); }\n};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nstruct Pet {\n    Pos pos;\n    int type;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Pos> humans;\nvector<vector<bool>> wall;\n\nbool has_pet(Pos p) {\n    for(int i=0; i<N; i++) if(pets[i].pos == p) return true;\n    return false;\n}\n\nbool adjacent_to_pet(Pos p) {\n    for(int d=0; d<4; d++) {\n        Pos adj = p.move(d);\n        if(adj.valid() && has_pet(adj)) return true;\n    }\n    return false;\n}\n\nPos get_dest(Pos cur, char act) {\n    if(act == 'U') return cur.move(0);\n    if(act == 'D') return cur.move(1);\n    if(act == 'L') return cur.move(2);\n    if(act == 'R') return cur.move(3);\n    return cur;\n}\n\nbool validate_actions(const string& actions) {\n    vector<Pos> new_pos(M);\n    vector<Pos> wall_targets;\n    \n    for(int i=0; i<M; i++) {\n        if(actions[i] == 'U' || actions[i] == 'D' || actions[i] == 'L' || actions[i] == 'R') {\n            Pos dest = get_dest(humans[i], actions[i]);\n            if(!dest.valid() || wall[dest.x][dest.y] || has_pet(dest)) return false;\n            new_pos[i] = dest;\n        } else {\n            new_pos[i] = humans[i];\n        }\n        \n        if(actions[i] == 'u' || actions[i] == 'd' || actions[i] == 'l' || actions[i] == 'r') {\n            Pos wt = humans[i].move(string(\"udlr\").find(actions[i]));\n            if(!wt.valid() || has_pet(wt) || adjacent_to_pet(wt)) return false;\n            for(int j=0; j<M; j++) if(humans[j] == wt) return false;\n            wall_targets.push_back(wt);\n        }\n    }\n    \n    for(int i=0; i<M; i++) {\n        for(int j=i+1; j<M; j++) {\n            if(new_pos[i] == new_pos[j]) return false;\n        }\n    }\n    \n    for(auto& wt : wall_targets) {\n        for(int i=0; i<M; i++) {\n            if(new_pos[i] == wt) return false;\n        }\n    }\n    \n    for(int i=0; i<M; i++) {\n        for(int j=0; j<M; j++) {\n            if(i != j && new_pos[i] == humans[j] && \n               (actions[j] == '.' || actions[j] == 'u' || actions[j] == 'd' || \n                actions[j] == 'l' || actions[j] == 'r')) {\n                return false;\n            }\n        }\n    }\n    \n    return true;\n}\n\nvector<int> find_path(Pos from, Pos to) {\n    vector<vector<int>> prev(GRID, vector<int>(GRID, -1));\n    queue<Pos> q;\n    q.push(from);\n    prev[from.x][from.y] = -2;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        if(cur == to) break;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur.move(d);\n            if(!nxt.valid() || wall[nxt.x][nxt.y] || has_pet(nxt)) continue;\n            if(prev[nxt.x][nxt.y] != -1) continue;\n            prev[nxt.x][nxt.y] = d;\n            q.push(nxt);\n        }\n    }\n    \n    if(prev[to.x][to.y] == -1) return {};\n    vector<int> path;\n    Pos cur = to;\n    while(cur != from) {\n        int d = prev[cur.x][cur.y];\n        path.push_back(d);\n        cur = cur.move(rev_dir[d]);\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Count reachable pets from a position\nint count_reachable_pets(Pos start, int max_dist=1e9) {\n    vector<vector<int>> dist(GRID, vector<int>(GRID, 1e9));\n    queue<Pos> q;\n    q.push(start);\n    dist[start.x][start.y] = 0;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        if(dist[cur.x][cur.y] >= max_dist) continue;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur.move(d);\n            if(nxt.valid() && !wall[nxt.x][nxt.y] && dist[nxt.x][nxt.y] > dist[cur.x][cur.y]+1) {\n                dist[nxt.x][nxt.y] = dist[cur.x][cur.y] + 1;\n                q.push(nxt);\n            }\n        }\n    }\n    \n    int cnt = 0;\n    for(int i=0; i<N; i++) {\n        if(dist[pets[i].pos.x][pets[i].pos.y] < 1e9) cnt++;\n    }\n    return cnt;\n}\n\n// BFS to get all cells reachable from start\nvector<Pos> get_reachable_cells(Pos start) {\n    vector<vector<bool>> vis(GRID, vector<bool>(GRID, false));\n    vector<Pos> cells;\n    queue<Pos> q;\n    q.push(start);\n    vis[start.x][start.y] = true;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        cells.push_back(cur);\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur.move(d);\n            if(nxt.valid() && !wall[nxt.x][nxt.y] && !vis[nxt.x][nxt.y]) {\n                vis[nxt.x][nxt.y] = true;\n                q.push(nxt);\n            }\n        }\n    }\n    return cells;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    pets.resize(N);\n    for(int i=0; i<N; i++) {\n        cin >> pets[i].pos.x >> pets[i].pos.y >> pets[i].type;\n        pets[i].pos.x--; pets[i].pos.y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for(int i=0; i<M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n    }\n    \n    wall.assign(GRID, vector<bool>(GRID, false));\n    \n    // Strategy: Each human gets a \"home region\" - a rectangular area they'll claim\n    // First, divide the grid into M approximately equal regions\n    struct Region {\n        int x1, y1, x2, y2; // inclusive bounds\n        Pos corner; // Corner to start from\n        bool claimed;\n        int human_idx;\n    };\n    \n    // Create regions by dividing the grid\n    vector<Region> regions;\n    int cols = min(M, (int)ceil(sqrt(M * 900.0 / GRID)));\n    int rows = (M + cols - 1) / cols;\n    \n    // Adjust to fit 30x30\n    int region_w = GRID / cols;\n    int region_h = GRID / rows;\n    \n    vector<Pos> corners;\n    for(int r=0; r<rows; r++) {\n        for(int c=0; c<cols && (int)regions.size() < M; c++) {\n            int x1 = r * region_h;\n            int y1 = c * region_w;\n            int x2 = (r+1) * region_h - 1;\n            int y2 = (c+1) * region_w - 1;\n            if(r == rows-1) x2 = GRID-1;\n            if(c == cols-1) y2 = GRID-1;\n            \n            // Choose corner based on position relative to grid center\n            Pos corner;\n            if(r <= rows/2 && c <= cols/2) corner = Pos(x1, y1);\n            else if(r <= rows/2) corner = Pos(x1, y2);\n            else if(c <= cols/2) corner = Pos(x2, y1);\n            else corner = Pos(x2, y2);\n            \n            regions.push_back({x1, y1, x2, y2, corner, false, -1});\n            corners.push_back(corner);\n        }\n    }\n    \n    // Assign humans to nearest region corner\n    vector<int> human_region(M, -1);\n    vector<bool> region_taken(regions.size(), false);\n    vector<Pos> targets(M);\n    \n    for(int i=0; i<M; i++) {\n        int best_r = -1;\n        int best_score = 1e9;\n        for(int r=0; r<(int)regions.size(); r++) {\n            if(region_taken[r]) continue;\n            \n            // Score: distance to corner minus safety (fewer nearby pets is better)\n            int dist = manhattan(humans[i], corners[r]);\n            int nearby_pets = count_reachable_pets(corners[r], 5);\n            int score = dist + nearby_pets * 3;\n            \n            if(score < best_score) {\n                best_score = score;\n                best_r = r;\n            }\n        }\n        human_region[i] = best_r;\n        region_taken[best_r] = true;\n        targets[i] = corners[best_r];\n        regions[best_r].human_idx = i;\n        regions[best_r].claimed = true;\n    }\n    \n    vector<bool> at_target(M, false);\n    vector<int> phase(M, 0); // 0=moving to corner, 1=sealing region, 2=expanding\n    \n    // Pre-plan enclosure walls for each region\n    struct WallPlan {\n        vector<Pos> walls; // Walls to build to seal region\n        int current_wall;\n    };\n    vector<WallPlan> plans(M);\n    \n    for(int i=0; i<M; i++) {\n        if(human_region[i] == -1) continue;\n        Region& reg = regions[human_region[i]];\n        Pos corn = corners[human_region[i]];\n        \n        // Plan walls along two edges from the corner\n        int dx1=0, dy1=0, dx2=0, dy2=0;\n        if(corn.x == reg.x1 && corn.y == reg.y1) {\n            // Top-left corner: build right and down\n            for(int y=corn.y; y<=reg.y2; y++) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x<=reg.x2; x++) plans[i].walls.push_back(Pos(x, corn.y));\n        } else if(corn.x == reg.x1 && corn.y == reg.y2) {\n            // Top-right corner\n            for(int y=corn.y; y>=reg.y1; y--) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x<=reg.x2; x++) plans[i].walls.push_back(Pos(x, corn.y));\n        } else if(corn.x == reg.x2 && corn.y == reg.y1) {\n            // Bottom-left corner\n            for(int y=corn.y; y<=reg.y2; y++) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x>=reg.x1; x--) plans[i].walls.push_back(Pos(x, corn.y));\n        } else {\n            // Bottom-right corner\n            for(int y=corn.y; y>=reg.y1; y--) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x>=reg.x1; x--) plans[i].walls.push_back(Pos(x, corn.y));\n        }\n        plans[i].current_wall = 0;\n    }\n    \n    for(int turn = 0; turn < TURNS; turn++) {\n        string actions(M, '.');\n        \n        // Process each human\n        for(int i=0; i<M; i++) {\n            Pos h = humans[i];\n            \n            if(phase[i] == 0) {\n                // Move to corner\n                if(h == targets[i]) {\n                    phase[i] = 1;\n                } else {\n                    auto path = find_path(h, targets[i]);\n                    if(!path.empty()) {\n                        actions[i] = move_char[path[0]];\n                    }\n                }\n            }\n            \n            if(phase[i] == 1 && actions[i] == '.') {\n                // Build walls from plan\n                WallPlan& plan = plans[i];\n                bool acted = false;\n                \n                // Try to build next few planned walls\n                for(int attempt=0; attempt<3 && !acted; attempt++) {\n                    int idx = plan.current_wall + attempt;\n                    if(idx >= (int)plan.walls.size()) {\n                        phase[i] = 2; // Done sealing\n                        break;\n                    }\n                    \n                    Pos target = plan.walls[idx];\n                    \n                    // Skip if already walled\n                    if(wall[target.x][target.y]) {\n                        plan.current_wall = idx + 1;\n                        continue;\n                    }\n                    \n                    // If adjacent, try to build\n                    if(manhattan(h, target) == 1) {\n                        int d = -1;\n                        for(int k=0; k<4; k++) {\n                            if(h.move(k) == target) { d = k; break; }\n                        }\n                        \n                        if(d != -1 && !has_pet(target) && !adjacent_to_pet(target)) {\n                            // Check no human conflict\n                            bool conflict = false;\n                            for(int j=0; j<M; j++) {\n                                if(j != i && humans[j] == target) conflict = true;\n                                if(j != i && get_dest(humans[j], actions[j]) == target) conflict = true;\n                            }\n                            if(!conflict) {\n                                actions[i] = wall_char[d];\n                                plan.current_wall = idx + 1;\n                                acted = true;\n                            }\n                        }\n                    } else {\n                        // Move toward next wall target\n                        auto path = find_path(h, target);\n                        if(!path.empty()) {\n                            Pos nxt = h.move(path[0]);\n                            bool conflict = false;\n                            for(int j=0; j<M; j++) {\n                                if(j != i && get_dest(humans[j], actions[j]) == nxt) conflict = true;\n                                if(j != i && humans[j] == nxt && \n                                   (actions[j] == '.' || actions[j] == 'u' || actions[j] == 'd' || \n                                    actions[j] == 'l' || actions[j] == 'r')) conflict = true;\n                            }\n                            if(!conflict) {\n                                actions[i] = move_char[path[0]];\n                                acted = true;\n                            }\n                        }\n                    }\n                }\n                \n                // If stuck, try to move to better position\n                if(!acted && plan.current_wall < (int)plan.walls.size()) {\n                    Pos next_wall = plan.walls[plan.current_wall];\n                    // Move randomly toward it\n                    for(int d=0; d<4; d++) {\n                        Pos nxt = h.move(d);\n                        if(nxt.valid() && !wall[nxt.x][nxt.y] && !has_pet(nxt)) {\n                            if(manhattan(nxt, next_wall) < manhattan(h, next_wall)) {\n                                bool conflict = false;\n                                for(int j=0; j<M; j++) {\n                                    if(j != i && get_dest(humans[j], actions[j]) == nxt) conflict = true;\n                                }\n                                if(!conflict) {\n                                    actions[i] = move_char[d];\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Phase 2: Expand territory by building more walls\n            if(phase[i] == 2 && actions[i] == '.') {\n                // Try to build walls to claim more area\n                bool built = false;\n                \n                // Check if region is fully sealed\n                Region& reg = regions[human_region[i]];\n                Pos corn = corners[human_region[i]];\n                \n                // Try to extend walls outward\n                vector<int> dirs;\n                if(corn.x == reg.x1) dirs.push_back(1); // Down\n                else dirs.push_back(0); // Up\n                if(corn.y == reg.y1) dirs.push_back(3); // Right\n                else dirs.push_back(2); // Left\n                \n                for(int d : dirs) {\n                    Pos target = h.move(d);\n                    if(target.valid() && !wall[target.x][target.y] && \n                       !has_pet(target) && !adjacent_to_pet(target)) {\n                        bool conflict = false;\n                        for(int j=0; j<M; j++) {\n                            if(j != i && humans[j] == target) conflict = true;\n                            if(j != i && get_dest(humans[j], actions[j]) == target) conflict = true;\n                        }\n                        if(!conflict) {\n                            actions[i] = wall_char[d];\n                            built = true;\n                            break;\n                        }\n                    }\n                }\n                \n                // If can't build, move along expansion direction\n                if(!built) {\n                    for(int d : dirs) {\n                        Pos nxt = h.move(d);\n                        if(nxt.valid() && !wall[nxt.x][nxt.y] && !has_pet(nxt)) {\n                            bool conflict = false;\n                            for(int j=0; j<M; j++) {\n                                if(j != i && get_dest(humans[j], actions[j]) == nxt) conflict = true;\n                                if(j != i && humans[j] == nxt && \n                                   (actions[j] == '.' || actions[j] == 'u' || actions[j] == 'd' || \n                                    actions[j] == 'l' || actions[j] == 'r')) conflict = true;\n                            }\n                            if(!conflict) {\n                                actions[i] = move_char[d];\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Validate and fix if needed\n        if(!validate_actions(actions)) {\n            string fixed = actions;\n            // Try canceling wall actions first\n            for(int i=0; i<M; i++) {\n                if(fixed[i] == 'u' || fixed[i] == 'd' || fixed[i] == 'l' || fixed[i] == 'r') {\n                    string test = fixed;\n                    test[i] = '.';\n                    if(validate_actions(test)) {\n                        fixed = test;\n                        break;\n                    }\n                }\n            }\n            if(!validate_actions(fixed)) {\n                // Cancel all actions\n                fixed = string(M, '.');\n            }\n            actions = fixed;\n        }\n        \n        cout << actions << endl;\n        cout.flush();\n        \n        // Read pet movements\n        for(int i=0; i<N; i++) {\n            string movement;\n            cin >> movement;\n            if(movement != \".\") {\n                for(char m : movement) {\n                    if(m == 'U') pets[i].pos.x--;\n                    else if(m == 'D') pets[i].pos.x++;\n                    else if(m == 'L') pets[i].pos.y--;\n                    else if(m == 'R') pets[i].pos.y++;\n                }\n            }\n        }\n        \n        // Update state\n        for(int i=0; i<M; i++) {\n            char act = actions[i];\n            if(act == 'U') humans[i].x--;\n            else if(act == 'D') humans[i].x++;\n            else if(act == 'L') humans[i].y--;\n            else if(act == 'R') humans[i].y++;\n            else if(act == 'u' && humans[i].x > 0) wall[humans[i].x-1][humans[i].y] = true;\n            else if(act == 'd' && humans[i].x < GRID-1) wall[humans[i].x+1][humans[i].y] = true;\n            else if(act == 'l' && humans[i].y > 0) wall[humans[i].x][humans[i].y-1] = true;\n            else if(act == 'r' && humans[i].y < GRID-1) wall[humans[i].x][humans[i].y+1] = true;\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int MAXL = 200;\n\nint di[] = {-1, 1, 0, 0};\nint dj[] = {0, 0, -1, 1};\nchar dirs[] = {'U', 'D', 'L', 'R'};\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), v(19);\n    for (int i = 0; i < 20; i++) cin >> h[i];\n    for (int i = 0; i < 19; i++) cin >> v[i];\n    \n    // Precompute moves: nxt[d][i][j] = next cell index or -1\n    int nxt[4][N][N];\n    memset(nxt, -1, sizeof(nxt));\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 + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                bool wall = false;\n                if (d == 0 && i > 0 && v[i-1][j] == '1') wall = true;\n                if (d == 1 && i < N-1 && v[i][j] == '1') wall = true;\n                if (d == 2 && j > 0 && h[i][j-1] == '1') wall = true;\n                if (d == 3 && j < N-1 && h[i][j] == '1') wall = true;\n                if (!wall) nxt[d][i][j] = ni*N + nj;\n            }\n        }\n    }\n    \n    // BFS shortest path\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<char>> moveTo(N, vector<char>(N, ' '));\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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            if (nxt[d][i][j] == -1) continue;\n            int ni = i + di[d], nj = j + dj[d];\n            if (dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                prev[ni][nj] = {i, j};\n                moveTo[ni][nj] = dirs[d];\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    string path;\n    {\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path.push_back(moveTo[ci][cj]);\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi; cj = pj;\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    auto dchar = [](char c) {\n        if (c == 'U') return 0;\n        if (c == 'D') return 1;\n        if (c == 'L') return 2;\n        return 3;\n    };\n    \n    // Dense eval\n    auto eval = [&](const string &seq) {\n        double prob[N*N] = {0};\n        prob[si*N+sj] = 1.0;\n        double expScore = 0;\n        double probGoalBefore = 0;\n        int goalIdx = ti*N + tj;\n        \n        for (int t = 0; t < MAXL; t++) {\n            int d = dchar(seq[t]);\n            double nextProb[N*N] = {0};\n            for (int idx = 0; idx < N*N; idx++) {\n                double pr = prob[idx];\n                if (pr == 0) continue;\n                if (idx == goalIdx) continue;\n                int i = idx / N, j = idx % N;\n                nextProb[idx] += pr * p;\n                int nidx = nxt[d][i][j];\n                if (nidx != -1) nextProb[nidx] += pr * (1-p);\n                else nextProb[idx] += pr * (1-p);\n            }\n            memcpy(prob, nextProb, sizeof(prob));\n            double probHere = prob[goalIdx];\n            double newly = probHere - probGoalBefore;\n            expScore += newly * (401 - (t+1));\n            probGoalBefore = probHere;\n        }\n        return expScore;\n    };\n    \n    // Build initial sequence\n    int baseLen = path.size();\n    int repeat = max(1, min(MAXL / baseLen, 5));\n    string curSeq;\n    for (char c : path) {\n        for (int r = 0; r < repeat; r++) {\n            if ((int)curSeq.size() < MAXL) curSeq.push_back(c);\n        }\n    }\n    while ((int)curSeq.size() < MAXL) curSeq.push_back(path[curSeq.size() % baseLen]);\n    \n    double curScore = eval(curSeq);\n    string bestSeq = curSeq;\n    double bestScore = curScore;\n    \n    mt19937 rng(42);\n    uniform_int_distribution<int> posDist(0, MAXL-1);\n    uniform_int_distribution<int> dirDist(0, 3);\n    \n    auto startTime = chrono::steady_clock::now();\n    auto timeLimit = chrono::milliseconds(18); // per case budget\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (now - startTime > timeLimit) break;\n        \n        // Try multiple mutations per time check\n        for (int sub = 0; sub < 5; sub++) {\n            string candSeq = curSeq;\n            // mutate 1-2 positions\n            int numMut = 1 + (rng() % 2);\n            for (int m = 0; m < numMut; m++) {\n                candSeq[posDist(rng)] = dirs[dirDist(rng)];\n            }\n            double candScore = eval(candSeq);\n            if (candScore > curScore) {\n                curScore = candScore;\n                curSeq = candSeq;\n                if (candScore > bestScore) {\n                    bestScore = candScore;\n                    bestSeq = candSeq;\n                }\n            }\n        }\n    }\n    \n    cout << bestSeq << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 30;\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int to_table[8][4] = {\n    {1, 0, -1, -1},  // 0: left<->up\n    {3, -1, -1, 0},  // 1: left<->down\n    {-1, -1, 3, 2},  // 2: right<->down\n    {-1, 2, 1, -1},  // 3: up<->right\n    {1, 0, 3, 2},    // 4: left<->up, right<->down\n    {3, 2, 1, 0},    // 5: left<->down, up<->right\n    {2, -1, 0, -1},  // 6: left<->right\n    {-1, 3, -1, 1}   // 7: up<->down\n};\n\nint tile_type[N][N];\nint rot[N][N];\nint best_rot[N][N];\nint global_best_score = 0;\n\nint get_exit(int type, int r, int dir) {\n    if (to_table[type][dir] == -1) return -1;\n    return (to_table[type][dir] + r) % 4;\n}\n\nint node_id[N][N][4];\nint node_cnt;\nint mate[3600];\n\nvoid clear_graph() { fill(mate, mate + node_cnt, -1); }\nvoid add_edge(int u, int v) { mate[u] = v; mate[v] = u; }\nvoid remove_edge(int u) {\n    int v = mate[u];\n    if (v != -1) { mate[v] = -1; mate[u] = -1; }\n}\n\nvoid build_graph() {\n    clear_graph();\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 ex = get_exit(tile_type[i][j], rot[i][j], d);\n                if (ex == -1) continue;\n                int ni = i + di[ex], nj = j + dj[ex];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nd = (ex + 2) % 4;\n                int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                if (ex2 == d) {\n                    int u = node_id[i][j][d];\n                    int v = node_id[ni][nj][ex];\n                    if (mate[u] == -1 && mate[v] == -1) {\n                        add_edge(u, v);\n                    }\n                }\n            }\n        }\n    }\n}\n\nbool vis[3600];\nint comp_id[3600];\nint comp_len[3600];\nint comp_cnt;\n\nvoid find_cycles() {\n    fill(vis, vis + node_cnt, false);\n    fill(comp_id, comp_id + node_cnt, -1);\n    comp_cnt = 0;\n    for (int i = 0; i < node_cnt; i++) {\n        if (vis[i] || mate[i] == -1) continue;\n        int cur = i;\n        vector<int> path;\n        while (!vis[cur]) {\n            vis[cur] = true;\n            path.push_back(cur);\n            if (mate[cur] == -1) break;\n            cur = mate[cur];\n            if (vis[cur]) break;\n        }\n        if (path.size() >= 2 && mate[path.back()] == path[0]) {\n            for (int x : path) comp_id[x] = comp_cnt;\n            comp_len[comp_cnt] = path.size();\n            comp_cnt++;\n        } else {\n            for (int x : path) comp_id[x] = -2;\n        }\n    }\n}\n\nint get_score() {\n    find_cycles();\n    if (comp_cnt < 2) return 0;\n    int l1 = 0, l2 = 0;\n    for (int c = 0; c < comp_cnt; c++) {\n        int len = comp_len[c];\n        if (len > l1) { l2 = l1; l1 = len; }\n        else if (len > l2) { l2 = len; }\n    }\n    return l1 * l2;\n}\n\nvoid apply_rot(int i, int j, int new_r) {\n    int old_r = rot[i][j];\n    for (int d = 0; d < 4; d++) {\n        int ex = get_exit(tile_type[i][j], old_r, d);\n        if (ex != -1) {\n            int ni = i + di[ex], nj = j + dj[ex];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int u = node_id[i][j][d];\n                if (mate[u] != -1) remove_edge(u);\n            }\n        }\n    }\n    rot[i][j] = new_r;\n    for (int d = 0; d < 4; d++) {\n        int ex = get_exit(tile_type[i][j], new_r, d);\n        if (ex != -1) {\n            int ni = i + di[ex], nj = j + dj[ex];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int nd = (ex + 2) % 4;\n                int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                if (ex2 == d) {\n                    int u = node_id[i][j][d];\n                    int v = node_id[ni][nj][ex];\n                    if (mate[u] == -1 && mate[v] == -1) {\n                        add_edge(u, v);\n                    }\n                }\n            }\n        }\n    }\n}\n\nint count_conn(int i, int j, int r) {\n    int cnt = 0;\n    for (int d = 0; d < 4; d++) {\n        int ex = get_exit(tile_type[i][j], r, d);\n        if (ex == -1) continue;\n        int ni = i + di[ex], nj = j + dj[ex];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n        int nd = (ex + 2) % 4;\n        int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n        if (ex2 == d) cnt++;\n    }\n    return cnt;\n}\n\n// Check if a tile with given rotation connects in direction d\nbool connects(int i, int j, int r, int d) {\n    int ex = get_exit(tile_type[i][j], r, d);\n    if (ex == -1) return false;\n    int ni = i + di[ex], nj = j + dj[ex];\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    int nd = (ex + 2) % 4;\n    int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n    return ex2 == d;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = high_resolution_clock::now();\n    \n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++)\n            tile_type[i][j] = s[j] - '0';\n    }\n    \n    node_cnt = 0;\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                node_id[i][j][d] = node_cnt++;\n    \n    mt19937 rng(42);\n    uniform_real_distribution<> prob(0, 1);\n    uniform_int_distribution<> pos(0, N-1);\n    uniform_int_distribution<> rdelta(1, 3);\n    \n    auto do_greedy_pass = [&](int passes) {\n        for (int pass = 0; pass < passes; pass++) {\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    int best_r = rot[i][j];\n                    int best_c = count_conn(i, j, rot[i][j]);\n                    for (int r = 0; r < 4; r++) {\n                        int c = count_conn(i, j, r);\n                        if (c > best_c) { best_c = c; best_r = r; }\n                    }\n                    rot[i][j] = best_r;\n                }\n            }\n        }\n    };\n    \n    auto run_sa = [&](int max_iter, double temp_start, double alpha) -> int {\n        double temp = temp_start;\n        int cur_score = get_score();\n        int best_local = cur_score;\n        int best_local_rot[N][N];\n        memcpy(best_local_rot, rot, sizeof(rot));\n        \n        for (int iter = 0; iter < max_iter; iter++) {\n            auto now = high_resolution_clock::now();\n            if (duration_cast<milliseconds>(now - start).count() > 1950) break;\n            \n            int num_tiles = (temp > 3.0 && prob(rng) < 0.25) ? 2 : 1;\n            vector<tuple<int,int,int>> changes;\n            for (int t = 0; t < num_tiles; t++) {\n                int i = pos(rng), j = pos(rng);\n                int old_r = rot[i][j];\n                int new_r = (old_r + rdelta(rng)) % 4;\n                apply_rot(i, j, new_r);\n                changes.push_back({i, j, old_r});\n            }\n            \n            int ns = get_score();\n            \n            if (ns >= cur_score || (temp > 0.01 && prob(rng) < exp((ns - cur_score) / temp))) {\n                cur_score = ns;\n                if (ns > best_local) {\n                    best_local = ns;\n                    memcpy(best_local_rot, rot, sizeof(rot));\n                }\n            } else {\n                for (auto &[i, j, old_r] : changes) {\n                    apply_rot(i, j, old_r);\n                }\n            }\n            temp *= alpha;\n        }\n        memcpy(rot, best_local_rot, sizeof(rot));\n        return best_local;\n    };\n    \n    // Try multiple strategies\n    vector<tuple<int,int,int>> results; // (score, seed, strategy)\n    \n    // Strategy 1: Pure random + greedy + SA\n    {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                rot[i][j] = rng() % 4;\n        do_greedy_pass(3);\n        build_graph();\n        int s = run_sa(30000, 10.0, 0.9999);\n        if (s > global_best_score) {\n            global_best_score = s;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n    \n    // Strategy 2: Prefer horizontal straight lines + SA\n    {\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int t = tile_type[i][j];\n                if (t == 6) rot[i][j] = 0; // horizontal\n                else if (t == 7) rot[i][j] = 1; // vertical\n                else rot[i][j] = rng() % 4;\n            }\n        }\n        do_greedy_pass(3);\n        build_graph();\n        int s = run_sa(30000, 10.0, 0.9999);\n        if (s > global_best_score) {\n            global_best_score = s;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n    \n    // Strategy 3: Try to maximize initial cycle size by growing from seeds\n    {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                rot[i][j] = rng() % 4;\n        \n        // Repeatedly improve by scanning all tiles\n        for (int sweep = 0; sweep < 5; sweep++) {\n            build_graph();\n            // Target: try to make the largest cycle even larger\n            find_cycles();\n            if (comp_cnt == 0) break;\n            \n            // Find the largest cycle\n            int best_c = 0;\n            for (int c = 1; c < comp_cnt; c++)\n                if (comp_len[c] > comp_len[best_c]) best_c = c;\n            \n            // Try flipping tiles adjacent to this cycle to grow it\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    // Check if this tile touches the best cycle\n                    bool touches = false;\n                    for (int d = 0; d < 4; d++) {\n                        int u = node_id[i][j][d];\n                        if (mate[u] != -1 && comp_id[mate[u]] == best_c) {\n                            touches = true; break;\n                        }\n                    }\n                    if (!touches) continue;\n                    \n                    int best_r = rot[i][j];\n                    int best_s = get_score();\n                    for (int r = 0; r < 4; r++) {\n                        if (r == rot[i][j]) continue;\n                        apply_rot(i, j, r);\n                        int s = get_score();\n                        if (s > best_s) { best_s = s; best_r = r; }\n                        apply_rot(i, j, rot[i][j]);\n                    }\n                    apply_rot(i, j, best_r);\n                }\n            }\n        }\n        build_graph();\n        int s = run_sa(20000, 5.0, 0.9999);\n        if (s > global_best_score) {\n            global_best_score = s;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n    \n    // Strategy 4: More aggressive SA with restarts\n    {\n        for (int restart = 0; restart < 3; restart++) {\n            auto now = high_resolution_clock::now();\n            if (duration_cast<milliseconds>(now - start).count() > 1800) break;\n            \n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    rot[i][j] = rng() % 4;\n            \n            do_greedy_pass(3);\n            build_graph();\n            int s = run_sa(40000, 8.0, 0.99995);\n            if (s > global_best_score) {\n                global_best_score = s;\n                memcpy(best_rot, rot, sizeof(rot));\n            }\n        }\n    }\n    \n    // Output best\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cout << best_rot[i][j];\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 10;\nint N, T;\nint empty_r, empty_c;\nvector<string> board;\n\nconst int dr[] = {0, -1, 0, 1};\nconst int dc[] = {-1, 0, 1, 0};\nconst char dir_char[] = {'L', 'U', 'R', 'D'};\nconst int bit[] = {1, 2, 4, 8};\n\nauto start_time = chrono::steady_clock::now();\n\nbool in_board(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nint tile_val(char c) {\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return c - '0';\n}\n\nbool has_line(char tile, int d) {\n    return (tile_val(tile) & bit[d]) != 0;\n}\n\nbool is_connected(const vector<string>& b, int r1, int c1, int r2, int c2) {\n    if (!in_board(r1, c1) || !in_board(r2, c2)) return false;\n    if (b[r1][c1] == '0' || b[r2][c2] == '0') return false;\n    if (r1 == r2 && c1 + 1 == c2) {\n        return has_line(b[r1][c1], 2) && has_line(b[r2][c2], 0);\n    }\n    if (r1 == r2 && c1 - 1 == c2) {\n        return has_line(b[r1][c1], 0) && has_line(b[r2][c2], 2);\n    }\n    if (r1 + 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 3) && has_line(b[r2][c2], 1);\n    }\n    if (r1 - 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 1) && has_line(b[r2][c2], 3);\n    }\n    return false;\n}\n\nstruct BoardInfo {\n    int max_tree = 0;\n    int num_trees = 0;\n    int potential = 0;\n};\n\nBoardInfo analyze(const vector<string>& b) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    BoardInfo info;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] == '0' || vis[i][j]) continue;\n            \n            queue<pair<int,int>> q;\n            q.push({i, j});\n            vis[i][j] = true;\n            int edges = 0;\n            int nodes = 0;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front(); q.pop();\n                nodes++;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (in_board(nr, nc) && b[nr][nc] != '0') {\n                        if (is_connected(b, r, c, nr, nc)) {\n                            edges++;\n                            if (!vis[nr][nc]) {\n                                vis[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        } else {\n                            if (has_line(b[r][c], d)) info.potential++;\n                        }\n                    }\n                }\n            }\n            \n            edges /= 2;\n            if (edges == nodes - 1) {\n                info.num_trees++;\n                if (nodes > info.max_tree) info.max_tree = nodes;\n            }\n        }\n    }\n    \n    return info;\n}\n\nint evaluate(const vector<string>& b) {\n    auto info = analyze(b);\n    return info.max_tree * 100000 + (N * N - 1 - info.num_trees) * 1000 + info.potential * 100;\n}\n\n// Beam search that returns the best sequence found within max_depth\nstring beam_search(vector<string> b, int er, int ec, int max_depth, int beam_width) {\n    struct State {\n        vector<string> b;\n        int er, ec;\n        string moves;\n        int eval;\n    };\n    \n    vector<State> beam;\n    beam.reserve(beam_width);\n    int init_eval = evaluate(b);\n    beam.push_back({b, er, ec, \"\", init_eval});\n    \n    int best_eval = init_eval;\n    string best_moves;\n    \n    // Track seen states to avoid cycles\n    unordered_set<string> seen;\n    string h;\n    for (int i = 0; i < N; i++) h += b[i];\n    seen.insert(h);\n    \n    for (int depth = 0; depth < max_depth; depth++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2900) break;\n        \n        vector<State> next_states;\n        next_states.reserve(beam.size() * 3);\n        \n        for (const auto& s : beam) {\n            for (int d = 0; d < 4; d++) {\n                int nr = s.er + dr[d];\n                int nc = s.ec + dc[d];\n                if (!in_board(nr, nc)) continue;\n                \n                // Avoid immediate undo\n                if (!s.moves.empty()) {\n                    char last = s.moves.back();\n                    if ((last == 'L' && d == 2) || (last == 'R' && d == 0) ||\n                        (last == 'U' && d == 3) || (last == 'D' && d == 1)) {\n                        continue;\n                    }\n                }\n                \n                // Check for 2-step cycles (A->B->A)\n                if (s.moves.length() >= 3) {\n                    int len = s.moves.length();\n                    char m1 = s.moves[len-1], m2 = s.moves[len-2], m3 = s.moves[len-3];\n                    int d1 = (m1 == 'L') ? 0 : (m1 == 'U') ? 1 : (m1 == 'R') ? 2 : 3;\n                    int d2 = (m2 == 'L') ? 0 : (m2 == 'U') ? 1 : (m2 == 'R') ? 2 : 3;\n                    int d3 = (m3 == 'L') ? 0 : (m3 == 'U') ? 1 : (m3 == 'R') ? 2 : 3;\n                    // Avoid A->B->C->A pattern\n                    if (d == d1 || d == d2) {\n                        // Might be cycling, check more carefully\n                        if (d == d3) continue;\n                    }\n                }\n                \n                vector<string> nb = s.b;\n                swap(nb[s.er][s.ec], nb[nr][nc]);\n                \n                string nh;\n                for (int i = 0; i < N; i++) nh += nb[i];\n                \n                if (seen.count(nh)) continue;\n                seen.insert(nh);\n                \n                int neval = evaluate(nb);\n                string nmoves = s.moves + dir_char[d];\n                \n                if (neval > best_eval) {\n                    best_eval = neval;\n                    best_moves = nmoves;\n                    \n                    auto info = analyze(nb);\n                    if (info.max_tree == N * N - 1) return best_moves;\n                }\n                \n                next_states.push_back({move(nb), nr, nc, move(nmoves), neval});\n            }\n        }\n        \n        if (next_states.empty()) break;\n        \n        // Keep top beam_width states\n        if ((int)next_states.size() > beam_width) {\n            nth_element(next_states.begin(), \n                       next_states.begin() + beam_width, \n                       next_states.end(),\n                       [](const State& a, const State& b) { return a.eval > b.eval; });\n            next_states.resize(beam_width);\n        }\n        \n        beam = move(next_states);\n    }\n    \n    return best_moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0') {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    start_time = chrono::steady_clock::now();\n    \n    string all_moves;\n    int current_best = evaluate(board);\n    int rounds_without_improvement = 0;\n    \n    // Adaptive beam search with strict move limit\n    for (int round = 0; round < 15; round++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2800) break;\n        \n        // STRICT check: don't exceed T\n        if ((int)all_moves.length() >= T) break;\n        \n        int remaining = T - (int)all_moves.length();\n        if (remaining <= 2) break;\n        \n        // Adaptive parameters\n        int depth = min(60 + round * 15, remaining);\n        int width = min(80 + round * 15, 200);\n        \n        string new_moves = beam_search(board, empty_r, empty_c, depth, width);\n        \n        if (new_moves.empty() || new_moves.length() == 0) {\n            rounds_without_improvement++;\n            if (rounds_without_improvement > 3) break;\n            continue;\n        }\n        \n        // STRICT: truncate if would exceed T\n        if ((int)all_moves.length() + (int)new_moves.length() > T) {\n            int allowed = T - (int)all_moves.length();\n            new_moves = new_moves.substr(0, allowed);\n        }\n        \n        if (new_moves.empty()) break;\n        \n        // Apply the moves\n        int new_eval = 0;\n        for (char c : new_moves) {\n            int d = (c == 'L') ? 0 : (c == 'U') ? 1 : (c == 'R') ? 2 : 3;\n            int nr = empty_r + dr[d];\n            int nc = empty_c + dc[d];\n            if (!in_board(nr, nc)) {\n                cerr << \"Invalid move!\" << endl;\n                break;\n            }\n            swap(board[empty_r][empty_c], board[nr][nc]);\n            empty_r = nr;\n            empty_c = nc;\n            all_moves += c;\n        }\n        \n        new_eval = evaluate(board);\n        \n        if (new_eval > current_best) {\n            current_best = new_eval;\n            rounds_without_improvement = 0;\n        } else {\n            rounds_without_improvement++;\n        }\n        \n        auto info = analyze(board);\n        if (info.max_tree == N * N - 1) break;\n    }\n    \n    // Final deep search with remaining moves\n    int remaining = T - (int)all_moves.length();\n    if (remaining > 10) {\n        auto info = analyze(board);\n        if (info.max_tree < N * N - 1) {\n            int final_depth = min(remaining, 300);\n            int final_width = min(250, remaining * 2);\n            \n            string new_moves = beam_search(board, empty_r, empty_c, final_depth, final_width);\n            \n            if (!new_moves.empty()) {\n                // Truncate if needed\n                if ((int)all_moves.length() + (int)new_moves.length() > T) {\n                    new_moves = new_moves.substr(0, T - (int)all_moves.length());\n                }\n                \n                for (char c : new_moves) {\n                    int d = (c == 'L') ? 0 : (c == 'U') ? 1 : (c == 'R') ? 2 : 3;\n                    int nr = empty_r + dr[d];\n                    int nc = empty_c + dc[d];\n                    if (!in_board(nr, nc)) break;\n                    swap(board[empty_r][empty_c], board[nr][nc]);\n                    empty_r = nr;\n                    empty_c = nc;\n                    all_moves += c;\n                }\n            }\n        }\n    }\n    \n    // Final safety: ensure we don't exceed T\n    if ((int)all_moves.length() > T) {\n        all_moves = all_moves.substr(0, T);\n    }\n    \n    cout << all_moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\ntypedef long long ll;\n\nstruct Point {\n    ll x, y;\n    Point(ll x = 0, ll y = 0) : x(x), y(y) {}\n    \n    Point operator-(const Point& other) const {\n        return Point(x - other.x, y - other.y);\n    }\n    \n    ll cross(const Point& other) const {\n        return x * other.y - y * other.x;\n    }\n};\n\n// Check which side of line p1->p2 a point p lies on\nint side(const Point& p1, const Point& p2, const Point& p) {\n    ll val = (p2 - p1).cross(p - p1);\n    if (val > 0) return 1;\n    if (val < 0) return -1;\n    return 0;\n}\n\n// Count strawberries in each piece given a set of lines\nvector<int> countPieces(const vector<Point>& strawberries,\n                        const vector<pair<pair<ll, ll>, pair<ll, ll>>>& lines) {\n    int M = strawberries.size();\n    int L = lines.size();\n    \n    if (L == 0) {\n        return {M};\n    }\n    \n    // For each strawberry, determine which side of each line it's on\n    map<vector<int>, int> piece_counts;\n    \n    for (int i = 0; i < M; i++) {\n        const Point& straw = strawberries[i];\n        vector<int> signature(L);\n        bool on_line = false;\n        \n        for (int j = 0; j < L; j++) {\n            Point p1(lines[j].first.first, lines[j].first.second);\n            Point p2(lines[j].second.first, lines[j].second.second);\n            int s = side(p1, p2, straw);\n            if (s == 0) {\n                on_line = true;\n                break;\n            }\n            signature[j] = (s > 0) ? 1 : 0;\n        }\n        \n        if (!on_line) {\n            piece_counts[signature]++;\n        }\n    }\n    \n    vector<int> counts;\n    for (const auto& [sig, cnt] : piece_counts) {\n        if (cnt > 0) {\n            counts.push_back(cnt);\n        }\n    }\n    \n    return counts;\n}\n\n// Calculate matched pieces\nint calculateMatched(const vector<int>& piece_counts, const vector<int>& demands) {\n    vector<int> available(10, 0);\n    for (int cnt : piece_counts) {\n        if (cnt >= 1 && cnt <= 10) {\n            available[cnt - 1]++;\n        }\n    }\n    \n    int matched = 0;\n    for (int i = 0; i < 10; i++) {\n        matched += min(available[i], demands[i]);\n    }\n    return matched;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    const double time_limit = 2.9;\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> demands(10);\n    int total_demand = 0;\n    for (int i = 0; i < 10; i++) {\n        cin >> demands[i];\n        total_demand += demands[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Best configuration found\n    vector<pair<pair<ll, ll>, pair<ll, ll>>> best_lines;\n    int best_matched = 0;\n    \n    // Random number generator\n    mt19937 rng(12345);\n    \n    int iteration = 0;\n    \n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed >= time_limit) break;\n        \n        // Generate a candidate solution\n        vector<pair<pair<ll, ll>, pair<ll, ll>>> lines;\n        \n        // Strategy: Mix radial lines with random separators\n        int num_radial = min(60, K / 2 + uniform_int_distribution<int>(0, 20)(rng));\n        double angle_start = uniform_real_distribution<double>(0, 2 * M_PI)(rng);\n        \n        // Add radial lines through origin\n        for (int i = 0; i < num_radial && (int)lines.size() < K; i++) {\n            double angle = angle_start + 2.0 * M_PI * i / num_radial;\n            ll x1 = (ll)(500000000.0 * cos(angle));\n            ll y1 = (ll)(500000000.0 * sin(angle));\n            ll x2 = -x1;\n            ll y2 = -y1;\n            \n            if (x1 == x2 && y1 == y2) x2 = x1 + 1;\n            lines.push_back({{x1, y1}, {x2, y2}});\n        }\n        \n        // Add some lines that separate pairs of strawberries\n        if (N >= 2) {\n            int num_sep = min(K - (int)lines.size(), 30);\n            for (int i = 0; i < num_sep; i++) {\n                int a = uniform_int_distribution<int>(0, N-1)(rng);\n                int b = uniform_int_distribution<int>(0, N-1)(rng);\n                \n                if (a != b) {\n                    const Point& p1 = strawberries[a];\n                    const Point& p2 = strawberries[b];\n                    \n                    // Midpoint\n                    double mx = (p1.x + p2.x) / 2.0;\n                    double my = (p1.y + p2.y) / 2.0;\n                    \n                    // Perpendicular direction\n                    double dx = (double)(p2.y - p1.y);\n                    double dy = (double)(p1.x - p2.x);\n                    double len = sqrt(dx*dx + dy*dy);\n                    \n                    if (len > 0) {\n                        dx = dx / len * 15000.0;\n                        dy = dy / len * 15000.0;\n                        \n                        ll px = (ll)round(mx - dx);\n                        ll py = (ll)round(my - dy);\n                        ll qx = (ll)round(mx + dx);\n                        ll qy = (ll)round(my + dy);\n                        \n                        // Clamp to valid range\n                        auto clamp = [](ll& v) {\n                            v = max(-1000000000LL, min(1000000000LL, v));\n                        };\n                        clamp(px); clamp(py); clamp(qx); clamp(qy);\n                        \n                        if (px != qx || py != qy) {\n                            lines.push_back({{px, py}, {qx, qy}});\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Fill remaining with random offset radial-like lines\n        while ((int)lines.size() < K) {\n            double angle = uniform_real_distribution<double>(0, 2 * M_PI)(rng);\n            double offset = uniform_real_distribution<double>(-5000, 5000)(rng);\n            \n            ll x1 = (ll)(500000000.0 * cos(angle) + offset * cos(angle + M_PI/2));\n            ll y1 = (ll)(500000000.0 * sin(angle) + offset * sin(angle + M_PI/2));\n            ll x2 = (ll)(-500000000.0 * cos(angle) + offset * cos(angle + M_PI/2));\n            ll y2 = (ll)(-500000000.0 * sin(angle) + offset * sin(angle + M_PI/2));\n            \n            auto clamp = [](ll& v) {\n                v = max(-1000000000LL, min(1000000000LL, v));\n            };\n            clamp(x1); clamp(y1); clamp(x2); clamp(y2);\n            \n            if (x1 != x2 || y1 != y2) {\n                lines.push_back({{x1, y1}, {x2, y2}});\n            } else {\n                lines.push_back({{x1, y1}, {x1+1, y1}});\n            }\n        }\n        \n        // Evaluate\n        vector<int> piece_counts = countPieces(strawberries, lines);\n        int matched = calculateMatched(piece_counts, demands);\n        \n        if (matched > best_matched) {\n            best_matched = matched;\n            best_lines = lines;\n        }\n        \n        iteration++;\n    }\n    \n    // Final output\n    if ((int)best_lines.size() > K) {\n        best_lines.resize(K);\n    }\n    \n    cout << best_lines.size() << '\\n';\n    for (const auto& line : best_lines) {\n        cout << line.first.first << ' ' << line.first.second << ' '\n             << line.second.first << ' ' << line.second.second << '\\n';\n    }\n    \n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing P = pair<int,int>;\n\nint N, M, C;\nP initial_arr[1500];\nint dot_grid[65][65];\nvector<pair<P,P>> segment_list;\nvector<array<P,4>> operations;\n\nll weight(int x, int y) {\n    return (ll)(x-C)*(x-C) + (ll)(y-C)*(y-C) + 1;\n}\n\nbool in_grid(int x, int y) {\n    return (unsigned)x < (unsigned)N && (unsigned)y < (unsigned)N;\n}\n\nbool segments_overlap(P a1, P a2, P b1, P b2) {\n    ll cross = (ll)(a2.first - a1.first) * (b2.second - b1.second) - \n               (ll)(a2.second - a1.second) * (b2.first - b1.first);\n    if (cross != 0) return false;\n    \n    ll cross2 = (ll)(b1.first - a1.first) * (a2.second - a1.second) - \n                (ll)(b1.second - a1.second) * (a2.first - a1.first);\n    if (cross2 != 0) return false;\n    \n    ll dir_x = a2.first - a1.first;\n    ll dir_y = a2.second - a1.second;\n    \n    auto project = [&](P p) -> ll {\n        return (ll)(p.first - a1.first) * dir_x + (ll)(p.second - a1.second) * dir_y;\n    };\n    \n    ll t1 = 0, t2 = project(a2);\n    ll s1 = project(b1), s2 = project(b2);\n    if (t1 > t2) swap(t1, t2);\n    if (s1 > s2) swap(s1, s2);\n    \n    return max(t1, s1) < min(t2, s2);\n}\n\nbool would_overlap(P a, P b) {\n    for (auto &seg : segment_list) {\n        if (segments_overlap(a, b, seg.first, seg.second))\n            return true;\n    }\n    return false;\n}\n\nbool clear_path_fast(P a, P b, int ax1, int ay1, int ax2, int ay2, int ax3, int ay3) {\n    int dx = b.first - a.first;\n    int dy = b.second - a.second;\n    int g = gcd(abs(dx), abs(dy));\n    int sx = dx / g;\n    int sy = dy / g;\n    \n    int cx = a.first + sx;\n    int cy = a.second + sy;\n    for (int i = 1; i < g; i++) {\n        if (dot_grid[cx][cy]) {\n            if (!((cx == ax1 && cy == ay1) ||\n                  (cx == ax2 && cy == ay2) ||\n                  (cx == ax3 && cy == ay3)))\n                return false;\n        }\n        cx += sx;\n        cy += sy;\n    }\n    return true;\n}\n\nvoid add_segments(P p1, P p2, P p3, P p4) {\n    segment_list.emplace_back(p1, p2);\n    segment_list.emplace_back(p2, p3);\n    segment_list.emplace_back(p3, p4);\n    segment_list.emplace_back(p4, p1);\n}\n\nbool try_add_rect(P p1) {\n    int x = p1.first, y = p1.second;\n    if (dot_grid[x][y]) return false;\n    \n    // Try axis-aligned rectangles\n    for (int dx = 1; dx <= min(N, 15); dx++) {\n        for (int dy = 1; dy <= min(N, 15); dy++) {\n            // Orientation 1: p1 bottom-left\n            {\n                int p2x = x+dx, p2y = y;\n                int p3x = x+dx, p3y = y+dy;\n                int p4x = x, p4y = y+dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n            // Orientation 2: p1 bottom-right\n            {\n                int p2x = x-dx, p2y = y;\n                int p3x = x-dx, p3y = y+dy;\n                int p4x = x, p4y = y+dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n            // Orientation 3: p1 top-right\n            {\n                int p2x = x-dx, p2y = y;\n                int p3x = x-dx, p3y = y-dy;\n                int p4x = x, p4y = y-dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n            // Orientation 4: p1 top-left\n            {\n                int p2x = x+dx, p2y = y;\n                int p3x = x+dx, p3y = y-dy;\n                int p4x = x, p4y = y-dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Try 45-degree rotated squares\n    for (int d = 1; d <= min(N/2, 8); d++) {\n        vector<array<P,4>> diags = {\n            {{{x,y}, {x+d,y+d}, {x,y+2*d}, {x-d,y+d}}},\n            {{{x,y}, {x+d,y-d}, {x+2*d,y}, {x+d,y+d}}},\n            {{{x,y}, {x-d,y-d}, {x,y-2*d}, {x+d,y-d}}},\n            {{{x,y}, {x-d,y+d}, {x-2*d,y}, {x-d,y-d}}}\n        };\n        \n        for (auto &r : diags) {\n            bool ok = true;\n            for (auto &p : r) {\n                if (!in_grid(p.first, p.second)) { ok = false; break; }\n            }\n            if (!ok) continue;\n            \n            int p2x=r[1].first, p2y=r[1].second;\n            int p3x=r[2].first, p3y=r[2].second;\n            int p4x=r[3].first, p4y=r[3].second;\n            \n            if (!dot_grid[p2x][p2y] || !dot_grid[p3x][p3y] || !dot_grid[p4x][p4y]) continue;\n            \n            if (clear_path_fast(r[0], r[1], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                clear_path_fast(r[1], r[2], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                clear_path_fast(r[2], r[3], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                clear_path_fast(r[3], r[0], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                !would_overlap(r[0], r[1]) &&\n                !would_overlap(r[1], r[2]) &&\n                !would_overlap(r[2], r[3]) &&\n                !would_overlap(r[3], r[0])) {\n                \n                operations.push_back(r);\n                dot_grid[x][y] = 1;\n                add_segments(r[0], r[1], r[2], r[3]);\n                return true;\n            }\n        }\n    }\n    \n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.9;\n    \n    cin >> N >> M;\n    C = (N-1)/2;\n    \n    memset(dot_grid, 0, sizeof(dot_grid));\n    for (int i = 0; i < M; i++) {\n        int x, y; cin >> x >> y;\n        initial_arr[i] = {x,y};\n        dot_grid[x][y] = 1;\n    }\n    \n    // Precompute candidates sorted by weight\n    vector<P> candidates;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            if (!dot_grid[x][y]) {\n                candidates.push_back({x,y});\n            }\n        }\n    }\n    \n    sort(candidates.begin(), candidates.end(), [](P a, P b) {\n        return weight(a.first, a.second) > weight(b.first, b.second);\n    });\n    \n    // Main greedy loop\n    bool progress = true;\n    int check_cnt = 0;\n    while (progress) {\n        progress = false;\n        \n        for (auto &p : candidates) {\n            if (++check_cnt % 100 == 0) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - start_time).count();\n                if (elapsed > TIME_LIMIT) goto output_result;\n            }\n            \n            if (dot_grid[p.first][p.second]) continue;\n            \n            if (try_add_rect(p)) {\n                progress = true;\n                break;\n            }\n        }\n    }\n    \noutput_result:\n    cout << operations.size() << \"\\n\";\n    for (auto &op : operations) {\n        cout << op[0].first << \" \" << op[0].second << \" \"\n             << op[1].first << \" \" << op[1].second << \" \"\n             << op[2].first << \" \" << op[2].second << \" \"\n             << op[3].first << \" \" << op[3].second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\nconst int TOTAL = 100;\n\nint grid[N][N];\nint flavor[TOTAL];\nint total_count[4] = {0};\nint placed_count[4] = {0};\nchar dc[4] = {'L', 'R', 'F', 'B'};\n\nvoid tilt(int g[N][N], int d) {\n    if (d == 0) {\n        for (int i = 0; i < N; i++) {\n            int p = 0;\n            for (int j = 0; j < N; j++) if (g[i][j]) g[i][p++] = g[i][j];\n            while (p < N) g[i][p++] = 0;\n        }\n    } else if (d == 1) {\n        for (int i = 0; i < N; i++) {\n            int p = N-1;\n            for (int j = N-1; j >= 0; j--) if (g[i][j]) g[i][p--] = g[i][j];\n            while (p >= 0) g[i][p--] = 0;\n        }\n    } else if (d == 2) {\n        for (int j = 0; j < N; j++) {\n            int p = 0;\n            for (int i = 0; i < N; i++) if (g[i][j]) g[p++][j] = g[i][j];\n            while (p < N) g[p++][j] = 0;\n        }\n    } else {\n        for (int j = 0; j < N; j++) {\n            int p = N-1;\n            for (int i = N-1; i >= 0; i--) if (g[i][j]) g[p--][j] = g[i][j];\n            while (p >= 0) g[p--][j] = 0;\n        }\n    }\n}\n\nint64_t evaluate(int g[N][N]) {\n    bool vis[N][N] = {};\n    int64_t res = 0;\n    int qx[100], qy[100];\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!g[i][j] || vis[i][j]) continue;\n            int f = g[i][j], cnt = 0, h = 0, t = 0;\n            qx[0] = i; qy[0] = j;\n            vis[i][j] = true;\n            while (h <= t) {\n                int x = qx[h], y = qy[h]; h++; cnt++;\n                if (x > 0 && !vis[x-1][y] && g[x-1][y] == f)\n                    vis[x-1][y] = true, qx[++t] = x-1, qy[t] = y;\n                if (x < N-1 && !vis[x+1][y] && g[x+1][y] == f)\n                    vis[x+1][y] = true, qx[++t] = x+1, qy[t] = y;\n                if (y > 0 && !vis[x][y-1] && g[x][y-1] == f)\n                    vis[x][y-1] = true, qx[++t] = x, qy[t] = y-1;\n                if (y < N-1 && !vis[x][y+1] && g[x][y+1] == f)\n                    vis[x][y+1] = true, qx[++t] = x, qy[t] = y+1;\n            }\n            res += 1LL * cnt * cnt;\n        }\n    }\n    return res;\n}\n\n// Enhanced evaluation with awareness of remaining flavors\nint64_t evaluate_enhanced(int g[N][N], int step) {\n    int64_t base = evaluate(g);\n    \n    // Count remaining flavors\n    int rem[4] = {0};\n    for (int i = step + 1; i < TOTAL; i++) {\n        rem[flavor[i]]++;\n    }\n    \n    // For each flavor, find largest cluster and add potential bonus\n    // This encourages maintaining large clusters that can absorb future pieces\n    int64_t bonus = 0;\n    \n    bool vis[N][N] = {};\n    int qx[100], qy[100];\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!g[i][j] || vis[i][j]) continue;\n            \n            int f = g[i][j], cnt = 0, h = 0, t = 0;\n            qx[0] = i; qy[0] = j;\n            vis[i][j] = true;\n            \n            // Count empty neighbors (potential connection points)\n            int empty_neighbors = 0;\n            \n            while (h <= t) {\n                int x = qx[h], y = qy[h]; h++; cnt++;\n                \n                for (int k = 0; k < 4; k++) {\n                    int nx = x + (k == 2 ? -1 : k == 3 ? 1 : 0);\n                    int ny = y + (k == 0 ? -1 : k == 1 ? 1 : 0);\n                    \n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        if (!g[nx][ny]) {\n                            empty_neighbors++;\n                        } else if (!vis[nx][ny] && g[nx][ny] == f) {\n                            vis[nx][ny] = true;\n                            qx[++t] = nx;\n                            qy[t] = ny;\n                        }\n                    }\n                }\n            }\n            \n            // Bonus: potential to add remaining pieces of this flavor\n            if (rem[f] > 0 && empty_neighbors > 0) {\n                // If cluster has room to grow, it can absorb future pieces\n                int64_t potential_size = min(cnt + rem[f], cnt + empty_neighbors);\n                bonus += potential_size * potential_size - 1LL * cnt * cnt;\n            }\n        }\n    }\n    \n    return base + bonus / 2; // Conservative bonus\n}\n\nint64_t rollout(int g[N][N], int step, int depth, vector<int>& pos_indices, int& idx) {\n    int tmp[N][N];\n    memcpy(tmp, g, sizeof(tmp));\n    \n    int look = min(depth, TOTAL - step - 1);\n    \n    for (int k = 0; k < look; k++) {\n        if (idx >= (int)pos_indices.size()) break;\n        \n        int f = flavor[step + 1 + k];\n        int pos = pos_indices[idx++];\n        \n        int cnt = 0, r = 0, c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (!tmp[i][j] && ++cnt == pos) {\n                    r = i; c = j;\n                    i = N; break;\n                }\n            }\n        }\n        \n        tmp[r][c] = f;\n        \n        int best_d = 0;\n        int64_t best_sc = -1;\n        int tmp2[N][N];\n        \n        for (int d = 0; d < 4; d++) {\n            memcpy(tmp2, tmp, sizeof(tmp));\n            tilt(tmp2, d);\n            int64_t sc = evaluate(tmp2);\n            if (sc > best_sc) {\n                best_sc = sc;\n                best_d = d;\n            }\n        }\n        tilt(tmp, best_d);\n    }\n    \n    // Use enhanced evaluation for terminal state\n    return evaluate_enhanced(tmp, step + look);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < TOTAL; i++) {\n        cin >> flavor[i];\n        total_count[flavor[i]]++;\n    }\n    \n    memset(grid, 0, sizeof(grid));\n    memset(placed_count, 0, sizeof(placed_count));\n    \n    mt19937 rng(12345);\n    \n    for (int step = 0; step < TOTAL; step++) {\n        int p; cin >> p;\n        \n        int cnt = 0, r = 0, c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (!grid[i][j] && ++cnt == p) {\n                    r = i; c = j;\n                    i = N; break;\n                }\n            }\n        }\n        \n        int f = flavor[step];\n        placed_count[f]++;\n        grid[r][c] = f;\n        \n        int old_grid[N][N];\n        memcpy(old_grid, grid, sizeof(grid));\n        \n        int remaining = TOTAL - step - 1;\n        int num_sims, look_depth;\n        \n        // Slightly increased simulations\n        if (remaining >= 70) {\n            num_sims = 28; look_depth = 14;\n        } else if (remaining >= 50) {\n            num_sims = 24; look_depth = 12;\n        } else if (remaining >= 30) {\n            num_sims = 20; look_depth = 10;\n        } else if (remaining >= 15) {\n            num_sims = 15; look_depth = 7;\n        } else if (remaining >= 5) {\n            num_sims = 10; look_depth = min(5, remaining);\n        } else {\n            num_sims = 6; look_depth = remaining;\n        }\n        \n        vector<vector<int>> sim_positions(num_sims);\n        for (int s = 0; s < num_sims; s++) {\n            for (int k = 0; k < look_depth; k++) {\n                int empties = remaining - k;\n                if (empties <= 0) break;\n                uniform_int_distribution<int> dist(1, empties);\n                sim_positions[s].push_back(dist(rng));\n            }\n        }\n        \n        int best_d = 0;\n        int64_t best_score = -1;\n        \n        for (int d = 0; d < 4; d++) {\n            int tmp[N][N];\n            memcpy(tmp, old_grid, sizeof(tmp));\n            tilt(tmp, d);\n            \n            int64_t base_score = evaluate(tmp);\n            int64_t sim_total = 0;\n            int64_t sim_min = 1LL << 60;\n            int64_t sim_max = 0;\n            \n            for (int s = 0; s < num_sims; s++) {\n                int idx = 0;\n                int64_t sim_score = rollout(tmp, step, look_depth, sim_positions[s], idx);\n                sim_total += sim_score;\n                sim_min = min(sim_min, sim_score);\n                sim_max = max(sim_max, sim_score);\n            }\n            \n            int64_t avg_sim = sim_total / num_sims;\n            \n            // Enhanced weighting: consider variance\n            // If simulations are consistently better, trust them more\n            double future_weight = min(0.8, remaining / 100.0);\n            \n            // If min simulation score is already better than base, this direction is very promising\n            if (sim_min > base_score) {\n                future_weight *= 1.2; // Boost weight when all simulations agree it's better\n            }\n            \n            int64_t combined = base_score + (int64_t)((avg_sim - base_score) * future_weight);\n            \n            if (combined > best_score) {\n                best_score = combined;\n                best_d = d;\n            }\n        }\n        \n        memcpy(grid, old_grid, sizeof(old_grid));\n        tilt(grid, best_d);\n        cout << dc[best_d] << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nvector<int> get_degrees(const string& g, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            idx++;\n        }\n    }\n    return deg;\n}\n\nint count_edges(const string& g) {\n    int cnt = 0;\n    for (char c : g) if (c == '1') cnt++;\n    return cnt;\n}\n\n// Generate graphs - simplified and guaranteed fast\nvector<string> generate_graphs(int N, int M, double eps) {\n    int total_pairs = N * (N - 1) / 2;\n    vector<string> graphs;\n    mt19937 gen(42);\n    \n    // For N <= 6, enumerate all unique degree sequences\n    if (N <= 6) {\n        int max_mask = 1 << total_pairs;\n        set<vector<int>> seen_degs;\n        vector<pair<string, vector<int>>> candidates;\n        \n        for (int mask = 0; mask < max_mask; mask++) {\n            string g;\n            for (int i = 0; i < total_pairs; i++) {\n                g += ((mask >> i) & 1) ? '1' : '0';\n            }\n            auto deg = get_degrees(g, N);\n            sort(deg.begin(), deg.end());\n            \n            if (seen_degs.insert(deg).second) {\n                candidates.push_back({g, deg});\n            }\n        }\n        \n        // Greedy selection of M most diverse candidates\n        vector<bool> selected(candidates.size(), false);\n        \n        for (int k = 0; k < M && k < (int)candidates.size(); k++) {\n            int best_idx = -1;\n            int best_min_dist = -1;\n            \n            for (int i = 0; i < (int)candidates.size(); i++) {\n                if (selected[i]) continue;\n                \n                int min_dist = 1e9;\n                for (int j = 0; j < (int)candidates.size(); j++) {\n                    if (!selected[j]) continue;\n                    int dist = 0;\n                    for (int d = 0; d < N; d++)\n                        dist += abs(candidates[i].second[d] - candidates[j].second[d]);\n                    min_dist = min(min_dist, dist);\n                }\n                \n                if (graphs.empty() || min_dist > best_min_dist) {\n                    best_min_dist = min_dist;\n                    best_idx = i;\n                }\n            }\n            \n            if (best_idx >= 0) {\n                graphs.push_back(candidates[best_idx].first);\n                selected[best_idx] = true;\n            }\n        }\n        \n        // If we still need more graphs, duplicate with random edge flips\n        // But with a limit to prevent infinite loops\n        int attempts = 0;\n        while ((int)graphs.size() < M && attempts < 10000) {\n            int base = gen() % graphs.size();\n            string g = graphs[base];\n            // Flip some edges\n            int flips = max(1, total_pairs / 10);\n            for (int f = 0; f < flips; f++) {\n                int pos = gen() % total_pairs;\n                g[pos] = (g[pos] == '0') ? '1' : '0';\n            }\n            graphs.push_back(g);\n            attempts++;\n        }\n        \n        // Last resort: just copy existing graphs\n        while ((int)graphs.size() < M) {\n            graphs.push_back(graphs[gen() % graphs.size()]);\n        }\n        \n        return graphs;\n    }\n    \n    // For N >= 7: generate directly without enumeration\n    for (int k = 0; k < M; k++) {\n        double density = 0.15 + 0.7 * k / max(1, M - 1);\n        int target_edges = (int)(density * total_pairs);\n        \n        vector<vector<int>> adj(N, vector<int>(N, 0));\n        int edges_added = 0;\n        \n        // Create a list of all possible edges and shuffle\n        vector<pair<int,int>> edges;\n        for (int i = 0; i < N; i++)\n            for (int j = i+1; j < N; j++)\n                edges.push_back({i, j});\n        \n        mt19937 local_gen(gen() + k);\n        shuffle(edges.begin(), edges.end(), local_gen);\n        \n        for (auto [i, j] : edges) {\n            if (edges_added >= target_edges) break;\n            adj[i][j] = adj[j][i] = 1;\n            edges_added++;\n        }\n        \n        string g;\n        for (int i = 0; i < N; i++)\n            for (int j = i+1; j < N; j++)\n                g += (adj[i][j] ? '1' : '0');\n        graphs.push_back(g);\n    }\n    \n    return graphs;\n}\n\n// Fast prediction\nint predict(const string& H, const vector<string>& graphs, int N, double eps) {\n    auto H_deg = get_degrees(H, N);\n    sort(H_deg.begin(), H_deg.end());\n    int H_edges = count_edges(H);\n    \n    int total_pairs = N * (N - 1) / 2;\n    double p = eps, q = 1 - eps;\n    double var_edges = total_pairs * p * q;\n    \n    int best_k = 0;\n    double best_ll = -1e9;\n    \n    for (int k = 0; k < (int)graphs.size(); k++) {\n        auto G_deg = get_degrees(graphs[k], N);\n        sort(G_deg.begin(), G_deg.end());\n        int G_edges = count_edges(graphs[k]);\n        \n        // Edge log-likelihood\n        double exp_edges = G_edges * q + (total_pairs - G_edges) * p;\n        double edge_ll = -0.5 * pow(H_edges - exp_edges, 2) / var_edges;\n        \n        // Degree L1 distance\n        double l1 = 0;\n        for (int i = 0; i < N; i++) l1 += abs(H_deg[i] - G_deg[i]);\n        double exp_l1 = 2 * total_pairs * p;\n        double var_l1 = 4 * var_edges;\n        double l1_ll = -0.5 * pow(max(0.0, l1 - exp_l1), 2) / var_l1;\n        \n        double ll = edge_ll * 2.0 + l1_ll;\n        \n        if (ll > best_ll) {\n            best_ll = ll;\n            best_k = k;\n        }\n    }\n    \n    return best_k;\n}\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 N\n    int N;\n    if (eps <= 0.1) {\n        if (M <= 11) N = 4;\n        else if (M <= 34) N = 5;\n        else N = 6;\n    } else if (eps <= 0.2) {\n        if (M <= 11) N = 5;\n        else if (M <= 34) N = 6;\n        else if (M <= 80) N = 7;\n        else N = 8;\n    } else if (eps <= 0.3) {\n        if (M <= 20) N = 6;\n        else if (M <= 60) N = 8;\n        else N = 10;\n    } else {\n        if (M <= 30) N = 8;\n        else if (M <= 60) N = 12;\n        else N = 16;\n    }\n    \n    N = max(4, min(100, N));\n    \n    auto graphs = generate_graphs(N, M, eps);\n    \n    // Output\n    cout << N << '\\n';\n    for (const auto& g : graphs) cout << g << '\\n';\n    cout.flush();\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n        int t = predict(H, graphs, N, eps);\n        cout << t << '\\n';\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = 1e18;\nconst long long PENALTY = 1e9;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nchrono::steady_clock::time_point start_time;\n\nlong long elapsed_ms() {\n    return chrono::duration_cast<chrono::milliseconds>(\n        chrono::steady_clock::now() - start_time).count();\n}\n\nclass DSU {\n    vector<int> parent, sz;\npublic:\n    DSU(int n) : parent(n), sz(n, 1) {\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 (sz[x] < sz[y]) swap(x, y);\n        parent[y] = x;\n        sz[x] += sz[y];\n        return true;\n    }\n};\n\nbool is_connected(int N, const vector<Edge>& edges, const vector<bool>& removed) {\n    DSU dsu(N);\n    int comps = N;\n    for (const auto& e : edges) {\n        if (!removed[e.id]) {\n            if (dsu.unite(e.u, e.v)) {\n                comps--;\n                if (comps == 1) return true;\n            }\n        }\n    }\n    return comps == 1;\n}\n\nvector<long long> dijkstra(int src, int N, const vector<vector<pair<int,int>>>& adj,\n                            const vector<Edge>& edges) {\n    vector<long long> dist(N, INF);\n    dist[src] = 0;\n    priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n    pq.push({0, src});\n    \n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, eid] : adj[u]) {\n            long long nd = d + edges[eid].w;\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                pq.push({nd, v});\n            }\n        }\n    }\n    return dist;\n}\n\nvector<vector<pair<int,int>>> build_adj(int N, const vector<Edge>& edges, \n                                         const vector<bool>& removed) {\n    vector<vector<pair<int,int>>> adj(N);\n    for (const auto& e : edges) {\n        if (!removed[e.id]) {\n            adj[e.u].push_back({e.v, e.id});\n            adj[e.v].push_back({e.u, e.id});\n        }\n    }\n    return adj;\n}\n\n// Fast frustration estimate using very sparse sampling\ndouble fast_frustration(int N, const vector<vector<pair<int,int>>>& adj,\n                        const vector<Edge>& edges,\n                        const vector<vector<long long>>& orig_dist,\n                        int step) {\n    double total = 0;\n    long long cnt = 0;\n    \n    for (int src = 0; src < N; src += step) {\n        auto dist = dijkstra(src, N, adj, edges);\n        for (int dst = src + 1; dst < N; dst += step) {\n            long long dk = min(PENALTY, dist[dst]);\n            total += max(0LL, dk - orig_dist[src][dst]);\n            cnt++;\n        }\n    }\n    return cnt > 0 ? total / cnt : 0;\n}\n\n// Proxy for frustration: sum of importance of removed edges (faster to compute)\ndouble frustration_proxy(const vector<bool>& removed, const vector<double>& imp) {\n    double sum = 0;\n    for (int i = 0; i < (int)removed.size(); i++) {\n        if (removed[i]) sum += imp[i];\n    }\n    return sum;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::steady_clock::now();\n    srand(42);\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>>> full_adj(N);\n    \n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        full_adj[edges[i].u].push_back({edges[i].v, i});\n        full_adj[edges[i].v].push_back({edges[i].u, i});\n    }\n    \n    for (int i = 0; i < N; i++) {\n        int x, y; cin >> x >> y;\n    }\n    \n    // Compute original distances (this is necessary and we have time for it)\n    vector<vector<long long>> orig_dist(N, vector<long long>(N, INF));\n    for (int src = 0; src < N; src++) {\n        orig_dist[src] = dijkstra(src, N, full_adj, edges);\n    }\n    \n    // Compute edge importance\n    vector<double> importance(M, 0.0);\n    int num_samples = min(N, 200);\n    \n    for (int si = 0; si < num_samples; si++) {\n        int src = (si * N) / num_samples;\n        \n        vector<long long> dist(N, INF);\n        vector<long long> cnt(N, 0);\n        vector<vector<int>> incoming(N);\n        \n        dist[src] = 0;\n        cnt[src] = 1;\n        \n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        \n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            \n            for (auto [v, eid] : full_adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    cnt[v] = cnt[u];\n                    incoming[v] = {eid};\n                    pq.push({nd, v});\n                } else if (nd == dist[v]) {\n                    cnt[v] += cnt[u];\n                    incoming[v].push_back(eid);\n                }\n            }\n        }\n        \n        vector<double> score(N, 1.0);\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        \n        for (int u : order) {\n            if (dist[u] >= INF) continue;\n            for (int eid : incoming[u]) {\n                int v = (edges[eid].u == u) ? edges[eid].v : edges[eid].u;\n                if (dist[v] + edges[eid].w == dist[u]) {\n                    double contrib = score[u] * (double)cnt[v] / cnt[u];\n                    importance[eid] += contrib;\n                    score[v] += contrib;\n                }\n            }\n        }\n    }\n    \n    // Normalize importance\n    double max_imp = *max_element(importance.begin(), importance.end());\n    if (max_imp > 0) {\n        for (auto& imp : importance) imp /= max_imp;\n    }\n    \n    // Second importance: weight based\n    vector<int> deg(N, 0);\n    for (const auto& e : edges) {\n        deg[e.u]++; deg[e.v]++;\n    }\n    \n    vector<double> imp2(M);\n    for (const auto& e : edges) {\n        imp2[e.id] = (double)e.w / ((double)deg[e.u] * deg[e.v]);\n    }\n    max_imp = *max_element(imp2.begin(), imp2.end());\n    if (max_imp > 0) for (auto& x : imp2) x /= max_imp;\n    \n    vector<double> combined_imp(M);\n    for (int i = 0; i < M; i++) {\n        combined_imp[i] = 0.75 * importance[i] + 0.25 * imp2[i];\n    }\n    \n    // Construction: greedy with connectivity\n    auto construct = [&]() -> pair<vector<int>, vector<double>> {\n        vector<int> assignment(M, -1);\n        vector<int> day_count(D, 0);\n        vector<vector<bool>> day_removed(D, vector<bool>(M, false));\n        vector<double> day_imp(D, 0.0);\n        int target = (M + D - 1) / D;\n        \n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return combined_imp[a] > combined_imp[b];\n        });\n        \n        for (int eid : order) {\n            int best_d = -1;\n            double best_score = -1e18;\n            \n            vector<int> days(D);\n            iota(days.begin(), days.end(), 0);\n            \n            for (int d : days) {\n                if (day_count[d] >= K) continue;\n                \n                day_removed[d][eid] = true;\n                bool ok = is_connected(N, edges, day_removed[d]);\n                day_removed[d][eid] = false;\n                \n                if (!ok) continue;\n                \n                double overload = max(0, day_count[d] + 1 - target);\n                double score = -(day_imp[d] + combined_imp[eid]) - overload * 50;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_d = d;\n                }\n            }\n            \n            if (best_d == -1) {\n                for (int d : days) {\n                    if (day_count[d] < K) { best_d = d; break; }\n                }\n            }\n            \n            assignment[eid] = best_d;\n            day_removed[best_d][eid] = true;\n            day_count[best_d]++;\n            day_imp[best_d] += combined_imp[eid];\n        }\n        \n        // Fix any disconnections by moving edges\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int d = 0; d < D; d++) {\n                if (is_connected(N, edges, day_removed[d])) continue;\n                \n                vector<int> day_edges;\n                for (int i = 0; i < M; i++) {\n                    if (assignment[i] == d) day_edges.push_back(i);\n                }\n                sort(day_edges.begin(), day_edges.end(), [&](int a, int b) {\n                    return combined_imp[a] < combined_imp[b];\n                });\n                \n                for (int eid : day_edges) {\n                    for (int d2 = 0; d2 < D; d2++) {\n                        if (d2 == d || day_count[d2] >= K) continue;\n                        \n                        day_removed[d][eid] = false;\n                        day_removed[d2][eid] = true;\n                        \n                        if (is_connected(N, edges, day_removed[d]) && \n                            is_connected(N, edges, day_removed[d2])) {\n                            assignment[eid] = d2;\n                            day_count[d]--; day_count[d2]++;\n                            day_imp[d] -= combined_imp[eid];\n                            day_imp[d2] += combined_imp[eid];\n                            changed = true;\n                            break;\n                        } else {\n                            day_removed[d][eid] = true;\n                            day_removed[d2][eid] = false;\n                        }\n                    }\n                    if (is_connected(N, edges, day_removed[d])) break;\n                }\n            }\n        }\n        \n        return {assignment, day_imp};\n    };\n    \n    auto [assignment, day_imp] = construct();\n    \n    // Build state\n    vector<vector<bool>> day_removed(D, vector<bool>(M, false));\n    vector<int> day_count(D, 0);\n    for (int i = 0; i < M; i++) {\n        day_removed[assignment[i]][i] = true;\n        day_count[assignment[i]]++;\n    }\n    \n    // Compute initial frustrations\n    vector<vector<vector<pair<int,int>>>> day_adj(D);\n    int step = (N <= 600) ? 3 : (N <= 800) ? 4 : 5;\n    for (int d = 0; d < D; d++) {\n        day_adj[d] = build_adj(N, edges, day_removed[d]);\n    }\n    \n    vector<double> frustrations(D);\n    for (int d = 0; d < D; d++) {\n        frustrations[d] = fast_frustration(N, day_adj[d], edges, orig_dist, step);\n    }\n    \n    double current_avg = accumulate(frustrations.begin(), frustrations.end(), 0.0) / D;\n    double best_avg = current_avg;\n    vector<int> best_assignment = assignment;\n    \n    // Simulated annealing with strict time budgeting\n    double temp = 50.0;\n    long long iter = 0;\n    long long max_time = 5700; // Leave 300ms for output\n    int same_best = 0;\n    \n    while (elapsed_ms() < max_time) {\n        // Batch of iterations\n        int batch_size = 20;\n        for (int b = 0; b < batch_size && elapsed_ms() < max_time; b++) {\n            iter++;\n            \n            // Cool temperature\n            if (iter % 100 == 0) {\n                temp *= 0.998;\n                if (temp < 0.005) temp = 0.005;\n            }\n            \n            // If no improvement for a while, increase exploration\n            if (same_best > 5000) {\n                temp = min(temp * 2, 100.0);\n                same_best = 0;\n            }\n            \n            int op = rand() % 10;\n            \n            if (op < 8) {\n                // Swap\n                int e1 = rand() % M;\n                int e2 = rand() % M;\n                int d1 = assignment[e1];\n                int d2 = assignment[e2];\n                \n                if (d1 == d2) continue;\n                \n                day_removed[d1][e1] = false;\n                day_removed[d1][e2] = true;\n                day_removed[d2][e2] = false;\n                day_removed[d2][e1] = true;\n                \n                bool ok = is_connected(N, edges, day_removed[d1]) && \n                         is_connected(N, edges, day_removed[d2]);\n                \n                if (!ok) {\n                    day_removed[d1][e1] = true;\n                    day_removed[d1][e2] = false;\n                    day_removed[d2][e2] = true;\n                    day_removed[d2][e1] = false;\n                    continue;\n                }\n                \n                auto adj1 = build_adj(N, edges, day_removed[d1]);\n                auto adj2 = build_adj(N, edges, day_removed[d2]);\n                \n                double f1 = fast_frustration(N, adj1, edges, orig_dist, step);\n                double f2 = fast_frustration(N, adj2, edges, orig_dist, step);\n                \n                double new_avg = current_avg + (f1 - frustrations[d1] + f2 - frustrations[d2]) / D;\n                double delta = new_avg - current_avg;\n                \n                if (delta < 0 || exp(-delta / max(1e-9, temp)) > (double)rand() / RAND_MAX) {\n                    assignment[e1] = d2;\n                    assignment[e2] = d1;\n                    frustrations[d1] = f1;\n                    frustrations[d2] = f2;\n                    current_avg = new_avg;\n                    day_adj[d1] = move(adj1);\n                    day_adj[d2] = move(adj2);\n                    \n                    if (current_avg < best_avg) {\n                        best_avg = current_avg;\n                        best_assignment = assignment;\n                        same_best = 0;\n                    } else {\n                        same_best++;\n                    }\n                } else {\n                    day_removed[d1][e1] = true;\n                    day_removed[d1][e2] = false;\n                    day_removed[d2][e2] = true;\n                    day_removed[d2][e1] = false;\n                    same_best++;\n                }\n            } else {\n                // Move\n                int e = rand() % M;\n                int d1 = assignment[e];\n                int d2 = rand() % D;\n                \n                if (d1 == d2 || day_count[d2] >= K) continue;\n                \n                day_removed[d1][e] = false;\n                day_removed[d2][e] = true;\n                \n                bool ok = is_connected(N, edges, day_removed[d1]) && \n                         is_connected(N, edges, day_removed[d2]);\n                \n                if (!ok) {\n                    day_removed[d1][e] = true;\n                    day_removed[d2][e] = false;\n                    continue;\n                }\n                \n                auto adj1 = build_adj(N, edges, day_removed[d1]);\n                auto adj2 = build_adj(N, edges, day_removed[d2]);\n                \n                double f1 = fast_frustration(N, adj1, edges, orig_dist, step);\n                double f2 = fast_frustration(N, adj2, edges, orig_dist, step);\n                \n                double new_avg = current_avg + (f1 - frustrations[d1] + f2 - frustrations[d2]) / D;\n                double delta = new_avg - current_avg;\n                \n                if (delta < 0 || exp(-delta / max(1e-9, temp)) > (double)rand() / RAND_MAX) {\n                    assignment[e] = d2;\n                    frustrations[d1] = f1;\n                    frustrations[d2] = f2;\n                    current_avg = new_avg;\n                    day_count[d1]--;\n                    day_count[d2]++;\n                    day_adj[d1] = move(adj1);\n                    day_adj[d2] = move(adj2);\n                    \n                    if (current_avg < best_avg) {\n                        best_avg = current_avg;\n                        best_assignment = assignment;\n                        same_best = 0;\n                    } else {\n                        same_best++;\n                    }\n                } else {\n                    day_removed[d1][e] = true;\n                    day_removed[d2][e] = false;\n                    same_best++;\n                }\n            }\n        }\n    }\n    \n    // Output best found\n    for (int i = 0; i < M; i++) {\n        if (i > 0) cout << \" \";\n        cout << best_assignment[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct FastBitset {\n    static constexpr int N = 2744;\n    static constexpr int CHUNKS = (N + 63) / 64;\n    uint64_t bits[CHUNKS]{};\n    FastBitset() { clear(); }\n    void clear() { memset(bits, 0, sizeof bits); }\n    void set(int i) { bits[i>>6] |= 1ULL << (i&63); }\n    void reset(int i) { bits[i>>6] &= ~(1ULL << (i&63)); }\n    bool test(int i) const { return (bits[i>>6] >> (i&63)) & 1ULL; }\n    int count() const {\n        int c = 0;\n        for (int i = 0; i < CHUNKS; ++i) c += __builtin_popcountll(bits[i]);\n        return c;\n    }\n    FastBitset operator&(const FastBitset& o) const {\n        FastBitset r;\n        for (int i = 0; i < CHUNKS; ++i) r.bits[i] = bits[i] & o.bits[i];\n        return r;\n    }\n    template<typename F>\n    void forEachSetBit(F f) const {\n        for (int i = 0; i < CHUNKS; ++i) {\n            uint64_t w = bits[i];\n            while (w) {\n                int j = __builtin_ctzll(w);\n                f((i << 6) | j);\n                w &= w - 1;\n            }\n        }\n    }\n};\n\nint D, D2, D3;\nvector<vector<int>> adj;\n\ninline int encode(int x, int y, int z) { return x*D2 + y*D + z; }\ninline tuple<int,int,int> decode(int idx) {\n    int z = idx % D;\n    int y = (idx / D) % D;\n    int x = idx / D2;\n    return {x,y,z};\n}\n\nvector<array<array<int,3>,3>> rots;\nvector<array<array<int,3>,3>> inv_rots;\n\nvoid generate_rotations() {\n    int perm[3] = {0,1,2};\n    do {\n        for (int s0 = -1; s0 <= 1; s0+=2)\n        for (int s1 = -1; s1 <= 1; s1+=2)\n        for (int s2 = -1; s2 <= 1; s2+=2) {\n            int sign = 1;\n            for (int i=0;i<3;i++) for (int j=i+1;j<3;j++) if (perm[i]>perm[j]) sign = -sign;\n            if (sign * s0 * s1 * s2 != 1) continue;\n            array<array<int,3>,3> mat = {{{0}}};\n            mat[0][perm[0]] = s0;\n            mat[1][perm[1]] = s1;\n            mat[2][perm[2]] = s2;\n            rots.push_back(mat);\n        }\n    } while (next_permutation(perm, perm+3));\n    for (auto& mat : rots) {\n        array<array<int,3>,3> inv = {{{0}}};\n        for (int i=0;i<3;i++) for (int j=0;j<3;j++) inv[j][i] = mat[i][j];\n        inv_rots.push_back(inv);\n    }\n}\n\nFastBitset rotate_bitset(const FastBitset& src, const array<array<int,3>,3>& mat) {\n    FastBitset dst;\n    src.forEachSetBit([&](int idx) {\n        auto [x,y,z] = decode(idx);\n        int nx = mat[0][0]*x + mat[0][1]*y + mat[0][2]*z;\n        int ny = mat[1][0]*x + mat[1][1]*y + mat[1][2]*z;\n        int nz = mat[2][0]*x + mat[2][1]*y + mat[2][2]*z;\n        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n            dst.set(encode(nx,ny,nz));\n        }\n    });\n    return dst;\n}\n\nint main() {\n    auto start_time = steady_clock::now();\n    auto get_ms = [&]() {\n        return duration_cast<milliseconds>(steady_clock::now() - start_time).count();\n    };\n\n    generate_rotations();\n\n    cin >> D;\n    D2 = D*D;\n    D3 = D*D*D;\n\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i=0; i<D; i++) cin >> f1[i];\n    for (int i=0; i<D; i++) cin >> r1[i];\n    for (int i=0; i<D; i++) cin >> f2[i];\n    for (int i=0; i<D; i++) cin >> r2[i];\n\n    adj.resize(D3);\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        int idx = encode(x,y,z);\n        if (x>0)   adj[idx].push_back(encode(x-1, y, z));\n        if (x<D-1) adj[idx].push_back(encode(x+1, y, z));\n        if (y>0)   adj[idx].push_back(encode(x, y-1, z));\n        if (y<D-1) adj[idx].push_back(encode(x, y+1, z));\n        if (z>0)   adj[idx].push_back(encode(x, y, z-1));\n        if (z<D-1) adj[idx].push_back(encode(x, y, z+1));\n    }\n\n    FastBitset A1, A2;\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        if (f1[z][x]=='1' && r1[z][y]=='1') A1.set(encode(x,y,z));\n        if (f2[z][x]=='1' && r2[z][y]=='1') A2.set(encode(x,y,z));\n    }\n\n    FastBitset available1 = A1, available2 = A2;\n    vector<int> b1(D3, 0), b2(D3, 0);\n    int block_id = 1;\n\n    vector unc1_f(D, vector<bool>(D, false));\n    vector unc1_r(D, vector<bool>(D, false));\n    vector unc2_f(D, vector<bool>(D, false));\n    vector unc2_r(D, vector<bool>(D, false));\n\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f1[z][x]=='1') unc1_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r1[z][y]=='1') unc1_r[z][y] = true;\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f2[z][x]=='1') unc2_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r2[z][y]=='1') unc2_r[z][y] = true;\n\n    auto count_new_lines = [&](const FastBitset& voxels, bool is_obj1) -> int {\n        int cnt = 0;\n        voxels.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            if (is_obj1) {\n                if (unc1_f[z][x]) cnt++;\n                if (unc1_r[z][y]) cnt++;\n            } else {\n                if (unc2_f[z][x]) cnt++;\n                if (unc2_r[z][y]) cnt++;\n            }\n        });\n        return cnt;\n    };\n\n    // ----- Phase 1: extract shared blocks covering new lines -----\n    while (get_ms() < 3500) {\n        int best_vol = 0;\n        int best_gain = 0;\n        FastBitset best_comp2, best_preimage1;\n        int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n        for (int r = 0; r < 24; ++r) {\n            FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n            int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n            bool any = false;\n            rot_avail1.forEachSetBit([&](int idx) {\n                auto [x,y,z] = decode(idx);\n                any = true;\n                min_x = std::min(min_x, x); max_x = std::max(max_x, x);\n                min_y = std::min(min_y, y); max_y = std::max(max_y, y);\n                min_z = std::min(min_z, z); max_z = std::max(max_z, z);\n            });\n            if (!any) continue;\n\n            int dx_min = -min_x, dx_max = D-1 - max_x;\n            int dy_min = -min_y, dy_max = D-1 - max_y;\n            int dz_min = -min_z, dz_max = D-1 - max_z;\n\n            for (int dx = dx_min; dx <= dx_max; ++dx) {\n                for (int dy = dy_min; dy <= dy_max; ++dy) {\n                    for (int dz = dz_min; dz <= dz_max; ++dz) {\n                        FastBitset overlap;\n                        rot_avail1.forEachSetBit([&](int idx) {\n                            auto [x,y,z] = decode(idx);\n                            int nx = x+dx, ny = y+dy, nz = z+dz;\n                            if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                int idx2 = encode(nx,ny,nz);\n                                if (available2.test(idx2)) overlap.set(idx2);\n                            }\n                        });\n                        if (overlap.count() <= best_vol) continue;\n\n                        FastBitset visited;\n                        overlap.forEachSetBit([&](int seed) {\n                            if (visited.test(seed)) return;\n                            queue<int> q;\n                            q.push(seed);\n                            visited.set(seed);\n                            FastBitset comp;\n                            comp.set(seed);\n                            int sz = 1;\n                            while (!q.empty()) {\n                                int cur = q.front(); q.pop();\n                                for (int nb : adj[cur]) {\n                                    if (overlap.test(nb) && !visited.test(nb)) {\n                                        visited.set(nb);\n                                        comp.set(nb);\n                                        sz++;\n                                        q.push(nb);\n                                    }\n                                }\n                            }\n                            if (sz > best_vol) {\n                                FastBitset preimage;\n                                comp.forEachSetBit([&](int idx2) {\n                                    auto [x2,y2,z2] = decode(idx2);\n                                    int sx = x2 - dx, sy = y2 - dy, sz2 = z2 - dz;\n                                    int ox = inv_rots[r][0][0]*sx + inv_rots[r][0][1]*sy + inv_rots[r][0][2]*sz2;\n                                    int oy = inv_rots[r][1][0]*sx + inv_rots[r][1][1]*sy + inv_rots[r][1][2]*sz2;\n                                    int oz = inv_rots[r][2][0]*sx + inv_rots[r][2][1]*sy + inv_rots[r][2][2]*sz2;\n                                    preimage.set(encode(ox,oy,oz));\n                                });\n                                int new_lines = count_new_lines(preimage, true) + count_new_lines(comp, false);\n                                if (new_lines > 0) {\n                                    int gain = sz + 100 * new_lines;\n                                    if (gain > best_gain) {\n                                        best_gain = gain;\n                                        best_vol = sz;\n                                        best_comp2 = comp;\n                                        best_preimage1 = preimage;\n                                        best_r = r;\n                                        best_dx = dx; best_dy = dy; best_dz = dz;\n                                    }\n                                }\n                            }\n                        });\n                    }\n                }\n            }\n        }\n        if (best_vol < 2) break; // allow size 2 blocks\n\n        // Expand the block\n        {\n            FastBitset &preimage1 = best_preimage1;\n            FastBitset &comp2 = best_comp2;\n            int r = best_r, dx = best_dx, dy = best_dy, dz = best_dz;\n            queue<int> q1, q2;\n            preimage1.forEachSetBit([&](int v) { q1.push(v); });\n            comp2.forEachSetBit([&](int v) { q2.push(v); });\n            while (!q1.empty()) {\n                int v1 = q1.front(); q1.pop();\n                int v2 = q2.front(); q2.pop();\n                for (int nb1 : adj[v1]) {\n                    if (available1.test(nb1) && !preimage1.test(nb1)) {\n                        auto [x,y,z] = decode(nb1);\n                        int nx = rots[r][0][0]*x + rots[r][0][1]*y + rots[r][0][2]*z + dx;\n                        int ny = rots[r][1][0]*x + rots[r][1][1]*y + rots[r][1][2]*z + dy;\n                        int nz = rots[r][2][0]*x + rots[r][2][1]*y + rots[r][2][2]*z + dz;\n                        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                            int nb2 = encode(nx,ny,nz);\n                            if (available2.test(nb2) && !comp2.test(nb2)) {\n                                preimage1.set(nb1);\n                                comp2.set(nb2);\n                                available1.reset(nb1);\n                                available2.reset(nb2);\n                                q1.push(nb1);\n                                q2.push(nb2);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        int bid = block_id++;\n        best_preimage1.forEachSetBit([&](int idx) {\n            b1[idx] = bid;\n            available1.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc1_f[z][x] = false;\n            unc1_r[z][y] = false;\n        });\n        best_comp2.forEachSetBit([&](int idx) {\n            b2[idx] = bid;\n            available2.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc2_f[z][x] = false;\n            unc2_r[z][y] = false;\n        });\n    }\n\n    // ----- Finalization: cover remaining lines with shared 1x1 blocks -----\n    vector<int> remaining_voxels1, remaining_voxels2;\n\n    auto pick_best_voxel = [&](FastBitset& avail, \n                                const vector<vector<bool>>& unc_f, \n                                const vector<vector<bool>>& unc_r) -> int {\n        int best_idx = -1, best_cnt = -1;\n        avail.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            int cnt = 0;\n            if (unc_f[z][x]) cnt++;\n            if (unc_r[z][y]) cnt++;\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_idx = idx;\n            }\n        });\n        return best_idx;\n    };\n\n    FastBitset avail1_copy = available1;\n    vector unc1_f_copy = unc1_f, unc1_r_copy = unc1_r;\n    while (true) {\n        int v = pick_best_voxel(avail1_copy, unc1_f_copy, unc1_r_copy);\n        if (v == -1) break;\n        auto [x,y,z] = decode(v);\n        if (!unc1_f_copy[z][x] && !unc1_r_copy[z][y]) break;\n        remaining_voxels1.push_back(v);\n        avail1_copy.reset(v);\n        unc1_f_copy[z][x] = false;\n        unc1_r_copy[z][y] = false;\n    }\n\n    FastBitset avail2_copy = available2;\n    vector unc2_f_copy = unc2_f, unc2_r_copy = unc2_r;\n    while (true) {\n        int v = pick_best_voxel(avail2_copy, unc2_f_copy, unc2_r_copy);\n        if (v == -1) break;\n        auto [x,y,z] = decode(v);\n        if (!unc2_f_copy[z][x] && !unc2_r_copy[z][y]) break;\n        remaining_voxels2.push_back(v);\n        avail2_copy.reset(v);\n        unc2_f_copy[z][x] = false;\n        unc2_r_copy[z][y] = false;\n    }\n\n    // Share 1x1 blocks between the two objects\n    while (!remaining_voxels1.empty() && !remaining_voxels2.empty()) {\n        int v1 = remaining_voxels1.back(); remaining_voxels1.pop_back();\n        int v2 = remaining_voxels2.back(); remaining_voxels2.pop_back();\n        int bid = block_id++;\n        b1[v1] = bid;\n        b2[v2] = bid;\n        available1.reset(v1);\n        available2.reset(v2);\n    }\n    for (int v : remaining_voxels1) {\n        int bid = block_id++;\n        b1[v] = bid;\n        available1.reset(v);\n    }\n    for (int v : remaining_voxels2) {\n        int bid = block_id++;\n        b2[v] = bid;\n        available2.reset(v);\n    }\n\n    // ----- Phase 3: Add extra shared blocks from remaining available voxels -----\n    while (get_ms() < 5500) {\n        int best_vol = 0;\n        FastBitset best_comp2, best_preimage1;\n        int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n        for (int r = 0; r < 24; ++r) {\n            FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n            int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n            bool any = false;\n            rot_avail1.forEachSetBit([&](int idx) {\n                auto [x,y,z] = decode(idx);\n                any = true;\n                min_x = std::min(min_x, x); max_x = std::max(max_x, x);\n                min_y = std::min(min_y, y); max_y = std::max(max_y, y);\n                min_z = std::min(min_z, z); max_z = std::max(max_z, z);\n            });\n            if (!any) continue;\n\n            int dx_min = -min_x, dx_max = D-1 - max_x;\n            int dy_min = -min_y, dy_max = D-1 - max_y;\n            int dz_min = -min_z, dz_max = D-1 - max_z;\n\n            for (int dx = dx_min; dx <= dx_max; ++dx) {\n                for (int dy = dy_min; dy <= dy_max; ++dy) {\n                    for (int dz = dz_min; dz <= dz_max; ++dz) {\n                        FastBitset overlap;\n                        rot_avail1.forEachSetBit([&](int idx) {\n                            auto [x,y,z] = decode(idx);\n                            int nx = x+dx, ny = y+dy, nz = z+dz;\n                            if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                int idx2 = encode(nx,ny,nz);\n                                if (available2.test(idx2)) overlap.set(idx2);\n                            }\n                        });\n                        if (overlap.count() <= best_vol) continue;\n\n                        FastBitset visited;\n                        overlap.forEachSetBit([&](int seed) {\n                            if (visited.test(seed)) return;\n                            queue<int> q;\n                            q.push(seed);\n                            visited.set(seed);\n                            FastBitset comp;\n                            comp.set(seed);\n                            int sz = 1;\n                            while (!q.empty()) {\n                                int cur = q.front(); q.pop();\n                                for (int nb : adj[cur]) {\n                                    if (overlap.test(nb) && !visited.test(nb)) {\n                                        visited.set(nb);\n                                        comp.set(nb);\n                                        sz++;\n                                        q.push(nb);\n                                    }\n                                }\n                            }\n                            if (sz > best_vol) {\n                                FastBitset preimage;\n                                comp.forEachSetBit([&](int idx2) {\n                                    auto [x2,y2,z2] = decode(idx2);\n                                    int sx = x2 - dx, sy = y2 - dy, sz2 = z2 - dz;\n                                    int ox = inv_rots[r][0][0]*sx + inv_rots[r][0][1]*sy + inv_rots[r][0][2]*sz2;\n                                    int oy = inv_rots[r][1][0]*sx + inv_rots[r][1][1]*sy + inv_rots[r][1][2]*sz2;\n                                    int oz = inv_rots[r][2][0]*sx + inv_rots[r][2][1]*sy + inv_rots[r][2][2]*sz2;\n                                    preimage.set(encode(ox,oy,oz));\n                                });\n                                best_vol = sz;\n                                best_comp2 = comp;\n                                best_preimage1 = preimage;\n                                best_r = r;\n                                best_dx = dx; best_dy = dy; best_dz = dz;\n                            }\n                        });\n                    }\n                }\n            }\n        }\n        if (best_vol < 2) break;\n\n        // Expand\n        {\n            FastBitset &preimage1 = best_preimage1;\n            FastBitset &comp2 = best_comp2;\n            int r = best_r, dx = best_dx, dy = best_dy, dz = best_dz;\n            queue<int> q1, q2;\n            preimage1.forEachSetBit([&](int v) { q1.push(v); });\n            comp2.forEachSetBit([&](int v) { q2.push(v); });\n            while (!q1.empty()) {\n                int v1 = q1.front(); q1.pop();\n                int v2 = q2.front(); q2.pop();\n                for (int nb1 : adj[v1]) {\n                    if (available1.test(nb1) && !preimage1.test(nb1)) {\n                        auto [x,y,z] = decode(nb1);\n                        int nx = rots[r][0][0]*x + rots[r][0][1]*y + rots[r][0][2]*z + dx;\n                        int ny = rots[r][1][0]*x + rots[r][1][1]*y + rots[r][1][2]*z + dy;\n                        int nz = rots[r][2][0]*x + rots[r][2][1]*y + rots[r][2][2]*z + dz;\n                        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                            int nb2 = encode(nx,ny,nz);\n                            if (available2.test(nb2) && !comp2.test(nb2)) {\n                                preimage1.set(nb1);\n                                comp2.set(nb2);\n                                available1.reset(nb1);\n                                available2.reset(nb2);\n                                q1.push(nb1);\n                                q2.push(nb2);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        int bid = block_id++;\n        best_preimage1.forEachSetBit([&](int idx) {\n            b1[idx] = bid;\n            available1.reset(idx);\n        });\n        best_comp2.forEachSetBit([&](int idx) {\n            b2[idx] = bid;\n            available2.reset(idx);\n        });\n    }\n\n    int n = block_id - 1;\n    cout << n << \"\\n\";\n    for (int i=0; i<D3; i++) cout << b1[i] << \" \\n\"[i==D3-1];\n    for (int i=0; i<D3; i++) cout << b2[i] << \" \\n\"[i==D3-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\n#define rep(i, a, b) for (int i = (a); i < (b); i++)\n#define all(x) begin(x), end(x)\n\nusing ll = long long;\nconst ll INF = 1e18;\nconst ll MAX_DIST_SQ = 5000LL * 5000LL;\n\nstruct Edge {\n    int u, v;\n    ll w;\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    vector<pair<int, int>> pos(N);\n    rep(i, 0, N) cin >> pos[i].first >> pos[i].second;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, ll>>> adj(N);\n    rep(j, 0, M) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n\n    vector<pair<int, int>> residents(K);\n    rep(k, 0, K) cin >> residents[k].first >> residents[k].second;\n\n    // All-pairs shortest paths\n    vector<vector<ll>> dist(N, vector<ll>(N, INF));\n    vector<vector<int>> parent(N, vector<int>(N, -1));\n    \n    rep(s, 0, N) {\n        dist[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[s][u]) continue;\n            for (auto [v, w] : adj[u]) {\n                if (dist[s][v] > d + w) {\n                    dist[s][v] = d + w;\n                    parent[s][v] = u;\n                    pq.push({dist[s][v], v});\n                }\n            }\n        }\n    }\n\n    // Precompute squared distances\n    vector<vector<ll>> stationToRes(N, vector<ll>(K));\n    rep(i, 0, N) rep(k, 0, K) {\n        ll dx = pos[i].first - residents[k].first;\n        ll dy = pos[i].second - residents[k].second;\n        stationToRes[i][k] = dx * dx + dy * dy;\n    }\n\n    // Coverable stations for each resident\n    vector<vector<int>> coverableStations(K);\n    rep(k, 0, K) rep(i, 0, N) {\n        if (stationToRes[i][k] <= MAX_DIST_SQ) {\n            coverableStations[k].push_back(i);\n        }\n    }\n\n    // Nearest station for each resident\n    vector<int> nearestStation(K, 0);\n    rep(k, 0, K) {\n        ll best = stationToRes[0][k];\n        nearestStation[k] = 0;\n        rep(i, 1, N) {\n            if (stationToRes[i][k] < best) {\n                best = stationToRes[i][k];\n                nearestStation[k] = i;\n            }\n        }\n    }\n\n    // Compute P_i\n    auto computeP = [&](const vector<bool>& active, const vector<int>& assign) {\n        vector<int> P(N, 0);\n        rep(i, 0, N) {\n            if (!active[i]) continue;\n            ll maxDistSq = 0;\n            rep(k, 0, K) if (assign[k] == i) {\n                maxDistSq = max(maxDistSq, stationToRes[i][k]);\n            }\n            ll Pi = (ll)ceil(sqrt(maxDistSq));\n            if (Pi > 5000) Pi = 5000;\n            P[i] = (int)Pi;\n        }\n        return P;\n    };\n\n    // Fast edge cost: connect active stations to vertex 1 via shortest paths\n    auto computeEdgeCost = [&](const vector<bool>& active) {\n        vector<bool> used(N, false);\n        used[0] = true;\n        ll cost = 0;\n        \n        vector<pair<ll, int>> actDist;\n        rep(i, 0, N) if (active[i]) actDist.push_back({dist[0][i], i});\n        sort(all(actDist));\n        \n        for (auto [d, v] : actDist) {\n            if (used[v]) continue;\n            int cur = v;\n            while (!used[cur]) {\n                used[cur] = true;\n                int p = parent[0][cur];\n                if (p == -1) break;\n                for (auto [nxt, w] : adj[cur]) {\n                    if (nxt == p) { cost += w; break; }\n                }\n                cur = p;\n            }\n        }\n        return cost;\n    };\n\n    auto totalCost = [&](const vector<bool>& active, const vector<int>& assign) {\n        auto P = computeP(active, assign);\n        ll powerCost = 0;\n        rep(i, 0, N) powerCost += (ll)P[i] * P[i];\n        return powerCost + computeEdgeCost(active);\n    };\n\n    // Build initial solution\n    vector<bool> active(N, false);\n    active[0] = true;\n    rep(k, 0, K) active[nearestStation[k]] = true;\n\n    vector<int> assign(K);\n    rep(k, 0, K) assign[k] = nearestStation[k];\n\n    ll currentCost = totalCost(active, assign);\n    auto bestActive = active;\n    auto bestAssign = assign;\n    ll bestCost = currentCost;\n\n    // Greedy descent: remove stations\n    auto tryRemoveStations = [&]() {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            vector<int> actList;\n            rep(i, 1, N) if (active[i]) actList.push_back(i);\n            \n            for (int i : actList) {\n                if (!active[i]) continue;\n                auto savedActive = active;\n                auto savedAssign = assign;\n                \n                active[i] = false;\n                bool possible = true;\n                rep(k, 0, K) {\n                    if (assign[k] == i) {\n                        ll bestDist = INF;\n                        int bestSt = -1;\n                        for (int j : coverableStations[k]) {\n                            if (active[j] && stationToRes[j][k] < bestDist) {\n                                bestDist = stationToRes[j][k];\n                                bestSt = j;\n                            }\n                        }\n                        if (bestSt == -1) { possible = false; break; }\n                        assign[k] = bestSt;\n                    }\n                }\n                \n                if (possible) {\n                    ll newCost = totalCost(active, assign);\n                    if (newCost < currentCost) {\n                        currentCost = newCost;\n                        improved = true;\n                    } else {\n                        active = savedActive;\n                        assign = savedAssign;\n                    }\n                } else {\n                    active = savedActive;\n                    assign = savedAssign;\n                }\n            }\n        }\n    };\n\n    // Greedy descent: merge stations\n    auto tryMergeStations = [&]() {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            vector<int> actList;\n            rep(i, 1, N) if (active[i]) actList.push_back(i);\n            if (actList.size() < 2) break;\n            \n            for (int idx1 = 0; idx1 < (int)actList.size() && !improved; idx1++) {\n                int i = actList[idx1];\n                if (!active[i]) continue;\n                for (int idx2 = idx1 + 1; idx2 < (int)actList.size() && !improved; idx2++) {\n                    int j = actList[idx2];\n                    if (!active[j]) continue;\n                    \n                    // Try i covers j\n                    {\n                        auto savedActive = active;\n                        auto savedAssign = assign;\n                        active[j] = false;\n                        bool possible = true;\n                        rep(k, 0, K) {\n                            if (assign[k] == j) {\n                                if (stationToRes[i][k] > MAX_DIST_SQ) { possible = false; break; }\n                                assign[k] = i;\n                            }\n                        }\n                        if (possible) {\n                            ll newCost = totalCost(active, assign);\n                            if (newCost < currentCost) {\n                                currentCost = newCost;\n                                improved = true;\n                                break;\n                            }\n                        }\n                        active = savedActive;\n                        assign = savedAssign;\n                    }\n                    \n                    // Try j covers i\n                    {\n                        auto savedActive = active;\n                        auto savedAssign = assign;\n                        active[i] = false;\n                        bool possible = true;\n                        rep(k, 0, K) {\n                            if (assign[k] == i) {\n                                if (stationToRes[j][k] > MAX_DIST_SQ) { possible = false; break; }\n                                assign[k] = j;\n                            }\n                        }\n                        if (possible) {\n                            ll newCost = totalCost(active, assign);\n                            if (newCost < currentCost) {\n                                currentCost = newCost;\n                                improved = true;\n                            }\n                        }\n                        if (!improved) {\n                            active = savedActive;\n                            assign = savedAssign;\n                        }\n                    }\n                }\n            }\n        }\n    };\n\n    // Greedy descent: fine-tune assignments\n    auto fineTuneAssignments = [&]() {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            rep(k, 0, K) {\n                int cur = assign[k];\n                ll curDist = stationToRes[cur][k];\n                \n                rep(i, 0, N) {\n                    if (active[i] && i != cur && stationToRes[i][k] < curDist) {\n                        auto savedAssign = assign;\n                        assign[k] = i;\n                        ll newCost = totalCost(active, assign);\n                        if (newCost < currentCost) {\n                            currentCost = newCost;\n                            improved = true;\n                            break;\n                        }\n                        assign = savedAssign;\n                    }\n                }\n                if (improved) break;\n            }\n        }\n    };\n\n    // Initial greedy optimization\n    tryRemoveStations();\n    tryMergeStations();\n    fineTuneAssignments();\n    bestActive = active;\n    bestAssign = assign;\n    bestCost = currentCost;\n\n    // Simulated annealing with controlled iterations\n    mt19937 rng(42);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n    \n    const int SA_ITERS = 8000;\n    \n    for (int iter = 0; iter < SA_ITERS; iter++) {\n        double progress = (double)iter / SA_ITERS;\n        double T = 1e6 * pow(1e-6, progress);\n        \n        int action = rng() % 4;\n        \n        if (action == 0) {\n            // Remove station\n            vector<int> candidates;\n            rep(i, 1, N) if (active[i]) candidates.push_back(i);\n            if (candidates.empty()) continue;\n            \n            int i = candidates[rng() % candidates.size()];\n            auto savedActive = active;\n            auto savedAssign = assign;\n            \n            active[i] = false;\n            bool possible = true;\n            rep(k, 0, K) {\n                if (assign[k] == i) {\n                    ll bestDist = INF;\n                    int bestSt = -1;\n                    for (int j : coverableStations[k]) {\n                        if (active[j] && stationToRes[j][k] < bestDist) {\n                            bestDist = stationToRes[j][k];\n                            bestSt = j;\n                        }\n                    }\n                    if (bestSt == -1) { possible = false; break; }\n                    assign[k] = bestSt;\n                }\n            }\n            \n            if (possible) {\n                ll newCost = totalCost(active, assign);\n                ll delta = newCost - currentCost;\n                if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                    currentCost = newCost;\n                    if (newCost < bestCost) {\n                        bestCost = newCost;\n                        bestActive = active;\n                        bestAssign = assign;\n                    }\n                } else {\n                    active = savedActive;\n                    assign = savedAssign;\n                }\n            } else {\n                active = savedActive;\n                assign = savedAssign;\n            }\n        } else if (action == 1) {\n            // Add station\n            vector<int> candidates;\n            rep(i, 1, N) if (!active[i]) candidates.push_back(i);\n            if (candidates.empty()) continue;\n            \n            int i = candidates[rng() % candidates.size()];\n            auto savedActive = active;\n            auto savedAssign = assign;\n            \n            active[i] = true;\n            rep(k, 0, K) {\n                if (stationToRes[i][k] < stationToRes[assign[k]][k]) {\n                    assign[k] = i;\n                }\n            }\n            \n            ll newCost = totalCost(active, assign);\n            ll delta = newCost - currentCost;\n            if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                currentCost = newCost;\n                if (newCost < bestCost) {\n                    bestCost = newCost;\n                    bestActive = active;\n                    bestAssign = assign;\n                }\n            } else {\n                active = savedActive;\n                assign = savedAssign;\n            }\n        } else if (action == 2) {\n            // Reassign resident\n            int k = rng() % K;\n            int cur = assign[k];\n            \n            vector<int> candidates;\n            rep(i, 0, N) {\n                if (active[i] && i != cur && stationToRes[i][k] <= MAX_DIST_SQ) {\n                    candidates.push_back(i);\n                }\n            }\n            if (candidates.empty()) continue;\n            \n            int i = candidates[rng() % candidates.size()];\n            auto savedAssign = assign;\n            assign[k] = i;\n            \n            ll newCost = totalCost(active, assign);\n            ll delta = newCost - currentCost;\n            if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                currentCost = newCost;\n                if (newCost < bestCost) {\n                    bestCost = newCost;\n                    bestActive = active;\n                    bestAssign = assign;\n                }\n            } else {\n                assign = savedAssign;\n            }\n        } else {\n            // Swap assignments of two residents\n            int k1 = rng() % K;\n            int k2 = rng() % K;\n            if (k1 == k2) continue;\n            \n            int a1 = assign[k1];\n            int a2 = assign[k2];\n            if (a1 == a2) continue;\n            if (stationToRes[a2][k1] > MAX_DIST_SQ || stationToRes[a1][k2] > MAX_DIST_SQ) continue;\n            \n            auto savedAssign = assign;\n            assign[k1] = a2;\n            assign[k2] = a1;\n            \n            ll newCost = totalCost(active, assign);\n            ll delta = newCost - currentCost;\n            if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                currentCost = newCost;\n                if (newCost < bestCost) {\n                    bestCost = newCost;\n                    bestActive = active;\n                    bestAssign = assign;\n                }\n            } else {\n                assign = savedAssign;\n            }\n        }\n    }\n\n    // Final polish on best\n    active = bestActive;\n    assign = bestAssign;\n    currentCost = bestCost;\n    tryRemoveStations();\n    tryMergeStations();\n    fineTuneAssignments();\n    \n    if (currentCost < bestCost) {\n        bestActive = active;\n        bestAssign = assign;\n        bestCost = currentCost;\n    }\n\n    // Final P\n    auto P = computeP(bestActive, bestAssign);\n\n    // Build edge set\n    vector<bool> used(N, false);\n    used[0] = true;\n    vector<int> onEdge(M, 0);\n    \n    vector<pair<ll, int>> actDist;\n    rep(i, 0, N) if (bestActive[i]) actDist.push_back({dist[0][i], i});\n    sort(all(actDist));\n    \n    for (auto [d, v] : actDist) {\n        if (used[v]) continue;\n        int cur = v;\n        while (!used[cur]) {\n            used[cur] = true;\n            int p = parent[0][cur];\n            if (p == -1) break;\n            for (int j = 0; j < M; j++) {\n                if ((edges[j].u == cur && edges[j].v == p) ||\n                    (edges[j].u == p && edges[j].v == cur)) {\n                    onEdge[j] = 1;\n                    break;\n                }\n            }\n            cur = p;\n        }\n    }\n\n    // Verify and fix connectivity\n    vector<bool> reachable(N, false);\n    reachable[0] = true;\n    function<void(int)> dfs = [&](int u) {\n        reachable[u] = true;\n        for (int j = 0; j < M; j++) {\n            if (onEdge[j]) {\n                int v = -1;\n                if (edges[j].u == u) v = edges[j].v;\n                else if (edges[j].v == u) v = edges[j].u;\n                if (v != -1 && !reachable[v]) dfs(v);\n            }\n        }\n    };\n    dfs(0);\n    \n    rep(i, 0, N) {\n        if (bestActive[i] && !reachable[i]) {\n            int cur = i;\n            while (!reachable[cur]) {\n                reachable[cur] = true;\n                int p = parent[0][cur];\n                if (p == -1) break;\n                for (int j = 0; j < M; j++) {\n                    if ((edges[j].u == cur && edges[j].v == p) ||\n                        (edges[j].u == p && edges[j].v == cur)) {\n                        onEdge[j] = 1;\n                        break;\n                    }\n                }\n                cur = p;\n            }\n        }\n    }\n\n    // Output\n    rep(i, 0, N) cout << P[i] << (i + 1 < N ? ' ' : '\\n');\n    rep(j, 0, M) cout << onEdge[j] << (j + 1 < M ? ' ' : '\\n');\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL = N * (N + 1) / 2;\n\nint board[N][N];\npair<int,int> pos[TOTAL];\nvector<array<int,4>> moves;\n\nconst int dx[6] = {-1, -1, 0, 0, 1, 1};\nconst int dy[6] = {-1, 0, -1, 1, 0, 1};\n\nbool valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvoid do_swap(int x1, int y1, int x2, int y2) {\n    if (moves.size() >= 10000) return;\n    moves.push_back({x1, y1, x2, y2});\n    swap(board[x1][y1], board[x2][y2]);\n    pos[board[x1][y1]] = {x1, y1};\n    pos[board[x2][y2]] = {x2, y2};\n}\n\n// Get target layer for a value\nint target_layer(int val) {\n    int L = 0;\n    while ((L+1)*(L+2)/2 <= val) L++;\n    return L;\n}\n\n// Count local violations for a node\nint local_violations(int x, int y) {\n    if (x >= N-1) return 0;\n    int cnt = 0, p = board[x][y];\n    if (board[x+1][y] < p) cnt++;\n    if (board[x+1][y+1] < p) cnt++;\n    return cnt;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < N; i++)\n        for (int j = 0; j <= i; j++) {\n            cin >> board[i][j];\n            pos[board[i][j]] = {i, j};\n        }\n\n    // Phase 1: Move values to correct layers using bubble-up\n    // Process values by how far they are from target layer\n    vector<int> vals(TOTAL);\n    iota(vals.begin(), vals.end(), 0);\n    \n    // Sort: prioritize values that are deepest relative to target\n    sort(vals.begin(), vals.end(), [&](int a, int b) {\n        int da = pos[a].first - target_layer(a);\n        int db = pos[b].first - target_layer(b);\n        if (da != db) return da > db;\n        return a < b;\n    });\n    \n    for (int v : vals) {\n        if (moves.size() >= 9990) break;\n        int tl = target_layer(v);\n        int cx = pos[v].first, cy = pos[v].second;\n        \n        // Bubble up towards target layer\n        while (cx > tl && moves.size() < 9990) {\n            int px1 = cx-1, py1 = cy-1;\n            int px2 = cx-1, py2 = cy;\n            \n            int best_px = -1, best_py = -1;\n            if (valid(px1, py1) && board[px1][py1] > v) {\n                best_px = px1; best_py = py1;\n            }\n            if (valid(px2, py2) && board[px2][py2] > v) {\n                if (best_px == -1 || board[px2][py2] > board[best_px][best_py]) {\n                    best_px = px2; best_py = py2;\n                }\n            }\n            if (best_px == -1) break;\n            do_swap(cx, cy, best_px, best_py);\n            cx = best_px; cy = best_py;\n        }\n    }\n\n    // Phase 2: Bottom-up heapify\n    // Process from bottom to top, sifting down when needed\n    for (int x = N-2; x >= 0 && moves.size() < 10000; x--) {\n        for (int y = 0; y <= x && moves.size() < 10000; y++) {\n            int cur_x = x, cur_y = y;\n            while (cur_x < N-1 && moves.size() < 10000) {\n                int c1 = board[cur_x+1][cur_y];\n                int c2 = board[cur_x+1][cur_y+1];\n                int p = board[cur_x][cur_y];\n                \n                if (c1 < p && c1 <= c2) {\n                    do_swap(cur_x, cur_y, cur_x+1, cur_y);\n                    cur_x++;\n                } else if (c2 < p) {\n                    do_swap(cur_x, cur_y, cur_x+1, cur_y+1);\n                    cur_x++;\n                    cur_y++;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    // Phase 3: Iterative greedy improvement\n    // Find swaps that maximally reduce violations\n    int remaining = 10000 - moves.size();\n    for (int iter = 0; iter < remaining && iter < 5000; iter++) {\n        int best_gain = 0;\n        int bx1 = -1, by1 = -1, bx2 = -1, by2 = -1;\n        \n        // Scan for violation pairs\n        for (int x = 0; x < N-1; x++) {\n            for (int y = 0; y <= x; y++) {\n                int p = board[x][y];\n                \n                // Check child 1\n                if (board[x+1][y] < p) {\n                    int before = local_violations(x, y) + local_violations(x+1, y);\n                    if (x+1 < N-1) before += local_violations(x+1, y);\n                    if (x > 0) {\n                        if (y > 0) before += local_violations(x-1, y-1);\n                        if (y < x) before += local_violations(x-1, y);\n                    }\n                    \n                    // Simulate swap\n                    swap(board[x][y], board[x+1][y]);\n                    int after = local_violations(x, y) + local_violations(x+1, y);\n                    if (x+1 < N-1) after += local_violations(x+1, y);\n                    if (x > 0) {\n                        if (y > 0) after += local_violations(x-1, y-1);\n                        if (y < x) after += local_violations(x-1, y);\n                    }\n                    swap(board[x][y], board[x+1][y]);\n                    \n                    int gain = before - after;\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        bx1 = x; by1 = y;\n                        bx2 = x+1; by2 = y;\n                    }\n                }\n                \n                // Check child 2\n                if (board[x+1][y+1] < p) {\n                    int before = local_violations(x, y) + local_violations(x+1, y+1);\n                    if (x+1 < N-1) before += local_violations(x+1, y+1);\n                    if (x > 0) {\n                        if (y > 0) before += local_violations(x-1, y-1);\n                        if (y < x) before += local_violations(x-1, y);\n                    }\n                    \n                    swap(board[x][y], board[x+1][y+1]);\n                    int after = local_violations(x, y) + local_violations(x+1, y+1);\n                    if (x+1 < N-1) after += local_violations(x+1, y+1);\n                    if (x > 0) {\n                        if (y > 0) after += local_violations(x-1, y-1);\n                        if (y < x) after += local_violations(x-1, y);\n                    }\n                    swap(board[x][y], board[x+1][y+1]);\n                    \n                    int gain = before - after;\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        bx1 = x; by1 = y;\n                        bx2 = x+1; by2 = y+1;\n                    }\n                }\n            }\n        }\n        \n        if (best_gain <= 0) break;\n        do_swap(bx1, by1, bx2, by2);\n    }\n\n    if (moves.size() > 10000) moves.resize(10000);\n\n    cout << moves.size() << '\\n';\n    for (auto &[a,b,c,d] : moves)\n        cout << a << ' ' << b << ' ' << c << ' ' << d << '\\n';\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_I = 0, ENTRANCE_J = 4;\nint max_id;\n\nvector<string> grid(D, string(D, '.'));\nvector<vector<int>> dist(D, vector<int>(D, -1));\nvector<vector<bool>> obstacle(D, vector<bool>(D, false));\nvector<vector<bool>> occupied(D, vector<bool>(D, false));\n\nint dx[4] = {1, -1, 0, 0};\nint dy[4] = {0, 0, 1, -1};\n\nvoid bfs_distance(int si, int sj) {\n    for (int i = 0; i < D; i++)\n        fill(dist[i].begin(), dist[i].end(), -1);\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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 (nx >= 0 && nx < D && ny >= 0 && ny < D &&\n                dist[nx][ny] == -1 && !obstacle[nx][ny] && !occupied[nx][ny]) {\n                dist[nx][ny] = dist[x][y] + 1;\n                q.push({nx, ny});\n            }\n        }\n    }\n}\n\nbool reachable(int i, int j) {\n    return dist[i][j] != -1;\n}\n\nint count_reachable_empty() {\n    int cnt = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !occupied[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J) && reachable(i, j))\n                cnt++;\n    return cnt;\n}\n\npair<int,int> find_best_cell(int target_dist, int remaining) {\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int best_i = -1, best_j = -1, best_score = 1e9;\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_I && j == ENTRANCE_J) continue;\n            if (!reachable(i, j)) continue;\n            // temporarily place\n            occupied[i][j] = true;\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            int reachable_after = count_reachable_empty();\n            occupied[i][j] = false;\n            if (reachable_after < remaining - 1) continue; // would block future\n            int score = abs(dist[i][j] - target_dist);\n            if (score < best_score) {\n                best_score = score;\n                best_i = i; best_j = j;\n            }\n        }\n    }\n    return {best_i, best_j};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    for (int i = 0; i < N; i++) {\n        int ri, rj;\n        cin >> ri >> rj;\n        obstacle[ri][rj] = true;\n    }\n\n    max_id = D*D - 1 - N;\n    int total_containers = max_id;\n    vector<pair<int,int>> placements(total_containers);\n\n    // Compute max distance\n    bfs_distance(ENTRANCE_I, ENTRANCE_J);\n    int max_dist = 0;\n    for (int i = 0; i < D; i++)\n        for (int j = 0; j < D; j++)\n            if (!obstacle[i][j] && !(i==ENTRANCE_I && j==ENTRANCE_J))\n                max_dist = max(max_dist, dist[i][j]);\n\n    for (int d = 0; d < total_containers; d++) {\n        int tid;\n        cin >> tid;\n        int remaining = total_containers - d;\n        int target_dist = (int)((double)tid / max_id * max_dist);\n        auto [pi, pj] = find_best_cell(target_dist, remaining);\n        if (pi == -1) {\n            // fallback: any reachable\n            bfs_distance(ENTRANCE_I, ENTRANCE_J);\n            for (int i = 0; i < D && pi==-1; i++)\n                for (int j = 0; j < D && pi==-1; j++)\n                    if (!obstacle[i][j] && !occupied[i][j] && reachable(i,j) && !(i==ENTRANCE_I && j==ENTRANCE_J)) {\n                        pi = i; pj = j;\n                    }\n        }\n        occupied[pi][pj] = true;\n        placements[tid] = {pi, pj};\n        cout << pi << \" \" << pj << \"\\n\";\n        cout.flush();\n    }\n\n    // Removal: try sorted order, pick accessible with smallest ID\n    vector<bool> removed(total_containers, false);\n    for (int step = 0; step < total_containers; step++) {\n        bfs_distance(ENTRANCE_I, ENTRANCE_J);\n        int chosen = -1;\n        for (int id = 0; id < total_containers; id++) {\n            if (!removed[id]) {\n                auto [i, j] = placements[id];\n                if (reachable(i, j)) {\n                    chosen = id;\n                    break;\n                }\n            }\n        }\n        removed[chosen] = true;\n        occupied[placements[chosen].first][placements[chosen].second] = false;\n        cout << placements[chosen].first << \" \" << placements[chosen].second << \"\\n\";\n    }\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nvector<vector<int>> input(N, vector<int>(N));\nbool adj[M+1][M+1];\nbool needs_zero[M+1];\nvector<int> graph[M+1];\n\nint dx[4] = {-1, 0, 1, 0};\nint dy[4] = {0, 1, 0, -1};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> input[i][j];\n    \n    // Build adjacency matrix\n    memset(adj, 0, sizeof(adj));\n    memset(needs_zero, 0, sizeof(needs_zero));\n    \n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = input[i][j];\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                needs_zero[c] = true;\n            for (int d = 0; d < 4; d++) {\n                int ni = i + dx[d], nj = j + dy[d];\n                int nc = 0;\n                if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n                    nc = input[ni][nj];\n                if (c != nc)\n                    adj[c][nc] = adj[nc][c] = true;\n            }\n        }\n    }\n    \n    for (int c = 1; c <= m; c++)\n        for (int d = 0; d <= m; d++)\n            if (adj[c][d] && c != d)\n                graph[c].push_back(d);\n    \n    // Output: all 0 initially\n    vector<vector<int>> output(N, vector<int>(N, 0));\n    \n    // For each color, we'll assign a \"seed\" cell\n    // Then expand to satisfy adjacencies\n    \n    // Build spanning tree for ordering\n    vector<bool> visited(M+1, false);\n    vector<int> order;\n    queue<int> q;\n    \n    // Start with colors that need color 0\n    for (int c = 1; c <= m; c++) {\n        if (needs_zero[c] && !visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; c++) {\n        if (!visited[c]) {\n            visited[c] = true;\n            q.push(c);\n            while (!q.empty()) {\n                int u = q.front(); q.pop();\n                order.push_back(u);\n                for (int v : graph[u]) {\n                    if (v == 0 || visited[v]) continue;\n                    visited[v] = true;\n                    q.push(v);\n                }\n            }\n        }\n    }\n    \n    // Place colors in a compact region\n    // Use a rectangular block in the center, starting from row 2, col 2\n    // Place each color as a small connected region (1 cell for now)\n    \n    map<int, vector<pair<int,int>>> cells; // cells for each color\n    \n    int cur_r = 2, cur_c = 2;\n    int max_r = N-3, max_c = N-3;\n    \n    for (int c : order) {\n        // Find free cell\n        while (cur_r <= max_r && output[cur_r][cur_c] != 0) {\n            cur_c++;\n            if (cur_c > max_c) { cur_c = 2; cur_r++; }\n        }\n        if (cur_r > max_r) break;\n        \n        output[cur_r][cur_c] = c;\n        cells[c].push_back({cur_r, cur_c});\n    }\n    \n    // Now ensure all required adjacencies are satisfied\n    // For each adjacency pair, if not adjacent, add cells\n    \n    bool changed = true;\n    int iterations = 0;\n    while (changed && iterations < 100) {\n        changed = false;\n        iterations++;\n        \n        for (int c = 1; c <= m; c++) {\n            for (int d : graph[c]) {\n                if (d == 0 || c >= d) continue; // process each pair once\n                \n                // Check if c and d are adjacent in output\n                bool adj_found = false;\n                for (auto [r1, c1] : cells[c]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r1 + dx[k], nc = c1 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == d) {\n                            adj_found = true;\n                            break;\n                        }\n                    }\n                    if (adj_found) break;\n                }\n                if (adj_found) continue;\n                \n                // Try to add a cell of c adjacent to some cell of d\n                bool placed = false;\n                for (auto [r2, c2] : cells[d]) {\n                    for (int k = 0; k < 4; k++) {\n                        int nr = r2 + dx[k], nc = c2 + dy[k];\n                        if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                            output[nr][nc] = c;\n                            cells[c].push_back({nr, nc});\n                            placed = true;\n                            changed = true;\n                            break;\n                        }\n                    }\n                    if (placed) break;\n                }\n                \n                if (!placed) {\n                    // Try adding a cell of d adjacent to c\n                    for (auto [r1, c1] : cells[c]) {\n                        for (int k = 0; k < 4; k++) {\n                            int nr = r1 + dx[k], nc = c1 + dy[k];\n                            if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                                output[nr][nc] = d;\n                                cells[d].push_back({nr, nc});\n                                placed = true;\n                                changed = true;\n                                break;\n                            }\n                        }\n                        if (placed) break;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Check if any color needs color-0 adjacency but doesn't have it\n    for (int c = 1; c <= m; c++) {\n        if (!needs_zero[c]) continue;\n        if (cells[c].empty()) continue;\n        \n        bool touches_zero = false;\n        for (auto [r, col] : cells[c]) {\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dx[k], nc = col + dy[k];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N || output[nr][nc] == 0) {\n                    touches_zero = true;\n                    break;\n                }\n            }\n            if (touches_zero) break;\n        }\n        \n        if (!touches_zero) {\n            // Expand c towards the border\n            // Find path to border through color 0\n            for (auto [r, col] : cells[c]) {\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dx[k], nc = col + dy[k];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && output[nr][nc] == 0) {\n                        output[nr][nc] = c;\n                        cells[c].push_back({nr, nc});\n                        break;\n                    }\n                }\n                break;\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << output[i][j] << (j == N-1 ? '\\n' : ' ');\n        }\n    }\n    \n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nint query_count = 0;\n\nchar compare_sets(const vector<int>& L, const vector<int>& R) {\n    query_count++;\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res;\n    cin >> res;\n    return res;\n}\n\nchar compare_items(int a, int b) {\n    return compare_sets({a}, {b});\n}\n\nvector<int> merge_sort(const vector<int>& arr, int l, int r) {\n    if (l == r) return {arr[l]};\n    int m = (l + r) / 2;\n    auto left = merge_sort(arr, l, m);\n    auto right = merge_sort(arr, m + 1, r);\n    vector<int> res;\n    int i = 0, j = 0;\n    while (i < (int)left.size() && j < (int)right.size()) {\n        if (query_count >= Q) {\n            // Out of queries, interleave\n            while (i < (int)left.size() && j < (int)right.size()) {\n                res.push_back(left[i++]);\n                if (j < (int)right.size()) res.push_back(right[j++]);\n            }\n            while (i < (int)left.size()) res.push_back(left[i++]);\n            while (j < (int)right.size()) res.push_back(right[j++]);\n            return res;\n        }\n        char cmp = compare_items(left[i], right[j]);\n        if (cmp == '>') {\n            res.push_back(left[i++]);\n        } else if (cmp == '<') {\n            res.push_back(right[j++]);\n        } else {\n            res.push_back(left[i++]);\n            res.push_back(right[j++]);\n        }\n    }\n    while (i < (int)left.size()) res.push_back(left[i++]);\n    while (j < (int)right.size()) res.push_back(right[j++]);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> D >> Q;\n    \n    // Precompute harmonic numbers\n    vector<double> harmonic(N + 1, 0.0);\n    for (int i = 1; i <= N; i++) {\n        harmonic[i] = harmonic[i - 1] + 1.0 / i;\n    }\n    \n    query_count = 0;\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n\n    // Phase 1: Sort items (heaviest first)\n    vector<int> sorted = merge_sort(items, 0, N - 1);\n\n    // Phase 2: Estimate weights\n    double scale = 100000.0;\n    vector<double> est_weight(N);\n    vector<int> pos_of(N);\n    for (int i = 0; i < N; i++) {\n        pos_of[sorted[i]] = i;\n    }\n    for (int idx = 0; idx < N; idx++) {\n        int k = N - idx;\n        double expected = scale * (harmonic[N] - harmonic[N - k]);\n        est_weight[idx] = max(1.0, expected);\n    }\n\n    // Phase 3: Greedy assignment\n    vector<vector<int>> groups(D);\n    vector<double> group_sum(D, 0.0);\n    \n    for (int idx = 0; idx < N; idx++) {\n        int item = sorted[idx];\n        double w = est_weight[idx];\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_sum[g] < group_sum[best]) best = g;\n        }\n        groups[best].push_back(item);\n        group_sum[best] += w;\n    }\n\n    // Phase 4: Refinement\n    mt19937 rng(12345);\n    \n    vector<int> group_order(D);\n    iota(group_order.begin(), group_order.end(), 0);\n    \n    int no_progress = 0;\n    while (query_count + 2 <= Q && no_progress < 200) {\n        sort(group_order.begin(), group_order.end(), [&](int a, int b) {\n            return group_sum[a] < group_sum[b];\n        });\n        \n        int min_g = group_order[0];\n        int max_g = group_order.back();\n        \n        if (max_g == min_g || groups[max_g].size() <= 1 || groups[min_g].empty()) {\n            no_progress++;\n            continue;\n        }\n        \n        char cmp = compare_sets(groups[max_g], groups[min_g]);\n        \n        if (cmp == '=') {\n            double avg = (group_sum[max_g] + group_sum[min_g]) / 2.0;\n            group_sum[max_g] = avg;\n            group_sum[min_g] = avg;\n            no_progress = 0;\n            continue;\n        }\n        \n        if (cmp == '<') {\n            // Estimates wrong: min_g is heavier\n            double avg = (group_sum[max_g] + group_sum[min_g]) / 2.0;\n            group_sum[max_g] = avg * 0.9;\n            group_sum[min_g] = avg * 1.1;\n            no_progress++;\n            continue;\n        }\n        \n        // cmp == '>': max_g is heavier\n        // Try moving items one by one until balance or overshoot\n        vector<pair<int, double>> candidates;\n        for (int item : groups[max_g]) {\n            candidates.push_back({item, est_weight[pos_of[item]]});\n        }\n        sort(candidates.begin(), candidates.end(), [](auto& a, auto& b) {\n            return a.second < b.second;\n        });\n        \n        bool moved_any = false;\n        for (auto& [item, w] : candidates) {\n            if (query_count + 2 > Q) break;\n            if (groups[max_g].size() <= 1) break;\n            \n            // Temporarily move item\n            auto& v_max = groups[max_g];\n            v_max.erase(remove(v_max.begin(), v_max.end(), item), v_max.end());\n            groups[min_g].push_back(item);\n            \n            char cmp2 = compare_sets(groups[max_g], groups[min_g]);\n            \n            if (cmp2 == '=') {\n                // Perfect balance achieved\n                group_sum[max_g] -= w;\n                group_sum[min_g] += w;\n                moved_any = true;\n                break;\n            } else if (cmp2 == '<') {\n                // Overshoot: undo the move\n                groups[min_g].erase(remove(groups[min_g].begin(), groups[min_g].end(), item), groups[min_g].end());\n                groups[max_g].push_back(item);\n                // Can't move more items without overshooting\n                // But we've improved as much as possible with one item moves\n                if (!moved_any) {\n                    // Even the lightest item overshoots; estimates are off\n                    double avg = (group_sum[max_g] + group_sum[min_g] + w) / 2.0;\n                    group_sum[max_g] = avg * 1.05;\n                    group_sum[min_g] = avg * 0.95;\n                }\n                break;\n            } else {\n                // Still >, keep the move and try another item\n                group_sum[max_g] -= w;\n                group_sum[min_g] += w;\n                moved_any = true;\n            }\n        }\n        \n        if (moved_any) {\n            no_progress = 0;\n        } else {\n            no_progress++;\n        }\n    }\n\n    // Phase 5: Burn remaining queries\n    while (query_count + 2 <= Q) {\n        sort(group_order.begin(), group_order.end(), [&](int a, int b) {\n            return group_sum[a] < group_sum[b];\n        });\n        \n        bool did_something = false;\n        for (int i = 0; i < D - 1 && query_count + 2 <= Q; i++) {\n            int a = group_order[i];\n            int b = group_order[i + 1];\n            if (groups[a].empty() || groups[b].empty()) continue;\n            if (abs((int)groups[a].size() - (int)groups[b].size()) > 5) continue;\n            \n            char cmp = compare_sets(groups[a], groups[b]);\n            if (cmp == '>') {\n                double avg = (group_sum[a] + group_sum[b]) / 2.0;\n                group_sum[b] = avg * 1.1;\n                group_sum[a] = avg * 0.9;\n                did_something = true;\n            } else if (cmp == '=') {\n                double avg = (group_sum[a] + group_sum[b]) / 2.0;\n                group_sum[a] = avg;\n                group_sum[b] = avg;\n                did_something = true;\n            }\n        }\n        \n        if (!did_something) break;\n    }\n\n    // Phase 6: Burn any remaining queries\n    while (query_count < Q) {\n        int a = uniform_int_distribution<int>(0, N-1)(rng);\n        int b = uniform_int_distribution<int>(0, N-1)(rng);\n        if (a != b) compare_items(a, b);\n        else compare_items(0, 1);\n    }\n\n    // Build final assignment\n    vector<int> assignment(N);\n    for (int g = 0; g < D; g++) {\n        for (int item : groups[g]) {\n            assignment[item] = g;\n        }\n    }\n\n    cout << \"#c\";\n    for (int i = 0; i < N; i++) cout << \" \" << assignment[i];\n    cout << endl;\n\n    for (int i = 0; i < N; i++) {\n        if (i > 0) cout << \" \";\n        cout << assignment[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 200, M = 10;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int h = n / m;\n    int stacks[M][N];\n    int sizes[M];\n    for (int i = 0; i < m; ++i) {\n        sizes[i] = h;\n        for (int j = 0; j < h; ++j)\n            cin >> stacks[i][j];\n    }\n\n    vector<pair<int, int>> moves;\n    auto move_op = [&](int v, int dest) {\n        moves.emplace_back(v, dest + 1);\n    };\n    auto carry_out = [&](int v) {\n        moves.emplace_back(v, 0);\n    };\n\n    int stack_of[N + 1], index_of[N + 1];\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < sizes[i]; ++j) {\n            int v = stacks[i][j];\n            stack_of[v] = i;\n            index_of[v] = j;\n        }\n\n    int next_target = 1;\n    while (next_target <= n) {\n        int si = stack_of[next_target];\n        int pos = index_of[next_target];\n        if (pos == sizes[si] - 1) {\n            // carry out\n            carry_out(next_target);\n            sizes[si]--;\n            ++next_target;\n            continue;\n        }\n        // box just above next_target\n        int u = stacks[si][pos + 1];\n        int top_of_moved = stacks[si][sizes[si] - 1];\n        // choose destination\n        int dest = -1;\n        // prefer empty\n        for (int i = 0; i < m; ++i)\n            if (i != si && sizes[i] == 0) {\n                dest = i;\n                break;\n            }\n        if (dest == -1) {\n            // find stack with max top that is < top_of_moved\n            int best = -1;\n            for (int i = 0; i < m; ++i) {\n                if (i != si && sizes[i] > 0) {\n                    int t = stacks[i][sizes[i] - 1];\n                    if (t < top_of_moved && t > best) {\n                        best = t;\n                        dest = i;\n                    }\n                }\n            }\n            if (dest == -1) {\n                // else min top overall\n                int min_top = INT_MAX;\n                for (int i = 0; i < m; ++i) {\n                    if (i != si && sizes[i] > 0) {\n                        int t = stacks[i][sizes[i] - 1];\n                        if (t < min_top) {\n                            min_top = t;\n                            dest = i;\n                        }\n                    }\n                }\n            }\n            if (dest == -1) dest = (si + 1) % m;\n        }\n        move_op(u, dest);\n        int k = sizes[si] - (pos + 1);\n        for (int j = pos + 1; j < sizes[si]; ++j) {\n            int b = stacks[si][j];\n            stacks[dest][sizes[dest]++] = b;\n            stack_of[b] = dest;\n            index_of[b] = sizes[dest] - 1;\n        }\n        sizes[si] = pos + 1;\n    }\n\n    for (auto &[v, d] : moves)\n        cout << v << \" \" << d << \"\\n\";\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\nconst char dir_char[4] = {'R', 'D', 'L', 'U'};\n\nbool can_move(int i, int j, int ni, int nj) {\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    // Check if there's no wall between (i,j) and (ni,nj)\n    if (i == ni) {\n        // Horizontal move: check vertical walls\n        int min_j = min(j, nj);\n        return v[i][min_j] == '0';\n    } else {\n        // Vertical move: check horizontal walls\n        int min_i = min(i, ni);\n        return h[min_i][j] == '0';\n    }\n}\n\n// BFS to compute shortest path distances\nvector<vector<int>> compute_distances(int si, int sj) {\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int k = 0; k < 4; k++) {\n            int ni = i + dx[k], nj = j + dy[k];\n            if (can_move(i, j, ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return dist;\n}\n\n// Generate route string from coordinate sequence\nstring route_to_string(const vector<pair<int,int>>& route) {\n    string s;\n    for (size_t t = 1; t < route.size(); t++) {\n        int ci = route[t-1].first, cj = route[t-1].second;\n        int ni = route[t].first, nj = route[t].second;\n        \n        bool found = false;\n        for (int k = 0; k < 4; k++) {\n            if (ci + dx[k] == ni && cj + dy[k] == nj) {\n                if (can_move(ci, cj, ni, nj)) {\n                    s += dir_char[k];\n                    found = true;\n                    break;\n                }\n            }\n        }\n        if (!found) {\n            // This should not happen if route is valid\n            return \"\";\n        }\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    \n    vector<pair<int,pair<int,int>>> dirt_cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n            dirt_cells.push_back({-d[i][j], {i, j}});\n        }\n    }\n    sort(dirt_cells.begin(), dirt_cells.end());\n    \n    // Step 1: Build base route using priority-based DFS\n    vector<pair<int,int>> base_route;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    \n    function<void(int,int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        base_route.push_back({i, j});\n        \n        // Collect reachable unvisited neighbors with priority\n        vector<pair<int,pair<int,int>>> neighbors;\n        for (int k = 0; k < 4; k++) {\n            int ni = i + dx[k], nj = j + dy[k];\n            if (can_move(i, j, ni, nj) && !visited[ni][nj]) {\n                neighbors.push_back({-d[ni][nj], {ni, nj}});\n            }\n        }\n        sort(neighbors.begin(), neighbors.end());\n        \n        for (auto& [_, next] : neighbors) {\n            auto [ni, nj] = next;\n            dfs(ni, nj);\n            base_route.push_back({i, j}); // Return to current node\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Step 2: Create working route\n    vector<pair<int,int>> current_route = base_route;\n    int MAX_LENGTH = 100000;\n    \n    // Step 3: Insert extra visits for high-dirt cells\n    // We'll insert additional visits to top priority cells\n    \n    // Build map of cell positions in route\n    map<pair<int,int>, vector<int>> pos_map;\n    for (size_t pos = 0; pos < current_route.size(); pos++) {\n        pos_map[current_route[pos]].push_back(pos);\n    }\n    \n    int insertions = 0;\n    int max_insertions = min(200, N * N / 2);\n    \n    for (auto& [neg_d, cell] : dirt_cells) {\n        if (insertions >= max_insertions) break;\n        if (current_route.size() >= MAX_LENGTH - 200) break;\n        \n        int di = cell.first, dj = cell.second;\n        int dirt_val = -neg_d;\n        \n        // Only add extra visits for cells with high dirt value\n        if (dirt_val < 300) continue;\n        \n        auto& positions = pos_map[{di, dj}];\n        if (positions.size() < 1) continue;\n        \n        // Calculate average gap between visits\n        int L = current_route.size();\n        int num_visits = positions.size();\n        double avg_gap = (double)L / num_visits;\n        \n        // If average gap is large, add extra visit\n        if (avg_gap > 80 && L < MAX_LENGTH - 100) {\n            // Find the largest gap\n            int max_gap = 0;\n            int insert_after = -1;\n            \n            for (size_t p = 0; p < positions.size(); p++) {\n                int curr = positions[p];\n                int next = positions[(p + 1) % positions.size()];\n                int gap;\n                if (next > curr) {\n                    gap = next - curr;\n                } else {\n                    gap = L - curr + next;\n                }\n                \n                if (gap > max_gap) {\n                    max_gap = gap;\n                    // We'll insert near the midpoint of this gap\n                    int midpoint = (curr + gap / 2) % L;\n                    \n                    // Find a point near midpoint that's close to target cell\n                    for (int delta = 0; delta <= 10; delta++) {\n                        int check_pos = (midpoint - delta + L) % L;\n                        auto [ci, cj] = current_route[check_pos];\n                        \n                        vector<vector<int>> dist = compute_distances(ci, cj);\n                        if (dist[di][dj] != -1 && dist[di][dj] <= 10) {\n                            insert_after = check_pos;\n                            break;\n                        }\n                    }\n                    \n                    if (insert_after >= 0) break;\n                }\n            }\n            \n            if (insert_after >= 0 && max_gap > 50) {\n                // Get insertion point\n                auto [si, sj] = current_route[insert_after];\n                \n                // Find path from insertion point to target cell and back\n                // We'll use BFS to find shortest paths\n                vector<vector<int>> dist_to = compute_distances(si, sj);\n                \n                if (dist_to[di][dj] != -1 && dist_to[di][dj] <= 15) {\n                    // Build path from si,sj to di,dj\n                    vector<pair<int,int>> path_to;\n                    int ci = di, cj = dj;\n                    while (ci != si || cj != sj) {\n                        path_to.push_back({ci, cj});\n                        // Find predecessor\n                        for (int k = 0; k < 4; k++) {\n                            int pi = ci - dx[k], pj = cj - dy[k];\n                            if (pi >= 0 && pi < N && pj >= 0 && pj < N && \n                                can_move(pi, pj, ci, cj) && \n                                dist_to[pi][pj] == dist_to[ci][cj] - 1) {\n                                ci = pi; cj = pj;\n                                break;\n                            }\n                        }\n                    }\n                    path_to.push_back({si, sj});\n                    reverse(path_to.begin(), path_to.end());\n                    \n                    // Build path back (reverse of path_to)\n                    vector<pair<int,int>> path_back = path_to;\n                    reverse(path_back.begin(), path_back.end());\n                    \n                    // Remove duplicate endpoints\n                    if (path_to.size() > 1) path_to.erase(path_to.begin()); // Remove start (already in route)\n                    if (path_back.size() > 1) path_back.pop_back(); // Remove end (will continue from there)\n                    \n                    int additional_moves = path_to.size() + path_back.size();\n                    if (current_route.size() + additional_moves <= MAX_LENGTH) {\n                        // Insert into route\n                        vector<pair<int,int>> new_route;\n                        for (int i = 0; i <= insert_after; i++) {\n                            new_route.push_back(current_route[i]);\n                        }\n                        for (auto& p : path_to) new_route.push_back(p);\n                        for (auto& p : path_back) new_route.push_back(p);\n                        for (size_t i = insert_after + 1; i < current_route.size(); i++) {\n                            new_route.push_back(current_route[i]);\n                        }\n                        \n                        current_route = new_route;\n                        insertions++;\n                        \n                        // Rebuild position map\n                        pos_map.clear();\n                        for (size_t pos = 0; pos < current_route.size(); pos++) {\n                            pos_map[current_route[pos]].push_back(pos);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Step 4: Ensure route ends at (0,0)\n    if (current_route.back().first != 0 || current_route.back().second != 0) {\n        int ci = current_route.back().first, cj = current_route.back().second;\n        vector<vector<int>> dist = compute_distances(ci, cj);\n        \n        if (dist[0][0] != -1) {\n            vector<pair<int,int>> return_path;\n            int x = 0, y = 0;\n            vector<pair<int,int>> rev_path;\n            while (x != ci || y != cj) {\n                rev_path.push_back({x, y});\n                for (int k = 0; k < 4; k++) {\n                    int px = x - dx[k], py = y - dy[k];\n                    if (px >= 0 && px < N && py >= 0 && py < N &&\n                        can_move(px, py, x, y) &&\n                        dist[px][py] == dist[x][y] - 1) {\n                        x = px; y = py;\n                        break;\n                    }\n                }\n            }\n            rev_path.push_back({ci, cj});\n            reverse(rev_path.begin(), rev_path.end());\n            \n            // Skip first element (already in route)\n            for (size_t i = 1; i < rev_path.size(); i++) {\n                current_route.push_back(rev_path[i]);\n            }\n        }\n    }\n    \n    // Step 5: Generate output string\n    string ans = route_to_string(current_route);\n    \n    // Validate and truncate if needed\n    if (ans.empty() || ans.size() > MAX_LENGTH) {\n        // Fallback: use simple DFS route\n        vector<pair<int,int>> fallback;\n        vector<vector<bool>> vis(N, vector<bool>(N, false));\n        \n        function<void(int,int)> simple_dfs = [&](int i, int j) {\n            vis[i][j] = true;\n            fallback.push_back({i, j});\n            for (int k = 0; k < 4; k++) {\n                int ni = i + dx[k], nj = j + dy[k];\n                if (can_move(i, j, ni, nj) && !vis[ni][nj]) {\n                    simple_dfs(ni, nj);\n                    fallback.push_back({i, j});\n                }\n            }\n        };\n        simple_dfs(0, 0);\n        ans = route_to_string(fallback);\n    }\n    \n    if (ans.size() > MAX_LENGTH) {\n        ans = ans.substr(0, MAX_LENGTH);\n    }\n    \n    cout << ans << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint si, sj;\nchar grid[15][15];\nvector<pair<int,int>> pos[26];\nvector<string> targets;\nint dist[225][225];\n\nint cell_id(int i, int j) { return i*N + j; }\n\nvoid bfs_dist() {\n    int di[] = {1,-1,0,0};\n    int dj[] = {0,0,1,-1};\n    for (int i = 0; i < N*N; i++)\n        for (int j = 0; j < N*N; j++)\n            dist[i][j] = 1e9;\n    \n    for (int i = 0; i < N*N; i++) {\n        int si = i/N, sj = i%N;\n        dist[i][i] = 0;\n        queue<pair<int,int>> q;\n        q.push({si,sj});\n        while (!q.empty()) {\n            auto [ci, cj] = q.front(); q.pop();\n            int cid = cell_id(ci,cj);\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nid = cell_id(ni,nj);\n                if (dist[i][nid] > dist[i][cid] + 1) {\n                    dist[i][nid] = dist[i][cid] + 1;\n                    q.push({ni,nj});\n                }\n            }\n        }\n    }\n}\n\nint overlap(const string& a, const string& b) {\n    int max_len = min((int)a.size(), (int)b.size());\n    for (int len = max_len; len >= 0; len--) {\n        if (len == 0) return 0;\n        if (a.substr(a.size()-len) == b.substr(0, len))\n            return len;\n    }\n    return 0;\n}\n\nstring order_to_superstring(const vector<int>& order, const vector<string>& strs) {\n    if (order.empty()) return \"\";\n    string res = strs[order[0]];\n    for (int k = 1; k < (int)order.size(); k++) {\n        int ov = overlap(res, strs[order[k]]);\n        res += strs[order[k]].substr(ov);\n    }\n    return res;\n}\n\n// Build order from greedy merge (return the order, not the string)\nvector<int> build_greedy_order(const vector<string>& strs, int start) {\n    int K = strs.size();\n    vector<bool> used(K, false);\n    vector<int> order;\n    string res = strs[start];\n    order.push_back(start);\n    used[start] = true;\n    \n    for (int step = 1; step < K; step++) {\n        int best_idx = -1, best_ov = -1;\n        bool is_pre = true;\n        for (int i = 0; i < K; i++) {\n            if (used[i]) continue;\n            int ov_pre = overlap(strs[i], res);\n            if (ov_pre > best_ov) { best_ov = ov_pre; best_idx = i; is_pre = true; }\n            int ov_app = overlap(res, strs[i]);\n            if (ov_app > best_ov) { best_ov = ov_app; best_idx = i; is_pre = false; }\n        }\n        used[best_idx] = true;\n        if (is_pre) {\n            order.insert(order.begin(), best_idx);\n            res = strs[best_idx].substr(0, strs[best_idx].size() - best_ov) + res;\n        } else {\n            order.push_back(best_idx);\n            res += strs[best_idx].substr(best_ov);\n        }\n    }\n    return order;\n}\n\nint eval_cost(const string& s, int start_cell) {\n    int L = s.size();\n    if (L == 0) return 0;\n    vector<int> dp_cur(225, 1e9);\n    for (auto [i, j] : pos[s[0]-'A']) {\n        dp_cur[cell_id(i,j)] = dist[start_cell][cell_id(i,j)] + 1;\n    }\n    for (int k = 1; k < L; k++) {\n        vector<int> dp_next(225, 1e9);\n        for (auto [i, j] : pos[s[k]-'A']) {\n            int cid = cell_id(i,j);\n            for (auto [pi, pj] : pos[s[k-1]-'A']) {\n                int pid = cell_id(pi,pj);\n                if (dp_cur[pid] == 1e9) continue;\n                int nd = dp_cur[pid] + dist[pid][cid] + 1;\n                if (nd < dp_next[cid])\n                    dp_next[cid] = nd;\n            }\n        }\n        dp_cur = dp_next;\n    }\n    int ans = 1e9;\n    for (auto [i, j] : pos[s.back()-'A']) {\n        ans = min(ans, dp_cur[cell_id(i,j)]);\n    }\n    return ans;\n}\n\nvector<int> type_string(const string& s, int start_cell) {\n    int L = s.size();\n    vector<int> dp_cur(225, 1e9);\n    vector<vector<int>> prev(L, vector<int>(225, -1));\n    for (auto [i, j] : pos[s[0]-'A']) {\n        int cid = cell_id(i,j);\n        dp_cur[cid] = dist[start_cell][cid] + 1;\n    }\n    for (int k = 1; k < L; k++) {\n        vector<int> dp_next(225, 1e9);\n        for (auto [i, j] : pos[s[k]-'A']) {\n            int cid = cell_id(i,j);\n            for (auto [pi, pj] : pos[s[k-1]-'A']) {\n                int pid = cell_id(pi,pj);\n                if (dp_cur[pid] == 1e9) continue;\n                int nd = dp_cur[pid] + dist[pid][cid] + 1;\n                if (nd < dp_next[cid]) {\n                    dp_next[cid] = nd;\n                    prev[k][cid] = pid;\n                }\n            }\n        }\n        dp_cur = dp_next;\n    }\n    int best_end = -1;\n    for (auto [i, j] : pos[s.back()-'A']) {\n        int cid = cell_id(i,j);\n        if (best_end == -1 || dp_cur[cid] < dp_cur[best_end])\n            best_end = cid;\n    }\n    vector<int> path(L);\n    int cur = best_end;\n    for (int k = L-1; k >= 0; k--) {\n        path[k] = cur;\n        if (k > 0) cur = prev[k][cur];\n    }\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++) {\n            grid[i][j] = s[j];\n            pos[s[j]-'A'].push_back({i,j});\n        }\n    }\n    targets.resize(M);\n    for (int i = 0; i < M; i++) cin >> targets[i];\n    \n    bfs_dist();\n    int start_cell = cell_id(si, sj);\n    \n    // Precompute overlap matrix\n    vector<vector<int>> ov_mat(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++)\n        for (int j = 0; j < M; j++)\n            if (i != j)\n                ov_mat[i][j] = overlap(targets[i], targets[j]);\n    \n    string best_super;\n    int best_cost = 1e9;\n    vector<int> best_order;\n    \n    // Try greedy from many starting targets\n    for (int start = 0; start < min(M, 50); start++) {\n        vector<int> order = build_greedy_order(targets, start);\n        string sup = order_to_superstring(order, targets);\n        int cost = eval_cost(sup, start_cell);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_super = sup;\n            best_order = order;\n        }\n    }\n    \n    // Randomized variations\n    mt19937 rng(42);\n    for (int trial = 0; trial < 50; trial++) {\n        int start = rng() % M;\n        int K = M;\n        vector<bool> used(K, false);\n        string res = targets[start];\n        vector<int> order;\n        if (rng() % 2) {\n            // forward order (build by appending)\n            order.push_back(start);\n            used[start] = true;\n            for (int step = 1; step < K; step++) {\n                vector<tuple<int,int,bool>> cands;\n                for (int i = 0; i < K; i++) {\n                    if (used[i]) continue;\n                    int ov_app = overlap(res, targets[i]);\n                    cands.push_back({ov_app, i, false});\n                }\n                sort(cands.rbegin(), cands.rend());\n                int pick = min((int)cands.size()-1, (int)(rng() % min(3, (int)cands.size())));\n                auto [ov, idx, is_pre] = cands[pick];\n                used[idx] = true;\n                order.push_back(idx);\n                res += targets[idx].substr(ov);\n            }\n        } else {\n            // backward order (build by prepending)\n            order.push_back(start);\n            used[start] = true;\n            for (int step = 1; step < K; step++) {\n                vector<tuple<int,int,bool>> cands;\n                for (int i = 0; i < K; i++) {\n                    if (used[i]) continue;\n                    int ov_pre = overlap(targets[i], res);\n                    cands.push_back({ov_pre, i, true});\n                }\n                sort(cands.rbegin(), cands.rend());\n                int pick = min((int)cands.size()-1, (int)(rng() % min(3, (int)cands.size())));\n                auto [ov, idx, is_pre] = cands[pick];\n                used[idx] = true;\n                order.insert(order.begin(), idx);\n                res = targets[idx].substr(0, targets[idx].size() - ov) + res;\n            }\n        }\n        string sup = res;\n        int cost = eval_cost(sup, start_cell);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_super = sup;\n            best_order = order;\n        }\n    }\n    \n    // Local search on the best order: try swapping adjacent pairs\n    if (!best_order.empty()) {\n        bool improved = true;\n        int iter = 0;\n        while (improved && iter < 1000) {\n            improved = false;\n            iter++;\n            for (int i = 0; i < M-1; i++) {\n                swap(best_order[i], best_order[i+1]);\n                string sup = order_to_superstring(best_order, targets);\n                int cost = eval_cost(sup, start_cell);\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_super = sup;\n                    improved = true;\n                    break; // restart after any improvement\n                } else {\n                    swap(best_order[i], best_order[i+1]); // revert\n                }\n            }\n        }\n    }\n    \n    vector<int> output = type_string(best_super, start_cell);\n    for (int c : output) {\n        cout << c/N << \" \" << c%N << \"\\n\";\n    }\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <set>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nint main() {\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n    \n    // Read shapes (keep them for potential use)\n    vector<vector<pair<int,int>>> shapes(M);\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        shapes[k].resize(d);\n        for (int t = 0; t < d; t++) {\n            cin >> shapes[k][t].first >> shapes[k][t].second;\n        }\n    }\n    \n    const int MAXQ = 2 * N * N;\n    int qcnt = 0;\n    \n    vector<vector<int>> val(N, vector<int>(N, -1)); // -1 unknown\n    set<pair<int,int>> known_oil;\n    \n    auto query_set = [&](const vector<pair<int,int>> &s) -> double {\n        if (qcnt >= MAXQ) return -1.0;\n        qcnt++;\n        cout << \"q \" << s.size();\n        for (auto &p : s) cout << \" \" << p.first << \" \" << p.second;\n        cout << endl;\n        double x;\n        cin >> x;\n        return x;\n    };\n    \n    auto query_one = [&](int i, int j) -> int {\n        if (qcnt >= MAXQ) return -1;\n        qcnt++;\n        cout << \"q 1 \" << i << \" \" << j << endl;\n        int x;\n        cin >> x;\n        val[i][j] = x;\n        if (x > 0) known_oil.insert({i, j});\n        return x;\n    };\n    \n    auto submit = [&](const set<pair<int,int>> &ans) -> bool {\n        cout << \"a \" << ans.size();\n        for (auto &p : ans) cout << \" \" << p.first << \" \" << p.second;\n        cout << endl;\n        int r;\n        cin >> r;\n        return r == 1;\n    };\n    \n    // Helper to estimate v(S) from observed value\n    auto est_v = [&](double obs, int k) -> double {\n        return max(0.0, (obs - k * eps) / (1.0 - 2.0 * eps));\n    };\n    \n    // Phase 1: Query all rows (cost ~N * 1/sqrt(N) = sqrt(N) each, total ~N*sqrt(N))\n    vector<double> row_v(N, 0);\n    vector<bool> row_has_oil(N, false);\n    for (int i = 0; i < N; i++) {\n        vector<pair<int,int>> row;\n        for (int j = 0; j < N; j++) row.push_back({i, j});\n        double obs = query_set(row);\n        if (obs >= 0) {\n            row_v[i] = est_v(obs, N);\n            row_has_oil[i] = (row_v[i] > 0.5); // At least 0.5 oil in row\n        }\n    }\n    \n    // Phase 2: Query all columns\n    vector<double> col_v(N, 0);\n    vector<bool> col_has_oil(N, false);\n    for (int j = 0; j < N; j++) {\n        vector<pair<int,int>> col;\n        for (int i = 0; i < N; i++) col.push_back({i, j});\n        double obs = query_set(col);\n        if (obs >= 0) {\n            col_v[j] = est_v(obs, N);\n            col_has_oil[j] = (col_v[j] > 0.5);\n        }\n    }\n    \n    // Phase 3: For cells at intersection of active rows/cols, query them\n    // But use divination for larger groups first to save cost\n    vector<pair<int,int>> candidates;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (row_has_oil[i] && col_has_oil[j]) {\n                candidates.push_back({i, j});\n            }\n        }\n    }\n    \n    // If few candidates, just drill them\n    if ((int)candidates.size() <= N * 2 && qcnt + (int)candidates.size() < MAXQ) {\n        for (auto &p : candidates) {\n            if (val[p.first][p.second] == -1) {\n                query_one(p.first, p.second);\n            }\n        }\n    } else {\n        // Group candidates into blocks for divination\n        int block_size = max(2, (int)sqrt(candidates.size()) / 2);\n        vector<vector<pair<int,int>>> blocks;\n        \n        for (int bi = 0; bi < N; bi += block_size) {\n            for (int bj = 0; bj < N; bj += block_size) {\n                vector<pair<int,int>> block;\n                for (int i = bi; i < min(N, bi + block_size); i++) {\n                    for (int j = bj; j < min(N, bj + block_size); j++) {\n                        if (row_has_oil[i] && col_has_oil[j]) {\n                            block.push_back({i, j});\n                        }\n                    }\n                }\n                if (block.size() >= 2) {\n                    blocks.push_back(block);\n                } else if (block.size() == 1) {\n                    // Single cell, just drill\n                    if (val[block[0].first][block[0].second] == -1) {\n                        query_one(block[0].first, block[0].second);\n                    }\n                }\n            }\n        }\n        \n        // Divine each block; if it has oil, drill its cells\n        for (auto &block : blocks) {\n            if (qcnt + (int)block.size() + 2 >= MAXQ) break;\n            \n            double obs = query_set(block);\n            if (obs >= 0) {\n                double v_est = est_v(obs, block.size());\n                if (v_est > 0.3) {\n                    // This block has oil, drill its cells\n                    for (auto &p : block) {\n                        if (val[p.first][p.second] == -1) {\n                            query_one(p.first, p.second);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 4: Drill any remaining cells in active rows/cols that we missed\n    for (int i = 0; i < N && qcnt + 5 < MAXQ; i++) {\n        for (int j = 0; j < N && qcnt + 5 < MAXQ; j++) {\n            if (val[i][j] == -1 && row_has_oil[i] && col_has_oil[j]) {\n                query_one(i, j);\n            }\n        }\n    }\n    \n    // Phase 5: Build answer\n    set<pair<int,int>> ans = known_oil;\n    \n    if (submit(ans)) return 0;\n    \n    // Phase 6: If wrong, drill everything we haven't checked\n    for (int i = 0; i < N && qcnt + 5 < MAXQ; i++) {\n        for (int j = 0; j < N && qcnt + 5 < MAXQ; j++) {\n            if (val[i][j] == -1) {\n                query_one(i, j);\n            }\n        }\n    }\n    \n    ans = known_oil;\n    if (submit(ans)) return 0;\n    \n    // Last resort\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (val[i][j] == -1 || val[i][j] > 0)\n                ans.insert({i, j});\n    \n    submit(ans);\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <cstring>\n#include <functional>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nlong long area(const Rect& r) {\n    return (long long)(r.i1 - r.i0) * (r.j1 - r.j0);\n}\n\n// Compute L_d cost between prev and curr layouts\nlong long partition_change_cost(const vector<Rect>& prev, const vector<Rect>& curr, int W) {\n    static vector<char> H_prev, H_curr, V_prev, V_curr;\n    H_prev.assign(W * W, 0);\n    H_curr.assign(W * W, 0);\n    V_prev.assign(W * W, 0);\n    V_curr.assign(W * W, 0);\n    \n    auto mark_rect = [W](vector<char>& H, vector<char>& V, const Rect& r) {\n        if (r.i0 > 0 && r.i0 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H[r.i0 * W + j] = 1;\n            }\n        }\n        if (r.i1 > 0 && r.i1 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H[r.i1 * W + j] = 1;\n            }\n        }\n        if (r.j0 > 0 && r.j0 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V[i * W + r.j0] = 1;\n            }\n        }\n        if (r.j1 > 0 && r.j1 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V[i * W + r.j1] = 1;\n            }\n        }\n    };\n    \n    if (!prev.empty()) {\n        for (const auto& r : prev) {\n            mark_rect(H_prev, V_prev, r);\n        }\n    }\n    for (const auto& r : curr) {\n        mark_rect(H_curr, V_curr, r);\n    }\n    \n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (H_prev[i * W + j] != H_curr[i * W + j]) cost++;\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            if (V_prev[i * W + j] != V_curr[i * W + j]) cost++;\n        }\n    }\n    return cost;\n}\n\n// Compute area deficit penalty\nlong long area_penalty(const vector<Rect>& rects, const vector<int>& demands) {\n    long long penalty = 0;\n    for (size_t k = 0; k < demands.size(); ++k) {\n        long long rect_area = area(rects[k]);\n        if (rect_area < demands[k]) {\n            penalty += 100 * (demands[k] - rect_area);\n        }\n    }\n    return penalty;\n}\n\n// Create layout for given demands using recursive bisection\n// Ensures each rectangle gets at least its demanded area\nvector<Rect> create_layout(const vector<int>& demands) {\n    int N = demands.size();\n    vector<Rect> rects(N);\n    \n    // Pair (demand, original_index) sorted by demand descending\n    vector<pair<long long, int>> slots;\n    for (int k = 0; k < N; ++k) {\n        slots.emplace_back(demands[k], k);\n    }\n    sort(slots.begin(), slots.end(), greater<pair<long long, int>>());\n    \n    function<void(int, int, int, int, int, int)> assign;\n    assign = [&](int start, int end, int i0, int j0, int i1, int j1) {\n        if (start >= end) return;\n        if (start + 1 == end) {\n            int idx = slots[start].second;\n            rects[idx] = {i0, j0, i1, j1};\n            return;\n        }\n        \n        // Total demand for this group\n        long long total_demand = 0;\n        for (int i = start; i < end; ++i) {\n            total_demand += slots[i].first;\n        }\n        \n        int height = i1 - i0;\n        int width = j1 - j0;\n        long long region_area = (long long)height * width;\n        \n        // Split along longer dimension\n        if (height >= width) {\n            // Horizontal split\n            // Find best split point that balances areas\n            long long best_penalty = 1LL << 60;\n            int best_split = start + 1;\n            \n            for (int split = start + 1; split < end; ++split) {\n                long long area_above = 0;\n                for (int i = start; i < split; ++i) area_above += slots[i].first;\n                long long area_below = total_demand - area_above;\n                \n                // Compute ideal split position\n                int ideal_split_i = i0 + (int)((area_above * height + total_demand/2) / total_demand);\n                if (ideal_split_i <= i0) ideal_split_i = i0 + 1;\n                if (ideal_split_i >= i1) ideal_split_i = i1 - 1;\n                \n                long long actual_above = (long long)(ideal_split_i - i0) * width;\n                long long actual_below = region_area - actual_above;\n                \n                long long penalty = 0;\n                if (actual_above < area_above) penalty += 100 * (area_above - actual_above);\n                if (actual_below < area_below) penalty += 100 * (area_below - actual_below);\n                \n                // Also prefer splits that make rectangles closer to square\n                double aspect_above = (double)(ideal_split_i - i0) / width;\n                double aspect_below = (double)(i1 - ideal_split_i) / width;\n                if (aspect_above < 1) aspect_above = 1.0 / aspect_above;\n                if (aspect_below < 1) aspect_below = 1.0 / aspect_below;\n                long long aspect_penalty = (long long)((aspect_above + aspect_below) * 10);\n                \n                if (penalty + aspect_penalty < best_penalty) {\n                    best_penalty = penalty + aspect_penalty;\n                    best_split = split;\n                }\n            }\n            \n            // Compute actual split position\n            long long area_above = 0;\n            for (int i = start; i < best_split; ++i) area_above += slots[i].first;\n            int split_i = i0 + (int)((area_above * height + total_demand/2) / total_demand);\n            if (split_i <= i0) split_i = i0 + 1;\n            if (split_i >= i1) split_i = i1 - 1;\n            \n            assign(start, best_split, i0, j0, split_i, j1);\n            assign(best_split, end, split_i, j0, i1, j1);\n        } else {\n            // Vertical split\n            long long best_penalty = 1LL << 60;\n            int best_split = start + 1;\n            \n            for (int split = start + 1; split < end; ++split) {\n                long long area_left = 0;\n                for (int i = start; i < split; ++i) area_left += slots[i].first;\n                long long area_right = total_demand - area_left;\n                \n                int ideal_split_j = j0 + (int)((area_left * width + total_demand/2) / total_demand);\n                if (ideal_split_j <= j0) ideal_split_j = j0 + 1;\n                if (ideal_split_j >= j1) ideal_split_j = j1 - 1;\n                \n                long long actual_left = (long long)height * (ideal_split_j - j0);\n                long long actual_right = region_area - actual_left;\n                \n                long long penalty = 0;\n                if (actual_left < area_left) penalty += 100 * (area_left - actual_left);\n                if (actual_right < area_right) penalty += 100 * (area_right - actual_right);\n                \n                double aspect_left = (double)height / (ideal_split_j - j0);\n                double aspect_right = (double)height / (j1 - ideal_split_j);\n                if (aspect_left < 1) aspect_left = 1.0 / aspect_left;\n                if (aspect_right < 1) aspect_right = 1.0 / aspect_right;\n                long long aspect_penalty = (long long)((aspect_left + aspect_right) * 10);\n                \n                if (penalty + aspect_penalty < best_penalty) {\n                    best_penalty = penalty + aspect_penalty;\n                    best_split = split;\n                }\n            }\n            \n            long long area_left = 0;\n            for (int i = start; i < best_split; ++i) area_left += slots[i].first;\n            int split_j = j0 + (int)((area_left * width + total_demand/2) / total_demand);\n            if (split_j <= j0) split_j = j0 + 1;\n            if (split_j >= j1) split_j = j1 - 1;\n            \n            assign(start, best_split, i0, j0, i1, split_j);\n            assign(best_split, end, i0, split_j, i1, j1);\n        }\n    };\n    \n    assign(0, N, 0, 0, 1000, 1000);\n    return rects;\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    // Precompute optimal layout for each day\n    vector<vector<Rect>> day_layouts(D);\n    for (int d = 0; d < D; ++d) {\n        day_layouts[d] = create_layout(a[d]);\n    }\n    \n    // Use DP-like approach: for each day, decide whether to keep previous layout or switch\n    vector<vector<Rect>> output_layouts(D);\n    output_layouts[0] = day_layouts[0];\n    \n    for (int d = 1; d < D; ++d) {\n        // Cost to keep previous layout\n        long long penalty_keep = area_penalty(output_layouts[d-1], a[d]);\n        \n        // Cost to switch to new optimal layout\n        long long change_cost = partition_change_cost(output_layouts[d-1], day_layouts[d], W);\n        long long penalty_new = area_penalty(day_layouts[d], a[d]);\n        \n        // Also consider switching to this day's layout might help future days\n        // Simple heuristic: look ahead one day\n        long long future_benefit = 0;\n        if (d + 1 < D) {\n            // If we switch now, estimate cost for day d+1\n            long long change_next_if_switch = partition_change_cost(day_layouts[d], day_layouts[d+1], W);\n            long long penalty_next_if_switch = area_penalty(day_layouts[d+1], a[d+1]);\n            long long cost_next_if_switch = change_next_if_switch + penalty_next_if_switch;\n            \n            // If we keep current, estimate cost for day d+1\n            long long change_next_if_keep = partition_change_cost(output_layouts[d-1], day_layouts[d+1], W);\n            long long penalty_next_if_keep = area_penalty(day_layouts[d+1], a[d+1]);\n            long long cost_next_if_keep = change_next_if_keep + penalty_next_if_keep;\n            \n            future_benefit = cost_next_if_keep - cost_next_if_switch;\n        }\n        \n        long long cost_keep = penalty_keep;\n        long long cost_switch = change_cost + penalty_new - future_benefit;\n        \n        if (cost_switch < cost_keep) {\n            output_layouts[d] = day_layouts[d];\n        } else {\n            output_layouts[d] = output_layouts[d-1];\n        }\n    }\n\n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cout << output_layouts[d][k].i0 << \" \" << output_layouts[d][k].j0 << \" \"\n                 << output_layouts[d][k].i1 << \" \" << output_layouts[d][k].j1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <tuple>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\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<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> a[i][j];\n\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int s = 0; s < M; s++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> stamps[s][i][j];\n\n    vector<vector<int>> board = a;\n    vector<tuple<int,int,int>> ops;\n\n    // Greedy selection\n    for (int step = 0; step < K; step++) {\n        int best_m = -1, best_p = -1, best_q = -1;\n        long long best_gain = -1;\n\n        for (int m_idx = 0; m_idx < M; m_idx++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    long long gain = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            int old_val = board[p+i][q+j];\n                            int new_val = old_val + stamps[m_idx][i][j];\n                            gain += (new_val % MOD) - (old_val % MOD);\n                        }\n                    }\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_m = m_idx;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n\n        if (best_m == -1) break;\n        ops.emplace_back(best_m, best_p, best_q);\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                board[best_p+i][best_q+j] += stamps[best_m][i][j];\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &[m_idx, p, q] : ops)\n        cout << m_idx << ' ' << p << ' ' << q << '\\n';\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Pos { int x, y; };\nint target_gate(int cid) { return cid / N; }\n\nchar get_dir(int fx, int fy, int tx, int ty) {\n    if (tx == fx-1) return 'U';\n    if (tx == fx+1) return 'D';\n    if (ty == fy-1) return 'L';\n    if (ty == fy+1) return 'R';\n    return '.';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n; cin >> n;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> A[i][j];\n    \n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<queue<int>> recv_queue(N);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            recv_queue[i].push(A[i][j]);\n    \n    int cx[N], cy[N];\n    bool holding[N];\n    int container[N];\n    bool bombed[N];\n    \n    for (int i = 0; i < N; i++) {\n        cx[i] = i; cy[i] = 0;\n        holding[i] = false;\n        container[i] = -1;\n        bombed[i] = false;\n    }\n    \n    int dispatched = 0;\n    vector<string> output(N);\n    int next_for_gate[5] = {0, 5, 10, 15, 20};\n    \n    auto bfs = [&](int sx, int sy, int ex, int ey, bool avoid_containers) -> vector<pair<int,int>> {\n        vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1,-1}));\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        queue<pair<int,int>> q;\n        q.push({sx, sy});\n        visited[sx][sy] = true;\n        \n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            if (x == ex && y == ey) {\n                vector<pair<int,int>> path;\n                while (x != sx || y != sy) {\n                    path.push_back({x, y});\n                    tie(x, y) = parent[x][y];\n                }\n                reverse(path.begin(), path.end());\n                return path;\n            }\n            \n            int dx[] = {-1, 1, 0, 0};\n            int dy[] = {0, 0, -1, 1};\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) continue;\n                if (visited[nx][ny]) continue;\n                \n                bool occupied = false;\n                for (int c = 0; c < N; c++)\n                    if (!bombed[c] && cx[c] == nx && cy[c] == ny) occupied = true;\n                if (occupied) continue;\n                if (avoid_containers && grid[nx][ny] != -1) continue;\n                \n                visited[nx][ny] = true;\n                parent[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n        return {};\n    };\n    \n    for (int turn = 0; turn < MAX_TURNS && dispatched < N * N; turn++) {\n        // Step 1: Spawn\n        for (int i = 0; i < N; i++) {\n            if (!recv_queue[i].empty() && grid[i][0] == -1) {\n                bool blocked = false;\n                for (int c = 0; c < N; c++)\n                    if (!bombed[c] && holding[c] && cx[c] == i && cy[c] == 0)\n                        blocked = true;\n                if (!blocked) {\n                    grid[i][0] = recv_queue[i].front();\n                    recv_queue[i].pop();\n                }\n            }\n        }\n        \n        vector<char> act(N, '.');\n        \n        // Bomb small cranes asynchronously\n        for (int i = 1; i < N; i++) {\n            if (!bombed[i] && !holding[i]) {\n                act[i] = 'B';\n            }\n        }\n        \n        // Large crane\n        if (!bombed[0]) {\n            if (holding[0]) {\n                int cid = container[0];\n                int tgt = target_gate(cid);\n                Pos target;\n                \n                if (cid == next_for_gate[tgt] && grid[tgt][N-1] == -1) {\n                    // Deliver directly to dispatch\n                    target = {tgt, N-1};\n                } else {\n                    // Buffer near target gate\n                    // Try staging area (N-2, N-3) of target row\n                    target = {-1, -1};\n                    for (int col = N-2; col >= 1 && target.x == -1; col--) {\n                        if (grid[tgt][col] == -1) target = {tgt, col};\n                    }\n                    // Fallback: any empty non-gate position\n                    if (target.x == -1) {\n                        for (int col = 1; col < N-1 && target.x == -1; col++) {\n                            for (int row = 0; row < N && target.x == -1; row++) {\n                                if (grid[row][col] == -1) target = {row, col};\n                            }\n                        }\n                    }\n                    // Last resort: dispatch gate (will auto-dispatch)\n                    if (target.x == -1) target = {tgt, N-1};\n                }\n                \n                if (cx[0] == target.x && cy[0] == target.y) {\n                    if (grid[target.x][target.y] == -1) act[0] = 'Q';\n                } else {\n                    auto path = bfs(cx[0], cy[0], target.x, target.y, false);\n                    if (!path.empty()) {\n                        act[0] = get_dir(cx[0], cy[0], path[0].first, path[0].second);\n                    }\n                }\n            } else {\n                // Find best container\n                // Score = priority + distance penalty\n                int best_score = -1e9;\n                Pos best = {-1, -1};\n                \n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (grid[i][j] == -1) continue;\n                        if (j == N-1) continue;\n                        \n                        int cid = grid[i][j];\n                        int tgt = target_gate(cid);\n                        int dist = abs(cx[0] - i) + abs(cy[0] - j);\n                        \n                        int score = 0;\n                        \n                        // Highest priority: next expected and dispatch is empty\n                        if (cid == next_for_gate[tgt] && grid[tgt][N-1] == -1) {\n                            score = 1000000 - dist;\n                        } else {\n                            // Priority for receiving gates (unlock spawning)\n                            if (j == 0) score = 10000 - dist;\n                            else score = 5000 - dist;\n                            \n                            // Bonus for being near target gate\n                            int to_target = abs(i - tgt) + abs(j - (N-1));\n                            score -= to_target;\n                        }\n                        \n                        if (score > best_score) {\n                            best_score = score;\n                            best = {i, j};\n                        }\n                    }\n                }\n                \n                if (best.x != -1) {\n                    if (cx[0] == best.x && cy[0] == best.y) {\n                        act[0] = 'P';\n                    } else {\n                        auto path = bfs(cx[0], cy[0], best.x, best.y, false);\n                        if (!path.empty()) {\n                            act[0] = get_dir(cx[0], cy[0], path[0].first, path[0].second);\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Execute\n        for (int i = 0; i < N; i++) {\n            if (bombed[i]) continue;\n            \n            if (act[i] == 'P') {\n                if (!holding[i] && grid[cx[i]][cy[i]] != -1) {\n                    holding[i] = true;\n                    container[i] = grid[cx[i]][cy[i]];\n                    grid[cx[i]][cy[i]] = -1;\n                }\n            } else if (act[i] == 'Q') {\n                if (holding[i] && grid[cx[i]][cy[i]] == -1) {\n                    grid[cx[i]][cy[i]] = container[i];\n                    holding[i] = false;\n                    container[i] = -1;\n                }\n            } else if (act[i] == 'B') {\n                if (!holding[i]) bombed[i] = true;\n            } else if (act[i] == 'U') cx[i]--;\n            else if (act[i] == 'D') cx[i]++;\n            else if (act[i] == 'L') cy[i]--;\n            else if (act[i] == 'R') cy[i]++;\n        }\n        \n        for (int i = 0; i < N; i++) output[i] += act[i];\n        \n        // Step 3: Auto-dispatch\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N-1] != -1) {\n                int cid = grid[i][N-1];\n                dispatched++;\n                grid[i][N-1] = -1;\n                \n                if (target_gate(cid) == i && cid == next_for_gate[i]) {\n                    next_for_gate[i]++;\n                    if (next_for_gate[i] >= (i+1)*N) next_for_gate[i] = (i+1)*N;\n                }\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)output[i].size());\n    for (int i = 0; i < N; i++)\n        while ((int)output[i].size() < max_len) output[i] += '.';\n    \n    for (int i = 0; i < N; i++) cout << output[i] << '\\n';\n    \n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> h[i][j];\n\n    const int BASE = 100;\n    int cx = 0, cy = 0, load = 0;\n    vector<string> ops;\n\n    auto mdist = [](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_to = [&](int tx, int ty) {\n        while (cx < tx) { ops.push_back(\"D\"); cx++; }\n        while (cx > tx) { ops.push_back(\"U\"); cx--; }\n        while (cy < ty) { ops.push_back(\"R\"); cy++; }\n        while (cy > ty) { ops.push_back(\"L\"); cy--; }\n    };\n\n    auto deliver_load = [&]() {\n        // Collect up to 7 nearest negatives\n        vector<pair<int,pair<int,int>>> negs;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (h[i][j] < 0)\n                    negs.push_back({mdist(cx, cy, i, j), {i, j}});\n        sort(negs.begin(), negs.end());\n        int k = min((int)negs.size(), 7);\n        negs.resize(k);\n        \n        if (k == 1) {\n            auto [d, coords] = negs[0];\n            auto [ni, nj] = coords;\n            move_to(ni, nj);\n            int unload = min(load, -h[ni][nj]);\n            ops.push_back(\"-\" + to_string(unload));\n            h[ni][nj] += unload;\n            load -= unload;\n        } else if (k > 1) {\n            vector<int> perm(k);\n            iota(perm.begin(), perm.end(), 0);\n            int best_total_cost = 1e9;\n            vector<int> best_order;\n            \n            do {\n                int total = 0;\n                int sim_load = load;\n                int sx = cx, sy = cy;\n                for (int idx : perm) {\n                    auto [d, coords] = negs[idx];\n                    auto [ni, nj] = coords;\n                    total += mdist(sx, sy, ni, nj) * (BASE + sim_load);\n                    int need = -h[ni][nj];\n                    int deliver = min(sim_load, need);\n                    sim_load -= deliver;\n                    sx = ni; sy = nj;\n                    if (sim_load == 0) break;\n                }\n                if (total < best_total_cost) {\n                    best_total_cost = total;\n                    best_order = perm;\n                }\n            } while (next_permutation(perm.begin(), perm.end()));\n            \n            for (int idx : best_order) {\n                if (load == 0) break;\n                auto [d, coords] = negs[idx];\n                auto [ni, nj] = coords;\n                move_to(ni, nj);\n                int unload = min(load, -h[ni][nj]);\n                ops.push_back(\"-\" + to_string(unload));\n                h[ni][nj] += unload;\n                load -= unload;\n            }\n        }\n        // If there are still negatives and we have load, continue delivering\n        // (This handles the case where we visited some negatives but not all)\n        while (load > 0) {\n            int best_d = 1e9, ni = -1, nj = -1;\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (h[i][j] < 0) {\n                        int d = mdist(cx, cy, i, j);\n                        if (d < best_d) { best_d = d; ni = i; nj = j; }\n                    }\n            if (ni == -1) break;\n            move_to(ni, nj);\n            int unload = min(load, -h[ni][nj]);\n            ops.push_back(\"-\" + to_string(unload));\n            h[ni][nj] += unload;\n            load -= unload;\n        }\n    };\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (h[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n\n        if (load > 0) {\n            deliver_load();\n            continue;\n        }\n\n        // load == 0: choose the best starting positive\n        // Strategy: evaluate each positive as a \"seed\" for a multi-pickup trip\n        // We'll simulate: go to seed, then collect nearby positives greedily, then deliver\n        \n        int best_total_cost = 1e9;\n        int best_seed_x = -1, best_seed_y = -1;\n        \n        for (int seed_i = 0; seed_i < N; seed_i++) {\n            for (int seed_j = 0; seed_j < N; seed_j++) {\n                if (h[seed_i][seed_j] <= 0) continue;\n                \n                // Simulate a trip starting from this seed\n                int total_cost = mdist(cx, cy, seed_i, seed_j) * BASE;\n                int sim_load = h[seed_i][seed_j];\n                int sx = seed_i, sy = seed_j;\n                \n                // Make a copy of positive heights for simulation\n                vector<vector<int>> sim_pos(N, vector<int>(N, 0));\n                for (int i = 0; i < N; i++)\n                    for (int j = 0; j < N; j++)\n                        if (h[i][j] > 0)\n                            sim_pos[i][j] = h[i][j];\n                sim_pos[seed_i][seed_j] = 0;\n                \n                // Greedily collect nearby positives\n                while (true) {\n                    int best_pi = -1, best_pj = -1, best_d = 1e9;\n                    for (int i = 0; i < N; i++)\n                        for (int j = 0; j < N; j++)\n                            if (sim_pos[i][j] > 0) {\n                                int d = mdist(sx, sy, i, j);\n                                if (d < best_d) { best_d = d; best_pi = i; best_pj = j; }\n                            }\n                    if (best_pi == -1) break;\n                    \n                    // Decide if we should collect this positive\n                    // Heuristic: collect if distance <= 5 or if it's on the way to negatives\n                    // Also consider: the cost of detour vs benefit of not making separate trip\n                    int detour_cost = best_d * (BASE + sim_load);\n                    int future_empty_cost = best_d * BASE; // rough estimate of coming back later\n                    // We also save the delivery cost for this positive's soil separately\n                    // Simplified: collect if distance <= 5\n                    if (best_d <= 5) {\n                        total_cost += best_d * (BASE + sim_load);\n                        sim_load += sim_pos[best_pi][best_pj];\n                        sim_pos[best_pi][best_pj] = 0;\n                        sx = best_pi; sy = best_pj;\n                    } else {\n                        break;\n                    }\n                }\n                \n                // Now simulate delivering sim_load to negatives\n                // Use greedy nearest-negative delivery for simulation\n                int del_sx = sx, del_sy = sy;\n                int del_load = sim_load;\n                vector<vector<int>> sim_neg(N, vector<int>(N, 0));\n                for (int i = 0; i < N; i++)\n                    for (int j = 0; j < N; j++)\n                        if (h[i][j] < 0)\n                            sim_neg[i][j] = -h[i][j]; // store positive demand\n                \n                bool possible = true;\n                while (del_load > 0) {\n                    int best_ni = -1, best_nj = -1, best_d = 1e9;\n                    for (int i = 0; i < N; i++)\n                        for (int j = 0; j < N; j++)\n                            if (sim_neg[i][j] > 0) {\n                                int d = mdist(del_sx, del_sy, i, j);\n                                if (d < best_d) { best_d = d; best_ni = i; best_nj = j; }\n                            }\n                    if (best_ni == -1) { possible = false; break; }\n                    total_cost += best_d * (BASE + del_load);\n                    int deliver = min(del_load, sim_neg[best_ni][best_nj]);\n                    del_load -= deliver;\n                    sim_neg[best_ni][best_nj] -= deliver;\n                    del_sx = best_ni; del_sy = best_nj;\n                }\n                \n                if (!possible) continue;\n                \n                if (total_cost < best_total_cost) {\n                    best_total_cost = total_cost;\n                    best_seed_x = seed_i;\n                    best_seed_y = seed_j;\n                }\n            }\n        }\n\n        if (best_seed_x == -1) break;\n\n        // Execute the multi-pickup trip\n        // Move to seed\n        move_to(best_seed_x, best_seed_y);\n        int amount = h[best_seed_x][best_seed_y];\n        ops.push_back(\"+\" + to_string(amount));\n        load += amount;\n        h[best_seed_x][best_seed_y] = 0;\n\n        // Collect nearby positives (distance <= 5)\n        while (true) {\n            int best_pi = -1, best_pj = -1, best_d = 1e9;\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (h[i][j] > 0) {\n                        int d = mdist(cx, cy, i, j);\n                        if (d < best_d) { best_d = d; best_pi = i; best_pj = j; }\n                    }\n            if (best_pi == -1 || best_d > 5) break;\n            \n            move_to(best_pi, best_pj);\n            int amt = h[best_pi][best_pj];\n            ops.push_back(\"+\" + to_string(amt));\n            load += amt;\n            h[best_pi][best_pj] = 0;\n        }\n\n        // Deliver all load\n        deliver_load();\n    }\n\n    for (const auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <queue>\n#include <cmath>\n#include <cassert>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int seed_count = 2 * N * (N - 1);\n    vector<vector<int>> X(seed_count, vector<int>(M, 0));\n\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    // Track global maximums per dimension\n    vector<int> global_dim_max(M, 0);\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            global_dim_max[j] = max(global_dim_max[j], X[i][j]);\n        }\n    }\n\n    for (int t = 0; t < T; t++) {\n        // Compute values\n        vector<int> seed_val(seed_count, 0);\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                seed_val[i] += X[i][j];\n            }\n        }\n        \n        // Current max per dimension\n        vector<int> current_dim_max(M, 0);\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                current_dim_max[j] = max(current_dim_max[j], X[i][j]);\n            }\n        }\n        \n        // Selection\n        vector<int> selected;\n        set<int> selected_set;\n        \n        if (t < 3) {\n            // Early turns: Focus on preserving genes that carry dimension maximums\n            \n            // Identify carriers\n            vector<bool> is_carrier(seed_count, false);\n            for (int i = 0; i < seed_count; i++) {\n                for (int j = 0; j < M; j++) {\n                    if (X[i][j] == current_dim_max[j]) {\n                        is_carrier[i] = true;\n                        break;\n                    }\n                }\n            }\n            \n            // Calculate a composite score\n            vector<pair<int, int>> scores;\n            for (int i = 0; i < seed_count; i++) {\n                int score = seed_val[i];\n                if (is_carrier[i]) score += 500;  // Big bonus for carriers\n                scores.push_back({score, i});\n            }\n            sort(scores.begin(), scores.end(), greater<pair<int, int>>());\n            \n            for (int i = 0; i < N * N && i < (int)scores.size(); i++) {\n                selected.push_back(scores[i].second);\n                selected_set.insert(scores[i].second);\n            }\n        } else if (t < 7) {\n            // Middle turns: Balance value with diversity\n            // Count how many seeds carry each dimension's max\n            vector<int> carrier_count(M, 0);\n            for (int i = 0; i < seed_count; i++) {\n                for (int j = 0; j < M; j++) {\n                    if (X[i][j] == current_dim_max[j]) {\n                        carrier_count[j]++;\n                    }\n                }\n            }\n            \n            vector<pair<int, int>> scores;\n            for (int i = 0; i < seed_count; i++) {\n                int score = seed_val[i] * 100;\n                // Bonus for carrying rare maximums\n                for (int j = 0; j < M; j++) {\n                    if (X[i][j] == current_dim_max[j] && carrier_count[j] < 10) {\n                        score += 1000;  // Significant bonus for rare genes\n                    }\n                }\n                scores.push_back({score, i});\n            }\n            sort(scores.begin(), scores.end(), greater<pair<int, int>>());\n            \n            for (int i = 0; i < N * N && i < (int)scores.size(); i++) {\n                selected.push_back(scores[i].second);\n                selected_set.insert(scores[i].second);\n            }\n        } else {\n            // Late turns: Pure value\n            vector<pair<int, int>> by_val;\n            for (int i = 0; i < seed_count; i++) {\n                by_val.push_back({seed_val[i], i});\n            }\n            sort(by_val.begin(), by_val.end(), greater<pair<int, int>>());\n            \n            for (int i = 0; i < N * N && i < seed_count; i++) {\n                selected.push_back(by_val[i].second);\n                selected_set.insert(by_val[i].second);\n            }\n        }\n        \n        // Fill to exactly N*N\n        while ((int)selected.size() < N * N) {\n            for (int i = 0; i < seed_count && (int)selected.size() < N * N; i++) {\n                if (selected_set.find(i) == selected_set.end()) {\n                    selected.push_back(i);\n                    selected_set.insert(i);\n                }\n            }\n        }\n        selected.resize(N * N);\n        \n        // Sort selected by value for placement\n        vector<pair<int, int>> sel_sorted;\n        for (int idx : selected) {\n            sel_sorted.push_back({seed_val[idx], idx});\n        }\n        sort(sel_sorted.begin(), sel_sorted.end(), greater<pair<int, int>>());\n        vector<int> sorted_seeds;\n        for (auto& p : sel_sorted) sorted_seeds.push_back(p.second);\n        \n        // Grid arrangement\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        \n        if (t < 2) {\n            // Early: Snake pattern for wide mixing\n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                if (i % 2 == 0) {\n                    for (int j = 0; j < N; j++) {\n                        A[i][j] = sorted_seeds[pos++];\n                    }\n                } else {\n                    for (int j = N - 1; j >= 0; j--) {\n                        A[i][j] = sorted_seeds[pos++];\n                    }\n                }\n            }\n        } else if (t < 4) {\n            // Early-middle: Checkerboard to maximize gene mixing\n            // Split into two halves\n            vector<int> top_half, bottom_half;\n            for (int i = 0; i < (int)sorted_seeds.size(); i++) {\n                if (i < (int)sorted_seeds.size() / 2) {\n                    top_half.push_back(sorted_seeds[i]);\n                } else {\n                    bottom_half.push_back(sorted_seeds[i]);\n                }\n            }\n            \n            int pa = 0, pb = 0;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if ((i + j) % 2 == 0) {\n                        if (pa < (int)top_half.size()) {\n                            A[i][j] = top_half[pa++];\n                        } else if (pb < (int)bottom_half.size()) {\n                            A[i][j] = bottom_half[pb++];\n                        }\n                    } else {\n                        if (pb < (int)bottom_half.size()) {\n                            A[i][j] = bottom_half[pb++];\n                        } else if (pa < (int)top_half.size()) {\n                            A[i][j] = top_half[pa++];\n                        }\n                    }\n                }\n            }\n        } else if (t < 6) {\n            // Middle: Concentric - best seeds in center\n            vector<pair<int, int>> positions;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    positions.push_back({i, j});\n                }\n            }\n            \n            double cx = (N - 1) / 2.0, cy = (N - 1) / 2.0;\n            sort(positions.begin(), positions.end(), \n                 [cx, cy](const pair<int,int>& a, const pair<int,int>& b) {\n                     double da = pow(a.first - cx, 2) + pow(a.second - cy, 2);\n                     double db = pow(b.first - cx, 2) + pow(b.second - cy, 2);\n                     if (abs(da - db) < 1e-9) {\n                         return a.first * 100 + a.second < b.first * 100 + b.second;\n                     }\n                     return da < db;\n                 });\n            \n            for (int idx = 0; idx < (int)sorted_seeds.size(); idx++) {\n                A[positions[idx].first][positions[idx].second] = sorted_seeds[idx];\n            }\n        } else if (t < 8) {\n            // Late-middle: Horizontal stripes to create many adjacencies between similar seeds\n            // This allows good combinations to spread\n            int pos = 0;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    A[i][j] = sorted_seeds[pos++];\n                }\n            }\n        } else {\n            // Final turns: BFS from center to cluster best seeds\n            int start_i = N / 2, start_j = N / 2;\n            int seed_idx = 0;\n            \n            // Use BFS with fixed direction order\n            queue<pair<int, int>> q;\n            set<int> placed_pos;\n            \n            A[start_i][start_j] = sorted_seeds[seed_idx++];\n            placed_pos.insert(start_i * N + start_j);\n            q.push({start_i, start_j});\n            \n            const int di[] = {-1, 1, 0, 0};\n            const int dj[] = {0, 0, -1, 1};\n            \n            while (!q.empty() && seed_idx < (int)sorted_seeds.size()) {\n                auto [i, j] = q.front();\n                q.pop();\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = i + di[d];\n                    int nj = j + dj[d];\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N && \n                        placed_pos.find(ni * N + nj) == placed_pos.end()) {\n                        A[ni][nj] = sorted_seeds[seed_idx++];\n                        placed_pos.insert(ni * N + nj);\n                        q.push({ni, nj});\n                    }\n                }\n            }\n            \n            // Fill any remaining holes (should be none, but just in case)\n            for (int i = 0; i < N && seed_idx < (int)sorted_seeds.size(); i++) {\n                for (int j = 0; j < N && seed_idx < (int)sorted_seeds.size(); j++) {\n                    if (A[i][j] == -1) {\n                        A[i][j] = sorted_seeds[seed_idx++];\n                        placed_pos.insert(i * N + j);\n                    }\n                }\n            }\n        }\n        \n        // Final verification: ensure all positions are filled\n        // If any position is still -1, fill it with the best available unused seed\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (A[i][j] == -1) {\n                    // Find an unused seed\n                    for (int k = 0; k < seed_count; k++) {\n                        if (selected_set.find(k) == selected_set.end()) {\n                            A[i][j] = k;\n                            selected_set.insert(k);\n                            break;\n                        }\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 << A[i][j];\n                if (j < N - 1) cout << \" \";\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read new seeds\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                global_dim_max[j] = max(global_dim_max[j], X[i][j]);\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <queue>\n#include <cmath>\n#include <cassert>\n#include <set>\n#include <map>\n#include <random>\n#include <chrono>\nusing namespace std;\n\n// ---------- Constants ----------\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\nconst char MOVE_CHAR[4] = {'R', 'D', 'L', 'U'};\n\n// ---------- Types ----------\nstruct Point {\n    int x, y;\n    Point operator+(Point o) const { return {x+o.x, y+o.y}; }\n    bool operator==(Point o) const { return x==o.x && y==o.y; }\n};\n\n// ---------- Global state ----------\nint N, M, V;\nvector<string> start_grid, target_grid;\nvector<pair<int,int>> start_positions, target_positions;\nvector<int> parent;\nvector<int> length_to_parent;\nvector<int> leaf_order; // leaves index\nint root_x, root_y;\nvector<int> angles; // direction index (0: right, 1: down, 2: left, 3: up)\nvector<bool> holding; // true if fingertip carrying takoyaki\nvector<Point> fingertip_positions;\nvector<vector<int>> children;\n\n// ---------- Function declarations ----------\nvoid design_tree();\nvoid compute_fingertip_positions();\nvoid simulate_turn(vector<string>& commands, int& turn);\nbool pick_if_possible(int leaf_idx);\nbool place_if_possible(int leaf_idx);\nvoid move_root_to_target(Point target, vector<string>& commands);\nvoid set_angle(int node, int desired_angle, vector<string>& commands);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Read input\n    cin >> N >> M >> V;\n    start_grid.resize(N);\n    target_grid.resize(N);\n    for (int i = 0; i < N; i++) cin >> start_grid[i];\n    for (int i = 0; i < N; i++) cin >> target_grid[i];\n\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (start_grid[i][j] == '1')\n                start_positions.emplace_back(i, j);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (target_grid[i][j] == '1')\n                target_positions.emplace_back(i, j);\n\n    // Design tree\n    design_tree();\n\n    // Set initial root near center of start positions\n    int sumx = 0, sumy = 0;\n    for (auto& p : start_positions) { sumx += p.first; sumy += p.second; }\n    root_x = sumx / M;\n    root_y = sumy / M;\n    root_x = min(max(root_x, 0), N-1);\n    root_y = min(max(root_y, 0), N-1);\n\n    // Output tree info\n    int Vp = parent.size();\n    cout << Vp << \"\\n\";\n    for (int i = 1; i < Vp; i++)\n        cout << parent[i] << \" \" << length_to_parent[i] << \"\\n\";\n    cout << root_x << \" \" << root_y << \"\\n\";\n\n    angles.assign(Vp, 0); // all edges initially to the right\n    holding.assign(Vp, false);\n\n    // Identify leaves\n    vector<bool> is_leaf(Vp, false);\n    for (int i = 0; i < Vp; i++) {\n        if (children[i].empty()) {\n            is_leaf[i] = true;\n            leaf_order.push_back(i);\n        }\n    }\n\n    // Simulation\n    vector<string> commands;\n    int turn = 0;\n    const int MAX_TURNS = 100000;\n\n    // Simple greedy assignment: for each leaf, find nearest start->target pair\n    vector<tuple<int,int,int>> tasks; // (dist, start_idx, target_idx)\n    for (size_t si = 0; si < start_positions.size(); si++) {\n        int best_ti = -1;\n        int best_dist = 1e9;\n        for (size_t ti = 0; ti < target_positions.size(); ti++) {\n            int d = abs(start_positions[si].first - target_positions[ti].first)\n                   + abs(start_positions[si].second - target_positions[ti].second);\n            if (d < best_dist) {\n                best_dist = d;\n                best_ti = ti;\n            }\n        }\n        tasks.emplace_back(best_dist, si, best_ti);\n    }\n    sort(tasks.begin(), tasks.end());\n\n    vector<bool> start_done(start_positions.size(), false);\n    vector<bool> target_done(target_positions.size(), false);\n    int placed = 0;\n\n    auto try_move_leaf_to = [&](int leaf, Point target) {\n        // move root toward target, then set leaf angle\n        while (turn < MAX_TURNS) {\n            Point cur = fingertip_positions[leaf];\n            if (cur.x == target.x && cur.y == target.y) break;\n            // move root greedily\n            int dx = target.x - cur.x;\n            int dy = target.y - cur.y;\n            int mx = (dx > 0) - (dx < 0);\n            int my = (dy > 0) - (dy < 0);\n            if (mx != 0 || my != 0) {\n                int dir = -1;\n                if (mx == 1 && my == 0) dir = 1; // down\n                else if (mx == -1 && my == 0) dir = 3; // up\n                else if (mx == 0 && my == 1) dir = 0; // right\n                else if (mx == 0 && my == -1) dir = 2; // left\n                else if (mx == 1 && my == 1) dir = (rand()%2) ? 1 : 0;\n                else if (mx == -1 && my == 1) dir = (rand()%2) ? 3 : 0;\n                else if (mx == 1 && my == -1) dir = (rand()%2) ? 1 : 2;\n                else if (mx == -1 && my == -1) dir = (rand()%2) ? 3 : 2;\n                if (dir >= 0) {\n                    int nx = root_x + DX[dir];\n                    int ny = root_y + DY[dir];\n                    if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n                        root_x = nx; root_y = ny;\n                        string cmd(2*Vp, '.');\n                        cmd[0] = MOVE_CHAR[dir];\n                        commands.push_back(cmd);\n                        turn++;\n                        compute_fingertip_positions();\n                        continue;\n                    }\n                }\n            }\n            // rotation to adjust fingertip if close\n            if (abs(cur.x - target.x) <= 1 && abs(cur.y - target.y) <= 1) {\n                for (int a = 0; a < 4; a++) {\n                    angles[leaf] = a;\n                    compute_fingertip_positions();\n                    if (fingertip_positions[leaf].x == target.x && fingertip_positions[leaf].y == target.y) {\n                        string cmd(2*Vp, '.');\n                        cmd[leaf] = (a == (angles[leaf]+3)%4) ? 'L' : ((a == (angles[leaf]+1)%4) ? 'R' : '.');\n                        commands.push_back(cmd);\n                        turn++;\n                        return;\n                    }\n                }\n            }\n        }\n    };\n\n    for (auto& [dist, si, ti] : tasks) {\n        if (start_done[si] || target_done[ti]) continue;\n        Point sp = {start_positions[si].first, start_positions[si].second};\n        Point tp = {target_positions[ti].first, target_positions[ti].second};\n\n        int leaf = leaf_order[0]; // simple: use first leaf for everything\n\n        // go to start\n        try_move_leaf_to(leaf, sp);\n        // pick\n        if (fingertip_positions[leaf] == sp && !holding[leaf] && start_grid[sp.x][sp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = true;\n            start_grid[sp.x][sp.y] = '0';\n            turn++;\n        }\n        // go to target\n        try_move_leaf_to(leaf, tp);\n        // place\n        if (fingertip_positions[leaf] == tp && holding[leaf] && target_grid[tp.x][tp.y]=='1') {\n            string cmd(2*Vp, '.');\n            cmd[Vp + leaf] = 'P';\n            commands.push_back(cmd);\n            holding[leaf] = false;\n            target_grid[tp.x][tp.y] = '0';\n            placed++;\n            turn++;\n        }\n        start_done[si] = true;\n        target_done[ti] = true;\n    }\n\n    for (auto& s : commands) cout << s << \"\\n\";\n    return 0;\n}\n\nvoid design_tree() {\n    // simple star-like: root + V-1 leaves with length 1..N-1\n    parent.push_back(-1);\n    length_to_parent.push_back(0);\n    children.resize(1);\n    for (int i = 1; i < V; i++) {\n        parent.push_back(0);\n        length_to_parent.push_back(1);\n        children[0].push_back(i);\n        children.push_back({});\n    }\n}\n\nvoid compute_fingertip_positions() {\n    fingertip_positions.resize(parent.size());\n    fingertip_positions[0] = {root_x, root_y};\n    for (int i = 1; i < (int)parent.size(); i++) {\n        int p = parent[i];\n        int len = length_to_parent[i];\n        int dir = angles[i];\n        Point offset = {DX[dir]*len, DY[dir]*len};\n        fingertip_positions[i] = fingertip_positions[p] + offset;\n    }\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_COORD = 100000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<int> mx(N), my(N), sx(N), sy(N);\n    for (int i = 0; i < N; i++) cin >> mx[i] >> my[i];\n    for (int i = 0; i < N; i++) cin >> sx[i] >> sy[i];\n    \n    // Build compressed coordinates\n    vector<int> xVals = {0, MAX_COORD}, yVals = {0, MAX_COORD};\n    for (int i = 0; i < N; i++) {\n        xVals.push_back(mx[i]); xVals.push_back(sx[i]);\n        yVals.push_back(my[i]); yVals.push_back(sy[i]);\n    }\n    sort(xVals.begin(), xVals.end());\n    xVals.erase(unique(xVals.begin(), xVals.end()), xVals.end());\n    sort(yVals.begin(), yVals.end());\n    yVals.erase(unique(yVals.begin(), yVals.end()), yVals.end());\n    \n    // Subsample\n    vector<int> xs = xVals, ys = yVals;\n    if ((int)xs.size() > 500) {\n        vector<int> nx; int step = xs.size() / 500;\n        for (int i = 0; i < (int)xs.size(); i += step) nx.push_back(xs[i]);\n        if (nx.back() != xs.back()) nx.push_back(xs.back());\n        xs = nx;\n    }\n    if ((int)ys.size() > 500) {\n        vector<int> ny; int step = ys.size() / 500;\n        for (int i = 0; i < (int)ys.size(); i += step) ny.push_back(ys[i]);\n        if (ny.back() != ys.back()) ny.push_back(ys.back());\n        ys = ny;\n    }\n    \n    int X = xs.size(), Y = ys.size();\n    \n    // Prefix sums\n    vector<vector<int>> mPref(Y + 1, vector<int>(X + 1, 0));\n    vector<vector<int>> sPref(Y + 1, vector<int>(X + 1, 0));\n    \n    for (int i = 0; i < N; i++) {\n        int ix = lower_bound(xs.begin(), xs.end(), mx[i]) - xs.begin();\n        int iy = lower_bound(ys.begin(), ys.end(), my[i]) - ys.begin();\n        if (ix < X && iy < Y) mPref[iy + 1][ix + 1]++;\n    }\n    for (int i = 0; i < N; i++) {\n        int ix = lower_bound(xs.begin(), xs.end(), sx[i]) - xs.begin();\n        int iy = lower_bound(ys.begin(), ys.end(), sy[i]) - ys.begin();\n        if (ix < X && iy < Y) sPref[iy + 1][ix + 1]++;\n    }\n    \n    for (int i = 0; i < Y; i++)\n        for (int j = 0; j < X; j++) {\n            mPref[i+1][j+1] += mPref[i][j+1] + mPref[i+1][j] - mPref[i][j];\n            sPref[i+1][j+1] += sPref[i][j+1] + sPref[i+1][j] - sPref[i][j];\n        }\n    \n    auto scoreComp = [&](int ix1, int ix2, int iy1, int iy2) {\n        if (ix1 > ix2 || iy1 > iy2) return 0;\n        int m = mPref[iy2+1][ix2+1] - mPref[iy1][ix2+1] - mPref[iy2+1][ix1] + mPref[iy1][ix1];\n        int s = sPref[iy2+1][ix2+1] - sPref[iy1][ix2+1] - sPref[iy2+1][ix1] + sPref[iy1][ix1];\n        return m - s;\n    };\n    \n    // Grid for initial search\n    const int G = 80;\n    int cellW = (MAX_COORD + G - 1) / G, cellH = (MAX_COORD + G - 1) / G;\n    \n    vector<vector<int>> val(G, vector<int>(G, 0));\n    for (int i = 0; i < G; i++) {\n        for (int j = 0; j < G; j++) {\n            int ix1 = lower_bound(xs.begin(), xs.end(), j*cellW) - xs.begin();\n            int ix2 = upper_bound(xs.begin(), xs.end(), min(MAX_COORD, (j+1)*cellW)) - xs.begin() - 1;\n            int iy1 = lower_bound(ys.begin(), ys.end(), i*cellH) - ys.begin();\n            int iy2 = upper_bound(ys.begin(), ys.end(), min(MAX_COORD, (i+1)*cellH)) - ys.begin() - 1;\n            val[i][j] = scoreComp(ix1, ix2, iy1, iy2);\n        }\n    }\n    \n    vector<vector<int>> prefG(G + 1, vector<int>(G + 1, 0));\n    for (int i = 0; i < G; i++)\n        for (int j = 0; j < G; j++)\n            prefG[i+1][j+1] = val[i][j] + prefG[i][j+1] + prefG[i+1][j] - prefG[i][j];\n    \n    auto getSumG = [&](int r1, int c1, int r2, int c2) {\n        return prefG[r2+1][c2+1] - prefG[r1][c2+1] - prefG[r2+1][c1] + prefG[r1][c1];\n    };\n    \n    // Find rectangles\n    struct Rect { int r1, c1, r2, c2, val; };\n    vector<Rect> rects;\n    \n    for (int r1 = 0; r1 < G; r1++) {\n        vector<int> rowSum(G, 0);\n        for (int r2 = r1; r2 < G; r2++) {\n            for (int c = 0; c < G; c++) rowSum[c] += val[r2][c];\n            int curr = 0, maxS = -1e9, cS = 0, cB = 0, cE = 0;\n            for (int c = 0; c < G; c++) {\n                if (curr <= 0) { curr = rowSum[c]; cS = c; }\n                else curr += rowSum[c];\n                if (curr > maxS) { maxS = curr; cB = cS; cE = c; }\n            }\n            if (maxS > 0) rects.push_back({r1, cB, r2, cE, maxS});\n        }\n    }\n    \n    sort(rects.begin(), rects.end(), [](const Rect &a, const Rect &b) { return a.val > b.val; });\n    if (rects.size() > 20) rects.resize(20);\n    \n    int bestScore = -1e9;\n    vector<pair<int,int>> bestPolygon;\n    \n    // Inner points for shape search\n    vector<int> iX, iY;\n    int stepX = max(1, X / 25), stepY = max(1, Y / 25);\n    for (int i = 0; i < X; i += stepX) iX.push_back(i);\n    for (int i = 0; i < Y; i += stepY) iY.push_back(i);\n    \n    for (auto &rc : rects) {\n        int ix1 = lower_bound(xs.begin(), xs.end(), rc.c1 * cellW) - xs.begin();\n        int ix2 = upper_bound(xs.begin(), xs.end(), min(MAX_COORD, (rc.c2+1)*cellW)) - xs.begin() - 1;\n        int iy1 = lower_bound(ys.begin(), ys.end(), rc.r1 * cellH) - ys.begin();\n        int iy2 = upper_bound(ys.begin(), ys.end(), min(MAX_COORD, (rc.r2+1)*cellH)) - ys.begin() - 1;\n        \n        if (ix1 >= ix2 || iy1 >= iy2) continue;\n        \n        int curScore = scoreComp(ix1, ix2, iy1, iy2);\n        \n        // Refine boundaries\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = ix1+1; i <= ix2; i++) {\n                int s = scoreComp(i, ix2, iy1, iy2);\n                if (s > curScore) { curScore = s; ix1 = i; changed = true; break; }\n            }\n            if (changed) continue;\n            for (int i = ix2-1; i >= ix1; i--) {\n                int s = scoreComp(ix1, i, iy1, iy2);\n                if (s > curScore) { curScore = s; ix2 = i; changed = true; break; }\n            }\n            if (changed) continue;\n            for (int i = iy1+1; i <= iy2; i++) {\n                int s = scoreComp(ix1, ix2, i, iy2);\n                if (s > curScore) { curScore = s; iy1 = i; changed = true; break; }\n            }\n            if (changed) continue;\n            for (int i = iy2-1; i >= iy1; i--) {\n                int s = scoreComp(ix1, ix2, iy1, i);\n                if (s > curScore) { curScore = s; iy2 = i; changed = true; break; }\n            }\n        }\n        \n        int x1 = xs[ix1], x2 = xs[ix2], y1 = ys[iy1], y2 = ys[iy2];\n        \n        struct Shape { vector<pair<int,int>> v; int score; };\n        vector<Shape> shapes;\n        shapes.push_back({{{x1,y1},{x2,y1},{x2,y2},{x1,y2}}, curScore});\n        \n        // L-shapes\n        for (int icx : iX) {\n            int cx = xs[icx]; if (cx <= x1 || cx >= x2) continue;\n            for (int icy : iY) {\n                int cy = ys[icy]; if (cy <= y1 || cy >= y2) continue;\n                \n                int s = scoreComp(icx, ix2, iy1, iy2) + scoreComp(ix1, icx-1, icy, iy2);\n                if (s > curScore) shapes.push_back({{{cx,cy},{x2,cy},{x2,y2},{x1,y2},{x1,y1},{cx,y1}}, s});\n                \n                s = scoreComp(ix1, icx, iy1, iy2) + scoreComp(icx+1, ix2, icy, iy2);\n                if (s > curScore) shapes.push_back({{{cx,cy},{x1,cy},{x1,y2},{x2,y2},{x2,y1},{cx,y1}}, s});\n                \n                s = scoreComp(ix1, ix2, iy1, icy) + scoreComp(ix1, icx, icy+1, iy2);\n                if (s > curScore) shapes.push_back({{{cx,cy},{x1,cy},{x1,y1},{x2,y1},{x2,y2},{cx,y2}}, s});\n                \n                s = scoreComp(ix1, ix2, iy1, icy) + scoreComp(icx, ix2, icy+1, iy2);\n                if (s > curScore) shapes.push_back({{{cx,cy},{x2,cy},{x2,y1},{x1,y1},{x1,y2},{cx,y2}}, s});\n            }\n        }\n        \n        // C-shapes (bottom only for speed)\n        if (shapes.size() < 80) {\n            for (int icy : iY) {\n                int cy = ys[icy]; if (cy <= y1 || cy >= y2) continue;\n                for (int icx1 : iX) {\n                    int cx1 = xs[icx1]; if (cx1 <= x1 || cx1 >= x2) continue;\n                    for (int icx2 : iX) {\n                        int cx2 = xs[icx2]; if (cx2 <= cx1 || cx2 >= x2) continue;\n                        int s = scoreComp(ix1, icx1, iy1, iy2) + \n                                scoreComp(icx2, ix2, iy1, iy2) + \n                                scoreComp(icx1, icx2-1, icy, iy2);\n                        if (s > curScore)\n                            shapes.push_back({{{cx1,cy},{cx2,cy},{cx2,y1},{x2,y1},{x2,y2},\n                                             {x1,y2},{x1,y1},{cx1,y1}}, s});\n                    }\n                }\n            }\n        }\n        \n        // Evaluate\n        for (auto &sh : shapes) {\n            auto &v = sh.v;\n            int sz = v.size();\n            vector<pair<int,int>> simp;\n            for (int i = 0; i < sz; i++) {\n                int p = (i-1+sz)%sz, n = (i+1)%sz;\n                if (!((v[p].first==v[i].first && v[i].first==v[n].first) ||\n                      (v[p].second==v[i].second && v[i].second==v[n].second)))\n                    simp.push_back(v[i]);\n            }\n            if (simp.size() < 4) simp = v;\n            if ((int)simp.size() > 1000) continue;\n            \n            long long perim = 0;\n            for (int i = 0; i < (int)simp.size(); i++) {\n                int j = (i+1)%simp.size();\n                perim += abs(simp[i].first-simp[j].first) + abs(simp[i].second-simp[j].second);\n            }\n            if (perim > 400000) continue;\n            \n            if (sh.score > bestScore) {\n                bestScore = sh.score;\n                bestPolygon = simp;\n            }\n        }\n    }\n    \n    if (bestPolygon.empty()) {\n        bestPolygon = {{0,0},{100,0},{100,100},{0,100}};\n    }\n    \n    cout << bestPolygon.size() << \"\\n\";\n    for (auto [x,y] : bestPolygon) cout << x << \" \" << y << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T, sigma;\nvector<long long> est_w, est_h;\n\nstruct Placement {\n    int p, r, d;\n    int b;\n};\n\npair<long long, long long> query(const vector<Placement>& placements) {\n    cout << placements.size() << \"\\n\";\n    for (const auto& pl : placements) {\n        cout << pl.p << \" \" << pl.r << \" \" << (pl.d == 0 ? \"U\" : \"L\") << \" \" << pl.b << \"\\n\";\n    }\n    cout.flush();\n    long long W, H;\n    cin >> W >> H;\n    return {W, H};\n}\n\n// Core greedy packing with configurable parameters\nvector<Placement> pack(double skip_mult, bool prefer_U, bool rotate_all, bool rotate_none) {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long, int>> placed; // x, y, w, h, id\n    \n    for (int idx = 0; idx < N; idx++) {\n        long long w_orig = est_w[idx];\n        long long h_orig = est_h[idx];\n        \n        struct Option {\n            Placement p;\n            long long x, y, w, h, new_W, new_H;\n            bool skip;\n        };\n        const long long INF = 1LL << 60;\n        Option best;\n        best.new_W = INF; best.new_H = INF; best.skip = true;\n        \n        // Determine which rotations to try\n        vector<int> rots;\n        if (rotate_all) rots = {1};\n        else if (rotate_none) rots = {0};\n        else rots = {0, 1};\n        \n        for (int rot_flag : rots) {\n            long long w = w_orig, h = h_orig;\n            if (rot_flag == 1) swap(w, h);\n            \n            // Try U and L\n            vector<int> dirs;\n            if (prefer_U) dirs = {0, 1};\n            else dirs = {1, 0};\n            \n            for (int dir : dirs) {\n                // b = -1\n                {\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        for (const auto& [px, py, pw, ph, pid] : placed) {\n                            if (x < px + pw && x + w > px) y = max(y, py + ph);\n                        }\n                    } else {\n                        for (const auto& [px, py, pw, ph, pid] : placed) {\n                            if (y < py + ph && y + h > py) x = max(x, px + pw);\n                        }\n                    }\n                    Placement p;\n                    p.p = idx; p.r = rot_flag; p.d = dir; p.b = -1;\n                    Option opt;\n                    opt.p = p; opt.x = x; opt.y = y; opt.w = w; opt.h = h; opt.skip = false;\n                    opt.new_W = x + w; opt.new_H = y + h;\n                    for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                        opt.new_W = max(opt.new_W, px2 + pw2);\n                        opt.new_H = max(opt.new_H, py2 + ph2);\n                    }\n                    if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n                }\n                \n                // b = each placed rectangle\n                int n_placed = (int)placed.size();\n                int step = max(1, n_placed / 20); // limit to ~20 references\n                for (int pi = 0; pi < n_placed; pi += step) {\n                    auto& [px, py, pw, ph, pid] = placed[pi];\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        x = px + pw;\n                        for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                            if (x < px2 + pw2 && x + w > px2) y = max(y, py2 + ph2);\n                        }\n                    } else {\n                        y = py + ph;\n                        for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                            if (y < py2 + ph2 && y + h > py2) x = max(x, px2 + pw2);\n                        }\n                    }\n                    Placement p;\n                    p.p = idx; p.r = rot_flag; p.d = dir; p.b = pid;\n                    Option opt;\n                    opt.p = p; opt.x = x; opt.y = y; opt.w = w; opt.h = h; opt.skip = false;\n                    opt.new_W = x + w; opt.new_H = y + h;\n                    for (const auto& [px2, py2, pw2, ph2, pid2] : placed) {\n                        opt.new_W = max(opt.new_W, px2 + pw2);\n                        opt.new_H = max(opt.new_H, py2 + ph2);\n                    }\n                    if (opt.new_W + opt.new_H < best.new_W + best.new_H) best = opt;\n                }\n            }\n        }\n        \n        // Skip decision\n        long long current_W = 0, current_H = 0;\n        for (const auto& [px, py, pw, ph, pid] : placed) {\n            current_W = max(current_W, px + pw);\n            current_H = max(current_H, py + ph);\n        }\n        long long current_sum = current_W + current_H;\n        long long skip_cost = w_orig + h_orig;\n        \n        if (!best.skip && best.new_W + best.new_H <= current_sum + skip_cost * skip_mult) {\n            placements.push_back(best.p);\n            placed.emplace_back(best.x, best.y, best.w, best.h, idx);\n        }\n    }\n    \n    return placements;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> T >> sigma;\n    est_w.resize(N);\n    est_h.resize(N);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> est_w[i] >> est_h[i];\n    }\n    \n    auto time_limit = chrono::milliseconds(2900);\n    long long best_score = LLONG_MAX;\n    \n    // Generate diverse parameter combinations\n    struct Config {\n        double skip_mult;\n        bool prefer_U;\n        bool rotate_all;\n        bool rotate_none;\n    };\n    \n    vector<Config> configs;\n    for (double mult : {1.0, 0.6, 0.8, 1.2, 1.5, 2.0, 0.4, 0.9, 1.1, 1.8}) {\n        for (bool pref_U : {true, false}) {\n            configs.push_back({mult, pref_U, false, false});\n        }\n    }\n    // Add forced rotation configs\n    for (double mult : {1.0, 0.8, 1.2}) {\n        for (bool pref_U : {true, false}) {\n            configs.push_back({mult, pref_U, true, false}); // all rotated\n            configs.push_back({mult, pref_U, false, true}); // none rotated\n        }\n    }\n    \n    // Shuffle for diversity\n    mt19937 rng(42);\n    shuffle(configs.begin(), configs.end(), rng);\n    \n    for (int turn = 0; turn < T; turn++) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time);\n        if (elapsed > time_limit) break;\n        \n        Config cfg = configs[turn % configs.size()];\n        vector<Placement> placements = pack(cfg.skip_mult, cfg.prefer_U, cfg.rotate_all, cfg.rotate_none);\n        \n        auto [W, H] = query(placements);\n        \n        vector<bool> used(N, false);\n        for (const auto& pl : placements) used[pl.p] = true;\n        long long penalty = 0;\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) penalty += est_w[i] + est_h[i];\n        }\n        long long score = W + H + penalty;\n        \n        if (score < best_score) best_score = score;\n    }\n    \n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct Xor128 {\n    unsigned x,y,z,w;\n    Xor128(unsigned s=123456789):x(s),y(362436069),z(521288629),w(88675123){}\n    unsigned next(){unsigned t=x^(x<<11);x=y;y=z;z=w;return w=w^(w>>19)^t^(t>>8);}\n    double prob(){return next()/4294967295.0;}\n};\n\nint main(){\n    auto start=steady_clock::now();\n    ios::sync_with_stdio(false);cin.tie(nullptr);\n    int N,M,H;cin>>N>>M>>H;\n    vector<int> A(N);\n    for(int i=0;i<N;++i)cin>>A[i];\n    vector<pair<int,int>> edges(M);\n    for(int i=0;i<M;++i)cin>>edges[i].first>>edges[i].second;\n    for(int i=0;i<N;++i){int x,y;cin>>x>>y;}\n\n    vector<vector<int>> adj(N);\n    for(auto&e:edges){\n        adj[e.first].push_back(e.second);\n        adj[e.second].push_back(e.first);\n    }\n\n    vector<int> parent(N,-1);\n    vector<vector<int>> children(N);\n    vector<int> depth(N,0);\n    long long curScore=0;\n\n    auto rebuildAndValidate=[&]()->bool{\n        for(int i=0;i<N;++i)children[i].clear();\n        for(int i=0;i<N;++i)if(parent[i]!=-1)children[parent[i]].push_back(i);\n        fill(depth.begin(),depth.end(),-1);\n        queue<int> q;\n        for(int i=0;i<N;++i)if(parent[i]==-1){depth[i]=0;q.push(i);}\n        int cnt=0;\n        while(!q.empty()){\n            int v=q.front();q.pop();\n            cnt++;\n            if(depth[v]>H)return false;\n            for(int c:children[v]){\n                if(depth[c]!=-1)return false;\n                depth[c]=depth[v]+1;\n                q.push(c);\n            }\n        }\n        if(cnt!=N)return false;\n        curScore=1;\n        for(int i=0;i<N;++i)curScore+=(depth[i]+1LL)*A[i];\n        return true;\n    };\n\n    // find best initial among several\n    vector<int> bestParent(N,-1);\n    long long bestScore=-1;\n    Xor128 rng(12345);\n    for(int trial=0;trial<30;++trial){\n        parent.assign(N,-1);\n        vector<int> order(N);iota(order.begin(),order.end(),0);\n        if(trial==0)sort(order.begin(),order.end(),[&](int i,int j){return A[i]>A[j];});\n        else shuffle(order.begin(),order.end(),mt19937(rng.next()));\n        vector<bool> placed(N,false);\n        vector<int> tmpD(N,0);\n        for(int u:order){\n            int bestp=-1,bestd=-1;\n            for(int p:adj[u])if(placed[p]&&tmpD[p]<H){\n                if(tmpD[p]>bestd){bestd=tmpD[p];bestp=p;}\n            }\n            if(bestp!=-1){parent[u]=bestp;tmpD[u]=bestd+1;}\n            else{parent[u]=-1;tmpD[u]=0;}\n            placed[u]=true;\n        }\n        if(rebuildAndValidate()){\n            if(curScore>bestScore){\n                bestScore=curScore;bestParent=parent;\n            }\n        }\n    }\n    parent=bestParent;\n    rebuildAndValidate();\n    bestScore=curScore;\n\n    double T0=200.0,T1=0.3;\n    int maxIter=90000;\n    long long currentSc=curScore;\n    vector<int> currentParent=parent;\n    vector<int> currentDepth=depth;\n    vector<vector<int>> currentChildren=children;\n\n    for(int iter=0;iter<maxIter;++iter){\n        if(steady_clock::now()-start>milliseconds(1950))break;\n        double progress=(double)iter/maxIter;\n        double T=T0*pow(T1/T0,progress);\n        int u=rng.next()%N;\n        if(adj[u].empty())continue;\n        int oldp=currentParent[u];\n        int p=adj[u][rng.next()%adj[u].size()];\n        if(p==u||p==oldp)continue;\n        // try\n        parent=currentParent;\n        parent[u]=p;\n        if(rebuildAndValidate()){\n            long long newSc=curScore;\n            long long delta=newSc-currentSc;\n            if(delta>=0||rng.prob()<exp(delta/T)){\n                currentSc=newSc;\n                currentParent=parent;\n                currentDepth=depth;\n                currentChildren=children;\n                if(currentSc>bestScore){\n                    bestScore=currentSc;\n                    bestParent=currentParent;\n                }\n            }\n        }\n    }\n\n    parent=bestParent;\n    for(int i=0;i<N;++i){\n        if(i)cout<<' ';\n        cout<<parent[i];\n    }\n    cout<<'\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\nusing pii = pair<int,int>;\n\nint N;\nvector<string> board;\nvector<pair<char,int>> answer;\n\nvoid shiftRowLeft(int i) {\n    answer.push_back({'L', i});\n    for (int j = 0; j < N-1; j++)\n        board[i][j] = board[i][j+1];\n    board[i][N-1] = '.';\n}\n\nvoid shiftRowRight(int i) {\n    answer.push_back({'R', i});\n    for (int j = N-1; j > 0; j--)\n        board[i][j] = board[i][j-1];\n    board[i][0] = '.';\n}\n\nvoid shiftColUp(int j) {\n    answer.push_back({'U', j});\n    for (int i = 0; i < N-1; i++)\n        board[i][j] = board[i+1][j];\n    board[N-1][j] = '.';\n}\n\nvoid shiftColDown(int j) {\n    answer.push_back({'D', j});\n    for (int i = N-1; i > 0; i--)\n        board[i][j] = board[i-1][j];\n    board[0][j] = '.';\n}\n\n// Check if Oni at (i,j) can be removed in given direction\nbool canRemoveUp(int i, int j) {\n    for (int k = 0; k < i; k++)\n        if (board[k][j] == 'o') return false;\n    return true;\n}\nbool canRemoveDown(int i, int j) {\n    for (int k = i+1; k < N; k++)\n        if (board[k][j] == 'o') return false;\n    return true;\n}\nbool canRemoveLeft(int i, int j) {\n    for (int k = 0; k < j; k++)\n        if (board[i][k] == 'o') return false;\n    return true;\n}\nbool canRemoveRight(int i, int j) {\n    for (int k = j+1; k < N; k++)\n        if (board[i][k] == 'o') return false;\n    return true;\n}\n\n// Count Oni in a row that can be removed in a direction, and find farthest\nint countRemovableInRowLeft(int i, int& farthest_j) {\n    int count = 0;\n    farthest_j = -1;\n    for (int j = 0; j < N; j++) {\n        if (board[i][j] == 'x' && canRemoveLeft(i, j)) {\n            count++;\n            farthest_j = max(farthest_j, j);\n        }\n    }\n    return count;\n}\n\nint countRemovableInRowRight(int i, int& nearest_j) {\n    int count = 0;\n    nearest_j = N;\n    for (int j = 0; j < N; j++) {\n        if (board[i][j] == 'x' && canRemoveRight(i, j)) {\n            count++;\n            nearest_j = min(nearest_j, j);\n        }\n    }\n    return count;\n}\n\nint countRemovableInColUp(int j, int& farthest_i) {\n    int count = 0;\n    farthest_i = -1;\n    for (int i = 0; i < N; i++) {\n        if (board[i][j] == 'x' && canRemoveUp(i, j)) {\n            count++;\n            farthest_i = max(farthest_i, i);\n        }\n    }\n    return count;\n}\n\nint countRemovableInColDown(int j, int& nearest_i) {\n    int count = 0;\n    nearest_i = N;\n    for (int i = 0; i < N; i++) {\n        if (board[i][j] == 'x' && canRemoveDown(i, j)) {\n            count++;\n            nearest_i = min(nearest_i, i);\n        }\n    }\n    return count;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    board.resize(N);\n    for (int i = 0; i < N; i++) cin >> board[i];\n\n    // Main loop: repeatedly find and execute best batch removal\n    while (true) {\n        // Count remaining Oni\n        int remaining = 0;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (board[i][j] == 'x') remaining++;\n        if (remaining == 0) break;\n\n        double best_efficiency = -1.0;\n        char best_dir = 0;\n        int best_idx = -1;\n        int best_dist = 0;\n        int best_count = 0;\n\n        // Check all rows - LEFT\n        for (int i = 0; i < N; i++) {\n            int farthest_j;\n            int count = countRemovableInRowLeft(i, farthest_j);\n            if (count > 0) {\n                int dist = farthest_j + 1;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'L';\n                    best_idx = i;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        // Check all rows - RIGHT\n        for (int i = 0; i < N; i++) {\n            int nearest_j;\n            int count = countRemovableInRowRight(i, nearest_j);\n            if (count > 0) {\n                int dist = N - nearest_j;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'R';\n                    best_idx = i;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        // Check all columns - UP\n        for (int j = 0; j < N; j++) {\n            int farthest_i;\n            int count = countRemovableInColUp(j, farthest_i);\n            if (count > 0) {\n                int dist = farthest_i + 1;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'U';\n                    best_idx = j;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        // Check all columns - DOWN\n        for (int j = 0; j < N; j++) {\n            int nearest_i;\n            int count = countRemovableInColDown(j, nearest_i);\n            if (count > 0) {\n                int dist = N - nearest_i;\n                double eff = (double)count / (2 * dist);\n                if (eff > best_efficiency) {\n                    best_efficiency = eff;\n                    best_dir = 'D';\n                    best_idx = j;\n                    best_dist = dist;\n                    best_count = count;\n                }\n            }\n        }\n\n        if (best_dir == 0) break; // No removable Oni found (should not happen)\n\n        // Execute the batch removal\n        if (best_dir == 'L') {\n            for (int s = 0; s < best_dist; s++) shiftRowLeft(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftRowRight(best_idx);\n        } else if (best_dir == 'R') {\n            for (int s = 0; s < best_dist; s++) shiftRowRight(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftRowLeft(best_idx);\n        } else if (best_dir == 'U') {\n            for (int s = 0; s < best_dist; s++) shiftColUp(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftColDown(best_idx);\n        } else if (best_dir == 'D') {\n            for (int s = 0; s < best_dist; s++) shiftColDown(best_idx);\n            for (int s = 0; s < best_dist; s++) shiftColUp(best_idx);\n        }\n    }\n\n    // Output\n    for (auto [d, p] : answer)\n        cout << d << ' ' << p << '\\n';\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nint best_a[N], best_b[N];\nlong long best_error;\n\n// Fast evaluation using fixed-point iteration\n// Returns true if converged, false if cycling\nbool evaluate(const int a[], const int b[], int cnt[]) {\n    // Initialize cnt with targets as starting guess\n    for (int i = 0; i < N; ++i) cnt[i] = T[i];\n    \n    int iter;\n    for (iter = 0; iter < 200; ++iter) {\n        int new_cnt[N] = {0};\n        new_cnt[0] = 1; // Start at node 0\n        \n        for (int i = 0; i < N; ++i) {\n            if (cnt[i] > 0) {\n                int odd_visits = (cnt[i] + 1) / 2;  // ceil(cnt/2)\n                int even_visits = cnt[i] / 2;        // floor(cnt/2)\n                new_cnt[a[i]] += odd_visits;\n                new_cnt[b[i]] += even_visits;\n            }\n        }\n        \n        // Check convergence\n        bool converged = true;\n        int total = 0;\n        for (int i = 0; i < N; ++i) {\n            total += new_cnt[i];\n            if (abs(new_cnt[i] - cnt[i]) > 1) converged = false;\n        }\n        \n        memcpy(cnt, new_cnt, sizeof(int) * N);\n        \n        // Normalize to L\n        if (total != L && total > 0) {\n            long long scale = (long long)L * 1000000 / total;\n            for (int i = 0; i < N; ++i) {\n                cnt[i] = (int)((long long)cnt[i] * scale / 1000000);\n            }\n            // Fix rounding\n            int sum = 0;\n            for (int i = 0; i < N; ++i) sum += cnt[i];\n            cnt[0] += L - sum;\n        }\n        \n        if (converged && iter > 5) break;\n    }\n    return true;\n}\n\n// Full simulation for verification\nvoid full_simulate(const int a[], const int b[], int cnt[]) {\n    memset(cnt, 0, sizeof(int) * N);\n    int cur = 0;\n    for (int week = 0; week < L; ++week) {\n        cnt[cur]++;\n        cur = (cnt[cur] & 1) ? a[cur] : b[cur];\n    }\n}\n\nlong long calc_error(const int cnt[]) {\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += abs(cnt[i] - T[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) cin >> T[i];\n    \n    auto start_time = steady_clock::now();\n    const double time_limit = 1.98;\n    mt19937 rng(12345);\n    uniform_int_distribution<int> rand_emp(0, N-1);\n    uniform_real_distribution<double> rand_real(0.0, 1.0);\n    \n    best_error = 1e18;\n    \n    // Weighted initialization\n    vector<int> weighted;\n    for (int i = 0; i < N; ++i) {\n        int times = max(1, T[i] / 10);\n        for (int t = 0; t < min(times, 300); ++t) {\n            weighted.push_back(i);\n        }\n    }\n    \n    int a[N], b[N];\n    int cnt[N];\n    int saved_a[N], saved_b[N], saved_cnt[N];\n    int total_evals = 0;\n    \n    // Main loop\n    while (true) {\n        auto now = steady_clock::now();\n        if (duration<double>(now - start_time).count() > time_limit) break;\n        \n        // Initialize\n        if (total_evals < 50) {\n            int init_type = total_evals % 5;\n            if (init_type == 0) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = weighted[rand() % weighted.size()];\n                    b[i] = weighted[rand() % weighted.size()];\n                }\n            } else if (init_type == 1) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = rand_emp(rng);\n                    b[i] = rand_emp(rng);\n                }\n            } else if (init_type == 2) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = (i + 1) % N;\n                    b[i] = (i + 2) % N;\n                }\n            } else if (init_type == 3) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = i;\n                    b[i] = (i + 1) % N;\n                }\n            } else {\n                // Point to nodes with high T\n                int top5[5];\n                vector<pair<int,int>> sorted;\n                for (int j = 0; j < N; ++j) sorted.push_back({T[j], j});\n                sort(sorted.rbegin(), sorted.rend());\n                for (int j = 0; j < 5; ++j) top5[j] = sorted[j].second;\n                for (int i = 0; i < N; ++i) {\n                    a[i] = top5[rand() % 5];\n                    b[i] = top5[rand() % 5];\n                }\n            }\n        } else {\n            // Mutate best solution\n            memcpy(a, best_a, sizeof(a));\n            memcpy(b, best_b, sizeof(b));\n            int num_mutations = 5 + rand() % 25;\n            for (int m = 0; m < num_mutations; ++m) {\n                int i = rand_emp(rng);\n                if (rand() % 2) a[i] = rand_emp(rng);\n                else b[i] = rand_emp(rng);\n            }\n        }\n        \n        // Evaluate using fixed-point iteration (fast)\n        evaluate(a, b, cnt);\n        long long current_error = calc_error(cnt);\n        total_evals++;\n        \n        // Verify with full simulation occasionally\n        if (total_evals % 50 == 0 || current_error < best_error) {\n            full_simulate(a, b, cnt);\n            current_error = calc_error(cnt);\n        }\n        \n        if (current_error < best_error) {\n            best_error = current_error;\n            memcpy(best_a, a, sizeof(a));\n            memcpy(best_b, b, sizeof(b));\n        }\n        \n        // Local search\n        double temp = 300.0;\n        int streak = 0;\n        \n        for (int iter = 0; iter < 1000; ++iter) {\n            auto now2 = steady_clock::now();\n            if (duration<double>(now2 - start_time).count() > time_limit) break;\n            \n            memcpy(saved_a, a, sizeof(a));\n            memcpy(saved_b, b, sizeof(b));\n            memcpy(saved_cnt, cnt, sizeof(cnt));\n            \n            // Pick node to mutate\n            int i;\n            if (rand_real(rng) < 0.5) {\n                i = rand_emp(rng);\n            } else {\n                // Weighted by error\n                int total_err = 0;\n                for (int j = 0; j < N; ++j) total_err += abs(cnt[j] - T[j]);\n                if (total_err > 0) {\n                    int r = rand() % total_err;\n                    int cum = 0;\n                    for (int j = 0; j < N; ++j) {\n                        cum += abs(cnt[j] - T[j]);\n                        if (r < cum) { i = j; break; }\n                    }\n                }\n            }\n            \n            if (rand() % 2) a[i] = rand_emp(rng);\n            else b[i] = rand_emp(rng);\n            \n            total_evals++;\n            evaluate(a, b, cnt);\n            long long new_error = calc_error(cnt);\n            \n            if (new_error <= current_error || \n                rand_real(rng) < exp((current_error - new_error) / temp)) {\n                current_error = new_error;\n                streak = 0;\n                if (new_error < best_error) {\n                    // Verify with full simulation\n                    full_simulate(a, b, cnt);\n                    new_error = calc_error(cnt);\n                    if (new_error < best_error) {\n                        best_error = new_error;\n                        memcpy(best_a, a, sizeof(a));\n                        memcpy(best_b, b, sizeof(b));\n                    }\n                }\n            } else {\n                memcpy(a, saved_a, sizeof(a));\n                memcpy(b, saved_b, sizeof(b));\n                memcpy(cnt, saved_cnt, sizeof(cnt));\n                streak++;\n            }\n            \n            if (streak > 30) {\n                temp *= 0.9;\n                streak = 0;\n            }\n            temp *= 0.999;\n            if (temp < 0.01) break;\n        }\n    }\n    \n    // Output best\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#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        return parent[x] == x ? x : parent[x] = find(parent[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]) 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    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<long long> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n    \n    vector<long long> estX(N), estY(N);\n    for (int i = 0; i < N; ++i) {\n        estX[i] = (lx[i] + rx[i]) / 2;\n        estY[i] = (ly[i] + ry[i]) / 2;\n    }\n    \n    // ---------- Balanced k-means clustering ----------\n    // Initialize M cluster centers via k-means++\n    vector<long long> cx(M), cy(M);\n    vector<bool> chosen(N, false);\n    mt19937 rng(42);\n    uniform_int_distribution<int> dist(0, N-1);\n    int first = dist(rng);\n    chosen[first] = true;\n    cx[0] = estX[first]; cy[0] = estY[first];\n    for (int k = 1; k < M; ++k) {\n        vector<long long> min_dist2(N, LLONG_MAX);\n        for (int i = 0; i < N; ++i) {\n            if (chosen[i]) continue;\n            long long dx = estX[i] - cx[k-1];\n            long long dy = estY[i] - cy[k-1];\n            min_dist2[i] = min(min_dist2[i], dx*dx + dy*dy);\n        }\n        long long sum = 0;\n        for (int i = 0; i < N; ++i) if (!chosen[i]) sum += min_dist2[i];\n        uniform_int_distribution<long long> dsum(0, sum==0?0:sum-1);\n        long long rnd = dsum(rng);\n        int selected = -1;\n        for (int i = 0; i < N; ++i) {\n            if (chosen[i]) continue;\n            rnd -= min_dist2[i];\n            if (rnd < 0) { selected = i; break; }\n        }\n        if (selected == -1) selected = 0;\n        chosen[selected] = true;\n        cx[k] = estX[selected]; cy[k] = estY[selected];\n    }\n    \n    // Capacitated assignment: sort all pairs (city, cluster) by distance, assign greedily\n    vector<int> group_of_city(N, -1);\n    vector<int> pos_in_group_city(N, -1);\n    vector<vector<int>> groups(M);\n    for (int iter = 0; iter < 3; ++iter) {\n        // Build distances from each city to each center\n        vector<tuple<long long, int, int>> pairs; // dist2, city, cluster\n        for (int i = 0; i < N; ++i) {\n            for (int k = 0; k < M; ++k) {\n                long long dx = estX[i] - cx[k];\n                long long dy = estY[i] - cy[k];\n                pairs.emplace_back(dx*dx + dy*dy, i, k);\n            }\n        }\n        sort(pairs.begin(), pairs.end());\n        vector<int> cap(M);\n        for (int k = 0; k < M; ++k) cap[k] = G[k];\n        vector<vector<int>> temp_groups(M);\n        for (auto &tup : pairs) {\n            int city = get<1>(tup);\n            int clust = get<2>(tup);\n            if (group_of_city[city] != -1) continue; // already assigned in this iteration\n            if (cap[clust] > 0) {\n                group_of_city[city] = clust;\n                temp_groups[clust].push_back(city);\n                cap[clust]--;\n            }\n        }\n        // Update centers\n        for (int k = 0; k < M; ++k) {\n            long long sx = 0, sy = 0;\n            for (int c : temp_groups[k]) {\n                sx += estX[c]; sy += estY[c];\n            }\n            if (!temp_groups[k].empty()) {\n                cx[k] = sx / temp_groups[k].size();\n                cy[k] = sy / temp_groups[k].size();\n            }\n        }\n        groups = move(temp_groups);\n        // reset group_of_city for next iteration\n        fill(group_of_city.begin(), group_of_city.end(), -1);\n    }\n    // Final assignment is in 'groups', but they aren't occupied in order yet. We'll just use them as groups.\n    // Sort each group by Morton order for spatial coherence\n    auto morton = [](long long x, long long y) -> unsigned long long {\n        auto interleave = [](unsigned int a) -> unsigned long long {\n            unsigned long long b = a;\n            b = (b | (b << 16)) & 0x0000FFFF0000FFFFULL;\n            b = (b | (b << 8))  & 0x00FF00FF00FF00FFULL;\n            b = (b | (b << 4))  & 0x0F0F0F0F0F0F0F0FULL;\n            b = (b | (b << 2))  & 0x3333333333333333ULL;\n            b = (b | (b << 1))  & 0x5555555555555555ULL;\n            return b;\n        };\n        unsigned int ix = (unsigned int)max(0LL, min(10000LL, x));\n        unsigned int iy = (unsigned int)max(0LL, min(10000LL, y));\n        return interleave(ix) | (interleave(iy) << 1);\n    };\n    for (int g = 0; g < M; ++g) {\n        sort(groups[g].begin(), groups[g].end(), [&](int a, int b) {\n            return morton(estX[a], estY[a]) < morton(estX[b], estY[b]);\n        });\n        for (int j = 0; j < G[g]; ++j) {\n            int city = groups[g][j];\n            group_of_city[city] = g;\n            pos_in_group_city[city] = j;\n        }\n    }\n    \n    vector<vector<pair<int,int>>> final_edges(M);\n    vector<DSU> dsu;\n    dsu.reserve(M);\n    for (int g = 0; g < M; ++g) dsu.emplace_back(G[g]);\n    \n    int queries_used = 0;\n    \n    // Phase 1: sliding window with dynamic step based on group size vs query budget\n    // Allocate queries proportionally to group size (with minimum 1 for size>2)\n    int total_queries = Q;\n    vector<int> group_queries(M, 0);\n    int sum_sizes = N;\n    int rem_queries = total_queries;\n    for (int g = 0; g < M; ++g) {\n        int sz = G[g];\n        if (sz <= 2) continue;\n        int alloc = max(1, (int)((long long)total_queries * sz / sum_sizes));\n        group_queries[g] = alloc;\n        rem_queries -= alloc;\n    }\n    // distribute remaining to largest groups\n    for (int g = 0; g < M && rem_queries > 0; ++g) {\n        if (G[g] > 2) {\n            group_queries[g]++;\n            rem_queries--;\n        }\n    }\n    \n    for (int g = 0; g < M && queries_used < Q; ++g) {\n        int sz = G[g];\n        if (sz <= 2) {\n            if (sz == 2) {\n                final_edges[g].emplace_back(0, 1);\n                dsu[g].unite(0, 1);\n            }\n            continue;\n        }\n        int max_q = group_queries[g];\n        int step = L - 2;\n        if (step < 1) step = 1;\n        // Adjust step to not exceed available queries\n        int max_windows = (sz - 1 + step - 1) / step; // rough count\n        if (max_windows > max_q) {\n            step = (sz - 1 + max_q - 1) / max_q; // increase step to fit budget\n            if (step < 1) step = 1;\n        }\n        for (int start = 0; start + 1 < sz && queries_used < Q; start += step) {\n            int end = min(start + L, sz);\n            if (end - start < 2) break;\n            \n            cout << \"? \" << end - start;\n            for (int j = start; j < end; ++j) cout << \" \" << groups[g][j];\n            cout << \"\\n\";\n            cout.flush();\n            ++queries_used;\n            \n            for (int j = 0; j < (end - start) - 1; ++j) {\n                int a, b;\n                cin >> a >> b;\n                int pa = pos_in_group_city[a];\n                int pb = pos_in_group_city[b];\n                if (pa < start || pa >= end || pb < start || pb >= end) continue;\n                if (dsu[g].unite(pa, pb))\n                    final_edges[g].emplace_back(pa, pb);\n            }\n        }\n    }\n    \n    // Phase 2: remaining queries for component connection (same as before)\n    while (queries_used < Q) {\n        int best_g = -1, best_cnt = 0;\n        for (int g = 0; g < M; ++g) {\n            int sz = G[g];\n            if (sz <= 2) continue;\n            unordered_map<int, vector<int>> comps;\n            for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n            int cnt = comps.size();\n            if (cnt > best_cnt && cnt > 1) {\n                best_cnt = cnt;\n                best_g = g;\n            }\n        }\n        if (best_g == -1) break;\n        \n        int g = best_g;\n        int sz = G[g];\n        unordered_map<int, vector<int>> comps;\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        vector<int> reps;\n        for (auto &kv : comps) {\n            reps.push_back(kv.second.front());\n            if ((int)reps.size() == L) break;\n        }\n        if (reps.size() < 2) break;\n        \n        cout << \"? \" << reps.size();\n        for (int r : reps) cout << \" \" << groups[g][r];\n        cout << \"\\n\";\n        cout.flush();\n        ++queries_used;\n        \n        for (int j = 0; j < (int)reps.size() - 1; ++j) {\n            int a, b;\n            cin >> a >> b;\n            int pa = pos_in_group_city[a];\n            int pb = pos_in_group_city[b];\n            if (dsu[g].unite(pa, pb))\n                final_edges[g].emplace_back(pa, pb);\n        }\n    }\n    \n    cout << \"!\\n\";\n    cout.flush();\n    \n    // Phase 3: post-query component MST (unchanged logic)\n    for (int g = 0; g < M; ++g) {\n        if (G[g] <= 1) continue;\n        const auto &cities = groups[g];\n        int sz = cities.size();\n        \n        unordered_map<int, vector<int>> comps;\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        if (comps.size() == 1) continue;\n        \n        vector<int> comp_ids;\n        for (auto &kv : comps) comp_ids.push_back(kv.first);\n        int C = comp_ids.size();\n        \n        vector<tuple<long long, int, int>> comp_edges;\n        for (int i = 0; i < C; ++i) {\n            for (int j = i+1; j < C; ++j) {\n                long long best = LLONG_MAX;\n                for (int u : comps[comp_ids[i]]) {\n                    long long xu = estX[cities[u]], yu = estY[cities[u]];\n                    for (int v : comps[comp_ids[j]]) {\n                        long long dx = xu - estX[cities[v]];\n                        long long dy = yu - estY[cities[v]];\n                        long long d2 = dx*dx + dy*dy;\n                        if (d2 < best) best = d2;\n                    }\n                }\n                comp_edges.emplace_back(best, i, j);\n            }\n        }\n        sort(comp_edges.begin(), comp_edges.end());\n        DSU comp_dsu(C);\n        for (auto &e : comp_edges) {\n            int i = get<1>(e), j = get<2>(e);\n            if (comp_dsu.unite(i, j)) {\n                int u = -1, v = -1;\n                long long best_d2 = LLONG_MAX;\n                for (int a : comps[comp_ids[i]]) {\n                    long long xa = estX[cities[a]], ya = estY[cities[a]];\n                    for (int b : comps[comp_ids[j]]) {\n                        long long dx = xa - estX[cities[b]];\n                        long long dy = ya - estY[cities[b]];\n                        long long d2 = dx*dx + dy*dy;\n                        if (d2 < best_d2) {\n                            best_d2 = d2;\n                            u = a; v = b;\n                        }\n                    }\n                }\n                if (u != -1 && v != -1) {\n                    dsu[g].unite(u, v);\n                    final_edges[g].emplace_back(u, v);\n                }\n            }\n        }\n        \n        comps.clear();\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        if (comps.size() > 1) {\n            vector<tuple<long long, int, int>> cand;\n            vector<int> keys;\n            for (auto &kv : comps) keys.push_back(kv.first);\n            for (size_t ci = 0; ci < keys.size(); ++ci) {\n                for (size_t cj = ci+1; cj < keys.size(); ++cj) {\n                    for (int u : comps[keys[ci]]) {\n                        for (int v : comps[keys[cj]]) {\n                            long long dx = estX[cities[u]] - estX[cities[v]];\n                            long long dy = estY[cities[u]] - estY[cities[v]];\n                            long long d2 = dx*dx + dy*dy;\n                            cand.emplace_back(d2, u, v);\n                        }\n                    }\n                }\n            }\n            sort(cand.begin(), cand.end());\n            for (auto &e : cand) {\n                int u = get<1>(e), v = get<2>(e);\n                if (dsu[g].unite(u, v))\n                    final_edges[g].emplace_back(u, v);\n            }\n        }\n    }\n    \n    // Output\n    for (int g = 0; g < M; ++g) {\n        for (int i = 0; i < G[g]; ++i) {\n            if (i) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << \"\\n\";\n        for (auto &e : final_edges[g]) {\n            cout << groups[g][e.first] << \" \" << groups[g][e.second] << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nvector<string> blocks;\nvector<pair<int,int>> targets;\nvector<pair<char,char>> actions;\nint cur_x, cur_y;\n\nbool valid(int x, int y) { return x>=0 && x<N && y>=0 && y<N; }\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dc[4] = {'U', 'D', 'L', 'R'};\n\npair<int,int> slide(int x, int y, int d) {\n    while (true) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (!valid(nx, ny) || blocks[nx][ny] == '#') break;\n        x = nx; y = ny;\n    }\n    return {x, y};\n}\n\nvector<pair<char,char>> bfs(int sx, int sy, int gx, int gy) {\n    vector dist(N, vector<int>(N, 1e9));\n    vector act(N, vector<pair<char,char>>(N, {'?','?'}));\n    vector prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    queue<pair<int,int>> q;\n    dist[sx][sy] = 0;\n    q.push({sx, sy});\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        if (x == gx && y == gy) break;\n        // moves\n        for (int k=0; k<4; k++) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (valid(nx, ny) && blocks[nx][ny] == '.' && dist[nx][ny] > dist[x][y] + 1) {\n                dist[nx][ny] = dist[x][y] + 1;\n                act[nx][ny] = {'M', dc[k]};\n                prev[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n        // slides\n        for (int k=0; k<4; k++) {\n            auto [nx, ny] = slide(x, y, k);\n            if ((nx != x || ny != y) && dist[nx][ny] > dist[x][y] + 1) {\n                dist[nx][ny] = dist[x][y] + 1;\n                act[nx][ny] = {'S', dc[k]};\n                prev[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    vector<pair<char,char>> path;\n    int x = gx, y = gy;\n    while (!(x == sx && y == sy)) {\n        auto a = act[x][y];\n        path.push_back(a);\n        auto p = prev[x][y];\n        x = p.first; y = p.second;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid move(char d) {\n    int k = string(\"UDLR\").find(d);\n    actions.push_back({'M', d});\n    cur_x += dx[k]; cur_y += dy[k];\n}\n\nvoid slide_action(char d) {\n    int k = string(\"UDLR\").find(d);\n    actions.push_back({'S', d});\n    while (true) {\n        int nx = cur_x + dx[k], ny = cur_y + dy[k];\n        if (!valid(nx, ny) || blocks[nx][ny] == '#') break;\n        cur_x = nx; cur_y = ny;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    blocks.assign(N, string(N, '.'));\n    targets.resize(M);\n    for (int i=0; i<M; i++) cin >> targets[i].first >> targets[i].second;\n    cur_x = targets[0].first;\n    cur_y = targets[0].second;\n    for (int t=1; t<M; t++) {\n        int tx = targets[t].first, ty = targets[t].second;\n        vector<pair<char,char>> path = bfs(cur_x, cur_y, tx, ty);\n        for (auto [a, d] : path) {\n            if (a == 'M') move(d);\n            else slide_action(d);\n        }\n    }\n    for (auto [a,d] : actions) cout << a << ' ' << d << '\\n';\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect { int a, b, c, d; };\nstruct Point { int x, y, r, id; };\n\nstruct Node {\n    int split_dim, split_pos;\n    int x1, y1, x2, y2;\n    vector<int> indices;\n    Node *left, *right;\n    \n    Node() : split_dim(-1), split_pos(0), x1(0), y1(0), x2(0), y2(0),\n             left(nullptr), right(nullptr) {}\n    ~Node() { delete left; delete right; }\n};\n\nint n;\nvector<Point> pts;\nvector<Rect> best_ans;\ndouble best_score_val = -1;\nmt19937 rng(random_device{}());\n\ninline long long area(int x1, int y1, int x2, int y2) {\n    return 1LL * (x2 - x1) * (y2 - y1);\n}\n\ninline double calcSat(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    if (s >= r) return 1.0;\n    double ratio = (double)s / r;\n    double t = 1.0 - ratio;\n    return 1.0 - t * t;\n}\n\nNode* buildTree(int x1, int y1, int x2, int y2, vector<int>& idxs) {\n    Node* node = new Node();\n    node->x1 = x1; node->y1 = y1; node->x2 = x2; node->y2 = y2;\n    node->indices = idxs;\n    if (idxs.size() == 1) return node;\n    \n    long long totalArea = area(x1, y1, x2, y2);\n    long long sumR = 0;\n    for (int i : idxs) sumR += pts[i].r;\n    \n    struct Cand { double score; int pos, dim, k; };\n    vector<Cand> cands;\n    \n    auto addCands = [&](bool isX) {\n        vector<int> ord = idxs;\n        if (isX) sort(ord.begin(), ord.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n        else sort(ord.begin(), ord.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n        \n        for (int k = 0; k < (int)ord.size() - 1; k++) {\n            int v1 = isX ? pts[ord[k]].x : pts[ord[k]].y;\n            int v2 = isX ? pts[ord[k+1]].x : pts[ord[k+1]].y;\n            if (v1 >= v2) continue;\n            \n            long long leftR = 0;\n            for (int i = 0; i <= k; i++) leftR += pts[ord[i]].r;\n            \n            int mn = max((isX ? x1 : y1) + 1, v1 + 1);\n            int mx = min((isX ? x2 : y2) - 1, v2);\n            if (mn > mx) continue;\n            \n            int pos = (isX ? x1 : y1) + (int)((double)((isX ? x2 : y2) - (isX ? x1 : y1)) * leftR / sumR);\n            pos = max(mn, min(mx, pos));\n            \n            long long leftA = isX ? area(x1, y1, pos, y2) : area(x1, y1, x2, pos);\n            double ar = (double)leftA / totalArea;\n            double nr = (double)leftR / sumR;\n            double balance = max(0.0, nr - ar) + max(0.0, (1.0-nr) - (1.0-ar));\n            double score = -fabs(ar - nr) - balance;\n            cands.push_back({score, pos, isX ? 0 : 1, k});\n        }\n    };\n    \n    addCands(true);\n    addCands(false);\n    if (cands.empty()) return node;\n    \n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) { return a.score > b.score; });\n    \n    int topN = min(30, (int)cands.size());\n    vector<double> w(topN);\n    double maxS = cands[0].score;\n    for (int i = 0; i < topN; i++) w[i] = exp((cands[i].score - maxS) * 10.0);\n    discrete_distribution<int> dist(w.begin(), w.end());\n    Cand best = cands[dist(rng)];\n    \n    if (best.dim == 0)\n        sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].x < pts[j].x; });\n    else\n        sort(idxs.begin(), idxs.end(), [&](int i, int j) { return pts[i].y < pts[j].y; });\n    \n    vector<int> L(idxs.begin(), idxs.begin() + best.k + 1);\n    vector<int> R(idxs.begin() + best.k + 1, idxs.end());\n    \n    if (best.dim == 0) {\n        if (best.pos - x1 < 1 || x2 - best.pos < 1) return node;\n        node->split_dim = 0; node->split_pos = best.pos;\n        node->left = buildTree(x1, y1, best.pos, y2, L);\n        node->right = buildTree(best.pos, y1, x2, y2, R);\n    } else {\n        if (best.pos - y1 < 1 || y2 - best.pos < 1) return node;\n        node->split_dim = 1; node->split_pos = best.pos;\n        node->left = buildTree(x1, y1, x2, best.pos, L);\n        node->right = buildTree(x1, best.pos, x2, y2, R);\n    }\n    return node;\n}\n\nvoid propagateBounds(Node* node) {\n    if (node->split_dim == -1) return;\n    if (node->split_dim == 0) {\n        node->left->x1 = node->x1; node->left->y1 = node->y1;\n        node->left->x2 = node->split_pos; node->left->y2 = node->y2;\n        node->right->x1 = node->split_pos; node->right->y1 = node->y1;\n        node->right->x2 = node->x2; node->right->y2 = node->y2;\n    } else {\n        node->left->x1 = node->x1; node->left->y1 = node->y1;\n        node->left->x2 = node->x2; node->left->y2 = node->split_pos;\n        node->right->x1 = node->x1; node->right->y1 = node->split_pos;\n        node->right->x2 = node->x2; node->right->y2 = node->y2;\n    }\n    propagateBounds(node->left);\n    propagateBounds(node->right);\n}\n\nvoid extractRects(Node* node, vector<Rect>& ans) {\n    if (node->split_dim == -1) {\n        if (!node->indices.empty())\n            ans[node->indices[0]] = {node->x1, node->y1, node->x2, node->y2};\n        return;\n    }\n    extractRects(node->left, ans);\n    extractRects(node->right, ans);\n}\n\nvoid optimizeNode(Node* node) {\n    if (node->split_dim == -1) return;\n    \n    optimizeNode(node->left);\n    optimizeNode(node->right);\n    \n    int mn, mx;\n    if (node->split_dim == 0) {\n        int maxL = -1, minR = 10001;\n        for (int i : node->left->indices) maxL = max(maxL, pts[i].x);\n        for (int i : node->right->indices) minR = min(minR, pts[i].x);\n        mn = max(node->x1+1, maxL+1);\n        mx = min(node->x2-1, minR);\n    } else {\n        int maxL = -1, minR = 10001;\n        for (int i : node->left->indices) maxL = max(maxL, pts[i].y);\n        for (int i : node->right->indices) minR = min(minR, pts[i].y);\n        mn = max(node->y1+1, maxL+1);\n        mx = min(node->y2-1, minR);\n    }\n    if (mn >= mx) return;\n    \n    long long leftR = 0, rightR = 0;\n    for (int i : node->left->indices) leftR += pts[i].r;\n    for (int i : node->right->indices) rightR += pts[i].r;\n    \n    auto tryPos = [&](int pos) -> double {\n        long long la, ra;\n        if (node->split_dim == 0) {\n            la = area(node->x1, node->y1, pos, node->y2);\n            ra = area(pos, node->y1, node->x2, node->y2);\n        } else {\n            la = area(node->x1, node->y1, node->x2, pos);\n            ra = area(node->x1, pos, node->x2, node->y2);\n        }\n        return calcSat(la, leftR) + calcSat(ra, rightR);\n    };\n    \n    double bestSat = tryPos(node->split_pos);\n    int bestPos = node->split_pos;\n    \n    int step = max(1, (mx - mn) / 10000);\n    for (int pos = mn; pos <= mx; pos += step) {\n        double sat = tryPos(pos);\n        if (sat > bestSat) { bestSat = sat; bestPos = pos; }\n    }\n    // Local refinement\n    for (int pos = max(mn, bestPos - step); pos <= min(mx, bestPos + step); pos++) {\n        double sat = tryPos(pos);\n        if (sat > bestSat) { bestSat = sat; bestPos = pos; }\n    }\n    \n    node->split_pos = bestPos;\n}\n\ndouble evaluateSolution(const vector<Rect>& ans) {\n    double total = 0;\n    for (int i = 0; i < n; i++) {\n        if (ans[i].a > pts[i].x || ans[i].c <= pts[i].x ||\n            ans[i].b > pts[i].y || ans[i].d <= pts[i].y) continue;\n        total += calcSat(area(ans[i].a, ans[i].b, ans[i].c, ans[i].d), pts[i].r);\n    }\n    return total * 1e9 / n;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    \n    cin >> n;\n    pts.resize(n);\n    best_ans.resize(n);\n    for (int i = 0; i < n; i++) {\n        cin >> pts[i].x >> pts[i].y >> pts[i].r;\n        pts[i].id = i;\n    }\n    \n    vector<int> all(n);\n    iota(all.begin(), all.end(), 0);\n    \n    while (true) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start).count();\n        if (elapsed > 4950) break;\n        \n        Node* root = buildTree(0, 0, 10000, 10000, all);\n        propagateBounds(root);\n        \n        for (int opt = 0; opt < 6; opt++) {\n            optimizeNode(root);\n            propagateBounds(root);\n        }\n        \n        vector<Rect> cur(n);\n        extractRects(root, cur);\n        double sc = evaluateSolution(cur);\n        if (sc > best_score_val) {\n            best_score_val = sc;\n            best_ans = cur;\n        }\n        delete root;\n    }\n    \n    for (int i = 0; i < n; i++)\n        cout << best_ans[i].a << \" \" << best_ans[i].b << \" \"\n             << best_ans[i].c << \" \" << best_ans[i].d << \"\\n\";\n    \n    return 0;\n}","ahc002":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <bitset>\n#include <queue>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nconst int N = 50;\nconst int MAX_TILES = 2500;\n\nstruct State {\n    int score;\n    int est_score;\n    short i, j;\n    bitset<MAX_TILES> visited;\n    int prev_idx;\n    char move_char;\n};\n\nint si, sj;\nint tile_id[N][N];\nint p[N][N];\nint M;\nint max_p[MAX_TILES];\nint tile_adj[MAX_TILES][4];\nint tile_deg[MAX_TILES];\nint bfs_tag[MAX_TILES];\nint current_bfs_tag = 0;\n\nint quick_heuristic(const State& st, int ni, int nj) {\n    int nt = tile_id[ni][nj];\n    int sum = p[ni][nj];\n    int cur_t = tile_id[st.i][st.j];\n    for (int k = 0; k < tile_deg[cur_t]; ++k) {\n        int v = tile_adj[cur_t][k];\n        if (v != nt && !st.visited[v]) sum += max_p[v];\n    }\n    return sum;\n}\n\nint full_potential(const State& st, int depth_limit) {\n    current_bfs_tag++;\n    int start_tile = tile_id[st.i][st.j];\n    queue<pair<int,int>> q;\n    int pot = 0;\n    for (int k = 0; k < tile_deg[start_tile]; ++k) {\n        int v = tile_adj[start_tile][k];\n        if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n            bfs_tag[v] = current_bfs_tag;\n            q.push({v, 1});\n            pot += max_p[v];\n        }\n    }\n    while (!q.empty()) {\n        auto [u, d] = q.front(); q.pop();\n        if (d == depth_limit) continue;\n        for (int k = 0; k < tile_deg[u]; ++k) {\n            int v = tile_adj[u][k];\n            if (!st.visited[v] && bfs_tag[v] != current_bfs_tag) {\n                bfs_tag[v] = current_bfs_tag;\n                q.push({v, d + 1});\n                pot += max_p[v];\n            }\n        }\n    }\n    return pot;\n}\n\nint path_score(const string& path) {\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    vector<bool> used(M, false);\n    int ci = si, cj = sj;\n    used[tile_id[ci][cj]] = true;\n    int score = p[ci][cj];\n    for (char c : path) {\n        int k = (c == 'U' ? 0 : (c == 'D' ? 1 : (c == 'L' ? 2 : 3)));\n        ci += di[k]; cj += dj[k];\n        int t = tile_id[ci][cj];\n        if (used[t]) return -1;\n        used[t] = true;\n        score += p[ci][cj];\n    }\n    return score;\n}\n\npair<int, string> run_beam_search(int seed, int beam_width, int cand_width, int full_depth,\n                                  const State* init_state = nullptr,\n                                  const chrono::steady_clock::time_point& start_time = chrono::steady_clock::now(),\n                                  const chrono::milliseconds& time_limit = chrono::milliseconds(2000),\n                                  int max_depth = 2500) {\n    mt19937 rng(seed);\n    uniform_int_distribution<int> dist(0, 100);\n\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n\n    State init;\n    if (init_state) {\n        init = *init_state;\n    } else {\n        init.score = p[si][sj];\n        init.i = si; init.j = sj;\n        init.visited.reset();\n        init.visited[tile_id[si][sj]] = 1;\n        init.prev_idx = -1;\n    }\n    init.est_score = init.score + full_potential(init, full_depth);\n\n    vector<State> beam;\n    beam.push_back(init);\n    vector<vector<State>> beam_history;\n    beam_history.push_back(beam);\n\n    int best_score = init.score;\n    int best_depth = 0;\n    int best_state_idx = 0;\n\n    for (int depth = 1; depth <= max_depth; ++depth) {\n        if (chrono::steady_clock::now() - start_time > time_limit) break;\n\n        vector<State> candidates;\n        for (int s_idx = 0; s_idx < (int)beam.size(); ++s_idx) {\n            const State& st = beam[s_idx];\n            short i = st.i, j = st.j;\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nt = tile_id[ni][nj];\n                if (nt == tile_id[i][j] || st.visited[nt]) continue;\n\n                State nxt = st;\n                nxt.i = ni; nxt.j = nj;\n                nxt.score += p[ni][nj];\n                nxt.visited[nt] = 1;\n                nxt.prev_idx = s_idx;\n                nxt.move_char = (k == 0 ? 'U' : (k == 1 ? 'D' : (k == 2 ? 'L' : 'R')));\n                nxt.est_score = nxt.score + quick_heuristic(nxt, ni, nj);\n                candidates.push_back(move(nxt));\n            }\n        }\n        if (candidates.empty()) break;\n\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)candidates.size() > cand_width) candidates.resize(cand_width);\n\n        for (State& st : candidates) {\n            st.est_score = st.score + full_potential(st, full_depth) + dist(rng);\n        }\n\n        sort(candidates.begin(), candidates.end(),\n             [](const State& a, const State& b) { return a.est_score > b.est_score; });\n        if ((int)candidates.size() > beam_width) candidates.resize(beam_width);\n\n        if (candidates[0].score > best_score) {\n            best_score = candidates[0].score;\n            best_depth = depth;\n            best_state_idx = 0;\n        }\n\n        beam = move(candidates);\n        beam_history.push_back(beam);\n    }\n\n    for (int d = 0; d < (int)beam_history.size(); ++d) {\n        for (int idx = 0; idx < (int)beam_history[d].size(); ++idx) {\n            if (beam_history[d][idx].score > best_score) {\n                best_score = beam_history[d][idx].score;\n                best_depth = d;\n                best_state_idx = idx;\n            }\n        }\n    }\n\n    string path;\n    int cur_depth = best_depth;\n    int cur_idx = best_state_idx;\n    while (cur_depth > 0) {\n        const State& st = beam_history[cur_depth][cur_idx];\n        path.push_back(st.move_char);\n        cur_idx = st.prev_idx;\n        --cur_depth;\n    }\n    reverse(path.begin(), path.end());\n\n    return {best_score, path};\n}\n\nstring greedy_extend(const string& base_path, bitset<MAX_TILES>& used_tile) {\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    int ci = si, cj = sj;\n    used_tile.reset();\n    used_tile[tile_id[ci][cj]] = true;\n    for (char c : base_path) {\n        int k = (c == 'U' ? 0 : (c == 'D' ? 1 : (c == 'L' ? 2 : 3)));\n        ci += di[k]; cj += dj[k];\n        used_tile[tile_id[ci][cj]] = true;\n    }\n    string extra;\n    while (true) {\n        int best_ni = -1, best_nj = -1, best_val = -1;\n        char best_move = 0;\n        for (int k = 0; k < 4; ++k) {\n            int ni = ci + di[k], nj = cj + dj[k];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            int nt = tile_id[ni][nj];\n            if (nt == tile_id[ci][cj] || used_tile[nt]) continue;\n            if (p[ni][nj] > best_val) {\n                best_val = p[ni][nj];\n                best_ni = ni; best_nj = nj;\n                best_move = \"UDLR\"[k];\n            }\n        }\n        if (best_ni == -1) break;\n        extra.push_back(best_move);\n        used_tile[tile_id[best_ni][best_nj]] = true;\n        ci = best_ni; cj = best_nj;\n    }\n    return extra;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n\n    auto start_time = chrono::steady_clock::now();\n    auto time_limit = chrono::milliseconds(1950);\n\n    cin >> si >> sj;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> tile_id[i][j];\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> p[i][j];\n\n    M = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (tile_id[i][j] >= M) M = tile_id[i][j] + 1;\n\n    for (int t = 0; t < M; ++t) max_p[t] = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            if (p[i][j] > max_p[t]) max_p[t] = p[i][j];\n        }\n\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int t = tile_id[i][j];\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int nt = tile_id[ni][nj];\n                    if (nt != t) {\n                        bool exists = false;\n                        for (int idx = 0; idx < tile_deg[t]; ++idx) {\n                            if (tile_adj[t][idx] == nt) { exists = true; break; }\n                        }\n                        if (!exists) tile_adj[t][tile_deg[t]++] = nt;\n                    }\n                }\n            }\n        }\n    }\n\n    string best_path;\n    int best_score = -1;\n\n    // Main runs\n    for (int run = 0; run < 2; ++run) {\n        if (chrono::steady_clock::now() - start_time > time_limit) break;\n        auto [score, path] = run_beam_search(42 + run * 100, 260, 1300, 10, nullptr, start_time, time_limit, 2500);\n        bitset<MAX_TILES> used;\n        string extra = greedy_extend(path, used);\n        path += extra;\n        score = path_score(path);\n        if (score > best_score) {\n            best_score = score;\n            best_path = move(path);\n        }\n    }\n\n    // Third run\n    if (chrono::steady_clock::now() - start_time < time_limit - chrono::milliseconds(300)) {\n        auto [score, path] = run_beam_search(7777, 180, 900, 8, nullptr, start_time, time_limit, 2400);\n        bitset<MAX_TILES> used;\n        string extra = greedy_extend(path, used);\n        path += extra;\n        score = path_score(path);\n        if (score > best_score) {\n            best_score = score;\n            best_path = move(path);\n        }\n    }\n\n    // Fourth quick run if time left\n    if (chrono::steady_clock::now() - start_time < time_limit - chrono::milliseconds(300)) {\n        auto [score, path] = run_beam_search(5555, 100, 500, 6, nullptr, start_time, time_limit, 2000);\n        bitset<MAX_TILES> used;\n        string extra = greedy_extend(path, used);\n        path += extra;\n        score = path_score(path);\n        if (score > best_score) {\n            best_score = score;\n            best_path = move(path);\n        }\n    }\n\n    // Post\u2011process extension from the best path\n    if (chrono::steady_clock::now() - start_time < time_limit - chrono::milliseconds(400)) {\n        bitset<MAX_TILES> vis;\n        int ci = si, cj = sj;\n        vis[tile_id[ci][cj]] = true;\n        for (char c : best_path) {\n            int k = (c == 'U' ? 0 : (c == 'D' ? 1 : (c == 'L' ? 2 : 3)));\n            ci += di[k]; cj += dj[k];\n            vis[tile_id[ci][cj]] = true;\n        }\n        State end_state;\n        end_state.score = best_score;\n        end_state.i = ci; end_state.j = cj;\n        end_state.visited = vis;\n        end_state.prev_idx = -1;\n\n        auto [score2, extra2] = run_beam_search(9999, 60, 400, 7, &end_state, start_time, time_limit, 600);\n        if (!extra2.empty()) {\n            string combined = best_path + extra2;\n            int sc = path_score(combined);\n            if (sc > best_score) {\n                best_score = sc;\n                best_path = combined;\n            }\n        }\n    }\n\n    cout << best_path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr double INF = 1e18;\n\n// Forward declarations\nstruct EdgeEstimator;\n\nstruct EdgeEstimator {\n    // We maintain a more explicit model:\n    // h[i][j] = H_row[i] + (j >= split_col[i] ? H_split[i] : 0) + delta[i][j]\n    // v[i][j] = V_col[j] + (i >= split_row[j] ? V_split[j] : 0) + gamma[i][j]\n    \n    double H_base[N];           // Row base for horizontal edges\n    double H_split[N];          // Split difference (could be 0)\n    int H_split_idx[N];         // Column where split occurs\n    double H_local[N][N-1];     // Local deviations\n    \n    double V_base[N];           // Column base for vertical edges  \n    double V_split[N];          // Split difference\n    int V_split_idx[N];         // Row where split occurs\n    double V_local[N-1][N];     // Local deviations\n    \n    // Counts\n    int H_cnt[N][N-1];\n    int V_cnt[N-1][N];\n    \n    // For tracking row/col statistics\n    double H_sum[N], H_sum2[N];\n    int H_n[N];\n    double V_sum[N], V_sum2[N];\n    int V_n[N];\n    \n    EdgeEstimator() {\n        // Initialize with better default (midpoint of [1000+D, 9000-D] for D~1000)\n        double init_val = 5000.0;\n        for (int i = 0; i < N; i++) {\n            H_base[i] = init_val;\n            H_split[i] = 0.0;\n            H_split_idx[i] = -1;\n            H_sum[i] = H_sum2[i] = 0.0;\n            H_n[i] = 0;\n            \n            V_base[i] = init_val;\n            V_split[i] = 0.0;\n            V_split_idx[i] = -1;\n            V_sum[i] = V_sum2[i] = 0.0;\n            V_n[i] = 0;\n        }\n        memset(H_local, 0, sizeof(H_local));\n        memset(V_local, 0, sizeof(V_local));\n        memset(H_cnt, 0, sizeof(H_cnt));\n        memset(V_cnt, 0, sizeof(V_cnt));\n    }\n    \n    inline double get_H(int i, int j) const {\n        double val = H_base[i] + H_local[i][j];\n        if (H_split_idx[i] >= 0 && j >= H_split_idx[i]) {\n            val += H_split[i];\n        }\n        return clamp(val, 100.0, 10000.0);\n    }\n    \n    inline double get_V(int i, int j) const {\n        double val = V_base[j] + V_local[i][j];\n        if (V_split_idx[j] >= 0 && i >= V_split_idx[j]) {\n            val += V_split[j];\n        }\n        return clamp(val, 100.0, 10000.0);\n    }\n    \n    double H_std(int i) const {\n        if (H_n[i] < 2) return 2000.0;\n        double mean = H_sum[i] / H_n[i];\n        double var = H_sum2[i] / H_n[i] - mean * mean;\n        return sqrt(max(0.0, var));\n    }\n    \n    double V_std(int j) const {\n        if (V_n[j] < 2) return 2000.0;\n        double mean = V_sum[j] / V_n[j];\n        double var = V_sum2[j] / V_n[j] - mean * mean;\n        return sqrt(max(0.0, var));\n    }\n};\n\nstruct Dijkstra {\n    double dist[N][N];\n    pair<int,int> prev[N][N];\n    \n    vector<pair<int,int>> find_path(int si, int sj, int ti, int tj,\n                                     EdgeEstimator& est, double bonus) {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                dist[i][j] = INF;\n        \n        dist[si][sj] = 0;\n        using State = tuple<double, int, int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n        pq.push({0.0, si, sj});\n        \n        const int di[] = {-1, 1, 0, 0};\n        const int dj[] = {0, 0, -1, 1};\n        \n        while (!pq.empty()) {\n            auto [d, i, j] = pq.top(); pq.pop();\n            if (d > dist[i][j]) continue;\n            if (i == ti && j == tj) break;\n            \n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                \n                double edge_w;\n                int edge_cnt;\n                \n                if (k == 0) { // Up\n                    edge_w = est.get_V(ni, nj);\n                    edge_cnt = est.V_cnt[ni][nj];\n                } else if (k == 1) { // Down\n                    edge_w = est.get_V(i, j);\n                    edge_cnt = est.V_cnt[i][j];\n                } else if (k == 2) { // Left\n                    edge_w = est.get_H(ni, nj);\n                    edge_cnt = est.H_cnt[ni][nj];\n                } else { // Right\n                    edge_w = est.get_H(i, j);\n                    edge_cnt = est.H_cnt[i][j];\n                }\n                \n                // UCB-style exploration\n                double exploration = bonus / sqrt(1.0 + edge_cnt);\n                double nd = d + edge_w + exploration;\n                \n                if (nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i, j};\n                    pq.push({nd, ni, nj});\n                }\n            }\n        }\n        \n        // Reconstruct\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 [pi, pj] = prev[ci][cj];\n            ci = pi; cj = pj;\n        }\n        path.push_back({si, sj});\n        reverse(path.begin(), path.end());\n        return path;\n    }\n};\n\nstring path_to_str(const vector<pair<int,int>>& path) {\n    string s;\n    s.reserve(path.size());\n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        if (c == a-1) s += 'U';\n        else if (c == a+1) s += 'D';\n        else if (d == b-1) s += 'L';\n        else s += 'R';\n    }\n    return s;\n}\n\ndouble calc_path_len(const vector<pair<int,int>>& path, EdgeEstimator& est) {\n    double len = 0;\n    for (size_t i = 1; i < path.size(); i++) {\n        auto [a, b] = path[i-1];\n        auto [c, d] = path[i];\n        if (c == a-1) len += est.get_V(c, d);\n        else if (c == a+1) len += est.get_V(a, b);\n        else if (d == b-1) len += est.get_H(c, d);\n        else len += est.get_H(a, b);\n    }\n    return len;\n}\n\nvoid update_est(EdgeEstimator& est, const vector<pair<int,int>>& path,\n                double observed, double predicted, int qidx) {\n    if (predicted < 1.0) return;\n    \n    // Expected noise is 1.0, so use observed/predicted directly\n    double scale = observed / predicted;\n    scale = clamp(scale, 0.7, 1.4); // Tighter clamp for stability\n    \n    // Learning rate: decrease over time but stay substantial\n    double lr = 0.35 / pow(1.0 + qidx * 0.001, 0.6);\n    \n    // Collect edges and their current estimates\n    struct EdgeInfo {\n        int type; // 0=H, 1=V\n        int i, j;\n        double old_val;\n        double* local_ptr;\n        double* base_ptr;\n        double* split_ptr; // nullptr if no split\n        int* cnt_ptr;\n    };\n    \n    vector<EdgeInfo> edges;\n    edges.reserve(path.size());\n    \n    for (size_t k = 1; k < path.size(); k++) {\n        auto [a, b] = path[k-1];\n        auto [c, d] = path[k];\n        \n        EdgeInfo ei;\n        if (c == a-1) { // Up: V at (c,d)\n            ei.type = 1;\n            ei.i = c; ei.j = d;\n            ei.old_val = est.get_V(c, d);\n            ei.local_ptr = &est.V_local[c][d];\n            ei.base_ptr = &est.V_base[d];\n            ei.split_ptr = (est.V_split_idx[d] >= 0 && c >= est.V_split_idx[d]) ? &est.V_split[d] : nullptr;\n            ei.cnt_ptr = &est.V_cnt[c][d];\n        } else if (c == a+1) { // Down: V at (a,b)\n            ei.type = 1;\n            ei.i = a; ei.j = b;\n            ei.old_val = est.get_V(a, b);\n            ei.local_ptr = &est.V_local[a][b];\n            ei.base_ptr = &est.V_base[b];\n            ei.split_ptr = (est.V_split_idx[b] >= 0 && a >= est.V_split_idx[b]) ? &est.V_split[b] : nullptr;\n            ei.cnt_ptr = &est.V_cnt[a][b];\n        } else if (d == b-1) { // Left: H at (c,d)\n            ei.type = 0;\n            ei.i = c; ei.j = d;\n            ei.old_val = est.get_H(c, d);\n            ei.local_ptr = &est.H_local[c][d];\n            ei.base_ptr = &est.H_base[c];\n            ei.split_ptr = (est.H_split_idx[c] >= 0 && d >= est.H_split_idx[c]) ? &est.H_split[c] : nullptr;\n            ei.cnt_ptr = &est.H_cnt[c][d];\n        } else { // Right: H at (a,b)\n            ei.type = 0;\n            ei.i = a; ei.j = b;\n            ei.old_val = est.get_H(a, b);\n            ei.local_ptr = &est.H_local[a][b];\n            ei.base_ptr = &est.H_base[a];\n            ei.split_ptr = (est.H_split_idx[a] >= 0 && b >= est.H_split_idx[a]) ? &est.H_split[a] : nullptr;\n            ei.cnt_ptr = &est.H_cnt[a][b];\n        }\n        edges.push_back(ei);\n    }\n    \n    // Update each edge proportionally to its contribution\n    for (auto& ei : edges) {\n        (*ei.cnt_ptr)++;\n        \n        double target = ei.old_val * scale;\n        double err = target - ei.old_val;\n        \n        // Update local variation\n        *ei.local_ptr += lr * 0.6 * err;\n        *ei.base_ptr += lr * 0.3 * err;\n        if (ei.split_ptr) {\n            *ei.split_ptr += lr * 0.1 * err;\n        }\n        \n        // Track statistics\n        if (ei.type == 0) {\n            est.H_sum[ei.i] += err;\n            est.H_sum2[ei.i] += err * err;\n            est.H_n[ei.i]++;\n        } else {\n            est.V_sum[ei.j] += err;\n            est.V_sum2[ei.j] += err * err;\n            est.V_n[ei.j]++;\n        }\n    }\n}\n\nvoid find_splits(EdgeEstimator& est, int qidx) {\n    if (qidx < 20) return;\n    \n    // Horizontal splits\n    for (int i = 0; i < N; i++) {\n        if (est.H_split_idx[i] >= 0) continue;\n        \n        int visited = 0;\n        for (int j = 0; j < N-1; j++) visited += (est.H_cnt[i][j] > 0);\n        if (visited < 15) continue;\n        \n        // Try all possible split points\n        double best_diff = 0;\n        int best_s = -1;\n        \n        for (int s = 5; s < N-6; s++) {\n            double left_sum = 0, right_sum = 0;\n            double left_sum2 = 0, right_sum2 = 0;\n            int left_n = 0, right_n = 0;\n            \n            for (int j = 0; j < s; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    double v = est.get_H(i, j);\n                    left_sum += v;\n                    left_sum2 += v * v;\n                    left_n++;\n                }\n            }\n            for (int j = s; j < N-1; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    double v = est.get_H(i, j);\n                    right_sum += v;\n                    right_sum2 += v * v;\n                    right_n++;\n                }\n            }\n            \n            if (left_n >= 5 && right_n >= 5) {\n                double left_mean = left_sum / left_n;\n                double right_mean = right_sum / right_n;\n                \n                double left_var = left_sum2/left_n - left_mean*left_mean;\n                double right_var = right_sum2/right_n - right_mean*right_mean;\n                \n                double pooled_se = sqrt(left_var/left_n + right_var/right_n);\n                double diff = fabs(left_mean - right_mean);\n                \n                // Weight by statistical significance\n                double score = diff * diff / (pooled_se * pooled_se + 100.0);\n                \n                if (score > best_diff) {\n                    best_diff = score;\n                    best_s = s;\n                }\n            }\n        }\n        \n        if (best_diff > 4.0) { // Statistically significant\n            est.H_split_idx[i] = best_s;\n            \n            // Compute split value\n            double left_avg = 0, right_avg = 0;\n            int lc = 0, rc = 0;\n            for (int j = 0; j < best_s; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    left_avg += est.H_local[i][j];\n                    lc++;\n                }\n            }\n            for (int j = best_s; j < N-1; j++) {\n                if (est.H_cnt[i][j] > 0) {\n                    right_avg += est.H_local[i][j];\n                    rc++;\n                }\n            }\n            if (lc > 0) left_avg /= lc;\n            if (rc > 0) right_avg /= rc;\n            \n            double split_val = right_avg - left_avg;\n            est.H_split[i] = split_val;\n            \n            // Adjust locals to be zero-mean around their segments\n            for (int j = 0; j < best_s; j++) {\n                if (est.H_cnt[i][j] > 0) est.H_local[i][j] -= left_avg;\n            }\n            for (int j = best_s; j < N-1; j++) {\n                if (est.H_cnt[i][j] > 0) est.H_local[i][j] -= right_avg;\n            }\n            // Add back properly\n            for (int j = 0; j < N-1; j++) {\n                est.H_local[i][j] = 0; // Reset after split detection\n            }\n        }\n    }\n    \n    // Vertical splits (similar logic)\n    for (int j = 0; j < N; j++) {\n        if (est.V_split_idx[j] >= 0) continue;\n        \n        int visited = 0;\n        for (int i = 0; i < N-1; i++) visited += (est.V_cnt[i][j] > 0);\n        if (visited < 15) continue;\n        \n        double best_diff = 0;\n        int best_s = -1;\n        \n        for (int s = 5; s < N-6; s++) {\n            double top_sum = 0, bottom_sum = 0;\n            double top_sum2 = 0, bottom_sum2 = 0;\n            int top_n = 0, bottom_n = 0;\n            \n            for (int i = 0; i < s; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    double v = est.get_V(i, j);\n                    top_sum += v;\n                    top_sum2 += v * v;\n                    top_n++;\n                }\n            }\n            for (int i = s; i < N-1; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    double v = est.get_V(i, j);\n                    bottom_sum += v;\n                    bottom_sum2 += v * v;\n                    bottom_n++;\n                }\n            }\n            \n            if (top_n >= 5 && bottom_n >= 5) {\n                double top_mean = top_sum / top_n;\n                double bottom_mean = bottom_sum / bottom_n;\n                \n                double top_var = top_sum2/top_n - top_mean*top_mean;\n                double bottom_var = bottom_sum2/bottom_n - bottom_mean*bottom_mean;\n                \n                double pooled_se = sqrt(top_var/top_n + bottom_var/bottom_n);\n                double diff = fabs(top_mean - bottom_mean);\n                double score = diff * diff / (pooled_se * pooled_se + 100.0);\n                \n                if (score > best_diff) {\n                    best_diff = score;\n                    best_s = s;\n                }\n            }\n        }\n        \n        if (best_diff > 4.0) {\n            est.V_split_idx[j] = best_s;\n            \n            double top_avg = 0, bottom_avg = 0;\n            int tc = 0, bc = 0;\n            for (int i = 0; i < best_s; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    top_avg += est.V_local[i][j];\n                    tc++;\n                }\n            }\n            for (int i = best_s; i < N-1; i++) {\n                if (est.V_cnt[i][j] > 0) {\n                    bottom_avg += est.V_local[i][j];\n                    bc++;\n                }\n            }\n            if (tc > 0) top_avg /= tc;\n            if (bc > 0) bottom_avg /= bc;\n            \n            double split_val = bottom_avg - top_avg;\n            est.V_split[j] = split_val;\n            \n            for (int i = 0; i < N-1; i++) {\n                est.V_local[i][j] = 0; // Reset locals\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    EdgeEstimator est;\n    Dijkstra dij;\n    \n    double explore_bonus = 2000.0;\n    \n    for (int k = 0; k < 1000; k++) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        // Detect splits early and periodically\n        if (k == 20 || k == 40 || k == 60 || k == 80 || k == 100 || \n            (k > 100 && k % 25 == 0)) {\n            find_splits(est, k);\n        }\n        \n        auto path = dij.find_path(si, sj, ti, tj, est, explore_bonus);\n        double predicted = calc_path_len(path, est);\n        \n        cout << path_to_str(path) << '\\n';\n        cout.flush();\n        \n        int observed;\n        cin >> observed;\n        \n        update_est(est, path, observed, predicted, k);\n        \n        // Decay exploration\n        explore_bonus *= 0.997;\n        if (explore_bonus < 50) explore_bonus = 50;\n    }\n    \n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nint N, M;\nvector<string> strings;\n\nstruct Candidate {\n    int r, c, dir;\n};\nvector<vector<Candidate>> string_candidates;\n\nchar best_grid[20][20];\nint best_matched = 0;\nint best_empty = 0;\n\nbool compatible(const string &s, const Candidate &cand, const char grid[20][20]) {\n    int len = s.size();\n    if (cand.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            char g = grid[cand.r][(cand.c + p) % N];\n            if (g != '.' && g != s[p]) return false;\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            char g = grid[(cand.r + p) % N][cand.c];\n            if (g != '.' && g != s[p]) return false;\n        }\n    }\n    return true;\n}\n\nvoid place(const string &s, const Candidate &cand, char grid[20][20]) {\n    int len = s.size();\n    if (cand.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            grid[cand.r][(cand.c + p) % N] = s[p];\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            grid[(cand.r + p) % N][cand.c] = s[p];\n        }\n    }\n}\n\nbool check_match(const string &s, const Candidate &cand, const char grid[20][20]) {\n    int len = s.size();\n    if (cand.dir == 0) {\n        for (int p = 0; p < len; ++p) {\n            if (grid[cand.r][(cand.c + p) % N] != s[p]) return false;\n        }\n    } else {\n        for (int p = 0; p < len; ++p) {\n            if (grid[(cand.r + p) % N][cand.c] != s[p]) return false;\n        }\n    }\n    return true;\n}\n\nvoid evaluate_and_update(char grid[20][20]) {\n    int matched = 0, empty = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (grid[i][j] == '.') ++empty;\n    for (int i = 0; i < M; ++i) {\n        bool found = false;\n        for (auto &cand : string_candidates[i]) {\n            if (check_match(strings[i], cand, grid)) {\n                found = true;\n                break;\n            }\n        }\n        if (found) ++matched;\n    }\n    if (matched > best_matched || (matched == best_matched && empty < best_empty)) {\n        best_matched = matched;\n        best_empty = empty;\n        memcpy(best_grid, grid, sizeof(best_grid));\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    strings.resize(M);\n    for (int i = 0; i < M; ++i) cin >> strings[i];\n\n    // Generate all candidates\n    string_candidates.resize(M);\n    for (int i = 0; i < M; ++i) {\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                string_candidates[i].push_back({r, c, 0});\n                string_candidates[i].push_back({r, c, 1});\n            }\n        }\n    }\n\n    const char letters[] = {'A','B','C','D','E','F','G','H'};\n    mt19937 rng(42);\n\n    // Order: length descending\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return strings[a].size() > strings[b].size();\n    });\n\n    auto start_time = high_resolution_clock::now();\n\n    while (true) {\n        auto now = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(now - start_time).count() > 2900) break;\n\n        char grid[20][20];\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                grid[i][j] = '.';\n\n        // shuffle within same length groups\n        vector<int> run_order = order;\n        int start_idx = 0;\n        while (start_idx < M) {\n            int cur_len = strings[run_order[start_idx]].size();\n            int end_idx = start_idx;\n            while (end_idx < M && strings[run_order[end_idx]].size() == cur_len) ++end_idx;\n            shuffle(run_order.begin() + start_idx, run_order.begin() + end_idx, rng);\n            start_idx = end_idx;\n        }\n\n        // Place strings\n        for (int idx : run_order) {\n            const string &s = strings[idx];\n            int valid_count = 0;\n            Candidate chosen;\n            for (auto &cand : string_candidates[idx]) {\n                if (compatible(s, cand, grid)) {\n                    ++valid_count;\n                    if (uniform_int_distribution<int>(1, valid_count)(rng) == 1) {\n                        chosen = cand;\n                    }\n                }\n            }\n            if (valid_count > 0) {\n                place(s, chosen, grid);\n            }\n        }\n\n        // Fill remaining '.' with random letters\n        uniform_int_distribution<int> letter_dist(0,7);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (grid[i][j] == '.')\n                    grid[i][j] = letters[letter_dist(rng)];\n\n        evaluate_and_update(grid);\n    }\n\n    // Output best\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dir[4] = {'U', 'D', 'L', 'R'};\n\nint N, si, sj;\nvector<string> grid;\nvector<vector<int>> cost;\nvector<vector<bool>> road;\nvector<vector<bitset<5000>>> visMask;\nint totalRoads = 0;\nvector<vector<int>> roadId;\n\nbool inside(int i, int j) {\n    return i>=0 && i<N && j>=0 && j<N;\n}\n\npair<int, vector<pair<int,int>>> shortestPath(int si, int sj, int ti, int tj) {\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    priority_queue<pair<int,pair<int,int>>, vector<pair<int,pair<int,int>>>, greater<>> pq;\n    dist[si][sj] = 0;\n    pq.push({0, {si, sj}});\n    \n    while(!pq.empty()) {\n        auto [d, pos] = pq.top(); pq.pop();\n        auto [i, j] = pos;\n        if(d != dist[i][j]) continue;\n        if(i==ti && j==tj) break;\n        for(int k=0;k<4;k++) {\n            int ni = i+dx[k], nj = j+dy[k];\n            if(inside(ni,nj) && road[ni][nj]) {\n                int nd = d + cost[ni][nj];\n                if(nd < dist[ni][nj]) {\n                    dist[ni][nj] = nd;\n                    prev[ni][nj] = {i,j};\n                    pq.push({nd, {ni,nj}});\n                }\n            }\n        }\n    }\n    \n    vector<pair<int,int>> path;\n    if(dist[ti][tj] >= 1e8) return {1e9, path};\n    \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; cj = p.second;\n        if(ci == -1) break;\n    }\n    path.push_back({si,sj});\n    reverse(path.begin(), path.end());\n    return {dist[ti][tj], path};\n}\n\nstring pathToDir(const vector<pair<int,int>>& path) {\n    string res;\n    for(int i=0;i+1<(int)path.size();i++) {\n        int di = path[i+1].first - path[i].first;\n        int dj = path[i+1].second - path[i].second;\n        if(di == -1) res += 'U';\n        else if(di == 1) res += 'D';\n        else if(dj == -1) res += 'L';\n        else if(dj == 1) res += 'R';\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(0);\n    \n    cin >> N >> si >> sj;\n    grid.resize(N);\n    cost.assign(N, vector<int>(N,0));\n    road.assign(N, vector<bool>(N,false));\n    roadId.assign(N, vector<int>(N,-1));\n    \n    for(int i=0;i<N;i++) {\n        cin >> grid[i];\n        for(int j=0;j<N;j++) {\n            if(grid[i][j] != '#') {\n                road[i][j] = true;\n                cost[i][j] = grid[i][j] - '0';\n                roadId[i][j] = totalRoads++;\n            }\n        }\n    }\n    \n    // Compute visibility masks\n    visMask.assign(N, vector<bitset<5000>>(N));\n    for(int i=0;i<N;i++) {\n        for(int j=0;j<N;j++) {\n            if(!road[i][j]) continue;\n            for(int jj=j; jj<N && road[i][jj]; jj++) \n                visMask[i][j].set(roadId[i][jj]);\n            for(int jj=j-1; jj>=0 && road[i][jj]; jj--) \n                visMask[i][j].set(roadId[i][jj]);\n            for(int ii=i; ii<N && road[ii][j]; ii++) \n                visMask[i][j].set(roadId[ii][j]);\n            for(int ii=i-1; ii>=0 && road[ii][j]; ii--) \n                visMask[i][j].set(roadId[ii][j]);\n        }\n    }\n    \n    // Greedy set cover\n    bitset<5000> covered;\n    vector<pair<int,int>> chosen;\n    covered.set(roadId[si][sj]);\n    chosen.push_back({si,sj});\n    \n    while((int)covered.count() < totalRoads) {\n        int best = -1, bi = -1, bj = -1;\n        for(int i=0;i<N;i++) {\n            for(int j=0;j<N;j++) {\n                if(!road[i][j]) continue;\n                bitset<5000> newCov = visMask[i][j] | covered;\n                int gain = (int)newCov.count() - (int)covered.count();\n                if(gain > best) {\n                    best = gain;\n                    bi = i; bj = j;\n                }\n            }\n        }\n        if(best<=0) break;\n        covered |= visMask[bi][bj];\n        chosen.push_back({bi,bj});\n    }\n    \n    int M = (int)chosen.size();\n    \n    // Precompute all-pairs shortest paths\n    vector<vector<int>> dist(M, vector<int>(M));\n    vector<vector<vector<pair<int,int>>>> pathCache(M, vector<vector<pair<int,int>>>(M));\n    \n    for(int i=0;i<M;i++) {\n        for(int j=0;j<M;j++) {\n            if(i == j) {\n                dist[i][j] = 0;\n                pathCache[i][j] = {{chosen[i].first, chosen[i].second}};\n                continue;\n            }\n            if(i > j) {\n                dist[i][j] = dist[j][i];\n                auto rev = pathCache[j][i];\n                reverse(rev.begin(), rev.end());\n                pathCache[i][j] = rev;\n                continue;\n            }\n            auto [d, path] = shortestPath(chosen[i].first, chosen[i].second,\n                                          chosen[j].first, chosen[j].second);\n            dist[i][j] = d;\n            pathCache[i][j] = path;\n        }\n    }\n    \n    // Build initial tour: Nearest neighbor from start (0)\n    vector<int> tour;\n    vector<bool> used(M, false);\n    tour.push_back(0);\n    used[0] = true;\n    \n    for(int step=1; step<M; step++) {\n        int cur = tour.back();\n        int best = -1;\n        int bestD = 1e9;\n        for(int i=1;i<M;i++) {\n            if(!used[i] && dist[cur][i] < bestD) {\n                bestD = dist[cur][i];\n                best = i;\n            }\n        }\n        if(best == -1) {\n            for(int i=0;i<M;i++) {\n                if(!used[i]) {\n                    best = i;\n                    break;\n                }\n            }\n        }\n        tour.push_back(best);\n        used[best] = true;\n    }\n    \n    // 2-opt improvement\n    {\n        bool improved = true;\n        while(improved) {\n            improved = false;\n            for(int i=0; i<M; i++) {\n                for(int j=i+2; j<M; j++) {\n                    if(i==0 && j==M-1) continue;\n                    int a = tour[i], b = tour[(i+1)%M];\n                    int c = tour[j], d = tour[(j+1)%M];\n                    int oldCost = dist[a][b] + dist[c][d];\n                    int newCost = dist[a][c] + dist[b][d];\n                    if(newCost < oldCost) {\n                        reverse(tour.begin()+i+1, tour.begin()+j+1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Build full path\n    vector<pair<int,int>> fullPath;\n    for(int i=0;i<M;i++) {\n        int cur = tour[i];\n        int nxt = tour[(i+1)%M];\n        const auto& pp = pathCache[cur][nxt];\n        \n        if(fullPath.empty()) {\n            fullPath = pp;\n        } else {\n            for(int k=1; k<(int)pp.size(); k++) {\n                fullPath.push_back(pp[k]);\n            }\n        }\n    }\n    \n    // Remove consecutive duplicates only\n    vector<pair<int,int>> cleanPath;\n    for(const auto& p : fullPath) {\n        if(cleanPath.empty() || cleanPath.back() != p) {\n            cleanPath.push_back(p);\n        }\n    }\n    \n    string ans = pathToDir(cleanPath);\n    cout << ans << \"\\n\";\n    \n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, K, R;\nvector<vector<int>> d;\nvector<vector<int>> dep;\nvector<vector<int>> rev_dep;\nvector<int> in_degree;\nvector<int> descendants;\n\nvector<vector<double>> s_est;\nvector<vector<int>> s_obs_count;\nvector<int> total_assigned;\nvector<vector<int>> completion_times;\nvector<vector<int>> completion_count;\n\nenum TaskStatus { NOT_STARTED = 0, IN_PROGRESS = 1, COMPLETED = 2 };\nvector<TaskStatus> task_status;\nvector<int> task_assigned_to;\nvector<int> task_start_day;\nvector<bool> member_busy;\nvector<int> member_current_task;\n\nvoid parse_input() {\n    cin >> N >> M >> K >> R;\n    d.resize(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            cin >> d[i][k];\n        }\n    }\n    dep.resize(N);\n    rev_dep.resize(N);\n    in_degree.assign(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        dep[v].push_back(u);\n        rev_dep[u].push_back(v);\n        in_degree[v]++;\n    }\n}\n\nvoid init_estimation() {\n    s_est.assign(M, vector<double>(K, 0.0));\n    s_obs_count.assign(M, vector<int>(K, 0));\n    completion_times.assign(N, vector<int>(M, -1));\n    completion_count.assign(N, vector<int>(M, 0));\n    \n    // Compute average and max difficulty per skill\n    vector<double> avg_diff(K, 0);\n    vector<int> max_diff(K, 0);\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) {\n            avg_diff[k] += d[i][k];\n            max_diff[k] = max(max_diff[k], d[i][k]);\n        }\n    }\n    for (int k = 0; k < K; k++) {\n        avg_diff[k] /= N;\n    }\n    \n    // Initialize with good estimates + diversity\n    // Members have skills 20-60, tasks have difficulty up to ~40\n    for (int j = 0; j < M; j++) {\n        // Each member has a \"base competence\" level\n        double base = 22.0 + (j % 8) * 3.0 + (j / 8) * 5.0;\n        for (int k = 0; k < K; k++) {\n            // Start above average task difficulty, with variation\n            double est = avg_diff[k] + base * 0.5 + (k % 3) * 3.0;\n            // Add some randomness based on member and skill\n            est += sin(j * 1.7 + k * 2.3) * 8.0;\n            s_est[j][k] = clamp(est, 10.0, 55.0);\n        }\n    }\n}\n\nvoid init_scheduling() {\n    task_status.assign(N, NOT_STARTED);\n    task_assigned_to.assign(N, -1);\n    task_start_day.assign(N, -1);\n    member_busy.assign(M, false);\n    member_current_task.assign(M, -1);\n    total_assigned.assign(M, 0);\n}\n\nvoid precompute_descendants() {\n    descendants.assign(N, 0);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < N; i++) {\n        for (int u : rev_dep[i]) indeg[u]++;\n    }\n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (indeg[i] == 0) q.push(i);\n    }\n    vector<int> topo;\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) q.push(u);\n        }\n    }\n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        descendants[v] = 1;\n        for (int u : rev_dep[v]) {\n            descendants[v] += descendants[u];\n        }\n    }\n}\n\ndouble estimate_w(int i, int j) {\n    double w = 0;\n    for (int k = 0; k < K; k++) {\n        double gap = d[i][k] - s_est[j][k];\n        if (gap > 0) w += gap;\n    }\n    return w;\n}\n\nint estimate_t(int i, int j) {\n    double w = estimate_w(i, j);\n    if (w < 0.5) return 1;\n    return max(1, (int)round(w));\n}\n\nvoid update_skill_estimate(int task, int member, int actual_t) {\n    completion_times[task][member] = actual_t;\n    completion_count[task][member]++;\n    \n    if (actual_t == 1) {\n        // Perfect match: strong update\n        for (int k = 0; k < K; k++) {\n            if (d[task][k] > 0) {\n                if (d[task][k] > s_est[member][k]) {\n                    s_est[member][k] = d[task][k];\n                }\n                // Also slightly boost related skills \n                // (if member is good at k, they might be good at k\u00b11)\n                s_obs_count[member][k] += 2; // Count perfect matches twice\n            }\n        }\n        return;\n    }\n    \n    // Longer task: actual_t \u2248 w + noise\n    double current_w = estimate_w(task, member);\n    double observed_w = actual_t;\n    double diff = observed_w - current_w;\n    \n    if (abs(diff) < 0.2) return;\n    \n    // Clamp to avoid overreacting to noise\n    if (diff > 15) diff = 15;\n    if (diff < -15) diff = -15;\n    \n    vector<double> gaps(K, 0);\n    double total_gap = 0;\n    for (int k = 0; k < K; k++) {\n        gaps[k] = max(0.0, (double)d[task][k] - s_est[member][k]);\n        total_gap += gaps[k];\n    }\n    \n    if (total_gap < 0.01) return;\n    \n    for (int k = 0; k < K; k++) {\n        if (gaps[k] > 0.01) {\n            int obs = s_obs_count[member][k];\n            double lr = 0.45 / (1.0 + 0.1 * obs);\n            \n            double adjustment = diff * (gaps[k] / total_gap) * lr;\n            s_est[member][k] -= adjustment;\n            s_est[member][k] = max(0.0, s_est[member][k]);\n            s_obs_count[member][k]++;\n        }\n    }\n}\n\nbool is_task_ready(int task) {\n    if (task_status[task] != NOT_STARTED) return false;\n    for (int dep_task : dep[task]) {\n        if (task_status[dep_task] != COMPLETED) return false;\n    }\n    return true;\n}\n\nint count_blocked(int task) {\n    if (task_status[task] == COMPLETED) return 0;\n    return descendants[task];\n}\n\nvector<int> compute_critical_path() {\n    vector<int> longest(N, 0);\n    \n    vector<int> indeg(N, 0);\n    for (int i = 0; i < N; i++) {\n        if (task_status[i] == COMPLETED) continue;\n        for (int u : rev_dep[i]) indeg[u]++;\n    }\n    \n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (task_status[i] != COMPLETED && indeg[i] == 0) q.push(i);\n    }\n    \n    vector<int> topo;\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        topo.push_back(v);\n        for (int u : rev_dep[v]) {\n            indeg[u]--;\n            if (indeg[u] == 0) q.push(u);\n        }\n    }\n    \n    for (int idx = topo.size() - 1; idx >= 0; idx--) {\n        int v = topo[idx];\n        if (task_status[v] == COMPLETED) {\n            longest[v] = 0;\n        } else {\n            int min_est = 1000000;\n            for (int j = 0; j < M; j++) {\n                min_est = min(min_est, estimate_t(v, j));\n            }\n            min_est = max(1, min_est);\n            \n            int max_succ = 0;\n            for (int u : rev_dep[v]) {\n                max_succ = max(max_succ, longest[u]);\n            }\n            longest[v] = min_est + max_succ;\n        }\n    }\n    \n    return longest;\n}\n\nvector<int> get_ready_tasks() {\n    vector<int> ready;\n    for (int i = 0; i < N; i++) {\n        if (is_task_ready(i)) {\n            ready.push_back(i);\n        }\n    }\n    \n    if (ready.empty()) return ready;\n    \n    vector<int> crit = compute_critical_path();\n    \n    sort(ready.begin(), ready.end(), [&](int a, int b) {\n        if (crit[a] != crit[b]) return crit[a] > crit[b];\n        if (descendants[a] != descendants[b]) return descendants[a] > descendants[b];\n        return a < b;\n    });\n    \n    return ready;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    parse_input();\n    init_estimation();\n    init_scheduling();\n    precompute_descendants();\n    \n    int current_day = 0;\n    \n    while (true) {\n        current_day++;\n        \n        // Adaptive exploration based on observation coverage\n        int total_skill_obs = 0;\n        for (int j = 0; j < M; j++) {\n            for (int k = 0; k < K; k++) {\n                total_skill_obs += min(10, s_obs_count[j][k]);\n            }\n        }\n        int max_possible = M * K * 10;\n        bool exploration_phase = (total_skill_obs < max_possible * 0.6); // Increased from 0.5\n        \n        vector<int> ready_tasks = get_ready_tasks();\n        vector<int> crit = compute_critical_path();\n        \n        vector<int> available;\n        for (int j = 0; j < M; j++) {\n            if (!member_busy[j]) {\n                available.push_back(j);\n            }\n        }\n        \n        vector<pair<int,int>> assignments;\n        vector<bool> used(M, false);\n        set<int> assigned_tasks;\n        \n        // Phase 1: 1-day tasks (perfect matches) - most important!\n        if (!ready_tasks.empty() && !available.empty()) {\n            vector<tuple<int,int,int>> one_day_opts;\n            \n            for (int task : ready_tasks) {\n                for (int j : available) {\n                    double w = estimate_w(task, j);\n                    if (w < 0.5) {\n                        one_day_opts.push_back({-crit[task], j, task});\n                    }\n                }\n            }\n            \n            // Sort by urgency (most critical first)\n            sort(one_day_opts.begin(), one_day_opts.end());\n            \n            for (auto &[neg_c, j, task] : one_day_opts) {\n                if (!used[j] && assigned_tasks.find(task) == assigned_tasks.end()) {\n                    assignments.push_back({j, task});\n                    used[j] = true;\n                    assigned_tasks.insert(task);\n                }\n            }\n        }\n        \n        // Phase 2: Best assignments for remaining ready tasks\n        for (int task : ready_tasks) {\n            if ((int)assignments.size() >= (int)available.size()) break;\n            if (assigned_tasks.find(task) != assigned_tasks.end()) continue;\n            \n            int best_member = -1;\n            double best_score = -1e18;\n            \n            for (int j : available) {\n                if (used[j]) continue;\n                \n                int est_t = estimate_t(task, j);\n                double score = -est_t * 100.0;\n                \n                // Critical path urgency\n                score += crit[task] * 3.0;\n                score += count_blocked(task) * 0.5;\n                \n                // Exploration bonus\n                if (exploration_phase) {\n                    int unexplored = 0;\n                    for (int k = 0; k < K; k++) {\n                        if (d[task][k] > s_est[j][k] && s_obs_count[j][k] < 3) {\n                            unexplored++;\n                        }\n                    }\n                    score += unexplored * 25.0; // Increased exploration bonus\n                }\n                \n                // Load balance\n                score -= total_assigned[j] * 0.2;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_member = j;\n                }\n            }\n            \n            if (best_member != -1) {\n                int est_t = estimate_t(task, best_member);\n                if (est_t < 70 || exploration_phase) { // Slightly stricter threshold\n                    assignments.push_back({best_member, task});\n                    used[best_member] = true;\n                    assigned_tasks.insert(task);\n                }\n            }\n        }\n        \n        // Phase 3: If critical tasks remain unassigned and members available, assign them anyway\n        if ((int)assignments.size() < (int)available.size() && !ready_tasks.empty()) {\n            for (int task : ready_tasks) {\n                if ((int)assignments.size() >= (int)available.size()) break;\n                if (assigned_tasks.find(task) != assigned_tasks.end()) continue;\n                if (crit[task] < 50) continue; // Only force critical tasks\n                \n                for (int j : available) {\n                    if (!used[j]) {\n                        int est_t = estimate_t(task, j);\n                        if (est_t < 150) { // Allow longer tasks if critical\n                            assignments.push_back({j, task});\n                            used[j] = true;\n                            assigned_tasks.insert(task);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto &p : assignments) {\n            int member = p.first;\n            int task = p.second;\n            cout << \" \" << (member + 1) << \" \" << (task + 1);\n            \n            task_status[task] = IN_PROGRESS;\n            task_assigned_to[task] = member;\n            task_start_day[task] = current_day;\n            member_busy[member] = true;\n            member_current_task[member] = task;\n            total_assigned[member]++;\n        }\n        cout << \"\\n\";\n        \n        // Output predictions\n        for (int j = 0; j < M; j++) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << \" \" << max(0, (int)round(s_est[j][k]));\n            }\n            cout << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read completions\n        string line;\n        getline(cin, line);\n        while (line.empty()) {\n            if (!getline(cin, line)) break;\n        }\n        \n        istringstream iss(line);\n        vector<int> vals;\n        int x;\n        while (iss >> x) vals.push_back(x);\n        \n        if (vals.empty()) continue;\n        if (vals.size() == 1 && vals[0] == -1) {\n            break;\n        }\n        \n        int n_comp = vals[0];\n        for (int i = 0; i < n_comp; i++) {\n            int member = vals[i + 1] - 1;\n            member_busy[member] = false;\n            \n            int task = member_current_task[member];\n            if (task != -1 && task_status[task] == IN_PROGRESS) {\n                int actual_t = current_day - task_start_day[task] + 1;\n                update_skill_estimate(task, member, actual_t);\n                task_status[task] = COMPLETED;\n                task_assigned_to[task] = -1;\n                member_current_task[member] = -1;\n            }\n        }\n        \n        if (current_day >= 2000) break;\n    }\n    \n    return 0;\n}","ahc006":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <climits>\n#include <tuple>\n#include <cmath>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    const int N = 1000, K = 50, DEPOT = 0, MAXN = 2*N+1;\n    vector<int> x(MAXN), y(MAXN);\n    x[DEPOT] = y[DEPOT] = 400;\n    for (int i = 0; i < N; ++i) {\n        cin >> x[2*i+1] >> y[2*i+1] >> x[2*i+2] >> y[2*i+2];\n    }\n    vector<vector<int>> dist(MAXN, vector<int>(MAXN));\n    for (int i = 0; i < MAXN; ++i)\n        for (int j = 0; j <= i; ++j)\n            dist[i][j] = dist[j][i] = abs(x[i]-x[j]) + abs(y[i]-y[j]);\n    \n    auto routeLen = [&](const vector<int>& r){\n        int len=0;\n        for(size_t i=0;i+1<r.size();++i) len += dist[r[i]][r[i+1]];\n        return len;\n    };\n    \n    auto insertTwo = [&](vector<int> r, int p, int d, int posP, int posD){\n        if (posP <= posD) {\n            r.insert(r.begin() + posP, p);\n            r.insert(r.begin() + posD + 1, d);\n        } else {\n            r.insert(r.begin() + posD, d);\n            r.insert(r.begin() + posP + 1, p);\n        }\n        return r;\n    };\n    \n    const int W = 12;\n    auto bestInsertFast = [&](const vector<int>& r, int pNode, int dNode) -> tuple<int,int,int> {\n        int bestExtra = INT_MAX;\n        int bestP = -1, bestD = -1;\n        int m = (int)r.size();\n        vector<pair<int,int>> candP;\n        candP.reserve(W);\n        for (int i = 0; i < m-1; ++i) {\n            int pi = i+1;\n            int extraP = dist[r[i]][pNode] + dist[pNode][r[pi]] - dist[r[i]][r[pi]];\n            auto it = lower_bound(candP.begin(), candP.end(), make_pair(extraP, i),\n                                   [](auto& a, auto& b){ return a.first < b.first; });\n            if ((int)candP.size() < W) {\n                candP.insert(it, {extraP, i});\n            } else if (it != candP.end()) {\n                candP.insert(it, {extraP, i});\n                candP.pop_back();\n            }\n        }\n        for (auto& p : candP) {\n            int i = p.second;\n            int pi = i+1;\n            int extraP = p.first;\n            if (extraP >= bestExtra) continue;\n            for (int j = i; j < m-1; ++j) {\n                int dj = j+1;\n                int extraD = dist[r[j]][dNode] + dist[dNode][r[dj]] - dist[r[j]][r[dj]];\n                int total = extraP + extraD;\n                if (total < bestExtra) {\n                    bestExtra = total;\n                    bestP = pi;\n                    bestD = dj;\n                }\n            }\n        }\n        return {bestP, bestD, bestExtra};\n    };\n    \n    auto bestInsertFull = [&](const vector<int>& r, int pNode, int dNode) -> tuple<int,int,int> {\n        int bestExtra = INT_MAX, bestP = -1, bestD = -1;\n        int m = (int)r.size();\n        for (int i = 0; i < m-1; ++i) {\n            int pi = i+1;\n            int extraP = dist[r[i]][pNode] + dist[pNode][r[pi]] - dist[r[i]][r[pi]];\n            for (int j = i; j < m-1; ++j) {\n                int dj = j+1;\n                int extraD = dist[r[j]][dNode] + dist[dNode][r[dj]] - dist[r[j]][r[dj]];\n                int total = extraP + extraD;\n                if (total < bestExtra) {\n                    bestExtra = total;\n                    bestP = pi;\n                    bestD = dj;\n                }\n            }\n        }\n        return {bestP, bestD, bestExtra};\n    };\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    uniform_real_distribution<double> realDist(0.0, 1.0);\n    \n    vector<int> bestSelected;\n    vector<int> bestRouteVec;\n    int bestLenGlobal = INT_MAX;\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    // 1) Initial build with sorted orders\n    {\n        vector<int> sel(N);\n        iota(sel.begin(), sel.end(), 0);\n        sort(sel.begin(), sel.end(), [&](int a, int b){\n            int pa = 2*a+1, da = 2*a+2;\n            int pb = 2*b+1, db = 2*b+2;\n            int costA = dist[DEPOT][pa] + dist[da][DEPOT];\n            int costB = dist[DEPOT][pb] + dist[db][DEPOT];\n            return costA < costB;\n        });\n        sel.resize(K);\n        vector<int> rte = {DEPOT, DEPOT};\n        for (int id : sel) {\n            int p = 2*id+1, d = 2*id+2;\n            auto [bp, bd, _] = bestInsertFull(rte, p, d);\n            rte = insertTwo(rte, p, d, bp, bd);\n        }\n        int len = routeLen(rte);\n        bestLenGlobal = len;\n        bestRouteVec = rte;\n        bestSelected = sel;\n    }\n    // 2) random starts\n    for (int tries = 0; tries < 3; ++tries) {\n        if (chrono::duration<double>(chrono::steady_clock::now() - startTime).count() > 0.3) break;\n        vector<int> sel(N);\n        iota(sel.begin(), sel.end(), 0);\n        shuffle(sel.begin(), sel.end(), rng);\n        sel.resize(K);\n        vector<int> rte = {DEPOT, DEPOT};\n        for (int id : sel) {\n            int p = 2*id+1, d = 2*id+2;\n            auto [bp, bd, _] = bestInsertFull(rte, p, d);\n            rte = insertTwo(rte, p, d, bp, bd);\n        }\n        int len = routeLen(rte);\n        if (len < bestLenGlobal) {\n            bestLenGlobal = len;\n            bestRouteVec = rte;\n            bestSelected = sel;\n        }\n    }\n    \n    vector<int> curSelected = bestSelected;\n    vector<int> curRoute = bestRouteVec;\n    int curLen = bestLenGlobal;\n    \n    vector<bool> chosen(N, false);\n    for (int id : curSelected) chosen[id] = true;\n    vector<int> avail;\n    for (int i = 0; i < N; ++i) if (!chosen[i]) avail.push_back(i);\n    \n    uniform_int_distribution<int> selDist(0, K-1);\n    uniform_int_distribution<int> availDist(0, (int)avail.size()-1);\n    \n    double temperature = 200.0;\n    double cool = 0.999995;\n    int saIter = 0;\n    const double TIME_SA_END = 1.70;\n    \n    while (true) {\n        if (saIter % 2000 == 0) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - startTime).count() > TIME_SA_END) break;\n        }\n        saIter++;\n        \n        int idxR = selDist(rng), oldId = curSelected[idxR];\n        int idxA = availDist(rng), newId = avail[idxA];\n        int oldP = 2*oldId+1, oldD = 2*oldId+2;\n        int newP = 2*newId+1, newD = 2*newId+2;\n        \n        vector<int> tempRoute;\n        tempRoute.reserve(curRoute.size()-2);\n        for (int node : curRoute) if (node != oldP && node != oldD) tempRoute.push_back(node);\n        \n        auto [bp, bd, extra] = bestInsertFast(tempRoute, newP, newD);\n        vector<int> cand = insertTwo(tempRoute, newP, newD, bp, bd);\n        int candLen = routeLen(cand);\n        \n        int delta = candLen - curLen;\n        if (delta < 0 || realDist(rng) < exp(-delta / temperature)) {\n            curRoute = move(cand);\n            curLen = candLen;\n            curSelected[idxR] = newId;\n            chosen[oldId] = false; chosen[newId] = true;\n            avail[idxA] = avail.back();\n            avail.pop_back();\n            avail.push_back(oldId);\n            availDist = uniform_int_distribution<int>(0, max(0,(int)avail.size()-1));\n            \n            if (curLen < bestLenGlobal) {\n                bestLenGlobal = curLen;\n                bestRouteVec = curRoute;\n                bestSelected = curSelected;\n            }\n        }\n        temperature *= cool;\n    }\n    \n    // Hill climbing (only improvements)\n    const double TIME_HILL_END = 1.95;\n    while (chrono::duration<double>(chrono::steady_clock::now() - startTime).count() < TIME_HILL_END) {\n        int idxR = selDist(rng), oldId = curSelected[idxR];\n        int idxA = availDist(rng), newId = avail[idxA];\n        int oldP = 2*oldId+1, oldD = 2*oldId+2;\n        int newP = 2*newId+1, newD = 2*newId+2;\n        \n        vector<int> tempRoute;\n        tempRoute.reserve(curRoute.size()-2);\n        for (int node : curRoute) if (node != oldP && node != oldD) tempRoute.push_back(node);\n        \n        auto [bp, bd, extra] = bestInsertFast(tempRoute, newP, newD);\n        vector<int> cand = insertTwo(tempRoute, newP, newD, bp, bd);\n        int candLen = routeLen(cand);\n        \n        if (candLen < curLen) {\n            curRoute = move(cand);\n            curLen = candLen;\n            curSelected[idxR] = newId;\n            chosen[oldId] = false; chosen[newId] = true;\n            avail[idxA] = avail.back();\n            avail.pop_back();\n            avail.push_back(oldId);\n            availDist = uniform_int_distribution<int>(0, max(0,(int)avail.size()-1));\n            \n            if (curLen < bestLenGlobal) {\n                bestLenGlobal = curLen;\n                bestRouteVec = curRoute;\n                bestSelected = curSelected;\n            }\n        }\n    }\n    \n    cout << K;\n    for (int id : bestSelected) cout << \" \" << id+1;\n    cout << \"\\n\" << bestRouteVec.size();\n    for (int node : bestRouteVec) cout << \" \" << x[node] << \" \" << y[node];\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <queue>\n#include <cstring>\n#include <map>\nusing namespace std;\n\nstruct Edge { int u, v, d; };\n\nclass UnionFind {\npublic:\n    vector<int> parent, rank;\n    int comps;\n    UnionFind(int n) : comps(n) {\n        parent.resize(n); rank.resize(n, 0);\n        for (int i = 0; i < n; i++) parent[i] = i;\n    }\n    int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); }\n    bool unite(int x, int y) {\n        int px = find(x), py = find(y);\n        if (px == py) return false;\n        if (rank[px] < rank[py]) parent[px] = py;\n        else if (rank[py] < rank[px]) parent[py] = px;\n        else { parent[py] = px; rank[px]++; }\n        comps--; return true;\n    }\n    bool connected(int x, int y) { return find(x) == find(y); }\n};\n\nbool canFinish(const vector<Edge>& edges, int startIdx, int M, UnionFind& uf,\n               int& outMinEdgesNeeded) {\n    int compToIdx[400];\n    memset(compToIdx, -1, sizeof(compToIdx));\n    int C = 0;\n    for (int j = 0; j < 400; j++) {\n        int c = uf.find(j);\n        if (compToIdx[c] == -1) compToIdx[c] = C++;\n    }\n    if (C <= 1) { outMinEdgesNeeded = 0; return true; }\n    \n    vector<vector<int>> compGraph(C);\n    for (int j = startIdx; j < M; j++) {\n        int cu = compToIdx[uf.find(edges[j].u)];\n        int cv = compToIdx[uf.find(edges[j].v)];\n        if (cu != cv) {\n            compGraph[cu].push_back(cv);\n            compGraph[cv].push_back(cu);\n        }\n    }\n    \n    vector<bool> vis(C, false);\n    queue<int> q;\n    q.push(0); vis[0] = true;\n    int cnt = 0;\n    while (!q.empty()) {\n        int cur = q.front(); q.pop();\n        cnt++;\n        for (int nxt : compGraph[cur]) {\n            if (!vis[nxt]) { vis[nxt] = true; q.push(nxt); }\n        }\n    }\n    \n    // Minimum edges needed = C - 1 (spanning tree of component graph)\n    outMinEdgesNeeded = C - 1;\n    return cnt == C;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false); cin.tie(nullptr);\n    \n    const int N = 400, M = 1995, TARGET = 399;\n    \n    vector<pair<int,int>> coords(N);\n    for (int i = 0; i < N; i++) cin >> coords[i].first >> coords[i].second;\n    \n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        int dx = coords[edges[i].u].first - coords[edges[i].v].first;\n        int dy = coords[edges[i].u].second - coords[edges[i].v].second;\n        edges[i].d = round(sqrt(dx*dx + dy*dy));\n    }\n    \n    // Simulate 5 rounds of MST extraction\n    vector<bool> usedInRounds(M, false);\n    vector<int> edgeRound(M, 5);\n    for (int round = 0; round < 5; round++) {\n        vector<pair<double,int>> remaining;\n        for (int i = 0; i < M; i++) {\n            if (!usedInRounds[i]) remaining.push_back({(double)edges[i].d, i});\n        }\n        sort(remaining.begin(), remaining.end());\n        UnionFind tmpUf(N);\n        for (auto& [d, idx] : remaining) {\n            if (tmpUf.unite(edges[idx].u, edges[idx].v)) {\n                usedInRounds[idx] = true;\n                edgeRound[idx] = round;\n            }\n        }\n    }\n    \n    // Compute d_i rank globally\n    vector<int> dRank(M);\n    vector<int> sortedByD(M);\n    iota(sortedByD.begin(), sortedByD.end(), 0);\n    sort(sortedByD.begin(), sortedByD.end(), [&](int a, int b) {\n        return edges[a].d < edges[b].d;\n    });\n    for (int i = 0; i < M; i++) dRank[sortedByD[i]] = i;\n    \n    UnionFind uf(N);\n    int accepted = 0;\n    vector<int> seenByRound(5, 0), acceptedByRound(5, 0);\n    \n    for (int i = 0; i < M; i++) {\n        int li; cin >> li;\n        bool accept = false;\n        int stillNeed = uf.comps - 1;\n        int remaining = M - i - 1;\n        \n        if (stillNeed > 0 && !uf.connected(edges[i].u, edges[i].v)) {\n            double ratio = (double)li / max(1.0, (double)edges[i].d);\n            int imp = edgeRound[i];\n            seenByRound[imp]++;\n            \n            // Safety check with minimum edges needed\n            int minEdgesNeeded = 0;\n            bool finishable = canFinish(edges, i + 1, M, uf, minEdgesNeeded);\n            \n            if (!finishable) {\n                accept = true;\n            } else {\n                // Compute how many \"extra\" edges we have beyond the minimum\n                int extraEdges = remaining - minEdgesNeeded;\n                \n                // Base threshold by importance\n                double threshold;\n                if (imp == 0) threshold = 2.1;\n                else if (imp == 1) threshold = 1.75;\n                else if (imp == 2) threshold = 1.45;\n                else if (imp == 3) threshold = 1.2;\n                else threshold = 1.08;\n                \n                // Bonus for edges with very small d_i\n                if (dRank[i] < M * 0.05) threshold += 0.3;\n                else if (dRank[i] < M * 0.15) threshold += 0.15;\n                else if (dRank[i] < M * 0.30) threshold += 0.05;\n                \n                // Adjust for stillNeed\n                if (stillNeed > 300) threshold += 0.2;\n                else if (stillNeed > 200) threshold += 0.1;\n                else if (stillNeed < 80) threshold += 0.2;\n                else if (stillNeed < 40) threshold += 0.4;\n                else if (stillNeed < 15) threshold += 0.6;\n                else if (stillNeed < 5) threshold = 3.0;\n                \n                // Adjust for remaining buffer\n                if (remaining < stillNeed * 3) threshold = 3.0;\n                else if (remaining < stillNeed * 5) threshold += 0.7;\n                else if (remaining < stillNeed * 8) threshold += 0.3;\n                \n                // Adjust for extra edges beyond minimum\n                if (extraEdges < stillNeed) {\n                    // Very tight: must be aggressive\n                    threshold += 0.5;\n                } else if (extraEdges < stillNeed * 3) {\n                    threshold += 0.2;\n                } else if (extraEdges > stillNeed * 10) {\n                    // Plenty of extras: be selective\n                    threshold -= 0.1;\n                }\n                \n                // If ahead of schedule, be more selective\n                double expectedAccepted = TARGET * (double)(i + 1) / M;\n                double aheadRatio = (expectedAccepted > 0) ? accepted / expectedAccepted : 1.0;\n                \n                if (aheadRatio > 1.2 && stillNeed > 50) {\n                    threshold -= 0.25;\n                } else if (aheadRatio > 1.1 && stillNeed > 50) {\n                    threshold -= 0.12;\n                } else if (aheadRatio < 0.85 && stillNeed > 10) {\n                    threshold += 0.4;\n                } else if (aheadRatio < 0.95 && stillNeed > 10) {\n                    threshold += 0.2;\n                }\n                \n                // Round-based acceptance rate\n                if (imp <= 2 && seenByRound[imp] > 0) {\n                    double acceptRate = (double)acceptedByRound[imp] / seenByRound[imp];\n                    if (acceptRate > 0.5) threshold -= 0.05;\n                }\n                \n                threshold = max(1.03, min(3.0, threshold));\n                \n                if (ratio <= threshold) accept = true;\n            }\n        }\n        \n        if (accept) {\n            uf.unite(edges[i].u, edges[i].v);\n            accepted++;\n            acceptedByRound[edgeRound[i]]++;\n        }\n        \n        cout << (accept ? 1 : 0) << endl;\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int GRID = 30;\nconst int TURNS = 300;\nconst int dx[] = {-1, 1, 0, 0};\nconst int dy[] = {0, 0, -1, 1};\nconst char wall_char[] = {'u', 'd', 'l', 'r'};\nconst char move_char[] = {'U', 'D', 'L', 'R'};\nconst int rev_dir[] = {1, 0, 3, 2};\n\nstruct Pos {\n    int x, y;\n    Pos() : x(0), y(0) {}\n    Pos(int x, int y) : x(x), y(y) {}\n    bool operator==(const Pos& o) const { return x==o.x && y==o.y; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n    bool operator<(const Pos& o) const { return tie(x,y) < tie(o.x,o.y); }\n    bool valid() const { return x>=0 && x<GRID && y>=0 && y<GRID; }\n    Pos move(int d) const { return Pos(x+dx[d], y+dy[d]); }\n};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nstruct Pet {\n    Pos pos;\n    int type;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Pos> humans;\nvector<vector<bool>> wall;\n\nbool has_pet(Pos p) {\n    for(int i=0; i<N; i++) if(pets[i].pos == p) return true;\n    return false;\n}\n\nbool adjacent_to_pet(Pos p) {\n    for(int d=0; d<4; d++) {\n        Pos adj = p.move(d);\n        if(adj.valid() && has_pet(adj)) return true;\n    }\n    return false;\n}\n\nPos get_dest(Pos cur, char act) {\n    if(act == 'U') return cur.move(0);\n    if(act == 'D') return cur.move(1);\n    if(act == 'L') return cur.move(2);\n    if(act == 'R') return cur.move(3);\n    return cur;\n}\n\nbool validate_actions(const string& actions) {\n    vector<Pos> new_pos(M);\n    vector<Pos> wall_targets;\n    \n    for(int i=0; i<M; i++) {\n        if(actions[i] == 'U' || actions[i] == 'D' || actions[i] == 'L' || actions[i] == 'R') {\n            Pos dest = get_dest(humans[i], actions[i]);\n            if(!dest.valid() || wall[dest.x][dest.y] || has_pet(dest)) return false;\n            new_pos[i] = dest;\n        } else {\n            new_pos[i] = humans[i];\n        }\n        \n        if(actions[i] == 'u' || actions[i] == 'd' || actions[i] == 'l' || actions[i] == 'r') {\n            Pos wt = humans[i].move(string(\"udlr\").find(actions[i]));\n            if(!wt.valid() || has_pet(wt) || adjacent_to_pet(wt)) return false;\n            for(int j=0; j<M; j++) if(humans[j] == wt) return false;\n            wall_targets.push_back(wt);\n        }\n    }\n    \n    for(int i=0; i<M; i++) {\n        for(int j=i+1; j<M; j++) {\n            if(new_pos[i] == new_pos[j]) return false;\n        }\n    }\n    \n    for(auto& wt : wall_targets) {\n        for(int i=0; i<M; i++) {\n            if(new_pos[i] == wt) return false;\n        }\n    }\n    \n    for(int i=0; i<M; i++) {\n        for(int j=0; j<M; j++) {\n            if(i != j && new_pos[i] == humans[j] && \n               (actions[j] == '.' || actions[j] == 'u' || actions[j] == 'd' || \n                actions[j] == 'l' || actions[j] == 'r')) {\n                return false;\n            }\n        }\n    }\n    \n    return true;\n}\n\nvector<int> find_path(Pos from, Pos to) {\n    vector<vector<int>> prev(GRID, vector<int>(GRID, -1));\n    queue<Pos> q;\n    q.push(from);\n    prev[from.x][from.y] = -2;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        if(cur == to) break;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur.move(d);\n            if(!nxt.valid() || wall[nxt.x][nxt.y] || has_pet(nxt)) continue;\n            if(prev[nxt.x][nxt.y] != -1) continue;\n            prev[nxt.x][nxt.y] = d;\n            q.push(nxt);\n        }\n    }\n    \n    if(prev[to.x][to.y] == -1) return {};\n    vector<int> path;\n    Pos cur = to;\n    while(cur != from) {\n        int d = prev[cur.x][cur.y];\n        path.push_back(d);\n        cur = cur.move(rev_dir[d]);\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Count reachable pets from a position\nint count_reachable_pets(Pos start, int max_dist=1e9) {\n    vector<vector<int>> dist(GRID, vector<int>(GRID, 1e9));\n    queue<Pos> q;\n    q.push(start);\n    dist[start.x][start.y] = 0;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        if(dist[cur.x][cur.y] >= max_dist) continue;\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur.move(d);\n            if(nxt.valid() && !wall[nxt.x][nxt.y] && dist[nxt.x][nxt.y] > dist[cur.x][cur.y]+1) {\n                dist[nxt.x][nxt.y] = dist[cur.x][cur.y] + 1;\n                q.push(nxt);\n            }\n        }\n    }\n    \n    int cnt = 0;\n    for(int i=0; i<N; i++) {\n        if(dist[pets[i].pos.x][pets[i].pos.y] < 1e9) cnt++;\n    }\n    return cnt;\n}\n\n// BFS to get all cells reachable from start\nvector<Pos> get_reachable_cells(Pos start) {\n    vector<vector<bool>> vis(GRID, vector<bool>(GRID, false));\n    vector<Pos> cells;\n    queue<Pos> q;\n    q.push(start);\n    vis[start.x][start.y] = true;\n    \n    while(!q.empty()) {\n        Pos cur = q.front(); q.pop();\n        cells.push_back(cur);\n        for(int d=0; d<4; d++) {\n            Pos nxt = cur.move(d);\n            if(nxt.valid() && !wall[nxt.x][nxt.y] && !vis[nxt.x][nxt.y]) {\n                vis[nxt.x][nxt.y] = true;\n                q.push(nxt);\n            }\n        }\n    }\n    return cells;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    pets.resize(N);\n    for(int i=0; i<N; i++) {\n        cin >> pets[i].pos.x >> pets[i].pos.y >> pets[i].type;\n        pets[i].pos.x--; pets[i].pos.y--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for(int i=0; i<M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n        humans[i].x--; humans[i].y--;\n    }\n    \n    wall.assign(GRID, vector<bool>(GRID, false));\n    \n    // Strategy: Each human gets a \"home region\" - a rectangular area they'll claim\n    // First, divide the grid into M approximately equal regions\n    struct Region {\n        int x1, y1, x2, y2; // inclusive bounds\n        Pos corner; // Corner to start from\n        bool claimed;\n        int human_idx;\n    };\n    \n    // Create regions by dividing the grid\n    vector<Region> regions;\n    int cols = min(M, (int)ceil(sqrt(M * 900.0 / GRID)));\n    int rows = (M + cols - 1) / cols;\n    \n    // Adjust to fit 30x30\n    int region_w = GRID / cols;\n    int region_h = GRID / rows;\n    \n    vector<Pos> corners;\n    for(int r=0; r<rows; r++) {\n        for(int c=0; c<cols && (int)regions.size() < M; c++) {\n            int x1 = r * region_h;\n            int y1 = c * region_w;\n            int x2 = (r+1) * region_h - 1;\n            int y2 = (c+1) * region_w - 1;\n            if(r == rows-1) x2 = GRID-1;\n            if(c == cols-1) y2 = GRID-1;\n            \n            // Choose corner based on position relative to grid center\n            Pos corner;\n            if(r <= rows/2 && c <= cols/2) corner = Pos(x1, y1);\n            else if(r <= rows/2) corner = Pos(x1, y2);\n            else if(c <= cols/2) corner = Pos(x2, y1);\n            else corner = Pos(x2, y2);\n            \n            regions.push_back({x1, y1, x2, y2, corner, false, -1});\n            corners.push_back(corner);\n        }\n    }\n    \n    // Assign humans to nearest region corner\n    vector<int> human_region(M, -1);\n    vector<bool> region_taken(regions.size(), false);\n    vector<Pos> targets(M);\n    \n    for(int i=0; i<M; i++) {\n        int best_r = -1;\n        int best_score = 1e9;\n        for(int r=0; r<(int)regions.size(); r++) {\n            if(region_taken[r]) continue;\n            \n            // Score: distance to corner minus safety (fewer nearby pets is better)\n            int dist = manhattan(humans[i], corners[r]);\n            int nearby_pets = count_reachable_pets(corners[r], 5);\n            int score = dist + nearby_pets * 3;\n            \n            if(score < best_score) {\n                best_score = score;\n                best_r = r;\n            }\n        }\n        human_region[i] = best_r;\n        region_taken[best_r] = true;\n        targets[i] = corners[best_r];\n        regions[best_r].human_idx = i;\n        regions[best_r].claimed = true;\n    }\n    \n    vector<bool> at_target(M, false);\n    vector<int> phase(M, 0); // 0=moving to corner, 1=sealing region, 2=expanding\n    \n    // Pre-plan enclosure walls for each region\n    struct WallPlan {\n        vector<Pos> walls; // Walls to build to seal region\n        int current_wall;\n    };\n    vector<WallPlan> plans(M);\n    \n    for(int i=0; i<M; i++) {\n        if(human_region[i] == -1) continue;\n        Region& reg = regions[human_region[i]];\n        Pos corn = corners[human_region[i]];\n        \n        // Plan walls along two edges from the corner\n        int dx1=0, dy1=0, dx2=0, dy2=0;\n        if(corn.x == reg.x1 && corn.y == reg.y1) {\n            // Top-left corner: build right and down\n            for(int y=corn.y; y<=reg.y2; y++) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x<=reg.x2; x++) plans[i].walls.push_back(Pos(x, corn.y));\n        } else if(corn.x == reg.x1 && corn.y == reg.y2) {\n            // Top-right corner\n            for(int y=corn.y; y>=reg.y1; y--) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x<=reg.x2; x++) plans[i].walls.push_back(Pos(x, corn.y));\n        } else if(corn.x == reg.x2 && corn.y == reg.y1) {\n            // Bottom-left corner\n            for(int y=corn.y; y<=reg.y2; y++) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x>=reg.x1; x--) plans[i].walls.push_back(Pos(x, corn.y));\n        } else {\n            // Bottom-right corner\n            for(int y=corn.y; y>=reg.y1; y--) plans[i].walls.push_back(Pos(corn.x, y));\n            for(int x=corn.x; x>=reg.x1; x--) plans[i].walls.push_back(Pos(x, corn.y));\n        }\n        plans[i].current_wall = 0;\n    }\n    \n    for(int turn = 0; turn < TURNS; turn++) {\n        string actions(M, '.');\n        \n        // Process each human\n        for(int i=0; i<M; i++) {\n            Pos h = humans[i];\n            \n            if(phase[i] == 0) {\n                // Move to corner\n                if(h == targets[i]) {\n                    phase[i] = 1;\n                } else {\n                    auto path = find_path(h, targets[i]);\n                    if(!path.empty()) {\n                        actions[i] = move_char[path[0]];\n                    }\n                }\n            }\n            \n            if(phase[i] == 1 && actions[i] == '.') {\n                // Build walls from plan\n                WallPlan& plan = plans[i];\n                bool acted = false;\n                \n                // Try to build next few planned walls\n                for(int attempt=0; attempt<3 && !acted; attempt++) {\n                    int idx = plan.current_wall + attempt;\n                    if(idx >= (int)plan.walls.size()) {\n                        phase[i] = 2; // Done sealing\n                        break;\n                    }\n                    \n                    Pos target = plan.walls[idx];\n                    \n                    // Skip if already walled\n                    if(wall[target.x][target.y]) {\n                        plan.current_wall = idx + 1;\n                        continue;\n                    }\n                    \n                    // If adjacent, try to build\n                    if(manhattan(h, target) == 1) {\n                        int d = -1;\n                        for(int k=0; k<4; k++) {\n                            if(h.move(k) == target) { d = k; break; }\n                        }\n                        \n                        if(d != -1 && !has_pet(target) && !adjacent_to_pet(target)) {\n                            // Check no human conflict\n                            bool conflict = false;\n                            for(int j=0; j<M; j++) {\n                                if(j != i && humans[j] == target) conflict = true;\n                                if(j != i && get_dest(humans[j], actions[j]) == target) conflict = true;\n                            }\n                            if(!conflict) {\n                                actions[i] = wall_char[d];\n                                plan.current_wall = idx + 1;\n                                acted = true;\n                            }\n                        }\n                    } else {\n                        // Move toward next wall target\n                        auto path = find_path(h, target);\n                        if(!path.empty()) {\n                            Pos nxt = h.move(path[0]);\n                            bool conflict = false;\n                            for(int j=0; j<M; j++) {\n                                if(j != i && get_dest(humans[j], actions[j]) == nxt) conflict = true;\n                                if(j != i && humans[j] == nxt && \n                                   (actions[j] == '.' || actions[j] == 'u' || actions[j] == 'd' || \n                                    actions[j] == 'l' || actions[j] == 'r')) conflict = true;\n                            }\n                            if(!conflict) {\n                                actions[i] = move_char[path[0]];\n                                acted = true;\n                            }\n                        }\n                    }\n                }\n                \n                // If stuck, try to move to better position\n                if(!acted && plan.current_wall < (int)plan.walls.size()) {\n                    Pos next_wall = plan.walls[plan.current_wall];\n                    // Move randomly toward it\n                    for(int d=0; d<4; d++) {\n                        Pos nxt = h.move(d);\n                        if(nxt.valid() && !wall[nxt.x][nxt.y] && !has_pet(nxt)) {\n                            if(manhattan(nxt, next_wall) < manhattan(h, next_wall)) {\n                                bool conflict = false;\n                                for(int j=0; j<M; j++) {\n                                    if(j != i && get_dest(humans[j], actions[j]) == nxt) conflict = true;\n                                }\n                                if(!conflict) {\n                                    actions[i] = move_char[d];\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Phase 2: Expand territory by building more walls\n            if(phase[i] == 2 && actions[i] == '.') {\n                // Try to build walls to claim more area\n                bool built = false;\n                \n                // Check if region is fully sealed\n                Region& reg = regions[human_region[i]];\n                Pos corn = corners[human_region[i]];\n                \n                // Try to extend walls outward\n                vector<int> dirs;\n                if(corn.x == reg.x1) dirs.push_back(1); // Down\n                else dirs.push_back(0); // Up\n                if(corn.y == reg.y1) dirs.push_back(3); // Right\n                else dirs.push_back(2); // Left\n                \n                for(int d : dirs) {\n                    Pos target = h.move(d);\n                    if(target.valid() && !wall[target.x][target.y] && \n                       !has_pet(target) && !adjacent_to_pet(target)) {\n                        bool conflict = false;\n                        for(int j=0; j<M; j++) {\n                            if(j != i && humans[j] == target) conflict = true;\n                            if(j != i && get_dest(humans[j], actions[j]) == target) conflict = true;\n                        }\n                        if(!conflict) {\n                            actions[i] = wall_char[d];\n                            built = true;\n                            break;\n                        }\n                    }\n                }\n                \n                // If can't build, move along expansion direction\n                if(!built) {\n                    for(int d : dirs) {\n                        Pos nxt = h.move(d);\n                        if(nxt.valid() && !wall[nxt.x][nxt.y] && !has_pet(nxt)) {\n                            bool conflict = false;\n                            for(int j=0; j<M; j++) {\n                                if(j != i && get_dest(humans[j], actions[j]) == nxt) conflict = true;\n                                if(j != i && humans[j] == nxt && \n                                   (actions[j] == '.' || actions[j] == 'u' || actions[j] == 'd' || \n                                    actions[j] == 'l' || actions[j] == 'r')) conflict = true;\n                            }\n                            if(!conflict) {\n                                actions[i] = move_char[d];\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Validate and fix if needed\n        if(!validate_actions(actions)) {\n            string fixed = actions;\n            // Try canceling wall actions first\n            for(int i=0; i<M; i++) {\n                if(fixed[i] == 'u' || fixed[i] == 'd' || fixed[i] == 'l' || fixed[i] == 'r') {\n                    string test = fixed;\n                    test[i] = '.';\n                    if(validate_actions(test)) {\n                        fixed = test;\n                        break;\n                    }\n                }\n            }\n            if(!validate_actions(fixed)) {\n                // Cancel all actions\n                fixed = string(M, '.');\n            }\n            actions = fixed;\n        }\n        \n        cout << actions << endl;\n        cout.flush();\n        \n        // Read pet movements\n        for(int i=0; i<N; i++) {\n            string movement;\n            cin >> movement;\n            if(movement != \".\") {\n                for(char m : movement) {\n                    if(m == 'U') pets[i].pos.x--;\n                    else if(m == 'D') pets[i].pos.x++;\n                    else if(m == 'L') pets[i].pos.y--;\n                    else if(m == 'R') pets[i].pos.y++;\n                }\n            }\n        }\n        \n        // Update state\n        for(int i=0; i<M; i++) {\n            char act = actions[i];\n            if(act == 'U') humans[i].x--;\n            else if(act == 'D') humans[i].x++;\n            else if(act == 'L') humans[i].y--;\n            else if(act == 'R') humans[i].y++;\n            else if(act == 'u' && humans[i].x > 0) wall[humans[i].x-1][humans[i].y] = true;\n            else if(act == 'd' && humans[i].x < GRID-1) wall[humans[i].x+1][humans[i].y] = true;\n            else if(act == 'l' && humans[i].y > 0) wall[humans[i].x][humans[i].y-1] = true;\n            else if(act == 'r' && humans[i].y < GRID-1) wall[humans[i].x][humans[i].y+1] = true;\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int MAXL = 200;\n\nint di[] = {-1, 1, 0, 0};\nint dj[] = {0, 0, -1, 1};\nchar dirs[] = {'U', 'D', 'L', 'R'};\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), v(19);\n    for (int i = 0; i < 20; i++) cin >> h[i];\n    for (int i = 0; i < 19; i++) cin >> v[i];\n    \n    int nxt[4][N][N];\n    memset(nxt, -1, sizeof(nxt));\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 + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                bool wall = false;\n                if (d == 0 && i > 0 && v[i-1][j] == '1') wall = true;\n                if (d == 1 && i < N-1 && v[i][j] == '1') wall = true;\n                if (d == 2 && j > 0 && h[i][j-1] == '1') wall = true;\n                if (d == 3 && j < N-1 && h[i][j] == '1') wall = true;\n                if (!wall) nxt[d][i][j] = ni*N + nj;\n            }\n        }\n    }\n    \n    // BFS shortest path\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<char>> moveTo(N, vector<char>(N, ' '));\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\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            if (nxt[d][i][j] == -1) continue;\n            int ni = i + di[d], nj = j + dj[d];\n            if (dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                prev[ni][nj] = {i, j};\n                moveTo[ni][nj] = dirs[d];\n                q.push({ni, nj});\n            }\n        }\n    }\n    \n    string path;\n    {\n        int ci = ti, cj = tj;\n        while (ci != si || cj != sj) {\n            path.push_back(moveTo[ci][cj]);\n            auto [pi, pj] = prev[ci][cj];\n            ci = pi; cj = pj;\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    auto dchar = [](char c) {\n        if (c == 'U') return 0;\n        if (c == 'D') return 1;\n        if (c == 'L') return 2;\n        return 3;\n    };\n    \n    auto eval = [&](const string &seq, int L = MAXL) {\n        double prob[N*N] = {0};\n        prob[si*N+sj] = 1.0;\n        double expScore = 0;\n        double probGoalBefore = 0;\n        int goalIdx = ti*N + tj;\n        \n        for (int t = 0; t < L; t++) {\n            int d = dchar(seq[t]);\n            double nextProb[N*N] = {0};\n            for (int idx = 0; idx < N*N; idx++) {\n                double pr = prob[idx];\n                if (pr == 0) continue;\n                if (idx == goalIdx) continue;\n                int i = idx / N, j = idx % N;\n                nextProb[idx] += pr * p;\n                int nidx = nxt[d][i][j];\n                if (nidx != -1) nextProb[nidx] += pr * (1-p);\n                else nextProb[idx] += pr * (1-p);\n            }\n            memcpy(prob, nextProb, sizeof(prob));\n            double probHere = prob[goalIdx];\n            double newly = probHere - probGoalBefore;\n            expScore += newly * (401 - (t+1));\n            probGoalBefore = probHere;\n        }\n        return expScore;\n    };\n    \n    int baseLen = path.size();\n    string curSeq;\n    double curScore = -1;\n    for (int rep = 1; rep <= min(MAXL/baseLen, 6); rep++) {\n        string seq;\n        for (char c : path) {\n            for (int r = 0; r < rep; r++) {\n                if ((int)seq.size() < MAXL) seq.push_back(c);\n            }\n        }\n        while ((int)seq.size() < MAXL) seq.push_back(path[seq.size() % baseLen]);\n        double sc = eval(seq);\n        if (sc > curScore) {\n            curScore = sc;\n            curSeq = seq;\n        }\n    }\n    string bestSeq = curSeq;\n    double bestScore = curScore;\n    \n    mt19937 rng(42);\n    uniform_int_distribution<int> posDist(0, MAXL-1);\n    uniform_int_distribution<int> dirDist(0, 3);\n    \n    auto startTime = chrono::steady_clock::now();\n    auto phase1Limit = chrono::milliseconds(13);\n    \n    // Phase 1: random hill climbing\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (now - startTime > phase1Limit) break;\n        \n        for (int sub = 0; sub < 10; sub++) {\n            string candSeq = curSeq;\n            int num = 1 + (rng() % 3);\n            for (int m = 0; m < num; m++) {\n                candSeq[posDist(rng)] = dirs[dirDist(rng)];\n            }\n            // occasional swap or reverse\n            if (rng() % 15 == 0) {\n                int p1 = posDist(rng), p2 = posDist(rng);\n                if (p1 > p2) swap(p1, p2);\n                if (rng() % 2) swap(candSeq[p1], candSeq[p2]);\n                else reverse(candSeq.begin() + p1, candSeq.begin() + p2 + 1);\n            }\n            double candScore = eval(candSeq);\n            if (candScore > curScore) {\n                curScore = candScore;\n                curSeq = candSeq;\n                if (candScore > bestScore) {\n                    bestScore = candScore;\n                    bestSeq = candSeq;\n                }\n            }\n        }\n    }\n    \n    // Phase 2: coordinate ascent\n    curSeq = bestSeq;\n    curScore = bestScore;\n    vector<int> order(MAXL);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    \n    auto globalLimit = chrono::milliseconds(18);\n    for (int pos : order) {\n        auto now = chrono::steady_clock::now();\n        if (now - startTime > globalLimit) break;\n        char orig = curSeq[pos];\n        for (int d = 0; d < 4; d++) {\n            if (dirs[d] == orig) continue;\n            curSeq[pos] = dirs[d];\n            double sc = eval(curSeq);\n            if (sc > curScore) {\n                curScore = sc;\n                bestScore = sc;\n                bestSeq = curSeq;\n            } else {\n                curSeq[pos] = orig;\n            }\n        }\n    }\n    \n    // Truncation check\n    for (int L = MAXL-5; L >= 20; L -= 5) {\n        if (chrono::steady_clock::now() - startTime > globalLimit) break;\n        double sc = eval(bestSeq, L);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestSeq = bestSeq.substr(0, L);\n        }\n    }\n    \n    cout << bestSeq << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace std::chrono;\n\nconst int N = 30;\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int to_table[8][4] = {\n    {1, 0, -1, -1},  // 0: left<->up\n    {3, -1, -1, 0},  // 1: left<->down\n    {-1, -1, 3, 2},  // 2: right<->down\n    {-1, 2, 1, -1},  // 3: up<->right\n    {1, 0, 3, 2},    // 4: left<->up, right<->down\n    {3, 2, 1, 0},    // 5: left<->down, up<->right\n    {2, -1, 0, -1},  // 6: left<->right\n    {-1, 3, -1, 1}   // 7: up<->down\n};\n\nint tile_type[N][N];\nint rot[N][N];\nint best_rot[N][N];\nint global_best_score = 0;\n\nint get_exit(int type, int r, int dir) {\n    if (to_table[type][dir] == -1) return -1;\n    return (to_table[type][dir] + r) % 4;\n}\n\nint node_id[N][N][4];\nint node_cnt;\nint mate[3600];\n\nvoid clear_graph() { fill(mate, mate + node_cnt, -1); }\nvoid add_edge(int u, int v) { mate[u] = v; mate[v] = u; }\nvoid remove_edge(int u) {\n    int v = mate[u];\n    if (v != -1) { mate[v] = -1; mate[u] = -1; }\n}\n\nvoid build_graph() {\n    clear_graph();\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 ex = get_exit(tile_type[i][j], rot[i][j], d);\n                if (ex == -1) continue;\n                int ni = i + di[ex], nj = j + dj[ex];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nd = (ex + 2) % 4;\n                int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                if (ex2 == d) {\n                    int u = node_id[i][j][d];\n                    int v = node_id[ni][nj][ex];\n                    if (mate[u] == -1 && mate[v] == -1) {\n                        add_edge(u, v);\n                    }\n                }\n            }\n        }\n    }\n}\n\nbool vis[3600];\nint comp_id[3600];\nint comp_len[3600];\nint comp_cnt;\n\nvoid find_cycles() {\n    fill(vis, vis + node_cnt, false);\n    fill(comp_id, comp_id + node_cnt, -1);\n    comp_cnt = 0;\n    for (int i = 0; i < node_cnt; i++) {\n        if (vis[i] || mate[i] == -1) continue;\n        int cur = i;\n        vector<int> path;\n        while (!vis[cur]) {\n            vis[cur] = true;\n            path.push_back(cur);\n            if (mate[cur] == -1) break;\n            cur = mate[cur];\n            if (vis[cur]) break;\n        }\n        if (path.size() >= 2 && mate[path.back()] == path[0]) {\n            for (int x : path) comp_id[x] = comp_cnt;\n            comp_len[comp_cnt] = path.size();\n            comp_cnt++;\n        } else {\n            for (int x : path) comp_id[x] = -2;\n        }\n    }\n}\n\nint get_score() {\n    find_cycles();\n    if (comp_cnt < 2) return 0;\n    int l1 = 0, l2 = 0;\n    for (int c = 0; c < comp_cnt; c++) {\n        int len = comp_len[c];\n        if (len > l1) { l2 = l1; l1 = len; }\n        else if (len > l2) { l2 = len; }\n    }\n    return l1 * l2;\n}\n\nvoid apply_rot(int i, int j, int new_r) {\n    int old_r = rot[i][j];\n    for (int d = 0; d < 4; d++) {\n        int ex = get_exit(tile_type[i][j], old_r, d);\n        if (ex != -1) {\n            int ni = i + di[ex], nj = j + dj[ex];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int u = node_id[i][j][d];\n                if (mate[u] != -1) remove_edge(u);\n            }\n        }\n    }\n    rot[i][j] = new_r;\n    for (int d = 0; d < 4; d++) {\n        int ex = get_exit(tile_type[i][j], new_r, d);\n        if (ex != -1) {\n            int ni = i + di[ex], nj = j + dj[ex];\n            if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                int nd = (ex + 2) % 4;\n                int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n                if (ex2 == d) {\n                    int u = node_id[i][j][d];\n                    int v = node_id[ni][nj][ex];\n                    if (mate[u] == -1 && mate[v] == -1) {\n                        add_edge(u, v);\n                    }\n                }\n            }\n        }\n    }\n}\n\nint count_conn(int i, int j, int r) {\n    int cnt = 0;\n    for (int d = 0; d < 4; d++) {\n        int ex = get_exit(tile_type[i][j], r, d);\n        if (ex == -1) continue;\n        int ni = i + di[ex], nj = j + dj[ex];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n        int nd = (ex + 2) % 4;\n        int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n        if (ex2 == d) cnt++;\n    }\n    return cnt;\n}\n\n// Check if a tile with given rotation connects in direction d\nbool connects(int i, int j, int r, int d) {\n    int ex = get_exit(tile_type[i][j], r, d);\n    if (ex == -1) return false;\n    int ni = i + di[ex], nj = j + dj[ex];\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    int nd = (ex + 2) % 4;\n    int ex2 = get_exit(tile_type[ni][nj], rot[ni][nj], nd);\n    return ex2 == d;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = high_resolution_clock::now();\n    \n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++)\n            tile_type[i][j] = s[j] - '0';\n    }\n    \n    node_cnt = 0;\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                node_id[i][j][d] = node_cnt++;\n    \n    mt19937 rng(42);\n    uniform_real_distribution<> prob(0, 1);\n    uniform_int_distribution<> pos(0, N-1);\n    uniform_int_distribution<> rdelta(1, 3);\n    \n    auto do_greedy_pass = [&](int passes) {\n        for (int pass = 0; pass < passes; pass++) {\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    int best_r = rot[i][j];\n                    int best_c = count_conn(i, j, rot[i][j]);\n                    for (int r = 0; r < 4; r++) {\n                        int c = count_conn(i, j, r);\n                        if (c > best_c) { best_c = c; best_r = r; }\n                    }\n                    rot[i][j] = best_r;\n                }\n            }\n        }\n    };\n    \n    auto run_sa = [&](int max_iter, double temp_start, double alpha) -> int {\n        double temp = temp_start;\n        int cur_score = get_score();\n        int best_local = cur_score;\n        int best_local_rot[N][N];\n        memcpy(best_local_rot, rot, sizeof(rot));\n        \n        for (int iter = 0; iter < max_iter; iter++) {\n            auto now = high_resolution_clock::now();\n            if (duration_cast<milliseconds>(now - start).count() > 1950) break;\n            \n            int num_tiles = (temp > 3.0 && prob(rng) < 0.25) ? 2 : 1;\n            vector<tuple<int,int,int>> changes;\n            for (int t = 0; t < num_tiles; t++) {\n                int i = pos(rng), j = pos(rng);\n                int old_r = rot[i][j];\n                int new_r = (old_r + rdelta(rng)) % 4;\n                apply_rot(i, j, new_r);\n                changes.push_back({i, j, old_r});\n            }\n            \n            int ns = get_score();\n            \n            if (ns >= cur_score || (temp > 0.01 && prob(rng) < exp((ns - cur_score) / temp))) {\n                cur_score = ns;\n                if (ns > best_local) {\n                    best_local = ns;\n                    memcpy(best_local_rot, rot, sizeof(rot));\n                }\n            } else {\n                for (auto &[i, j, old_r] : changes) {\n                    apply_rot(i, j, old_r);\n                }\n            }\n            temp *= alpha;\n        }\n        memcpy(rot, best_local_rot, sizeof(rot));\n        return best_local;\n    };\n    \n    // Try multiple strategies\n    vector<tuple<int,int,int>> results; // (score, seed, strategy)\n    \n    // Strategy 1: Pure random + greedy + SA\n    {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                rot[i][j] = rng() % 4;\n        do_greedy_pass(3);\n        build_graph();\n        int s = run_sa(30000, 10.0, 0.9999);\n        if (s > global_best_score) {\n            global_best_score = s;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n    \n    // Strategy 2: Prefer horizontal straight lines + SA\n    {\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int t = tile_type[i][j];\n                if (t == 6) rot[i][j] = 0; // horizontal\n                else if (t == 7) rot[i][j] = 1; // vertical\n                else rot[i][j] = rng() % 4;\n            }\n        }\n        do_greedy_pass(3);\n        build_graph();\n        int s = run_sa(30000, 10.0, 0.9999);\n        if (s > global_best_score) {\n            global_best_score = s;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n    \n    // Strategy 3: Try to maximize initial cycle size by growing from seeds\n    {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                rot[i][j] = rng() % 4;\n        \n        // Repeatedly improve by scanning all tiles\n        for (int sweep = 0; sweep < 5; sweep++) {\n            build_graph();\n            // Target: try to make the largest cycle even larger\n            find_cycles();\n            if (comp_cnt == 0) break;\n            \n            // Find the largest cycle\n            int best_c = 0;\n            for (int c = 1; c < comp_cnt; c++)\n                if (comp_len[c] > comp_len[best_c]) best_c = c;\n            \n            // Try flipping tiles adjacent to this cycle to grow it\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    // Check if this tile touches the best cycle\n                    bool touches = false;\n                    for (int d = 0; d < 4; d++) {\n                        int u = node_id[i][j][d];\n                        if (mate[u] != -1 && comp_id[mate[u]] == best_c) {\n                            touches = true; break;\n                        }\n                    }\n                    if (!touches) continue;\n                    \n                    int best_r = rot[i][j];\n                    int best_s = get_score();\n                    for (int r = 0; r < 4; r++) {\n                        if (r == rot[i][j]) continue;\n                        apply_rot(i, j, r);\n                        int s = get_score();\n                        if (s > best_s) { best_s = s; best_r = r; }\n                        apply_rot(i, j, rot[i][j]);\n                    }\n                    apply_rot(i, j, best_r);\n                }\n            }\n        }\n        build_graph();\n        int s = run_sa(20000, 5.0, 0.9999);\n        if (s > global_best_score) {\n            global_best_score = s;\n            memcpy(best_rot, rot, sizeof(rot));\n        }\n    }\n    \n    // Strategy 4: More aggressive SA with restarts\n    {\n        for (int restart = 0; restart < 3; restart++) {\n            auto now = high_resolution_clock::now();\n            if (duration_cast<milliseconds>(now - start).count() > 1800) break;\n            \n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    rot[i][j] = rng() % 4;\n            \n            do_greedy_pass(3);\n            build_graph();\n            int s = run_sa(40000, 8.0, 0.99995);\n            if (s > global_best_score) {\n                global_best_score = s;\n                memcpy(best_rot, rot, sizeof(rot));\n            }\n        }\n    }\n    \n    // Output best\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cout << best_rot[i][j];\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_N = 10;\nint N, T;\nint empty_r, empty_c;\nvector<string> board;\n\nconst int dr[] = {0, -1, 0, 1};\nconst int dc[] = {-1, 0, 1, 0};\nconst char dir_char[] = {'L', 'U', 'R', 'D'};\nconst int bit[] = {1, 2, 4, 8};\n\nauto start_time = chrono::steady_clock::now();\n\nbool in_board(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\nint tile_val(char c) {\n    if (c >= 'a' && c <= 'f') return c - 'a' + 10;\n    return c - '0';\n}\n\nbool has_line(char tile, int d) {\n    return (tile_val(tile) & bit[d]) != 0;\n}\n\nbool is_connected(const vector<string>& b, int r1, int c1, int r2, int c2) {\n    if (!in_board(r1, c1) || !in_board(r2, c2)) return false;\n    if (b[r1][c1] == '0' || b[r2][c2] == '0') return false;\n    if (r1 == r2 && c1 + 1 == c2) {\n        return has_line(b[r1][c1], 2) && has_line(b[r2][c2], 0);\n    }\n    if (r1 == r2 && c1 - 1 == c2) {\n        return has_line(b[r1][c1], 0) && has_line(b[r2][c2], 2);\n    }\n    if (r1 + 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 3) && has_line(b[r2][c2], 1);\n    }\n    if (r1 - 1 == r2 && c1 == c2) {\n        return has_line(b[r1][c1], 1) && has_line(b[r2][c2], 3);\n    }\n    return false;\n}\n\nstruct BoardInfo {\n    int max_tree = 0;\n    int num_trees = 0;\n    int potential = 0;\n};\n\nBoardInfo analyze(const vector<string>& b) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    BoardInfo info;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] == '0' || vis[i][j]) continue;\n            \n            queue<pair<int,int>> q;\n            q.push({i, j});\n            vis[i][j] = true;\n            int edges = 0;\n            int nodes = 0;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front(); q.pop();\n                nodes++;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (in_board(nr, nc) && b[nr][nc] != '0') {\n                        if (is_connected(b, r, c, nr, nc)) {\n                            edges++;\n                            if (!vis[nr][nc]) {\n                                vis[nr][nc] = true;\n                                q.push({nr, nc});\n                            }\n                        } else {\n                            if (has_line(b[r][c], d)) info.potential++;\n                        }\n                    }\n                }\n            }\n            \n            edges /= 2;\n            if (edges == nodes - 1) {\n                info.num_trees++;\n                if (nodes > info.max_tree) info.max_tree = nodes;\n            }\n        }\n    }\n    \n    return info;\n}\n\nint evaluate(const vector<string>& b) {\n    auto info = analyze(b);\n    return info.max_tree * 100000 + (N * N - 1 - info.num_trees) * 1000 + info.potential * 100;\n}\n\n// Beam search that returns the best sequence found within max_depth\nstring beam_search(vector<string> b, int er, int ec, int max_depth, int beam_width) {\n    struct State {\n        vector<string> b;\n        int er, ec;\n        string moves;\n        int eval;\n    };\n    \n    vector<State> beam;\n    beam.reserve(beam_width);\n    int init_eval = evaluate(b);\n    beam.push_back({b, er, ec, \"\", init_eval});\n    \n    int best_eval = init_eval;\n    string best_moves;\n    \n    // Track seen states to avoid cycles\n    unordered_set<string> seen;\n    string h;\n    for (int i = 0; i < N; i++) h += b[i];\n    seen.insert(h);\n    \n    for (int depth = 0; depth < max_depth; depth++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2900) break;\n        \n        vector<State> next_states;\n        next_states.reserve(beam.size() * 3);\n        \n        for (const auto& s : beam) {\n            for (int d = 0; d < 4; d++) {\n                int nr = s.er + dr[d];\n                int nc = s.ec + dc[d];\n                if (!in_board(nr, nc)) continue;\n                \n                // Avoid immediate undo\n                if (!s.moves.empty()) {\n                    char last = s.moves.back();\n                    if ((last == 'L' && d == 2) || (last == 'R' && d == 0) ||\n                        (last == 'U' && d == 3) || (last == 'D' && d == 1)) {\n                        continue;\n                    }\n                }\n                \n                // Check for 2-step cycles (A->B->A)\n                if (s.moves.length() >= 3) {\n                    int len = s.moves.length();\n                    char m1 = s.moves[len-1], m2 = s.moves[len-2], m3 = s.moves[len-3];\n                    int d1 = (m1 == 'L') ? 0 : (m1 == 'U') ? 1 : (m1 == 'R') ? 2 : 3;\n                    int d2 = (m2 == 'L') ? 0 : (m2 == 'U') ? 1 : (m2 == 'R') ? 2 : 3;\n                    int d3 = (m3 == 'L') ? 0 : (m3 == 'U') ? 1 : (m3 == 'R') ? 2 : 3;\n                    // Avoid A->B->C->A pattern\n                    if (d == d1 || d == d2) {\n                        // Might be cycling, check more carefully\n                        if (d == d3) continue;\n                    }\n                }\n                \n                vector<string> nb = s.b;\n                swap(nb[s.er][s.ec], nb[nr][nc]);\n                \n                string nh;\n                for (int i = 0; i < N; i++) nh += nb[i];\n                \n                if (seen.count(nh)) continue;\n                seen.insert(nh);\n                \n                int neval = evaluate(nb);\n                string nmoves = s.moves + dir_char[d];\n                \n                if (neval > best_eval) {\n                    best_eval = neval;\n                    best_moves = nmoves;\n                    \n                    auto info = analyze(nb);\n                    if (info.max_tree == N * N - 1) return best_moves;\n                }\n                \n                next_states.push_back({move(nb), nr, nc, move(nmoves), neval});\n            }\n        }\n        \n        if (next_states.empty()) break;\n        \n        // Keep top beam_width states\n        if ((int)next_states.size() > beam_width) {\n            nth_element(next_states.begin(), \n                       next_states.begin() + beam_width, \n                       next_states.end(),\n                       [](const State& a, const State& b) { return a.eval > b.eval; });\n            next_states.resize(beam_width);\n        }\n        \n        beam = move(next_states);\n    }\n    \n    return best_moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> board[i];\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0') {\n                empty_r = i;\n                empty_c = j;\n            }\n        }\n    }\n    \n    start_time = chrono::steady_clock::now();\n    \n    string all_moves;\n    int current_best = evaluate(board);\n    int rounds_without_improvement = 0;\n    \n    // Adaptive beam search with strict move limit\n    for (int round = 0; round < 15; round++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 2800) break;\n        \n        // STRICT check: don't exceed T\n        if ((int)all_moves.length() >= T) break;\n        \n        int remaining = T - (int)all_moves.length();\n        if (remaining <= 2) break;\n        \n        // Adaptive parameters\n        int depth = min(60 + round * 15, remaining);\n        int width = min(80 + round * 15, 200);\n        \n        string new_moves = beam_search(board, empty_r, empty_c, depth, width);\n        \n        if (new_moves.empty() || new_moves.length() == 0) {\n            rounds_without_improvement++;\n            if (rounds_without_improvement > 3) break;\n            continue;\n        }\n        \n        // STRICT: truncate if would exceed T\n        if ((int)all_moves.length() + (int)new_moves.length() > T) {\n            int allowed = T - (int)all_moves.length();\n            new_moves = new_moves.substr(0, allowed);\n        }\n        \n        if (new_moves.empty()) break;\n        \n        // Apply the moves\n        int new_eval = 0;\n        for (char c : new_moves) {\n            int d = (c == 'L') ? 0 : (c == 'U') ? 1 : (c == 'R') ? 2 : 3;\n            int nr = empty_r + dr[d];\n            int nc = empty_c + dc[d];\n            if (!in_board(nr, nc)) {\n                cerr << \"Invalid move!\" << endl;\n                break;\n            }\n            swap(board[empty_r][empty_c], board[nr][nc]);\n            empty_r = nr;\n            empty_c = nc;\n            all_moves += c;\n        }\n        \n        new_eval = evaluate(board);\n        \n        if (new_eval > current_best) {\n            current_best = new_eval;\n            rounds_without_improvement = 0;\n        } else {\n            rounds_without_improvement++;\n        }\n        \n        auto info = analyze(board);\n        if (info.max_tree == N * N - 1) break;\n    }\n    \n    // Final deep search with remaining moves\n    int remaining = T - (int)all_moves.length();\n    if (remaining > 10) {\n        auto info = analyze(board);\n        if (info.max_tree < N * N - 1) {\n            int final_depth = min(remaining, 300);\n            int final_width = min(250, remaining * 2);\n            \n            string new_moves = beam_search(board, empty_r, empty_c, final_depth, final_width);\n            \n            if (!new_moves.empty()) {\n                // Truncate if needed\n                if ((int)all_moves.length() + (int)new_moves.length() > T) {\n                    new_moves = new_moves.substr(0, T - (int)all_moves.length());\n                }\n                \n                for (char c : new_moves) {\n                    int d = (c == 'L') ? 0 : (c == 'U') ? 1 : (c == 'R') ? 2 : 3;\n                    int nr = empty_r + dr[d];\n                    int nc = empty_c + dc[d];\n                    if (!in_board(nr, nc)) break;\n                    swap(board[empty_r][empty_c], board[nr][nc]);\n                    empty_r = nr;\n                    empty_c = nc;\n                    all_moves += c;\n                }\n            }\n        }\n    }\n    \n    // Final safety: ensure we don't exceed T\n    if ((int)all_moves.length() > T) {\n        all_moves = all_moves.substr(0, T);\n    }\n    \n    cout << all_moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\ntypedef long long ll;\n\nstruct Point {\n    ll x, y;\n    Point(ll x = 0, ll y = 0) : x(x), y(y) {}\n    \n    Point operator-(const Point& other) const {\n        return Point(x - other.x, y - other.y);\n    }\n    \n    ll cross(const Point& other) const {\n        return x * other.y - y * other.x;\n    }\n};\n\n// Check which side of line p1->p2 a point p lies on\nint side(const Point& p1, const Point& p2, const Point& p) {\n    ll val = (p2 - p1).cross(p - p1);\n    if (val > 0) return 1;\n    if (val < 0) return -1;\n    return 0;\n}\n\n// Count strawberries in each piece given a set of lines\nvector<int> countPieces(const vector<Point>& strawberries,\n                        const vector<pair<pair<ll, ll>, pair<ll, ll>>>& lines) {\n    int M = strawberries.size();\n    int L = lines.size();\n    \n    if (L == 0) {\n        return {M};\n    }\n    \n    // For each strawberry, determine which side of each line it's on\n    map<vector<int>, int> piece_counts;\n    \n    for (int i = 0; i < M; i++) {\n        const Point& straw = strawberries[i];\n        vector<int> signature(L);\n        bool on_line = false;\n        \n        for (int j = 0; j < L; j++) {\n            Point p1(lines[j].first.first, lines[j].first.second);\n            Point p2(lines[j].second.first, lines[j].second.second);\n            int s = side(p1, p2, straw);\n            if (s == 0) {\n                on_line = true;\n                break;\n            }\n            signature[j] = (s > 0) ? 1 : 0;\n        }\n        \n        if (!on_line) {\n            piece_counts[signature]++;\n        }\n    }\n    \n    vector<int> counts;\n    for (const auto& [sig, cnt] : piece_counts) {\n        if (cnt > 0) {\n            counts.push_back(cnt);\n        }\n    }\n    \n    return counts;\n}\n\n// Calculate matched pieces\nint calculateMatched(const vector<int>& piece_counts, const vector<int>& demands) {\n    vector<int> available(10, 0);\n    for (int cnt : piece_counts) {\n        if (cnt >= 1 && cnt <= 10) {\n            available[cnt - 1]++;\n        }\n    }\n    \n    int matched = 0;\n    for (int i = 0; i < 10; i++) {\n        matched += min(available[i], demands[i]);\n    }\n    return matched;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::high_resolution_clock::now();\n    const double time_limit = 2.9;\n    \n    int N, K;\n    cin >> N >> K;\n    \n    vector<int> demands(10);\n    int total_demand = 0;\n    for (int i = 0; i < 10; i++) {\n        cin >> demands[i];\n        total_demand += demands[i];\n    }\n    \n    vector<Point> strawberries(N);\n    for (int i = 0; i < N; i++) {\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Best configuration found\n    vector<pair<pair<ll, ll>, pair<ll, ll>>> best_lines;\n    int best_matched = 0;\n    \n    // Random number generator\n    mt19937 rng(12345);\n    \n    int iteration = 0;\n    \n    while (true) {\n        auto current_time = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(current_time - start_time).count();\n        if (elapsed >= time_limit) break;\n        \n        // Generate a candidate solution\n        vector<pair<pair<ll, ll>, pair<ll, ll>>> lines;\n        \n        // Strategy: Mix radial lines with random separators\n        int num_radial = min(60, K / 2 + uniform_int_distribution<int>(0, 20)(rng));\n        double angle_start = uniform_real_distribution<double>(0, 2 * M_PI)(rng);\n        \n        // Add radial lines through origin\n        for (int i = 0; i < num_radial && (int)lines.size() < K; i++) {\n            double angle = angle_start + 2.0 * M_PI * i / num_radial;\n            ll x1 = (ll)(500000000.0 * cos(angle));\n            ll y1 = (ll)(500000000.0 * sin(angle));\n            ll x2 = -x1;\n            ll y2 = -y1;\n            \n            if (x1 == x2 && y1 == y2) x2 = x1 + 1;\n            lines.push_back({{x1, y1}, {x2, y2}});\n        }\n        \n        // Add some lines that separate pairs of strawberries\n        if (N >= 2) {\n            int num_sep = min(K - (int)lines.size(), 30);\n            for (int i = 0; i < num_sep; i++) {\n                int a = uniform_int_distribution<int>(0, N-1)(rng);\n                int b = uniform_int_distribution<int>(0, N-1)(rng);\n                \n                if (a != b) {\n                    const Point& p1 = strawberries[a];\n                    const Point& p2 = strawberries[b];\n                    \n                    // Midpoint\n                    double mx = (p1.x + p2.x) / 2.0;\n                    double my = (p1.y + p2.y) / 2.0;\n                    \n                    // Perpendicular direction\n                    double dx = (double)(p2.y - p1.y);\n                    double dy = (double)(p1.x - p2.x);\n                    double len = sqrt(dx*dx + dy*dy);\n                    \n                    if (len > 0) {\n                        dx = dx / len * 15000.0;\n                        dy = dy / len * 15000.0;\n                        \n                        ll px = (ll)round(mx - dx);\n                        ll py = (ll)round(my - dy);\n                        ll qx = (ll)round(mx + dx);\n                        ll qy = (ll)round(my + dy);\n                        \n                        // Clamp to valid range\n                        auto clamp = [](ll& v) {\n                            v = max(-1000000000LL, min(1000000000LL, v));\n                        };\n                        clamp(px); clamp(py); clamp(qx); clamp(qy);\n                        \n                        if (px != qx || py != qy) {\n                            lines.push_back({{px, py}, {qx, qy}});\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Fill remaining with random offset radial-like lines\n        while ((int)lines.size() < K) {\n            double angle = uniform_real_distribution<double>(0, 2 * M_PI)(rng);\n            double offset = uniform_real_distribution<double>(-5000, 5000)(rng);\n            \n            ll x1 = (ll)(500000000.0 * cos(angle) + offset * cos(angle + M_PI/2));\n            ll y1 = (ll)(500000000.0 * sin(angle) + offset * sin(angle + M_PI/2));\n            ll x2 = (ll)(-500000000.0 * cos(angle) + offset * cos(angle + M_PI/2));\n            ll y2 = (ll)(-500000000.0 * sin(angle) + offset * sin(angle + M_PI/2));\n            \n            auto clamp = [](ll& v) {\n                v = max(-1000000000LL, min(1000000000LL, v));\n            };\n            clamp(x1); clamp(y1); clamp(x2); clamp(y2);\n            \n            if (x1 != x2 || y1 != y2) {\n                lines.push_back({{x1, y1}, {x2, y2}});\n            } else {\n                lines.push_back({{x1, y1}, {x1+1, y1}});\n            }\n        }\n        \n        // Evaluate\n        vector<int> piece_counts = countPieces(strawberries, lines);\n        int matched = calculateMatched(piece_counts, demands);\n        \n        if (matched > best_matched) {\n            best_matched = matched;\n            best_lines = lines;\n        }\n        \n        iteration++;\n    }\n    \n    // Final output\n    if ((int)best_lines.size() > K) {\n        best_lines.resize(K);\n    }\n    \n    cout << best_lines.size() << '\\n';\n    for (const auto& line : best_lines) {\n        cout << line.first.first << ' ' << line.first.second << ' '\n             << line.second.first << ' ' << line.second.second << '\\n';\n    }\n    \n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\nusing P = pair<int,int>;\n\nint N, M, C;\nP initial_arr[1500];\nint dot_grid[65][65];\nvector<pair<P,P>> segment_list;\nvector<array<P,4>> operations;\n\nll weight(int x, int y) {\n    return (ll)(x-C)*(x-C) + (ll)(y-C)*(y-C) + 1;\n}\n\nbool in_grid(int x, int y) {\n    return (unsigned)x < (unsigned)N && (unsigned)y < (unsigned)N;\n}\n\nbool segments_overlap(P a1, P a2, P b1, P b2) {\n    ll cross = (ll)(a2.first - a1.first) * (b2.second - b1.second) - \n               (ll)(a2.second - a1.second) * (b2.first - b1.first);\n    if (cross != 0) return false;\n    \n    ll cross2 = (ll)(b1.first - a1.first) * (a2.second - a1.second) - \n                (ll)(b1.second - a1.second) * (a2.first - a1.first);\n    if (cross2 != 0) return false;\n    \n    ll dir_x = a2.first - a1.first;\n    ll dir_y = a2.second - a1.second;\n    \n    auto project = [&](P p) -> ll {\n        return (ll)(p.first - a1.first) * dir_x + (ll)(p.second - a1.second) * dir_y;\n    };\n    \n    ll t1 = 0, t2 = project(a2);\n    ll s1 = project(b1), s2 = project(b2);\n    if (t1 > t2) swap(t1, t2);\n    if (s1 > s2) swap(s1, s2);\n    \n    return max(t1, s1) < min(t2, s2);\n}\n\nbool would_overlap(P a, P b) {\n    for (auto &seg : segment_list) {\n        if (segments_overlap(a, b, seg.first, seg.second))\n            return true;\n    }\n    return false;\n}\n\nbool clear_path_fast(P a, P b, int ax1, int ay1, int ax2, int ay2, int ax3, int ay3) {\n    int dx = b.first - a.first;\n    int dy = b.second - a.second;\n    int g = gcd(abs(dx), abs(dy));\n    int sx = dx / g;\n    int sy = dy / g;\n    \n    int cx = a.first + sx;\n    int cy = a.second + sy;\n    for (int i = 1; i < g; i++) {\n        if (dot_grid[cx][cy]) {\n            if (!((cx == ax1 && cy == ay1) ||\n                  (cx == ax2 && cy == ay2) ||\n                  (cx == ax3 && cy == ay3)))\n                return false;\n        }\n        cx += sx;\n        cy += sy;\n    }\n    return true;\n}\n\nvoid add_segments(P p1, P p2, P p3, P p4) {\n    segment_list.emplace_back(p1, p2);\n    segment_list.emplace_back(p2, p3);\n    segment_list.emplace_back(p3, p4);\n    segment_list.emplace_back(p4, p1);\n}\n\nbool try_add_rect(P p1) {\n    int x = p1.first, y = p1.second;\n    if (dot_grid[x][y]) return false;\n    \n    // Try axis-aligned rectangles\n    for (int dx = 1; dx <= min(N, 15); dx++) {\n        for (int dy = 1; dy <= min(N, 15); dy++) {\n            // Orientation 1: p1 bottom-left\n            {\n                int p2x = x+dx, p2y = y;\n                int p3x = x+dx, p3y = y+dy;\n                int p4x = x, p4y = y+dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n            // Orientation 2: p1 bottom-right\n            {\n                int p2x = x-dx, p2y = y;\n                int p3x = x-dx, p3y = y+dy;\n                int p4x = x, p4y = y+dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n            // Orientation 3: p1 top-right\n            {\n                int p2x = x-dx, p2y = y;\n                int p3x = x-dx, p3y = y-dy;\n                int p4x = x, p4y = y-dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n            // Orientation 4: p1 top-left\n            {\n                int p2x = x+dx, p2y = y;\n                int p3x = x+dx, p3y = y-dy;\n                int p4x = x, p4y = y-dy;\n                \n                if (in_grid(p2x,p2y) && in_grid(p3x,p3y) && in_grid(p4x,p4y) &&\n                    dot_grid[p2x][p2y] && dot_grid[p3x][p3y] && dot_grid[p4x][p4y]) {\n                    \n                    P p2 = {p2x,p2y}, p3 = {p3x,p3y}, p4 = {p4x,p4y};\n                    \n                    if (clear_path_fast(p1, p2, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p2, p3, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p3, p4, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        clear_path_fast(p4, p1, p2x,p2y,p3x,p3y,p4x,p4y) &&\n                        !would_overlap(p1, p2) &&\n                        !would_overlap(p2, p3) &&\n                        !would_overlap(p3, p4) &&\n                        !would_overlap(p4, p1)) {\n                        \n                        operations.push_back({p1, p2, p3, p4});\n                        dot_grid[x][y] = 1;\n                        add_segments(p1, p2, p3, p4);\n                        return true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Try 45-degree rotated squares\n    for (int d = 1; d <= min(N/2, 8); d++) {\n        vector<array<P,4>> diags = {\n            {{{x,y}, {x+d,y+d}, {x,y+2*d}, {x-d,y+d}}},\n            {{{x,y}, {x+d,y-d}, {x+2*d,y}, {x+d,y+d}}},\n            {{{x,y}, {x-d,y-d}, {x,y-2*d}, {x+d,y-d}}},\n            {{{x,y}, {x-d,y+d}, {x-2*d,y}, {x-d,y-d}}}\n        };\n        \n        for (auto &r : diags) {\n            bool ok = true;\n            for (auto &p : r) {\n                if (!in_grid(p.first, p.second)) { ok = false; break; }\n            }\n            if (!ok) continue;\n            \n            int p2x=r[1].first, p2y=r[1].second;\n            int p3x=r[2].first, p3y=r[2].second;\n            int p4x=r[3].first, p4y=r[3].second;\n            \n            if (!dot_grid[p2x][p2y] || !dot_grid[p3x][p3y] || !dot_grid[p4x][p4y]) continue;\n            \n            if (clear_path_fast(r[0], r[1], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                clear_path_fast(r[1], r[2], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                clear_path_fast(r[2], r[3], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                clear_path_fast(r[3], r[0], p2x,p2y,p3x,p3y,p4x,p4y) &&\n                !would_overlap(r[0], r[1]) &&\n                !would_overlap(r[1], r[2]) &&\n                !would_overlap(r[2], r[3]) &&\n                !would_overlap(r[3], r[0])) {\n                \n                operations.push_back(r);\n                dot_grid[x][y] = 1;\n                add_segments(r[0], r[1], r[2], r[3]);\n                return true;\n            }\n        }\n    }\n    \n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 4.9;\n    \n    cin >> N >> M;\n    C = (N-1)/2;\n    \n    memset(dot_grid, 0, sizeof(dot_grid));\n    for (int i = 0; i < M; i++) {\n        int x, y; cin >> x >> y;\n        initial_arr[i] = {x,y};\n        dot_grid[x][y] = 1;\n    }\n    \n    // Precompute candidates sorted by weight\n    vector<P> candidates;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            if (!dot_grid[x][y]) {\n                candidates.push_back({x,y});\n            }\n        }\n    }\n    \n    sort(candidates.begin(), candidates.end(), [](P a, P b) {\n        return weight(a.first, a.second) > weight(b.first, b.second);\n    });\n    \n    // Main greedy loop\n    bool progress = true;\n    int check_cnt = 0;\n    while (progress) {\n        progress = false;\n        \n        for (auto &p : candidates) {\n            if (++check_cnt % 100 == 0) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - start_time).count();\n                if (elapsed > TIME_LIMIT) goto output_result;\n            }\n            \n            if (dot_grid[p.first][p.second]) continue;\n            \n            if (try_add_rect(p)) {\n                progress = true;\n                break;\n            }\n        }\n    }\n    \noutput_result:\n    cout << operations.size() << \"\\n\";\n    for (auto &op : operations) {\n        cout << op[0].first << \" \" << op[0].second << \" \"\n             << op[1].first << \" \" << op[1].second << \" \"\n             << op[2].first << \" \" << op[2].second << \" \"\n             << op[3].first << \" \" << op[3].second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 10;\nconst int TOTAL = 100;\n\nint grid[N][N];\nint flavor[TOTAL];\nint total_count[4] = {0};\nint placed_count[4] = {0};\nchar dc[4] = {'L', 'R', 'F', 'B'};\n\nvoid tilt(int g[N][N], int d) {\n    if (d == 0) {\n        for (int i = 0; i < N; i++) {\n            int p = 0;\n            for (int j = 0; j < N; j++) if (g[i][j]) g[i][p++] = g[i][j];\n            while (p < N) g[i][p++] = 0;\n        }\n    } else if (d == 1) {\n        for (int i = 0; i < N; i++) {\n            int p = N-1;\n            for (int j = N-1; j >= 0; j--) if (g[i][j]) g[i][p--] = g[i][j];\n            while (p >= 0) g[i][p--] = 0;\n        }\n    } else if (d == 2) {\n        for (int j = 0; j < N; j++) {\n            int p = 0;\n            for (int i = 0; i < N; i++) if (g[i][j]) g[p++][j] = g[i][j];\n            while (p < N) g[p++][j] = 0;\n        }\n    } else {\n        for (int j = 0; j < N; j++) {\n            int p = N-1;\n            for (int i = N-1; i >= 0; i--) if (g[i][j]) g[p--][j] = g[i][j];\n            while (p >= 0) g[p--][j] = 0;\n        }\n    }\n}\n\nint64_t evaluate(int g[N][N]) {\n    bool vis[N][N] = {};\n    int64_t res = 0;\n    int qx[100], qy[100];\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!g[i][j] || vis[i][j]) continue;\n            int f = g[i][j], cnt = 0, h = 0, t = 0;\n            qx[0] = i; qy[0] = j;\n            vis[i][j] = true;\n            while (h <= t) {\n                int x = qx[h], y = qy[h]; h++; cnt++;\n                if (x > 0 && !vis[x-1][y] && g[x-1][y] == f)\n                    vis[x-1][y] = true, qx[++t] = x-1, qy[t] = y;\n                if (x < N-1 && !vis[x+1][y] && g[x+1][y] == f)\n                    vis[x+1][y] = true, qx[++t] = x+1, qy[t] = y;\n                if (y > 0 && !vis[x][y-1] && g[x][y-1] == f)\n                    vis[x][y-1] = true, qx[++t] = x, qy[t] = y-1;\n                if (y < N-1 && !vis[x][y+1] && g[x][y+1] == f)\n                    vis[x][y+1] = true, qx[++t] = x, qy[t] = y+1;\n            }\n            res += 1LL * cnt * cnt;\n        }\n    }\n    return res;\n}\n\n// Enhanced evaluation - preserves the \"beneficial bug\" behavior\nint64_t evaluate_enhanced(int g[N][N], int step) {\n    int64_t base = evaluate(g);\n    \n    int rem[4] = {0};\n    for (int i = step + 1; i < TOTAL; i++) {\n        rem[flavor[i]]++;\n    }\n    \n    bool vis[N][N] = {};\n    int qx[100], qy[100];\n    int64_t bonus = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!g[i][j] || vis[i][j]) continue;\n            \n            int f = g[i][j], cnt = 0, h = 0, t = 0;\n            qx[0] = i; qy[0] = j;\n            vis[i][j] = true;\n            \n            int empty_neighbors = 0;\n            \n            while (h <= t) {\n                int x = qx[h], y = qy[h]; h++; cnt++;\n                \n                // Count empty neighbors for each cell (allows double-counting)\n                if (x > 0 && !g[x-1][y]) empty_neighbors++;\n                if (x < N-1 && !g[x+1][y]) empty_neighbors++;\n                if (y > 0 && !g[x][y-1]) empty_neighbors++;\n                if (y < N-1 && !g[x][y+1]) empty_neighbors++;\n                \n                // Continue BFS\n                if (x > 0 && !vis[x-1][y] && g[x-1][y] == f)\n                    vis[x-1][y] = true, qx[++t] = x-1, qy[t] = y;\n                if (x < N-1 && !vis[x+1][y] && g[x+1][y] == f)\n                    vis[x+1][y] = true, qx[++t] = x+1, qy[t] = y;\n                if (y > 0 && !vis[x][y-1] && g[x][y-1] == f)\n                    vis[x][y-1] = true, qx[++t] = x, qy[t] = y-1;\n                if (y < N-1 && !vis[x][y+1] && g[x][y+1] == f)\n                    vis[x][y+1] = true, qx[++t] = x, qy[t] = y+1;\n            }\n            \n            // Bonus for clusters with room to grow\n            if (rem[f] > 0 && empty_neighbors > 0) {\n                int can_absorb = min(rem[f], max(1, empty_neighbors / 3));\n                int64_t new_size = cnt + can_absorb;\n                int64_t potential_gain = new_size * new_size - 1LL * cnt * cnt;\n                bonus += potential_gain;\n            }\n        }\n    }\n    \n    int remaining = TOTAL - step - 1;\n    double bonus_weight = min(0.5, remaining / 200.0);\n    \n    return base + (int64_t)(bonus * bonus_weight);\n}\n\nint64_t rollout(int g[N][N], int step, int depth, vector<int>& pos_indices, int& idx) {\n    int tmp[N][N];\n    memcpy(tmp, g, sizeof(tmp));\n    \n    int look = min(depth, TOTAL - step - 1);\n    \n    for (int k = 0; k < look; k++) {\n        if (idx >= (int)pos_indices.size()) break;\n        \n        int f = flavor[step + 1 + k];\n        int pos = pos_indices[idx++];\n        \n        int cnt = 0, r = 0, c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (!tmp[i][j] && ++cnt == pos) {\n                    r = i; c = j;\n                    i = N; break;\n                }\n            }\n        }\n        \n        tmp[r][c] = f;\n        \n        int best_d = 0;\n        int64_t best_sc = -1;\n        int tmp2[N][N];\n        \n        for (int d = 0; d < 4; d++) {\n            memcpy(tmp2, tmp, sizeof(tmp));\n            tilt(tmp2, d);\n            int64_t sc = evaluate(tmp2);\n            if (sc > best_sc) {\n                best_sc = sc;\n                best_d = d;\n            }\n        }\n        tilt(tmp, best_d);\n    }\n    \n    return evaluate_enhanced(tmp, step + look);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < TOTAL; i++) {\n        cin >> flavor[i];\n        total_count[flavor[i]]++;\n    }\n    \n    memset(grid, 0, sizeof(grid));\n    memset(placed_count, 0, sizeof(placed_count));\n    \n    mt19937 rng(42);\n    \n    for (int step = 0; step < TOTAL; step++) {\n        int p; cin >> p;\n        \n        int cnt = 0, r = 0, c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (!grid[i][j] && ++cnt == p) {\n                    r = i; c = j;\n                    i = N; break;\n                }\n            }\n        }\n        \n        int f = flavor[step];\n        placed_count[f]++;\n        grid[r][c] = f;\n        \n        int old_grid[N][N];\n        memcpy(old_grid, grid, sizeof(grid));\n        \n        int remaining = TOTAL - step - 1;\n        int num_sims, look_depth;\n        \n        if (remaining >= 70) {\n            num_sims = 30; look_depth = 14;\n        } else if (remaining >= 50) {\n            num_sims = 25; look_depth = 12;\n        } else if (remaining >= 30) {\n            num_sims = 22; look_depth = 10;\n        } else if (remaining >= 15) {\n            num_sims = 16; look_depth = 7;\n        } else if (remaining >= 5) {\n            num_sims = 10; look_depth = min(5, remaining);\n        } else {\n            num_sims = 6; look_depth = remaining;\n        }\n        \n        vector<vector<int>> sim_positions(num_sims);\n        for (int s = 0; s < num_sims; s++) {\n            for (int k = 0; k < look_depth; k++) {\n                int empties = remaining - k;\n                if (empties <= 0) break;\n                uniform_int_distribution<int> dist(1, empties);\n                sim_positions[s].push_back(dist(rng));\n            }\n        }\n        \n        int best_d = 0;\n        int64_t best_score = -1;\n        \n        for (int d = 0; d < 4; d++) {\n            int tmp[N][N];\n            memcpy(tmp, old_grid, sizeof(tmp));\n            tilt(tmp, d);\n            \n            int64_t base_score = evaluate(tmp);\n            int64_t sim_total = 0;\n            int64_t sim_min = 1LL << 60;\n            \n            for (int s = 0; s < num_sims; s++) {\n                int idx = 0;\n                int64_t sim_score = rollout(tmp, step, look_depth, sim_positions[s], idx);\n                sim_total += sim_score;\n                sim_min = min(sim_min, sim_score);\n            }\n            \n            int64_t avg_sim = sim_total / num_sims;\n            \n            double future_weight = min(0.85, remaining / 95.0);\n            \n            if (sim_min > base_score) {\n                future_weight = min(1.0, future_weight * 1.2);\n            }\n            \n            int64_t combined = base_score + (int64_t)((avg_sim - base_score) * future_weight);\n            \n            if (combined > best_score) {\n                best_score = combined;\n                best_d = d;\n            }\n        }\n        \n        memcpy(grid, old_grid, sizeof(old_grid));\n        tilt(grid, best_d);\n        cout << dc[best_d] << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct GraphInvariants {\n    int edges;\n    int triangles;\n    int isolated;\n    vector<int> deg_sorted;\n    double deg_mean;\n    double deg_var;\n    \n    static GraphInvariants compute(const string& g, int N) {\n        vector<int> deg(N, 0);\n        vector<vector<int>> adj(N, vector<int>(N, 0));\n        int idx = 0;\n        int edges = 0;\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                if (g[idx] == '1') {\n                    deg[i]++; deg[j]++;\n                    adj[i][j] = adj[j][i] = 1;\n                    edges++;\n                }\n                idx++;\n            }\n        }\n        \n        int triangles = 0;\n        for (int i = 0; i < N; i++)\n            for (int j = i+1; j < N; j++)\n                if (adj[i][j])\n                    for (int k = j+1; k < N; k++)\n                        if (adj[i][k] && adj[j][k]) triangles++;\n        \n        sort(deg.begin(), deg.end());\n        double mean = 0;\n        for (int d : deg) mean += d;\n        mean /= N;\n        \n        double var = 0;\n        for (int d : deg) var += (d - mean) * (d - mean);\n        var /= N;\n        \n        int isolated = 0;\n        for (int d : deg) if (d == 0) isolated++;\n        \n        return {edges, triangles, isolated, deg, mean, var};\n    }\n    \n    double distance(const GraphInvariants& other, int N, double eps) const {\n        double d = 0;\n        int total_pairs = N * (N - 1) / 2;\n        \n        double edge_std = sqrt(total_pairs * eps * (1 - eps) + 0.01);\n        d += pow((edges - other.edges) / edge_std, 2) * 5.0;\n        \n        if (N <= 25) {\n            double tri_std = sqrt(max(1.0, (double)triangles * eps * (1-eps)) + 0.01);\n            d += pow((triangles - other.triangles) / tri_std, 2) * 0.5;\n        }\n        \n        double iso_std = sqrt(max(1.0, N * eps * (1-eps)) + 0.01);\n        d += pow((isolated - other.isolated) / iso_std, 2) * 0.3;\n        \n        double l1 = 0;\n        for (int i = 0; i < N; i++)\n            l1 += abs(deg_sorted[i] - other.deg_sorted[i]);\n        double l1_std = sqrt(4 * total_pairs * eps * (1 - eps) + 1.0);\n        d += pow(max(0.0, l1 - 2*total_pairs*eps) / l1_std, 2) * 0.5;\n        \n        return d;\n    }\n};\n\nvector<string> generate_graphs(int N, int M, double eps) {\n    int total_pairs = N * (N - 1) / 2;\n    vector<string> graphs;\n    mt19937 gen(42);\n    \n    if (N <= 6) {\n        int max_mask = 1 << total_pairs;\n        map<vector<int>, string> best_graph;\n        \n        for (int mask = 0; mask < max_mask; mask++) {\n            string g;\n            for (int i = 0; i < total_pairs; i++)\n                g += ((mask >> i) & 1) ? '1' : '0';\n            \n            auto inv = GraphInvariants::compute(g, N);\n            auto& best = best_graph[inv.deg_sorted];\n            if (best.empty() || abs(inv.edges - total_pairs/2) < \n                abs(GraphInvariants::compute(best, N).edges - total_pairs/2)) {\n                best = g;\n            }\n        }\n        \n        vector<pair<string, GraphInvariants>> candidates;\n        for (auto& [deg, g] : best_graph) {\n            candidates.push_back({g, GraphInvariants::compute(g, N)});\n        }\n        \n        vector<bool> selected(candidates.size(), false);\n        for (int k = 0; k < M && k < (int)candidates.size(); k++) {\n            int best_i = -1;\n            double best_min = -1;\n            \n            for (int i = 0; i < (int)candidates.size(); i++) {\n                if (selected[i]) continue;\n                double min_dist = 1e9;\n                for (int j = 0; j < (int)candidates.size(); j++) {\n                    if (!selected[j]) continue;\n                    double dist = candidates[i].second.distance(candidates[j].second, N, eps);\n                    min_dist = min(min_dist, dist);\n                }\n                if (graphs.empty() || min_dist > best_min) {\n                    best_min = min_dist;\n                    best_i = i;\n                }\n            }\n            if (best_i >= 0) {\n                graphs.push_back(candidates[best_i].first);\n                selected[best_i] = true;\n            }\n        }\n        \n        while ((int)graphs.size() < M) {\n            graphs.push_back(graphs[gen() % graphs.size()]);\n        }\n        return graphs;\n    }\n    \n    // For larger N: generate diverse candidates\n    const int NUM_CANDIDATES = min(30000, 80 * M);\n    vector<pair<string, GraphInvariants>> candidates;\n    \n    for (int c = 0; c < NUM_CANDIDATES; c++) {\n        double density;\n        if (c < 100) {\n            density = 0.05 + 0.9 * c / 100.0;\n        } else {\n            density = uniform_real_distribution<>(0.03, 0.97)(gen);\n        }\n        \n        int target_edges = (int)(density * total_pairs);\n        target_edges = max(0, min(total_pairs, target_edges));\n        \n        vector<pair<int,int>> all_edges;\n        for (int i = 0; i < N; i++)\n            for (int j = i+1; j < N; j++)\n                all_edges.push_back({i, j});\n        \n        vector<vector<int>> adj(N, vector<int>(N, 0));\n        \n        int structure_type = c % 4;\n        \n        if (structure_type == 0) {\n            // Completely random\n            mt19937 local_gen(gen() + c);\n            shuffle(all_edges.begin(), all_edges.end(), local_gen);\n            for (int e = 0; e < target_edges && e < (int)all_edges.size(); e++) {\n                auto [i, j] = all_edges[e];\n                adj[i][j] = adj[j][i] = 1;\n            }\n        } else if (structure_type == 1) {\n            // Hub-based\n            vector<int> hubs;\n            int num_hubs = max(1, min(5, N / 3));\n            for (int h = 0; h < num_hubs; h++) hubs.push_back(gen() % N);\n            \n            mt19937 local_gen(gen() + c);\n            shuffle(all_edges.begin(), all_edges.end(), local_gen);\n            int e = 0;\n            for (auto [i, j] : all_edges) {\n                if (e >= target_edges) break;\n                bool near_hub = (find(hubs.begin(), hubs.end(), i) != hubs.end()) ||\n                               (find(hubs.begin(), hubs.end(), j) != hubs.end());\n                if (near_hub || local_gen() % 3 == 0) {\n                    adj[i][j] = adj[j][i] = 1;\n                    e++;\n                }\n            }\n        } else if (structure_type == 2) {\n            // Block structure\n            int block_size = max(2, N / (3 + (int)(gen() % 3)));\n            for (int start = 0; start < N; start += block_size) {\n                int end = min(N, start + block_size);\n                for (int i = start; i < end; i++)\n                    for (int j = i+1; j < end; j++)\n                        if ((int)(gen() % 100) < (int)(density * 100))\n                            adj[i][j] = adj[j][i] = 1;\n            }\n            // Ensure approximately target_edges by adding/removing\n            int current_edges = 0;\n            for (int i = 0; i < N; i++)\n                for (int j = i+1; j < N; j++)\n                    if (adj[i][j]) current_edges++;\n            \n            if (current_edges < target_edges) {\n                mt19937 local_gen(gen() + c);\n                shuffle(all_edges.begin(), all_edges.end(), local_gen);\n                for (auto [i, j] : all_edges) {\n                    if (current_edges >= target_edges) break;\n                    if (!adj[i][j]) {\n                        adj[i][j] = adj[j][i] = 1;\n                        current_edges++;\n                    }\n                }\n            }\n        } else {\n            // Mix of random and structured\n            mt19937 local_gen(gen() + c);\n            shuffle(all_edges.begin(), all_edges.end(), local_gen);\n            \n            // First half: random edges\n            int half = target_edges / 2;\n            for (int e = 0; e < half && e < (int)all_edges.size(); e++) {\n                auto [i, j] = all_edges[e];\n                adj[i][j] = adj[j][i] = 1;\n            }\n            \n            // Second half: prefer edges connecting to high-degree vertices\n            vector<int> deg(N, 0);\n            for (int i = 0; i < N; i++)\n                for (int j = i+1; j < N; j++)\n                    if (adj[i][j]) { deg[i]++; deg[j]++; }\n            \n            int e = half;\n            for (auto [i, j] : all_edges) {\n                if (e >= target_edges) break;\n                if (!adj[i][j] && (deg[i] + deg[j] > 0 || local_gen() % 2 == 0)) {\n                    adj[i][j] = adj[j][i] = 1;\n                    deg[i]++; deg[j]++;\n                    e++;\n                }\n            }\n        }\n        \n        string g;\n        for (int i = 0; i < N; i++)\n            for (int j = i+1; j < N; j++)\n                g += (adj[i][j] ? '1' : '0');\n        \n        candidates.push_back({g, GraphInvariants::compute(g, N)});\n    }\n    \n    // Greedy selection\n    vector<bool> selected(candidates.size(), false);\n    for (int k = 0; k < M; k++) {\n        int best_i = -1;\n        double best_min = -1;\n        \n        int step = max(1, (int)candidates.size() / 3000);\n        \n        for (int i = 0; i < (int)candidates.size(); i += step) {\n            if (selected[i]) continue;\n            double min_dist = 1e9;\n            \n            for (int j = 0; j < (int)candidates.size(); j++) {\n                if (!selected[j]) continue;\n                double dist = candidates[i].second.distance(candidates[j].second, N, eps);\n                min_dist = min(min_dist, dist);\n                if (min_dist < best_min) break;\n            }\n            \n            if (graphs.empty() || min_dist > best_min) {\n                best_min = min_dist;\n                best_i = i;\n            }\n        }\n        \n        if (best_i >= 0) {\n            graphs.push_back(candidates[best_i].first);\n            selected[best_i] = true;\n        }\n    }\n    \n    while ((int)graphs.size() < M) {\n        int idx = gen() % candidates.size();\n        if (!selected[idx]) {\n            graphs.push_back(candidates[idx].first);\n            selected[idx] = true;\n        } else {\n            graphs.push_back(candidates[gen() % candidates.size()].first);\n        }\n    }\n    \n    return graphs;\n}\n\nint predict(const string& H, const vector<string>& graphs, int N, double eps) {\n    auto H_inv = GraphInvariants::compute(H, N);\n    \n    int best_k = 0;\n    double best_score = -1e9;\n    \n    for (int k = 0; k < (int)graphs.size(); k++) {\n        auto G_inv = GraphInvariants::compute(graphs[k], N);\n        double dist = H_inv.distance(G_inv, N, eps);\n        double score = -dist;\n        \n        if (score > best_score) {\n            best_score = score;\n            best_k = k;\n        }\n    }\n    \n    return best_k;\n}\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    int N;\n    \n    if (eps <= 0.05) {\n        if (M <= 11) N = 4;\n        else if (M <= 34) N = 5;\n        else if (M <= 100) N = 6;\n        else N = 7;\n    } else if (eps <= 0.12) {\n        if (M <= 11) N = 4;\n        else if (M <= 34) N = 5;\n        else if (M <= 100) N = 6;\n        else N = 7;\n    } else if (eps <= 0.25) {\n        if (M <= 11) N = 5;\n        else if (M <= 30) N = 6;\n        else if (M <= 80) N = 7;\n        else N = 8;\n    } else if (eps <= 0.35) {\n        if (M <= 15) N = 6;\n        else if (M <= 50) N = 7;\n        else if (M <= 100) N = 8;\n        else N = 9;\n    } else {\n        if (M <= 20) N = 7;\n        else if (M <= 60) N = 8;\n        else N = 9;\n    }\n    \n    N = max(4, min(100, N));\n    \n    auto graphs = generate_graphs(N, M, eps);\n    \n    cout << N << '\\n';\n    for (const auto& g : graphs) cout << g << '\\n';\n    cout.flush();\n    \n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n        int t = predict(H, graphs, N, eps);\n        t = max(0, min(M-1, t));\n        cout << t << '\\n';\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = 1e18;\nconst long long PENALTY = 1e9;\n\nstruct Edge {\n    int u, v, w, id;\n    double cx, cy; // center coordinates\n};\n\nstruct Vertex {\n    int x, y;\n};\n\nchrono::steady_clock::time_point start_time;\nlong long elapsed_ms() {\n    return chrono::duration_cast<chrono::milliseconds>(\n        chrono::steady_clock::now() - start_time).count();\n}\n\nclass DSU {\n    vector<int> p, sz;\npublic:\n    DSU(int n) : p(n), sz(n, 1) { iota(p.begin(), p.end(), 0); }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (sz[x] < sz[y]) swap(x, y);\n        p[y] = x; sz[x] += sz[y];\n        return true;\n    }\n};\n\nbool connected(int N, const vector<Edge>& edges, const vector<bool>& rm) {\n    DSU dsu(N);\n    for (const auto& e : edges) if (!rm[e.id]) dsu.unite(e.u, e.v);\n    int r = dsu.find(0);\n    for (int i = 1; i < N; i++) if (dsu.find(i) != r) return false;\n    return true;\n}\n\nvector<long long> dijkstra(int src, int N, const vector<vector<pair<int,int>>>& adj,\n                            const vector<Edge>& edges) {\n    vector<long long> dist(N, INF);\n    dist[src] = 0;\n    priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n    pq.push({0, src});\n    while (!pq.empty()) {\n        auto [d, u] = pq.top(); pq.pop();\n        if (d != dist[u]) continue;\n        for (auto [v, eid] : adj[u]) {\n            long long nd = d + edges[eid].w;\n            if (nd < dist[v]) { dist[v] = nd; pq.push({nd, v}); }\n        }\n    }\n    return dist;\n}\n\nvector<vector<pair<int,int>>> build_adj(int N, const vector<Edge>& edges, const vector<bool>& rm) {\n    vector<vector<pair<int,int>>> adj(N);\n    for (const auto& e : edges) if (!rm[e.id]) {\n        adj[e.u].push_back({e.v, e.id}); adj[e.v].push_back({e.u, e.id});\n    }\n    return adj;\n}\n\ndouble compute_frust(int N, const vector<vector<pair<int,int>>>& adj,\n                     const vector<Edge>& edges,\n                     const vector<vector<long long>>& orig, const vector<int>& srcs) {\n    double total = 0;\n    long long cnt = 0;\n    for (int src : srcs) {\n        auto dist = dijkstra(src, N, adj, edges);\n        for (int dst : srcs) {\n            if (src >= dst) continue;\n            long long dk = min(PENALTY, dist[dst]);\n            total += max(0LL, dk - orig[src][dst]);\n            cnt++;\n        }\n    }\n    return cnt ? total / cnt : 0;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    start_time = chrono::steady_clock::now();\n    srand(123456);\n    \n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n    \n    vector<Edge> edges(M);\n    vector<Vertex> verts(N);\n    vector<vector<pair<int,int>>> full_adj(N);\n    \n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        edges[i].u--; edges[i].v--;\n        edges[i].id = i;\n        full_adj[edges[i].u].push_back({edges[i].v, i});\n        full_adj[edges[i].v].push_back({edges[i].u, i});\n    }\n    \n    for (int i = 0; i < N; i++) {\n        cin >> verts[i].x >> verts[i].y;\n    }\n    \n    // Compute edge centers\n    for (auto& e : edges) {\n        e.cx = (verts[e.u].x + verts[e.v].x) / 2.0;\n        e.cy = (verts[e.u].y + verts[e.v].y) / 2.0;\n    }\n    \n    // Find bounding box\n    double minx = 1000, maxx = 0, miny = 1000, maxy = 0;\n    for (const auto& v : verts) {\n        minx = min(minx, (double)v.x);\n        maxx = max(maxx, (double)v.x);\n        miny = min(miny, (double)v.y);\n        maxy = max(maxy, (double)v.y);\n    }\n    \n    // Original distances\n    vector<vector<long long>> orig(N, vector<long long>(N, INF));\n    for (int src = 0; src < N; src++) orig[src] = dijkstra(src, N, full_adj, edges);\n    \n    // Source sampling\n    int num_srcs = min(N, (N <= 600) ? 150 : 120);\n    vector<int> srcs;\n    for (int i = 0; i < num_srcs; i++) srcs.push_back((i * N) / num_srcs);\n    \n    // Compute edge importance\n    vector<double> imp(M, 0.0);\n    int ns = min(N, 200);\n    for (int si = 0; si < ns; si++) {\n        int src = (si * N) / ns;\n        vector<long long> dist(N, INF);\n        vector<long long> cnt(N, 0);\n        vector<vector<int>> inc(N);\n        dist[src] = 0; cnt[src] = 1;\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<>> pq;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top(); pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, eid] : full_adj[u]) {\n                long long nd = d + edges[eid].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd; cnt[v] = cnt[u]; inc[v] = {eid}; pq.push({nd, v});\n                } else if (nd == dist[v]) {\n                    cnt[v] += cnt[u]; inc[v].push_back(eid);\n                }\n            }\n        }\n        vector<double> score(N, 1.0);\n        vector<int> ord(N); iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) { return dist[a] > dist[b]; });\n        for (int u : ord) {\n            if (dist[u] >= INF) continue;\n            for (int eid : inc[u]) {\n                int v = (edges[eid].u == u) ? edges[eid].v : edges[eid].u;\n                if (dist[v] + edges[eid].w == dist[u]) {\n                    double contrib = score[u] * (double)cnt[v] / cnt[u];\n                    imp[eid] += contrib; score[v] += contrib;\n                }\n            }\n        }\n    }\n    double mx = *max_element(imp.begin(), imp.end());\n    if (mx > 0) for (auto& x : imp) x /= mx;\n    \n    // Geometric assignment: assign each edge a \"base day\" based on its position\n    // Use a grid pattern with D \"colors\"\n    vector<int> geo_day(M);\n    int grid_cols = max(1, (int)sqrt(D * (maxx - minx) / (maxy - miny + 1)));\n    int grid_rows = max(1, D / grid_cols);\n    \n    for (int i = 0; i < M; i++) {\n        int col = (int)((edges[i].cx - minx) / (maxx - minx + 1) * grid_cols);\n        int row = (int)((edges[i].cy - miny) / (maxy - miny + 1) * grid_rows);\n        col = min(col, grid_cols - 1);\n        row = min(row, grid_rows - 1);\n        geo_day[i] = (row * grid_cols + col) % D;\n    }\n    \n    // Best solution\n    vector<int> best_assign(M);\n    double best_avg = 1e18;\n    int target = (M + D - 1) / D;\n    \n    // Try multiple strategies\n    for (int strategy = 0; strategy < 3 && elapsed_ms() < 3000; strategy++) {\n        vector<int> assign(M, -1), dcnt(D, 0);\n        vector<vector<bool>> drm(D, vector<bool>(M, false));\n        \n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        \n        if (strategy == 0) {\n            // Pure geometric: assign by location, then fix connectivity\n            for (int i = 0; i < M; i++) assign[i] = geo_day[i];\n            for (int i = 0; i < M; i++) { drm[assign[i]][i] = true; dcnt[assign[i]]++; }\n            \n            // Balance: move excess edges\n            for (int d = 0; d < D; d++) {\n                while (dcnt[d] > K) {\n                    // Find an edge to move\n                    vector<pair<double,int>> candidates;\n                    for (int i = 0; i < M; i++) if (assign[i] == d) candidates.push_back({imp[i], i});\n                    sort(candidates.begin(), candidates.end());\n                    \n                    bool moved = false;\n                    for (auto [_, eid] : candidates) {\n                        for (int d2 = 0; d2 < D; d2++) {\n                            if (d2 == d || dcnt[d2] >= K) continue;\n                            drm[d][eid] = false; drm[d2][eid] = true;\n                            if (connected(N, edges, drm[d]) && connected(N, edges, drm[d2])) {\n                                assign[eid] = d2; dcnt[d]--; dcnt[d2]++; moved = true; break;\n                            }\n                            drm[d][eid] = true; drm[d2][eid] = false;\n                        }\n                        if (moved) break;\n                    }\n                    if (!moved) break;\n                }\n            }\n            // Fill under-full days\n            for (int d = 0; d < D; d++) {\n                while (dcnt[d] < target) {\n                    bool filled = false;\n                    for (int d2 = 0; d2 < D; d2++) {\n                        if (dcnt[d2] > target) {\n                            vector<pair<double,int>> candidates;\n                            for (int i = 0; i < M; i++) if (assign[i] == d2) candidates.push_back({imp[i], i});\n                            sort(candidates.begin(), candidates.end());\n                            for (auto [_, eid] : candidates) {\n                                drm[d2][eid] = false; drm[d][eid] = true;\n                                if (connected(N, edges, drm[d2]) && connected(N, edges, drm[d])) {\n                                    assign[eid] = d; dcnt[d2]--; dcnt[d]++; filled = true; break;\n                                }\n                                drm[d2][eid] = true; drm[d][eid] = false;\n                            }\n                            if (filled) break;\n                        }\n                    }\n                    if (!filled) break;\n                }\n            }\n        } else if (strategy == 1) {\n            // Importance-sorted, but prefer geometric day\n            sort(order.begin(), order.end(), [&](int a, int b) { return imp[a] > imp[b]; });\n            \n            for (int eid : order) {\n                int bd = -1;\n                double bs = -1e18;\n                \n                // Try geometric day first, then others\n                vector<int> dys(D);\n                dys[0] = geo_day[eid];\n                for (int i = 1; i < D; i++) dys[i] = (dys[0] + i) % D;\n                \n                for (int d : dys) {\n                    if (dcnt[d] >= K) continue;\n                    drm[d][eid] = true;\n                    bool ok = connected(N, edges, drm[d]);\n                    drm[d][eid] = false;\n                    if (!ok) continue;\n                    // Prefer days closer to target\n                    double sc = -abs(dcnt[d] + 1 - target) * 10 + (d == geo_day[eid] ? 1 : 0);\n                    if (sc > bs) { bs = sc; bd = d; }\n                }\n                if (bd == -1) {\n                    for (int d = 0; d < D; d++) if (dcnt[d] < K) { bd = d; break; }\n                }\n                assign[eid] = bd;\n                drm[bd][eid] = true;\n                dcnt[bd]++;\n            }\n        } else {\n            // Importance-sorted greedy\n            sort(order.begin(), order.end(), [&](int a, int b) { return imp[a] > imp[b]; });\n            \n            for (int eid : order) {\n                int bd = -1;\n                double bs = -1e18;\n                for (int d = 0; d < D; d++) {\n                    if (dcnt[d] >= K) continue;\n                    drm[d][eid] = true;\n                    bool ok = connected(N, edges, drm[d]);\n                    drm[d][eid] = false;\n                    if (!ok) continue;\n                    double overload = max(0, dcnt[d] + 1 - target);\n                    double sc = -(dcnt[d] + 1) * imp[eid] - overload * 200;\n                    if (sc > bs) { bs = sc; bd = d; }\n                }\n                if (bd == -1) {\n                    for (int d = 0; d < D; d++) if (dcnt[d] < K) { bd = d; break; }\n                }\n                assign[eid] = bd;\n                drm[bd][eid] = true;\n                dcnt[bd]++;\n            }\n        }\n        \n        // Fix connectivity for strategies 1 and 2\n        if (strategy > 0) {\n            for (int d = 0; d < D; d++) {\n                int tries = 0;\n                while (!connected(N, edges, drm[d]) && tries++ < 500) {\n                    vector<pair<double,int>> des;\n                    for (int i = 0; i < M; i++) if (assign[i] == d) des.push_back({imp[i], i});\n                    sort(des.begin(), des.end());\n                    bool moved = false;\n                    for (auto [_, eid] : des) {\n                        for (int d2 = 0; d2 < D; d2++) {\n                            if (d2 == d || dcnt[d2] >= K) continue;\n                            drm[d][eid] = false; drm[d2][eid] = true;\n                            if (connected(N, edges, drm[d]) && connected(N, edges, drm[d2])) {\n                                assign[eid] = d2; dcnt[d]--; dcnt[d2]++; moved = true; break;\n                            }\n                            drm[d][eid] = true; drm[d2][eid] = false;\n                        }\n                        if (connected(N, edges, drm[d])) break;\n                    }\n                    if (!moved) break;\n                }\n            }\n        }\n        \n        // Also fix connectivity for strategy 0\n        if (strategy == 0) {\n            for (int d = 0; d < D; d++) {\n                if (!connected(N, edges, drm[d])) {\n                    int tries = 0;\n                    while (!connected(N, edges, drm[d]) && tries++ < 500) {\n                        vector<pair<double,int>> des;\n                        for (int i = 0; i < M; i++) if (assign[i] == d) des.push_back({imp[i], i});\n                        sort(des.begin(), des.end());\n                        bool moved = false;\n                        for (auto [_, eid] : des) {\n                            for (int d2 = 0; d2 < D; d2++) {\n                                if (d2 == d || dcnt[d2] >= K) continue;\n                                drm[d][eid] = false; drm[d2][eid] = true;\n                                if (connected(N, edges, drm[d]) && connected(N, edges, drm[d2])) {\n                                    assign[eid] = d2; dcnt[d]--; dcnt[d2]++; moved = true; break;\n                                }\n                                drm[d][eid] = true; drm[d2][eid] = false;\n                            }\n                            if (connected(N, edges, drm[d])) break;\n                        }\n                        if (!moved) break;\n                    }\n                }\n            }\n        }\n        \n        // Evaluate\n        double avg = 0;\n        for (int d = 0; d < D; d++) {\n            auto adj = build_adj(N, edges, drm[d]);\n            avg += compute_frust(N, adj, edges, orig, srcs);\n        }\n        avg /= D;\n        \n        if (avg < best_avg && strategy == 0) {\n            best_avg = avg;\n            best_assign = assign;\n        } else if (avg < best_avg) {\n            best_avg = avg;\n            best_assign = assign;\n        }\n    }\n    \n    // SA for final improvement\n    vector<int> assign = best_assign;\n    vector<vector<bool>> drm(D, vector<bool>(M, false));\n    vector<int> dcnt(D, 0);\n    for (int i = 0; i < M; i++) { drm[assign[i]][i] = true; dcnt[assign[i]]++; }\n    \n    vector<vector<vector<pair<int,int>>>> dadj(D);\n    vector<double> frust(D);\n    for (int d = 0; d < D; d++) {\n        dadj[d] = build_adj(N, edges, drm[d]);\n        frust[d] = compute_frust(N, dadj[d], edges, orig, srcs);\n    }\n    double cur_avg = accumulate(frust.begin(), frust.end(), 0.0) / D;\n    best_avg = cur_avg;\n    best_assign = assign;\n    \n    double temp = 20.0;\n    long long iter = 0;\n    \n    while (elapsed_ms() < 5700) {\n        for (int batch = 0; batch < 40 && elapsed_ms() < 5700; batch++) {\n            iter++;\n            if (iter % 200 == 0) { temp *= 0.998; if (temp < 0.003) temp = 0.003; }\n            \n            int worst = max_element(frust.begin(), frust.end()) - frust.begin();\n            \n            if (rand() % 10 < 7) {\n                vector<int> wedges;\n                for (int i = 0; i < M; i++) if (assign[i] == worst) wedges.push_back(i);\n                if (wedges.empty()) continue;\n                int e1 = wedges[rand() % wedges.size()];\n                int e2 = rand() % M;\n                int d1 = worst, d2 = assign[e2];\n                if (d1 == d2) continue;\n                \n                drm[d1][e1] = false; drm[d1][e2] = true;\n                drm[d2][e2] = false; drm[d2][e1] = true;\n                if (!connected(N, edges, drm[d1]) || !connected(N, edges, drm[d2])) {\n                    drm[d1][e1] = true; drm[d1][e2] = false;\n                    drm[d2][e2] = true; drm[d2][e1] = false; continue;\n                }\n                auto a1 = build_adj(N, edges, drm[d1]);\n                auto a2 = build_adj(N, edges, drm[d2]);\n                double f1 = compute_frust(N, a1, edges, orig, srcs);\n                double f2 = compute_frust(N, a2, edges, orig, srcs);\n                double new_avg = cur_avg + (f1 - frust[d1] + f2 - frust[d2]) / D;\n                double delta = new_avg - cur_avg;\n                if (delta < 0 || exp(-delta / max(1e-9, temp)) > (double)rand() / RAND_MAX) {\n                    assign[e1] = d2; assign[e2] = d1;\n                    frust[d1] = f1; frust[d2] = f2; cur_avg = new_avg;\n                    dadj[d1] = move(a1); dadj[d2] = move(a2);\n                    if (cur_avg < best_avg) { best_avg = cur_avg; best_assign = assign; }\n                } else {\n                    drm[d1][e1] = true; drm[d1][e2] = false;\n                    drm[d2][e2] = true; drm[d2][e1] = false;\n                }\n            } else {\n                vector<int> wedges;\n                for (int i = 0; i < M; i++) if (assign[i] == worst) wedges.push_back(i);\n                if (wedges.empty()) continue;\n                int e = wedges[rand() % wedges.size()];\n                int best_d = min_element(frust.begin(), frust.end()) - frust.begin();\n                if (best_d == worst || dcnt[best_d] >= K) continue;\n                drm[worst][e] = false; drm[best_d][e] = true;\n                if (!connected(N, edges, drm[worst]) || !connected(N, edges, drm[best_d])) {\n                    drm[worst][e] = true; drm[best_d][e] = false; continue;\n                }\n                auto a1 = build_adj(N, edges, drm[worst]);\n                auto a2 = build_adj(N, edges, drm[best_d]);\n                double f1 = compute_frust(N, a1, edges, orig, srcs);\n                double f2 = compute_frust(N, a2, edges, orig, srcs);\n                double new_avg = cur_avg + (f1 - frust[worst] + f2 - frust[best_d]) / D;\n                double delta = new_avg - cur_avg;\n                if (delta < 0 || exp(-delta / max(1e-9, temp)) > (double)rand() / RAND_MAX) {\n                    assign[e] = best_d;\n                    frust[worst] = f1; frust[best_d] = f2; cur_avg = new_avg;\n                    dcnt[worst]--; dcnt[best_d]++;\n                    dadj[worst] = move(a1); dadj[best_d] = move(a2);\n                    if (cur_avg < best_avg) { best_avg = cur_avg; best_assign = assign; }\n                } else {\n                    drm[worst][e] = true; drm[best_d][e] = false;\n                }\n            }\n        }\n    }\n    \n    // Output\n    vector<int> out_count(D, 0);\n    for (int i = 0; i < M; i++) out_count[best_assign[i]]++;\n    for (int d = 0; d < D; d++) {\n        if (out_count[d] > K) {\n            int excess = out_count[d] - K;\n            vector<int> eid;\n            for (int i = 0; i < M; i++) if (best_assign[i] == d) eid.push_back(i);\n            sort(eid.begin(), eid.end(), [&](int a, int b) { return imp[a] < imp[b]; });\n            for (int i = 0; i < excess; i++) {\n                for (int d2 = 0; d2 < D; d2++) {\n                    if (out_count[d2] < K) {\n                        best_assign[eid[i]] = d2;\n                        out_count[d]--; out_count[d2]++; break;\n                    }\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i < M; i++) {\n        if (i > 0) cout << \" \";\n        cout << best_assign[i] + 1;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct FastBitset {\n    static constexpr int N = 2744;\n    static constexpr int CHUNKS = (N + 63) / 64;\n    uint64_t bits[CHUNKS]{};\n    FastBitset() { clear(); }\n    void clear() { memset(bits, 0, sizeof bits); }\n    void set(int i) { bits[i>>6] |= 1ULL << (i&63); }\n    void reset(int i) { bits[i>>6] &= ~(1ULL << (i&63)); }\n    bool test(int i) const { return (bits[i>>6] >> (i&63)) & 1ULL; }\n    int count() const {\n        int c = 0;\n        for (int i = 0; i < CHUNKS; ++i) c += __builtin_popcountll(bits[i]);\n        return c;\n    }\n    FastBitset operator~() const {\n        FastBitset r;\n        for (int i = 0; i < CHUNKS; ++i) r.bits[i] = ~bits[i];\n        return r;\n    }\n    FastBitset operator|(const FastBitset& o) const {\n        FastBitset r;\n        for (int i = 0; i < CHUNKS; ++i) r.bits[i] = bits[i] | o.bits[i];\n        return r;\n    }\n    FastBitset operator&(const FastBitset& o) const {\n        FastBitset r;\n        for (int i = 0; i < CHUNKS; ++i) r.bits[i] = bits[i] & o.bits[i];\n        return r;\n    }\n    void operator|=(const FastBitset& o) {\n        for (int i = 0; i < CHUNKS; ++i) bits[i] |= o.bits[i];\n    }\n    void operator&=(const FastBitset& o) {\n        for (int i = 0; i < CHUNKS; ++i) bits[i] &= o.bits[i];\n    }\n    template<typename F>\n    void forEachSetBit(F f) const {\n        for (int i = 0; i < CHUNKS; ++i) {\n            uint64_t w = bits[i];\n            while (w) {\n                int j = __builtin_ctzll(w);\n                f((i << 6) | j);\n                w &= w - 1;\n            }\n        }\n    }\n};\n\nint D, D2, D3;\nvector<vector<int>> adj;\nvector<array<array<int,3>,3>> rots;\nvector<array<array<int,3>,3>> inv_rots;\n\nvoid generate_rotations() {\n    int perm[3] = {0,1,2};\n    do {\n        for (int s0 = -1; s0 <= 1; s0+=2)\n        for (int s1 = -1; s1 <= 1; s1+=2)\n        for (int s2 = -1; s2 <= 1; s2+=2) {\n            int sign = 1;\n            for (int i=0;i<3;i++) for (int j=i+1;j<3;j++) if (perm[i]>perm[j]) sign = -sign;\n            if (sign * s0 * s1 * s2 != 1) continue;\n            array<array<int,3>,3> mat = {{{0}}};\n            mat[0][perm[0]] = s0;\n            mat[1][perm[1]] = s1;\n            mat[2][perm[2]] = s2;\n            rots.push_back(mat);\n        }\n    } while (next_permutation(perm, perm+3));\n    for (auto& mat : rots) {\n        array<array<int,3>,3> inv = {{{0}}};\n        for (int i=0;i<3;i++) for (int j=0;j<3;j++) inv[j][i] = mat[i][j];\n        inv_rots.push_back(inv);\n    }\n}\n\ninline int encode(int x, int y, int z) { return x*D2 + y*D + z; }\ninline tuple<int,int,int> decode(int idx) {\n    int z = idx % D;\n    int y = (idx / D) % D;\n    int x = idx / D2;\n    return {x,y,z};\n}\n\nFastBitset rotate_bitset(const FastBitset& src, const array<array<int,3>,3>& mat) {\n    FastBitset dst;\n    src.forEachSetBit([&](int idx) {\n        auto [x,y,z] = decode(idx);\n        int nx = mat[0][0]*x + mat[0][1]*y + mat[0][2]*z;\n        int ny = mat[1][0]*x + mat[1][1]*y + mat[1][2]*z;\n        int nz = mat[2][0]*x + mat[2][1]*y + mat[2][2]*z;\n        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n            dst.set(encode(nx,ny,nz));\n        }\n    });\n    return dst;\n}\n\ntuple<vector<int>, vector<int>, int> solve(mt19937& rng, \n        const vector<string>& f1, const vector<string>& r1,\n        const vector<string>& f2, const vector<string>& r2,\n        const FastBitset& A1, const FastBitset& A2,\n        const vector<vector<bool>>& init_unc1_f,\n        const vector<vector<bool>>& init_unc1_r,\n        const vector<vector<bool>>& init_unc2_f,\n        const vector<vector<bool>>& init_unc2_r,\n        const steady_clock::time_point& start_time,\n        int time_limit_ms,\n        int weight) {\n    \n    auto get_ms = [&]() {\n        return duration_cast<milliseconds>(steady_clock::now() - start_time).count();\n    };\n    \n    FastBitset available1 = A1, available2 = A2;\n    vector<int> b1(D3, 0), b2(D3, 0);\n    int block_id = 1;\n\n    vector unc1_f = init_unc1_f, unc1_r = init_unc1_r;\n    vector unc2_f = init_unc2_f, unc2_r = init_unc2_r;\n\n    auto count_new_lines = [&](const FastBitset& voxels, bool is_obj1) -> int {\n        int cnt = 0;\n        voxels.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            if (is_obj1) {\n                if (unc1_f[z][x]) cnt++;\n                if (unc1_r[z][y]) cnt++;\n            } else {\n                if (unc2_f[z][x]) cnt++;\n                if (unc2_r[z][y]) cnt++;\n            }\n        });\n        return cnt;\n    };\n\n    vector<int> rot_order(24);\n    iota(rot_order.begin(), rot_order.end(), 0);\n    shuffle(rot_order.begin(), rot_order.end(), rng);\n\n    while (get_ms() < time_limit_ms * 0.65) {\n        int best_vol = 0;\n        int best_gain = 0;\n        vector<tuple<int, FastBitset, FastBitset, int, int, int, int>> candidates;\n        FastBitset best_comp2, best_preimage1;\n        int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n        for (int ri = 0; ri < 24; ++ri) {\n            int r = rot_order[ri];\n            FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n            int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n            bool any = false;\n            rot_avail1.forEachSetBit([&](int idx) {\n                auto [x,y,z] = decode(idx);\n                any = true;\n                min_x = std::min(min_x, x); max_x = std::max(max_x, x);\n                min_y = std::min(min_y, y); max_y = std::max(max_y, y);\n                min_z = std::min(min_z, z); max_z = std::max(max_z, z);\n            });\n            if (!any) continue;\n\n            int dx_min = -min_x, dx_max = D-1 - max_x;\n            int dy_min = -min_y, dy_max = D-1 - max_y;\n            int dz_min = -min_z, dz_max = D-1 - max_z;\n\n            // shuffle shift order\n            vector<int> xs(dx_max - dx_min + 1);\n            iota(xs.begin(), xs.end(), dx_min);\n            shuffle(xs.begin(), xs.end(), rng);\n            vector<int> ys(dy_max - dy_min + 1);\n            iota(ys.begin(), ys.end(), dy_min);\n            shuffle(ys.begin(), ys.end(), rng);\n            vector<int> zs(dz_max - dz_min + 1);\n            iota(zs.begin(), zs.end(), dz_min);\n            shuffle(zs.begin(), zs.end(), rng);\n\n            for (int dx : xs) {\n                for (int dy : ys) {\n                    for (int dz : zs) {\n                        FastBitset overlap;\n                        rot_avail1.forEachSetBit([&](int idx) {\n                            auto [x,y,z] = decode(idx);\n                            int nx = x+dx, ny = y+dy, nz = z+dz;\n                            if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                int idx2 = encode(nx,ny,nz);\n                                if (available2.test(idx2)) overlap.set(idx2);\n                            }\n                        });\n                        int ov_cnt = overlap.count();\n                        if (ov_cnt <= best_vol) continue;\n\n                        FastBitset visited;\n                        int visited_cnt = 0;\n                        overlap.forEachSetBit([&](int seed) {\n                            if (visited.test(seed)) return;\n                            if (ov_cnt - visited_cnt <= best_vol) return;\n                            queue<int> q;\n                            q.push(seed);\n                            visited.set(seed); visited_cnt++;\n                            FastBitset comp;\n                            comp.set(seed);\n                            int sz = 1;\n                            while (!q.empty()) {\n                                int cur = q.front(); q.pop();\n                                for (int nb : adj[cur]) {\n                                    if (overlap.test(nb) && !visited.test(nb)) {\n                                        visited.set(nb); visited_cnt++;\n                                        comp.set(nb);\n                                        sz++;\n                                        q.push(nb);\n                                    }\n                                }\n                            }\n                            if (sz > best_vol) {\n                                FastBitset preimage;\n                                comp.forEachSetBit([&](int idx2) {\n                                    auto [x2,y2,z2] = decode(idx2);\n                                    int sx = x2 - dx, sy = y2 - dy, sz2 = z2 - dz;\n                                    int ox = inv_rots[r][0][0]*sx + inv_rots[r][0][1]*sy + inv_rots[r][0][2]*sz2;\n                                    int oy = inv_rots[r][1][0]*sx + inv_rots[r][1][1]*sy + inv_rots[r][1][2]*sz2;\n                                    int oz = inv_rots[r][2][0]*sx + inv_rots[r][2][1]*sy + inv_rots[r][2][2]*sz2;\n                                    preimage.set(encode(ox,oy,oz));\n                                });\n                                int new_lines = count_new_lines(preimage, true) + count_new_lines(comp, false);\n                                if (new_lines > 0) {\n                                    int gain = sz + weight * new_lines;\n                                    if (gain > best_gain) {\n                                        best_gain = gain;\n                                        best_vol = sz;\n                                        best_comp2 = comp;\n                                        best_preimage1 = preimage;\n                                        best_r = r;\n                                        best_dx = dx; best_dy = dy; best_dz = dz;\n                                        candidates.clear();\n                                        candidates.push_back({gain, comp, preimage, r, dx, dy, dz});\n                                    } else if (gain >= best_gain * 0.9) {\n                                        candidates.push_back({gain, comp, preimage, r, dx, dy, dz});\n                                    }\n                                }\n                            }\n                        });\n                    }\n                }\n            }\n        }\n        if (best_vol < 2) break;\n\n        if (candidates.size() > 1) {\n            uniform_int_distribution<int> dist(0, (int)candidates.size()-1);\n            int idx = dist(rng);\n            auto [gain, comp2, preimage1, r, dx, dy, dz] = candidates[idx];\n            best_gain = gain;\n            best_comp2 = comp2;\n            best_preimage1 = preimage1;\n            best_r = r;\n            best_dx = dx; best_dy = dy; best_dz = dz;\n            best_vol = comp2.count();\n        }\n\n        // Expand\n        {\n            FastBitset &preimage1 = best_preimage1;\n            FastBitset &comp2 = best_comp2;\n            int r = best_r, dx = best_dx, dy = best_dy, dz = best_dz;\n            queue<int> q1, q2;\n            preimage1.forEachSetBit([&](int v) { q1.push(v); });\n            comp2.forEachSetBit([&](int v) { q2.push(v); });\n            while (!q1.empty()) {\n                int v1 = q1.front(); q1.pop();\n                q2.pop();\n                for (int nb1 : adj[v1]) {\n                    if (available1.test(nb1) && !preimage1.test(nb1)) {\n                        auto [x,y,z] = decode(nb1);\n                        int nx = rots[r][0][0]*x + rots[r][0][1]*y + rots[r][0][2]*z + dx;\n                        int ny = rots[r][1][0]*x + rots[r][1][1]*y + rots[r][1][2]*z + dy;\n                        int nz = rots[r][2][0]*x + rots[r][2][1]*y + rots[r][2][2]*z + dz;\n                        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                            int nb2 = encode(nx,ny,nz);\n                            if (available2.test(nb2) && !comp2.test(nb2)) {\n                                preimage1.set(nb1);\n                                comp2.set(nb2);\n                                available1.reset(nb1);\n                                available2.reset(nb2);\n                                q1.push(nb1);\n                                q2.push(nb2);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        int bid = block_id++;\n        best_preimage1.forEachSetBit([&](int idx) {\n            b1[idx] = bid;\n            available1.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc1_f[z][x] = false;\n            unc1_r[z][y] = false;\n        });\n        best_comp2.forEachSetBit([&](int idx) {\n            b2[idx] = bid;\n            available2.reset(idx);\n            auto [x,y,z] = decode(idx);\n            unc2_f[z][x] = false;\n            unc2_r[z][y] = false;\n        });\n    }\n\n    // Finalization\n    vector<int> remaining_voxels1, remaining_voxels2;\n\n    auto pick_best_voxel = [&](FastBitset& avail, \n                                const vector<vector<bool>>& unc_f, \n                                const vector<vector<bool>>& unc_r) -> int {\n        int best_idx = -1, best_cnt = -1;\n        avail.forEachSetBit([&](int idx) {\n            auto [x,y,z] = decode(idx);\n            int cnt = 0;\n            if (unc_f[z][x]) cnt++;\n            if (unc_r[z][y]) cnt++;\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_idx = idx;\n            }\n        });\n        return best_idx;\n    };\n\n    FastBitset avail1_copy = available1;\n    vector unc1_f_copy = unc1_f, unc1_r_copy = unc1_r;\n    while (true) {\n        int v = pick_best_voxel(avail1_copy, unc1_f_copy, unc1_r_copy);\n        if (v == -1) break;\n        auto [x,y,z] = decode(v);\n        if (!unc1_f_copy[z][x] && !unc1_r_copy[z][y]) break;\n        remaining_voxels1.push_back(v);\n        avail1_copy.reset(v);\n        unc1_f_copy[z][x] = false;\n        unc1_r_copy[z][y] = false;\n    }\n\n    FastBitset avail2_copy = available2;\n    vector unc2_f_copy = unc2_f, unc2_r_copy = unc2_r;\n    while (true) {\n        int v = pick_best_voxel(avail2_copy, unc2_f_copy, unc2_r_copy);\n        if (v == -1) break;\n        auto [x,y,z] = decode(v);\n        if (!unc2_f_copy[z][x] && !unc2_r_copy[z][y]) break;\n        remaining_voxels2.push_back(v);\n        avail2_copy.reset(v);\n        unc2_f_copy[z][x] = false;\n        unc2_r_copy[z][y] = false;\n    }\n\n    while (!remaining_voxels1.empty() && !remaining_voxels2.empty()) {\n        int v1 = remaining_voxels1.back(); remaining_voxels1.pop_back();\n        int v2 = remaining_voxels2.back(); remaining_voxels2.pop_back();\n        int bid = block_id++;\n        b1[v1] = bid;\n        b2[v2] = bid;\n        available1.reset(v1);\n        available2.reset(v2);\n    }\n    for (int v : remaining_voxels1) {\n        int bid = block_id++;\n        b1[v] = bid;\n        available1.reset(v);\n    }\n    for (int v : remaining_voxels2) {\n        int bid = block_id++;\n        b2[v] = bid;\n        available2.reset(v);\n    }\n\n    // Phase 3\n    while (get_ms() < time_limit_ms * 0.95) {\n        int best_vol = 0;\n        FastBitset best_comp2, best_preimage1;\n        int best_r = -1, best_dx=0, best_dy=0, best_dz=0;\n\n        for (int ri = 0; ri < 24; ++ri) {\n            int r = rot_order[ri];\n            if (get_ms() >= time_limit_ms * 0.95) break;\n            FastBitset rot_avail1 = rotate_bitset(available1, rots[r]);\n            int min_x=D, max_x=-1, min_y=D, max_y=-1, min_z=D, max_z=-1;\n            bool any = false;\n            rot_avail1.forEachSetBit([&](int idx) {\n                auto [x,y,z] = decode(idx);\n                any = true;\n                min_x = std::min(min_x, x); max_x = std::max(max_x, x);\n                min_y = std::min(min_y, y); max_y = std::max(max_y, y);\n                min_z = std::min(min_z, z); max_z = std::max(max_z, z);\n            });\n            if (!any) continue;\n\n            int dx_min = -min_x, dx_max = D-1 - max_x;\n            int dy_min = -min_y, dy_max = D-1 - max_y;\n            int dz_min = -min_z, dz_max = D-1 - max_z;\n\n            vector<int> xs(dx_max - dx_min + 1);\n            iota(xs.begin(), xs.end(), dx_min);\n            shuffle(xs.begin(), xs.end(), rng);\n            vector<int> ys(dy_max - dy_min + 1);\n            iota(ys.begin(), ys.end(), dy_min);\n            shuffle(ys.begin(), ys.end(), rng);\n            vector<int> zs(dz_max - dz_min + 1);\n            iota(zs.begin(), zs.end(), dz_min);\n            shuffle(zs.begin(), zs.end(), rng);\n\n            for (int dx : xs) {\n                for (int dy : ys) {\n                    for (int dz : zs) {\n                        FastBitset overlap;\n                        rot_avail1.forEachSetBit([&](int idx) {\n                            auto [x,y,z] = decode(idx);\n                            int nx = x+dx, ny = y+dy, nz = z+dz;\n                            if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                                int idx2 = encode(nx,ny,nz);\n                                if (available2.test(idx2)) overlap.set(idx2);\n                            }\n                        });\n                        int ov_cnt = overlap.count();\n                        if (ov_cnt <= best_vol) continue;\n\n                        FastBitset visited;\n                        int visited_cnt = 0;\n                        overlap.forEachSetBit([&](int seed) {\n                            if (visited.test(seed)) return;\n                            if (ov_cnt - visited_cnt <= best_vol) return;\n                            queue<int> q;\n                            q.push(seed);\n                            visited.set(seed); visited_cnt++;\n                            FastBitset comp;\n                            comp.set(seed);\n                            int sz = 1;\n                            while (!q.empty()) {\n                                int cur = q.front(); q.pop();\n                                for (int nb : adj[cur]) {\n                                    if (overlap.test(nb) && !visited.test(nb)) {\n                                        visited.set(nb); visited_cnt++;\n                                        comp.set(nb);\n                                        sz++;\n                                        q.push(nb);\n                                    }\n                                }\n                            }\n                            if (sz > best_vol) {\n                                FastBitset preimage;\n                                comp.forEachSetBit([&](int idx2) {\n                                    auto [x2,y2,z2] = decode(idx2);\n                                    int sx = x2 - dx, sy = y2 - dy, sz2 = z2 - dz;\n                                    int ox = inv_rots[r][0][0]*sx + inv_rots[r][0][1]*sy + inv_rots[r][0][2]*sz2;\n                                    int oy = inv_rots[r][1][0]*sx + inv_rots[r][1][1]*sy + inv_rots[r][1][2]*sz2;\n                                    int oz = inv_rots[r][2][0]*sx + inv_rots[r][2][1]*sy + inv_rots[r][2][2]*sz2;\n                                    preimage.set(encode(ox,oy,oz));\n                                });\n                                best_vol = sz;\n                                best_comp2 = comp;\n                                best_preimage1 = preimage;\n                                best_r = r;\n                                best_dx = dx; best_dy = dy; best_dz = dz;\n                            }\n                        });\n                    }\n                }\n            }\n        }\n        if (best_vol < 2) break;\n\n        // Expand\n        {\n            FastBitset &preimage1 = best_preimage1;\n            FastBitset &comp2 = best_comp2;\n            int r = best_r, dx = best_dx, dy = best_dy, dz = best_dz;\n            queue<int> q1, q2;\n            preimage1.forEachSetBit([&](int v) { q1.push(v); });\n            comp2.forEachSetBit([&](int v) { q2.push(v); });\n            while (!q1.empty()) {\n                int v1 = q1.front(); q1.pop();\n                q2.pop();\n                for (int nb1 : adj[v1]) {\n                    if (available1.test(nb1) && !preimage1.test(nb1)) {\n                        auto [x,y,z] = decode(nb1);\n                        int nx = rots[r][0][0]*x + rots[r][0][1]*y + rots[r][0][2]*z + dx;\n                        int ny = rots[r][1][0]*x + rots[r][1][1]*y + rots[r][1][2]*z + dy;\n                        int nz = rots[r][2][0]*x + rots[r][2][1]*y + rots[r][2][2]*z + dz;\n                        if (nx>=0 && nx<D && ny>=0 && ny<D && nz>=0 && nz<D) {\n                            int nb2 = encode(nx,ny,nz);\n                            if (available2.test(nb2) && !comp2.test(nb2)) {\n                                preimage1.set(nb1);\n                                comp2.set(nb2);\n                                available1.reset(nb1);\n                                available2.reset(nb2);\n                                q1.push(nb1);\n                                q2.push(nb2);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        int bid = block_id++;\n        best_preimage1.forEachSetBit([&](int idx) {\n            b1[idx] = bid;\n            available1.reset(idx);\n        });\n        best_comp2.forEachSetBit([&](int idx) {\n            b2[idx] = bid;\n            available2.reset(idx);\n        });\n    }\n\n    int n = block_id - 1;\n    return {b1, b2, n};\n}\n\ndouble evaluate(const vector<int>& b1, const vector<int>& b2, int n) {\n    vector<int> used1(n+1, 0), used2(n+1, 0);\n    vector<int> vol(n+1, 0);\n    for (int i=0; i<D3; i++) {\n        if (b1[i]) { used1[b1[i]] = 1; vol[b1[i]]++; }\n        if (b2[i]) { used2[b2[i]] = 1; }\n    }\n    double r1 = 0, r2 = 0, sum_inv = 0;\n    for (int i=1; i<=n; i++) {\n        if (!used1[i]) r1 += vol[i];\n        if (!used2[i]) r2 += vol[i];\n        if (used1[i] && used2[i]) sum_inv += 1.0 / vol[i];\n    }\n    return r1 + r2 + sum_inv;\n}\n\nint main() {\n    auto start_time = steady_clock::now();\n    auto get_ms = [&]() {\n        return duration_cast<milliseconds>(steady_clock::now() - start_time).count();\n    };\n\n    generate_rotations();\n\n    cin >> D;\n    D2 = D*D;\n    D3 = D*D*D;\n\n    vector<string> f1(D), r1(D), f2(D), r2(D);\n    for (int i=0; i<D; i++) cin >> f1[i];\n    for (int i=0; i<D; i++) cin >> r1[i];\n    for (int i=0; i<D; i++) cin >> f2[i];\n    for (int i=0; i<D; i++) cin >> r2[i];\n\n    adj.resize(D3);\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        int idx = encode(x,y,z);\n        if (x>0)   adj[idx].push_back(encode(x-1, y, z));\n        if (x<D-1) adj[idx].push_back(encode(x+1, y, z));\n        if (y>0)   adj[idx].push_back(encode(x, y-1, z));\n        if (y<D-1) adj[idx].push_back(encode(x, y+1, z));\n        if (z>0)   adj[idx].push_back(encode(x, y, z-1));\n        if (z<D-1) adj[idx].push_back(encode(x, y, z+1));\n    }\n\n    FastBitset A1, A2;\n    for (int x=0; x<D; x++) for (int y=0; y<D; y++) for (int z=0; z<D; z++) {\n        if (f1[z][x]=='1' && r1[z][y]=='1') A1.set(encode(x,y,z));\n        if (f2[z][x]=='1' && r2[z][y]=='1') A2.set(encode(x,y,z));\n    }\n\n    vector init_unc1_f(D, vector<bool>(D, false));\n    vector init_unc1_r(D, vector<bool>(D, false));\n    vector init_unc2_f(D, vector<bool>(D, false));\n    vector init_unc2_r(D, vector<bool>(D, false));\n\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f1[z][x]=='1') init_unc1_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r1[z][y]=='1') init_unc1_r[z][y] = true;\n    for (int z=0; z<D; z++) for (int x=0; x<D; x++) if (f2[z][x]=='1') init_unc2_f[z][x] = true;\n    for (int z=0; z<D; z++) for (int y=0; y<D; y++) if (r2[z][y]=='1') init_unc2_r[z][y] = true;\n\n    random_device rd;\n    vector<int> seeds = {0, 42, 12345, 99999, 77777};\n    vector<int> weights = {200, 100, 50, 10, 150};\n    \n    double best_eval = 1e18;\n    vector<int> best_b1, best_b2;\n    int best_n = 0;\n\n    int trials = 4;\n    int time_per_trial = 1400;\n\n    for (int t = 0; t < trials && get_ms() < 5500; t++) {\n        mt19937 rng(seeds[t] + rd());\n        auto [b1, b2, n] = solve(rng, f1, r1, f2, r2, A1, A2,\n                                  init_unc1_f, init_unc1_r, init_unc2_f, init_unc2_r,\n                                  start_time, time_per_trial, weights[t]);\n        double eval = evaluate(b1, b2, n);\n        if (eval < best_eval) {\n            best_eval = eval;\n            best_b1 = b1;\n            best_b2 = b2;\n            best_n = n;\n        }\n    }\n\n    cout << best_n << \"\\n\";\n    for (int i=0; i<D3; i++) cout << best_b1[i] << \" \\n\"[i==D3-1];\n    for (int i=0; i<D3; i++) cout << best_b2[i] << \" \\n\"[i==D3-1];\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\n#define rep(i, a, b) for (int i = (a); i < (b); i++)\n#define all(x) begin(x), end(x)\n\nusing ll = long long;\nconst ll INF = 1e18;\nconst ll MAX_DIST_SQ = 5000LL * 5000LL;\n\nstruct Edge {\n    int u, v;\n    ll w;\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    vector<pair<int, int>> pos(N);\n    rep(i, 0, N) cin >> pos[i].first >> pos[i].second;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, ll>>> adj(N);\n    rep(j, 0, M) {\n        int u, v; ll w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n\n    vector<pair<int, int>> residents(K);\n    rep(k, 0, K) cin >> residents[k].first >> residents[k].second;\n\n    // All-pairs shortest paths\n    vector<vector<ll>> dist(N, vector<ll>(N, INF));\n    vector<vector<int>> parent(N, vector<int>(N, -1));\n    \n    rep(s, 0, N) {\n        dist[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[s][u]) continue;\n            for (auto [v, w] : adj[u]) {\n                if (dist[s][v] > d + w) {\n                    dist[s][v] = d + w;\n                    parent[s][v] = u;\n                    pq.push({dist[s][v], v});\n                }\n            }\n        }\n    }\n\n    // Precompute squared distances\n    vector<vector<ll>> stationToRes(N, vector<ll>(K));\n    rep(i, 0, N) rep(k, 0, K) {\n        ll dx = pos[i].first - residents[k].first;\n        ll dy = pos[i].second - residents[k].second;\n        stationToRes[i][k] = dx * dx + dy * dy;\n    }\n\n    // Coverable stations for each resident\n    vector<vector<int>> coverableStations(K);\n    rep(k, 0, K) rep(i, 0, N) {\n        if (stationToRes[i][k] <= MAX_DIST_SQ) {\n            coverableStations[k].push_back(i);\n        }\n    }\n\n    // Nearest station for each resident\n    vector<int> nearestStation(K, 0);\n    rep(k, 0, K) {\n        ll best = stationToRes[0][k];\n        nearestStation[k] = 0;\n        rep(i, 1, N) {\n            if (stationToRes[i][k] < best) {\n                best = stationToRes[i][k];\n                nearestStation[k] = i;\n            }\n        }\n    }\n\n    // Compute P_i\n    auto computeP = [&](const vector<bool>& active, const vector<int>& assign) {\n        vector<int> P(N, 0);\n        rep(i, 0, N) {\n            if (!active[i]) continue;\n            ll maxDistSq = 0;\n            rep(k, 0, K) if (assign[k] == i) {\n                maxDistSq = max(maxDistSq, stationToRes[i][k]);\n            }\n            ll Pi = (ll)ceil(sqrt(maxDistSq));\n            if (Pi > 5000) Pi = 5000;\n            P[i] = (int)Pi;\n        }\n        return P;\n    };\n\n    // Fast edge cost: connect active stations to vertex 1 via shortest paths\n    auto computeEdgeCost = [&](const vector<bool>& active) {\n        vector<bool> used(N, false);\n        used[0] = true;\n        ll cost = 0;\n        \n        vector<pair<ll, int>> actDist;\n        rep(i, 0, N) if (active[i]) actDist.push_back({dist[0][i], i});\n        sort(all(actDist));\n        \n        for (auto [d, v] : actDist) {\n            if (used[v]) continue;\n            int cur = v;\n            while (!used[cur]) {\n                used[cur] = true;\n                int p = parent[0][cur];\n                if (p == -1) break;\n                for (auto [nxt, w] : adj[cur]) {\n                    if (nxt == p) { cost += w; break; }\n                }\n                cur = p;\n            }\n        }\n        return cost;\n    };\n\n    auto totalCost = [&](const vector<bool>& active, const vector<int>& assign) {\n        auto P = computeP(active, assign);\n        ll powerCost = 0;\n        rep(i, 0, N) powerCost += (ll)P[i] * P[i];\n        return powerCost + computeEdgeCost(active);\n    };\n\n    // Build initial solution\n    vector<bool> active(N, false);\n    active[0] = true;\n    rep(k, 0, K) active[nearestStation[k]] = true;\n\n    vector<int> assign(K);\n    rep(k, 0, K) assign[k] = nearestStation[k];\n\n    ll currentCost = totalCost(active, assign);\n    auto bestActive = active;\n    auto bestAssign = assign;\n    ll bestCost = currentCost;\n\n    // Greedy descent: remove stations\n    auto tryRemoveStations = [&]() {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            vector<int> actList;\n            rep(i, 1, N) if (active[i]) actList.push_back(i);\n            \n            for (int i : actList) {\n                if (!active[i]) continue;\n                auto savedActive = active;\n                auto savedAssign = assign;\n                \n                active[i] = false;\n                bool possible = true;\n                rep(k, 0, K) {\n                    if (assign[k] == i) {\n                        ll bestDist = INF;\n                        int bestSt = -1;\n                        for (int j : coverableStations[k]) {\n                            if (active[j] && stationToRes[j][k] < bestDist) {\n                                bestDist = stationToRes[j][k];\n                                bestSt = j;\n                            }\n                        }\n                        if (bestSt == -1) { possible = false; break; }\n                        assign[k] = bestSt;\n                    }\n                }\n                \n                if (possible) {\n                    ll newCost = totalCost(active, assign);\n                    if (newCost < currentCost) {\n                        currentCost = newCost;\n                        improved = true;\n                    } else {\n                        active = savedActive;\n                        assign = savedAssign;\n                    }\n                } else {\n                    active = savedActive;\n                    assign = savedAssign;\n                }\n            }\n        }\n    };\n\n    // Greedy descent: merge stations\n    auto tryMergeStations = [&]() {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            vector<int> actList;\n            rep(i, 1, N) if (active[i]) actList.push_back(i);\n            if (actList.size() < 2) break;\n            \n            for (int idx1 = 0; idx1 < (int)actList.size() && !improved; idx1++) {\n                int i = actList[idx1];\n                if (!active[i]) continue;\n                for (int idx2 = idx1 + 1; idx2 < (int)actList.size() && !improved; idx2++) {\n                    int j = actList[idx2];\n                    if (!active[j]) continue;\n                    \n                    // Try i covers j\n                    {\n                        auto savedActive = active;\n                        auto savedAssign = assign;\n                        active[j] = false;\n                        bool possible = true;\n                        rep(k, 0, K) {\n                            if (assign[k] == j) {\n                                if (stationToRes[i][k] > MAX_DIST_SQ) { possible = false; break; }\n                                assign[k] = i;\n                            }\n                        }\n                        if (possible) {\n                            ll newCost = totalCost(active, assign);\n                            if (newCost < currentCost) {\n                                currentCost = newCost;\n                                improved = true;\n                                break;\n                            }\n                        }\n                        active = savedActive;\n                        assign = savedAssign;\n                    }\n                    \n                    // Try j covers i\n                    {\n                        auto savedActive = active;\n                        auto savedAssign = assign;\n                        active[i] = false;\n                        bool possible = true;\n                        rep(k, 0, K) {\n                            if (assign[k] == i) {\n                                if (stationToRes[j][k] > MAX_DIST_SQ) { possible = false; break; }\n                                assign[k] = j;\n                            }\n                        }\n                        if (possible) {\n                            ll newCost = totalCost(active, assign);\n                            if (newCost < currentCost) {\n                                currentCost = newCost;\n                                improved = true;\n                            }\n                        }\n                        if (!improved) {\n                            active = savedActive;\n                            assign = savedAssign;\n                        }\n                    }\n                }\n            }\n        }\n    };\n\n    // Greedy descent: fine-tune assignments\n    auto fineTuneAssignments = [&]() {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            rep(k, 0, K) {\n                int cur = assign[k];\n                ll curDist = stationToRes[cur][k];\n                \n                rep(i, 0, N) {\n                    if (active[i] && i != cur && stationToRes[i][k] < curDist) {\n                        auto savedAssign = assign;\n                        assign[k] = i;\n                        ll newCost = totalCost(active, assign);\n                        if (newCost < currentCost) {\n                            currentCost = newCost;\n                            improved = true;\n                            break;\n                        }\n                        assign = savedAssign;\n                    }\n                }\n                if (improved) break;\n            }\n        }\n    };\n\n    // Initial greedy optimization\n    tryRemoveStations();\n    tryMergeStations();\n    fineTuneAssignments();\n    bestActive = active;\n    bestAssign = assign;\n    bestCost = currentCost;\n\n    // Simulated annealing with controlled iterations\n    mt19937 rng(42);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n    \n    const int SA_ITERS = 8000;\n    \n    for (int iter = 0; iter < SA_ITERS; iter++) {\n        double progress = (double)iter / SA_ITERS;\n        double T = 1e6 * pow(1e-6, progress);\n        \n        int action = rng() % 4;\n        \n        if (action == 0) {\n            // Remove station\n            vector<int> candidates;\n            rep(i, 1, N) if (active[i]) candidates.push_back(i);\n            if (candidates.empty()) continue;\n            \n            int i = candidates[rng() % candidates.size()];\n            auto savedActive = active;\n            auto savedAssign = assign;\n            \n            active[i] = false;\n            bool possible = true;\n            rep(k, 0, K) {\n                if (assign[k] == i) {\n                    ll bestDist = INF;\n                    int bestSt = -1;\n                    for (int j : coverableStations[k]) {\n                        if (active[j] && stationToRes[j][k] < bestDist) {\n                            bestDist = stationToRes[j][k];\n                            bestSt = j;\n                        }\n                    }\n                    if (bestSt == -1) { possible = false; break; }\n                    assign[k] = bestSt;\n                }\n            }\n            \n            if (possible) {\n                ll newCost = totalCost(active, assign);\n                ll delta = newCost - currentCost;\n                if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                    currentCost = newCost;\n                    if (newCost < bestCost) {\n                        bestCost = newCost;\n                        bestActive = active;\n                        bestAssign = assign;\n                    }\n                } else {\n                    active = savedActive;\n                    assign = savedAssign;\n                }\n            } else {\n                active = savedActive;\n                assign = savedAssign;\n            }\n        } else if (action == 1) {\n            // Add station\n            vector<int> candidates;\n            rep(i, 1, N) if (!active[i]) candidates.push_back(i);\n            if (candidates.empty()) continue;\n            \n            int i = candidates[rng() % candidates.size()];\n            auto savedActive = active;\n            auto savedAssign = assign;\n            \n            active[i] = true;\n            rep(k, 0, K) {\n                if (stationToRes[i][k] < stationToRes[assign[k]][k]) {\n                    assign[k] = i;\n                }\n            }\n            \n            ll newCost = totalCost(active, assign);\n            ll delta = newCost - currentCost;\n            if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                currentCost = newCost;\n                if (newCost < bestCost) {\n                    bestCost = newCost;\n                    bestActive = active;\n                    bestAssign = assign;\n                }\n            } else {\n                active = savedActive;\n                assign = savedAssign;\n            }\n        } else if (action == 2) {\n            // Reassign resident\n            int k = rng() % K;\n            int cur = assign[k];\n            \n            vector<int> candidates;\n            rep(i, 0, N) {\n                if (active[i] && i != cur && stationToRes[i][k] <= MAX_DIST_SQ) {\n                    candidates.push_back(i);\n                }\n            }\n            if (candidates.empty()) continue;\n            \n            int i = candidates[rng() % candidates.size()];\n            auto savedAssign = assign;\n            assign[k] = i;\n            \n            ll newCost = totalCost(active, assign);\n            ll delta = newCost - currentCost;\n            if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                currentCost = newCost;\n                if (newCost < bestCost) {\n                    bestCost = newCost;\n                    bestActive = active;\n                    bestAssign = assign;\n                }\n            } else {\n                assign = savedAssign;\n            }\n        } else {\n            // Swap assignments of two residents\n            int k1 = rng() % K;\n            int k2 = rng() % K;\n            if (k1 == k2) continue;\n            \n            int a1 = assign[k1];\n            int a2 = assign[k2];\n            if (a1 == a2) continue;\n            if (stationToRes[a2][k1] > MAX_DIST_SQ || stationToRes[a1][k2] > MAX_DIST_SQ) continue;\n            \n            auto savedAssign = assign;\n            assign[k1] = a2;\n            assign[k2] = a1;\n            \n            ll newCost = totalCost(active, assign);\n            ll delta = newCost - currentCost;\n            if (delta < 0 || prob(rng) < exp(-delta / T)) {\n                currentCost = newCost;\n                if (newCost < bestCost) {\n                    bestCost = newCost;\n                    bestActive = active;\n                    bestAssign = assign;\n                }\n            } else {\n                assign = savedAssign;\n            }\n        }\n    }\n\n    // Final polish on best\n    active = bestActive;\n    assign = bestAssign;\n    currentCost = bestCost;\n    tryRemoveStations();\n    tryMergeStations();\n    fineTuneAssignments();\n    \n    if (currentCost < bestCost) {\n        bestActive = active;\n        bestAssign = assign;\n        bestCost = currentCost;\n    }\n\n    // Final P\n    auto P = computeP(bestActive, bestAssign);\n\n    // Build edge set\n    vector<bool> used(N, false);\n    used[0] = true;\n    vector<int> onEdge(M, 0);\n    \n    vector<pair<ll, int>> actDist;\n    rep(i, 0, N) if (bestActive[i]) actDist.push_back({dist[0][i], i});\n    sort(all(actDist));\n    \n    for (auto [d, v] : actDist) {\n        if (used[v]) continue;\n        int cur = v;\n        while (!used[cur]) {\n            used[cur] = true;\n            int p = parent[0][cur];\n            if (p == -1) break;\n            for (int j = 0; j < M; j++) {\n                if ((edges[j].u == cur && edges[j].v == p) ||\n                    (edges[j].u == p && edges[j].v == cur)) {\n                    onEdge[j] = 1;\n                    break;\n                }\n            }\n            cur = p;\n        }\n    }\n\n    // Verify and fix connectivity\n    vector<bool> reachable(N, false);\n    reachable[0] = true;\n    function<void(int)> dfs = [&](int u) {\n        reachable[u] = true;\n        for (int j = 0; j < M; j++) {\n            if (onEdge[j]) {\n                int v = -1;\n                if (edges[j].u == u) v = edges[j].v;\n                else if (edges[j].v == u) v = edges[j].u;\n                if (v != -1 && !reachable[v]) dfs(v);\n            }\n        }\n    };\n    dfs(0);\n    \n    rep(i, 0, N) {\n        if (bestActive[i] && !reachable[i]) {\n            int cur = i;\n            while (!reachable[cur]) {\n                reachable[cur] = true;\n                int p = parent[0][cur];\n                if (p == -1) break;\n                for (int j = 0; j < M; j++) {\n                    if ((edges[j].u == cur && edges[j].v == p) ||\n                        (edges[j].u == p && edges[j].v == cur)) {\n                        onEdge[j] = 1;\n                        break;\n                    }\n                }\n                cur = p;\n            }\n        }\n    }\n\n    // Output\n    rep(i, 0, N) cout << P[i] << (i + 1 < N ? ' ' : '\\n');\n    rep(j, 0, M) cout << onEdge[j] << (j + 1 < M ? ' ' : '\\n');\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL = N * (N + 1) / 2;\n\nint initial_board[N][N];\npair<int,int> initial_pos[TOTAL];\n\nbool valid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nint target_layer(int val) {\n    int L = 0;\n    while ((L+1)*(L+2)/2 <= val) L++;\n    return L;\n}\n\nstruct State {\n    int board[N][N];\n    pair<int,int> pos[TOTAL];\n    vector<array<int,4>> moves;\n    \n    void do_swap(int x1, int y1, int x2, int y2) {\n        if (moves.size() >= 10000) return;\n        moves.push_back({x1, y1, x2, y2});\n        swap(board[x1][y1], board[x2][y2]);\n        pos[board[x1][y1]] = {x1, y1};\n        pos[board[x2][y2]] = {x2, y2};\n    }\n    \n    int count_violations() const {\n        int cnt = 0;\n        for (int x = 0; x < N-1; x++) {\n            for (int y = 0; y <= x; y++) {\n                int p = board[x][y];\n                if (board[x+1][y] < p) cnt++;\n                if (board[x+1][y+1] < p) cnt++;\n            }\n        }\n        return cnt;\n    }\n};\n\nvector<array<int,4>> run_algorithm(int seed) {\n    State S;\n    memcpy(S.board, initial_board, sizeof(initial_board));\n    memcpy(S.pos, initial_pos, sizeof(initial_pos));\n    \n    // Create ordering for Phase 1 based on seed\n    vector<int> vals(TOTAL);\n    iota(vals.begin(), vals.end(), 0);\n    \n    // Different sorting strategies based on seed\n    if (seed % 3 == 0) {\n        // By depth discrepancy (original)\n        sort(vals.begin(), vals.end(), [&](int a, int b) {\n            int da = target_layer(a) - S.pos[a].first;\n            int db = target_layer(b) - S.pos[b].first;\n            if (da != db) return da < db;\n            return a < b;\n        });\n    } else if (seed % 3 == 1) {\n        // By value (smallest first)\n        sort(vals.begin(), vals.end());\n    } else {\n        // By current layer (deepest first)\n        sort(vals.begin(), vals.end(), [&](int a, int b) {\n            return S.pos[a].first > S.pos[b].first;\n        });\n    }\n    \n    // Phase 1: Bubble up\n    for (int v : vals) {\n        if (S.moves.size() >= 9900) break;\n        int tl = target_layer(v);\n        int cx = S.pos[v].first, cy = S.pos[v].second;\n        \n        while (cx > tl && S.moves.size() < 9900) {\n            int best_px = -1, best_py = -1;\n            int best_val = -1;\n            \n            if (valid(cx-1, cy-1) && S.board[cx-1][cy-1] > v) {\n                best_px = cx-1; best_py = cy-1;\n                best_val = S.board[cx-1][cy-1];\n            }\n            if (valid(cx-1, cy) && S.board[cx-1][cy] > v) {\n                if (best_px == -1 || S.board[cx-1][cy] > best_val) {\n                    best_px = cx-1; best_py = cy;\n                    best_val = S.board[cx-1][cy];\n                }\n            }\n            \n            if (best_px == -1) break;\n            S.do_swap(cx, cy, best_px, best_py);\n            cx = best_px; cy = best_py;\n        }\n    }\n    \n    // Phase 2: Bottom-up heapify\n    for (int x = N-2; x >= 0 && S.moves.size() < 10000; x--) {\n        for (int y = 0; y <= x && S.moves.size() < 10000; y++) {\n            int cur_x = x, cur_y = y;\n            while (cur_x < N-1 && S.moves.size() < 10000) {\n                int left = S.board[cur_x+1][cur_y];\n                int right = S.board[cur_x+1][cur_y+1];\n                int parent = S.board[cur_x][cur_y];\n                \n                if (left < parent && left <= right) {\n                    S.do_swap(cur_x, cur_y, cur_x+1, cur_y);\n                    cur_x++;\n                } else if (right < parent) {\n                    S.do_swap(cur_x, cur_y, cur_x+1, cur_y+1);\n                    cur_x++;\n                    cur_y++;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Quick verification and fix\n    for (int x = 0; x < N-1 && S.moves.size() < 10000; x++) {\n        for (int y = 0; y <= x && S.moves.size() < 10000; y++) {\n            if (S.board[x+1][y] < S.board[x][y]) {\n                S.do_swap(x, y, x+1, y);\n            }\n            if (S.board[x+1][y+1] < S.board[x][y]) {\n                S.do_swap(x, y, x+1, y+1);\n            }\n        }\n    }\n    \n    if (S.moves.size() > 10000) S.moves.resize(10000);\n    return S.moves;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    for (int i = 0; i < N; i++)\n        for (int j = 0; j <= i; j++) {\n            cin >> initial_board[i][j];\n            initial_pos[initial_board[i][j]] = {i, j};\n        }\n\n    // Run algorithm with different seeds and pick the best result\n    vector<array<int,4>> best_moves;\n    size_t best_size = 10001;\n    \n    for (int seed = 0; seed < 5; seed++) {\n        auto moves = run_algorithm(seed);\n        if (moves.size() < best_size) {\n            best_size = moves.size();\n            best_moves = move(moves);\n        }\n    }\n    \n    cout << best_moves.size() << '\\n';\n    for (auto &[x1, y1, x2, y2] : best_moves)\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n\n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <queue>\n#include <vector>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D, N;\n    cin >> D >> N;\n    const int ER = 0, EC = 4;\n    \n    vector<vector<bool>> obs(D, vector<bool>(D, false));\n    vector<vector<bool>> occ(D, vector<bool>(D, false));\n    \n    for (int i = 0; i < N; i++) {\n        int ri, rj; cin >> ri >> rj;\n        obs[ri][rj] = true;\n    }\n    \n    int total = D*D - 1 - N;\n    vector<pair<int,int>> id_to_pos(total);\n    \n    int dr[4] = {1, -1, 0, 0};\n    int dc[4] = {0, 0, 1, -1};\n    \n    auto bfs = [&]() {\n        vector<vector<int>> dist(D, vector<int>(D, -1));\n        queue<pair<int,int>> q;\n        q.push({ER, EC}); dist[ER][EC] = 0;\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 &&\n                    dist[nr][nc] == -1 && !obs[nr][nc] && !occ[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + 1;\n                    q.push({nr, nc});\n                }\n            }\n        }\n        return dist;\n    };\n    \n    auto is_reachable = [&](int r, int c, const vector<vector<int>>& dist) {\n        if (r == ER && c == EC) return true;\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 && dist[nr][nc] != -1)\n                return true;\n        }\n        return false;\n    };\n    \n    // Placement: always farthest reachable (proven safe)\n    for (int turn = 0; turn < total; turn++) {\n        int tid; cin >> tid;\n        \n        auto dist = bfs();\n        \n        int br = -1, bc = -1, bd = -1;\n        for (int r = 0; r < D; r++)\n            for (int c = 0; c < D; c++)\n                if (!(r == ER && c == EC) && !obs[r][c] && !occ[r][c] && dist[r][c] > bd)\n                    bd = dist[r][c], br = r, bc = c;\n        \n        if (br == -1) {\n            for (int r = 0; r < D && br == -1; r++)\n                for (int c = 0; c < D && br == -1; c++)\n                    if (!(r == ER && c == EC) && !obs[r][c] && !occ[r][c])\n                        br = r, bc = c;\n        }\n        \n        occ[br][bc] = true;\n        id_to_pos[tid] = {br, bc};\n        cout << br << \" \" << bc << \"\\n\" << flush;\n    }\n    \n    // Removal: always pick reachable container with smallest ID\n    vector<bool> removed(total, false);\n    for (int step = 0; step < total; step++) {\n        auto dist = bfs();\n        \n        int chosen = -1;\n        for (int id = 0; id < total; id++) {\n            if (!removed[id]) {\n                auto [r, c] = id_to_pos[id];\n                if (is_reachable(r, c, dist)) {\n                    chosen = id;\n                    break;\n                }\n            }\n        }\n        \n        if (chosen == -1) {\n            for (int id = 0; id < total; id++) {\n                if (!removed[id]) {\n                    auto [r, c] = id_to_pos[id];\n                    if (is_reachable(r, c, dist)) { chosen = id; break; }\n                }\n            }\n        }\n        if (chosen == -1) {\n            for (int id = 0; id < total; id++)\n                if (!removed[id]) { chosen = id; break; }\n        }\n        \n        removed[chosen] = true;\n        occ[id_to_pos[chosen].first][id_to_pos[chosen].second] = false;\n        cout << id_to_pos[chosen].first << \" \" << id_to_pos[chosen].second << \"\\n\";\n    }\n    cout << flush;\n    \n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nint input[N][N];\nbool adj[M+1][M+1];\nbool needs_zero[M+1];\nint dx[4] = {-1, 0, 1, 0};\nint dy[4] = {0, 1, 0, -1};\n\nint output[N][N];\nbool is_zero[N][N];\n\n// For each color, track which colors it touches (for fast adjacency checking)\nvector<int> color_neighbors[M+1];\n\n// Check if eroding cell (r,c) would disconnect its color\n// Optimization: only need to check if (r,c) is an articulation point\nbool would_disconnect(int color, int r, int c) {\n    // Find all cells of this color\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (output[i][j] == color && !(i == r && j == c))\n                cells.push_back({i, j});\n    \n    if (cells.empty()) return true; // Last cell, would disconnect\n    if (cells.size() == 1) return false; // Only one cell left, trivially connected\n    \n    // BFS from first cell\n    set<pair<int,int>> cell_set(cells.begin(), cells.end());\n    set<pair<int,int>> visited;\n    queue<pair<int,int>> q;\n    q.push(cells[0]);\n    visited.insert(cells[0]);\n    \n    while (!q.empty()) {\n        auto [cr, cc] = q.front(); q.pop();\n        for (int k = 0; k < 4; k++) {\n            int nr = cr + dx[k], nc = cc + dy[k];\n            if (nr >= 0 && nr < n && nc >= 0 && nc < n && output[nr][nc] == color && \n                !(nr == r && nc == c) && !visited.count({nr, nc})) {\n                visited.insert({nr, nc});\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return visited.size() != cells.size();\n}\n\n// Check if removing (r,c) of 'color' would destroy adjacency with some color d\nbool would_destroy_adjacency(int color, int r, int c) {\n    for (int d : color_neighbors[color]) {\n        if (d == 0 || d == color) continue;\n        if (!adj[color][d]) continue;\n        \n        // Check if this cell is the ONLY connection between color and d\n        // First, check if (r,c) is adjacent to d\n        bool this_cell_adj_to_d = false;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dx[k], nc = c + dy[k];\n            if (nr >= 0 && nr < n && nc >= 0 && nc < n && output[nr][nc] == d) {\n                this_cell_adj_to_d = true;\n                break;\n            }\n        }\n        if (!this_cell_adj_to_d) continue; // This cell isn't involved in this adjacency\n        \n        // Check if there's another adjacent pair\n        bool found_other = false;\n        for (int i = 0; i < n && !found_other; i++) {\n            for (int j = 0; j < n && !found_other; j++) {\n                if (i == r && j == c) continue;\n                if (output[i][j] != color) continue;\n                for (int k = 0; k < 4; k++) {\n                    int ni = i + dx[k], nj = j + dy[k];\n                    if (ni >= 0 && ni < n && nj >= 0 && nj < n && output[ni][nj] == d) {\n                        found_other = true;\n                        break;\n                    }\n                }\n            }\n        }\n        if (!found_other) return true;\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> input[i][j];\n    \n    // Build adjacency and determine boundary colors\n    memset(adj, 0, sizeof(adj));\n    memset(needs_zero, 0, sizeof(needs_zero));\n    \n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = input[i][j];\n            if (i == 0 || i == n-1 || j == 0 || j == n-1)\n                needs_zero[c] = true;\n            for (int d = 0; d < 4; d++) {\n                int ni = i + dx[d], nj = j + dy[d];\n                int nc = 0;\n                if (ni >= 0 && ni < n && nj >= 0 && nj < n)\n                    nc = input[ni][nj];\n                if (c != nc)\n                    adj[c][nc] = adj[nc][c] = true;\n            }\n        }\n    }\n    \n    // Build color_neighbors from original map\n    for (int c = 1; c <= m; c++) {\n        for (int d = 1; d <= m; d++) {\n            if (adj[c][d] && c != d)\n                color_neighbors[c].push_back(d);\n        }\n    }\n    \n    memcpy(output, input, sizeof(input));\n    memset(is_zero, 0, sizeof(is_zero));\n    \n    // Multi-pass erosion\n    for (int pass = 0; pass < 5; pass++) {\n        queue<pair<int,int>> q;\n        bool in_queue[N][N] = {false};\n        \n        // Initialize queue with boundary cells of colors needing zero\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (is_zero[i][j]) continue;\n                // Check if adjacent to a zero cell or boundary\n                bool near_zero = false;\n                for (int k = 0; k < 4; k++) {\n                    int ni = i + dx[k], nj = j + dy[k];\n                    if (ni < 0 || ni >= n || nj < 0 || nj >= n || is_zero[ni][nj]) {\n                        near_zero = true;\n                        break;\n                    }\n                }\n                if (near_zero && needs_zero[output[i][j]]) {\n                    q.push({i, j});\n                    in_queue[i][j] = true;\n                }\n            }\n        }\n        \n        int eroded_this_pass = 0;\n        \n        while (!q.empty()) {\n            auto [r, c] = q.front(); q.pop();\n            in_queue[r][c] = false;\n            int color = output[r][c];\n            \n            if (is_zero[r][c]) continue;\n            if (!needs_zero[color]) continue;\n            \n            // Check if color has another cell touching zero\n            bool has_other_zero = false;\n            for (int i = 0; i < n && !has_other_zero; i++) {\n                for (int j = 0; j < n && !has_other_zero; j++) {\n                    if (i == r && j == c) continue;\n                    if (output[i][j] != color) continue;\n                    for (int k = 0; k < 4; k++) {\n                        int ni = i + dx[k], nj = j + dy[k];\n                        if (ni < 0 || ni >= n || nj < 0 || nj >= n || (is_zero[ni][nj] && !(ni == r && nj == c))) {\n                            has_other_zero = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (!has_other_zero) continue;\n            \n            // Check exposure of non-boundary colors\n            bool safe_exposure = true;\n            for (int k = 0; k < 4 && safe_exposure; k++) {\n                int ni = r + dx[k], nj = c + dy[k];\n                if (ni >= 0 && ni < n && nj >= 0 && nj < n && !is_zero[ni][nj] && output[ni][nj] != color) {\n                    int neighbor = output[ni][nj];\n                    if (!needs_zero[neighbor]) {\n                        bool already_touches = false;\n                        for (int k2 = 0; k2 < 4; k2++) {\n                            int nni = ni + dx[k2], nnj = nj + dy[k2];\n                            if (nni < 0 || nni >= n || nnj < 0 || nnj >= n || (is_zero[nni][nnj] && !(nni == r && nnj == c))) {\n                                already_touches = true;\n                                break;\n                            }\n                        }\n                        if (!already_touches) {\n                            safe_exposure = false;\n                        }\n                    }\n                }\n            }\n            if (!safe_exposure) continue;\n            \n            // Check adjacency preservation\n            if (would_destroy_adjacency(color, r, c)) continue;\n            \n            // Check connectivity\n            if (would_disconnect(color, r, c)) continue;\n            \n            // All checks passed, erode\n            output[r][c] = 0;\n            is_zero[r][c] = true;\n            eroded_this_pass++;\n            \n            // Add neighbors\n            for (int k = 0; k < 4; k++) {\n                int ni = r + dx[k], nc = c + dy[k];\n                if (ni >= 0 && ni < n && nc >= 0 && nc < n && !is_zero[ni][nc] && !in_queue[ni][nc]) {\n                    in_queue[ni][nc] = true;\n                    q.push({ni, nc});\n                }\n            }\n        }\n        \n        if (eroded_this_pass == 0) break; // No more progress\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << output[i][j] << (j == N-1 ? '\\n' : ' ');\n        }\n    }\n    \n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, D, Q;\nint query_count = 0;\nvector<double> harmonic;\n\nchar compare_sets(const vector<int>& L, const vector<int>& R) {\n    query_count++;\n    cout << L.size() << \" \" << R.size();\n    for (int x : L) cout << \" \" << x;\n    for (int x : R) cout << \" \" << x;\n    cout << endl;\n    char res;\n    cin >> res;\n    return res;\n}\n\nchar compare_items(int a, int b) {\n    return compare_sets({a}, {b});\n}\n\nvector<int> merge_sort(const vector<int>& arr, int l, int r) {\n    if (l == r) return {arr[l]};\n    int m = (l + r) / 2;\n    auto left = merge_sort(arr, l, m);\n    auto right = merge_sort(arr, m + 1, r);\n    vector<int> res;\n    int i = 0, j = 0;\n    while (i < (int)left.size() && j < (int)right.size()) {\n        if (query_count >= Q) {\n            while (i < (int)left.size() && j < (int)right.size()) {\n                res.push_back(left[i++]);\n                if (j < (int)right.size()) res.push_back(right[j++]);\n            }\n            while (i < (int)left.size()) res.push_back(left[i++]);\n            while (j < (int)right.size()) res.push_back(right[j++]);\n            return res;\n        }\n        char cmp = compare_items(left[i], right[j]);\n        if (cmp == '>') {\n            res.push_back(left[i++]);\n        } else if (cmp == '<') {\n            res.push_back(right[j++]);\n        } else {\n            res.push_back(left[i++]);\n            res.push_back(right[j++]);\n        }\n    }\n    while (i < (int)left.size()) res.push_back(left[i++]);\n    while (j < (int)right.size()) res.push_back(right[j++]);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> D >> Q;\n    \n    harmonic.resize(N + 1, 0.0);\n    for (int i = 1; i <= N; i++) {\n        harmonic[i] = harmonic[i - 1] + 1.0 / i;\n    }\n    \n    query_count = 0;\n    vector<int> items(N);\n    iota(items.begin(), items.end(), 0);\n\n    // Phase 1: Sort items (heaviest first)\n    vector<int> sorted = merge_sort(items, 0, N - 1);\n\n    // Phase 2: Estimate weights\n    double scale = 100000.0;\n    vector<double> est_weight(N);\n    vector<int> pos_of(N);\n    for (int i = 0; i < N; i++) {\n        pos_of[sorted[i]] = i;\n    }\n    for (int idx = 0; idx < N; idx++) {\n        int k = N - idx;\n        double expected = scale * (harmonic[N] - harmonic[N - k]);\n        est_weight[idx] = max(1.0, expected);\n    }\n\n    // Phase 3: Greedy assignment\n    vector<vector<int>> groups(D);\n    vector<double> group_sum(D, 0.0);\n    \n    for (int idx = 0; idx < N; idx++) {\n        int item = sorted[idx];\n        double w = est_weight[idx];\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (group_sum[g] < group_sum[best]) best = g;\n        }\n        groups[best].push_back(item);\n        group_sum[best] += w;\n    }\n\n    // Phase 4: Refinement\n    mt19937 rng(12345);\n    uniform_int_distribution<int> group_dist(0, D-1);\n    \n    vector<int> group_order(D);\n    iota(group_order.begin(), group_order.end(), 0);\n    \n    int no_progress = 0;\n    int random_tries = 0;\n    while (query_count + 2 <= Q) {\n        sort(group_order.begin(), group_order.end(), [&](int a, int b) {\n            return group_sum[a] < group_sum[b];\n        });\n        \n        int a = group_order[0];\n        int b = group_order.back();\n        \n        if (a == b || no_progress > 50 || random_tries > 0) {\n            if (no_progress > 50) {\n                no_progress = 0;\n                random_tries = 15; // Increased from 10\n            }\n            if (random_tries > 0) {\n                random_tries--;\n                a = group_dist(rng);\n                b = group_dist(rng);\n                if (a == b) continue;\n                if (group_sum[a] < group_sum[b]) swap(a, b);\n            }\n        }\n        \n        if (groups[a].size() <= 1 || groups[b].empty()) {\n            no_progress++;\n            continue;\n        }\n        \n        char cmp = compare_sets(groups[a], groups[b]);\n        \n        if (cmp == '=') {\n            double avg = (group_sum[a] + group_sum[b]) / 2.0;\n            group_sum[a] = avg;\n            group_sum[b] = avg;\n            no_progress = 0;\n            random_tries = 0;\n            continue;\n        }\n        \n        if (cmp == '<') {\n            swap(a, b);\n            double avg = (group_sum[a] + group_sum[b]) / 2.0;\n            group_sum[a] = avg * 1.2; // More aggressive adjustment\n            group_sum[b] = avg * 0.8;\n        }\n        \n        vector<pair<int, double>> candidates;\n        for (int item : groups[a]) {\n            candidates.push_back({item, est_weight[pos_of[item]]});\n        }\n        sort(candidates.begin(), candidates.end(), [](auto& x, auto& y) {\n            return x.second < y.second;\n        });\n        \n        bool moved_any = false;\n        for (auto& [item, w] : candidates) {\n            if (query_count + 2 > Q) break;\n            if (groups[a].size() <= 1) break;\n            \n            auto it = find(groups[a].begin(), groups[a].end(), item);\n            if (it == groups[a].end()) continue;\n            \n            groups[a].erase(it);\n            groups[b].push_back(item);\n            \n            char cmp2 = compare_sets(groups[a], groups[b]);\n            \n            if (cmp2 == '=') {\n                group_sum[a] -= w;\n                group_sum[b] += w;\n                moved_any = true;\n                break;\n            } else if (cmp2 == '<') {\n                groups[b].erase(remove(groups[b].begin(), groups[b].end(), item), groups[b].end());\n                groups[a].push_back(item);\n                if (!moved_any) {\n                    double avg = (group_sum[a] + group_sum[b] + w) / 2.0;\n                    group_sum[a] = avg * 1.1;\n                    group_sum[b] = avg * 0.9;\n                }\n                break;\n            } else {\n                group_sum[a] -= w;\n                group_sum[b] += w;\n                moved_any = true;\n            }\n        }\n        \n        if (moved_any) {\n            no_progress = 0;\n            random_tries = 0;\n        } else {\n            no_progress++;\n        }\n    }\n\n    // Burn remaining queries\n    while (query_count < Q) {\n        int a = uniform_int_distribution<int>(0, N-1)(rng);\n        int b = uniform_int_distribution<int>(0, N-1)(rng);\n        if (a != b) compare_items(a, b);\n        else compare_items(0, 1);\n    }\n\n    // Build final assignment\n    vector<int> assignment(N);\n    for (int g = 0; g < D; g++) {\n        for (int item : groups[g]) {\n            assignment[item] = g;\n        }\n    }\n\n    cout << \"#c\";\n    for (int i = 0; i < N; i++) cout << \" \" << assignment[i];\n    cout << endl;\n\n    for (int i = 0; i < N; i++) {\n        if (i > 0) cout << \" \";\n        cout << assignment[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 200, M = 10;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n    int h = n / m;\n    int stacks[M][N];\n    int sizes[M];\n    for (int i = 0; i < m; ++i) {\n        sizes[i] = h;\n        for (int j = 0; j < h; ++j)\n            cin >> stacks[i][j];\n    }\n\n    vector<pair<int, int>> moves;\n    auto move_op = [&](int v, int dest) {\n        moves.emplace_back(v, dest + 1);\n    };\n    auto carry_out = [&](int v) {\n        moves.emplace_back(v, 0);\n    };\n\n    int stack_of[N + 1], index_of[N + 1];\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < sizes[i]; ++j) {\n            int v = stacks[i][j];\n            stack_of[v] = i;\n            index_of[v] = j;\n        }\n\n    int next_target = 1;\n    while (next_target <= n) {\n        int si = stack_of[next_target];\n        int pos = index_of[next_target];\n        if (pos == sizes[si] - 1) {\n            // carry out\n            carry_out(next_target);\n            sizes[si]--;\n            ++next_target;\n            continue;\n        }\n        // box just above next_target\n        int u = stacks[si][pos + 1];\n        int top_of_moved = stacks[si][sizes[si] - 1];\n        // choose destination\n        int dest = -1;\n        // prefer empty\n        for (int i = 0; i < m; ++i)\n            if (i != si && sizes[i] == 0) {\n                dest = i;\n                break;\n            }\n        if (dest == -1) {\n            // find stack with max top that is < top_of_moved\n            int best = -1;\n            for (int i = 0; i < m; ++i) {\n                if (i != si && sizes[i] > 0) {\n                    int t = stacks[i][sizes[i] - 1];\n                    if (t < top_of_moved && t > best) {\n                        best = t;\n                        dest = i;\n                    }\n                }\n            }\n            if (dest == -1) {\n                // else min top overall\n                int min_top = INT_MAX;\n                for (int i = 0; i < m; ++i) {\n                    if (i != si && sizes[i] > 0) {\n                        int t = stacks[i][sizes[i] - 1];\n                        if (t < min_top) {\n                            min_top = t;\n                            dest = i;\n                        }\n                    }\n                }\n            }\n            if (dest == -1) dest = (si + 1) % m;\n        }\n        move_op(u, dest);\n        int k = sizes[si] - (pos + 1);\n        for (int j = pos + 1; j < sizes[si]; ++j) {\n            int b = stacks[si][j];\n            stacks[dest][sizes[dest]++] = b;\n            stack_of[b] = dest;\n            index_of[b] = sizes[dest] - 1;\n        }\n        sizes[si] = pos + 1;\n    }\n\n    for (auto &[v, d] : moves)\n        cout << v << \" \" << d << \"\\n\";\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\nconst char dir_char[4] = {'R', 'D', 'L', 'U'};\n\nbool can_move(int i, int j, int ni, int nj) {\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    // Check if there's no wall between (i,j) and (ni,nj)\n    if (i == ni) {\n        // Horizontal move: check vertical walls\n        int min_j = min(j, nj);\n        return v[i][min_j] == '0';\n    } else {\n        // Vertical move: check horizontal walls\n        int min_i = min(i, ni);\n        return h[min_i][j] == '0';\n    }\n}\n\n// BFS to compute shortest path distances\nvector<vector<int>> compute_distances(int si, int sj) {\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    dist[si][sj] = 0;\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int k = 0; k < 4; k++) {\n            int ni = i + dx[k], nj = j + dy[k];\n            if (can_move(i, j, ni, nj) && dist[ni][nj] == -1) {\n                dist[ni][nj] = dist[i][j] + 1;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return dist;\n}\n\n// Generate route string from coordinate sequence\nstring route_to_string(const vector<pair<int,int>>& route) {\n    string s;\n    for (size_t t = 1; t < route.size(); t++) {\n        int ci = route[t-1].first, cj = route[t-1].second;\n        int ni = route[t].first, nj = route[t].second;\n        \n        bool found = false;\n        for (int k = 0; k < 4; k++) {\n            if (ci + dx[k] == ni && cj + dy[k] == nj) {\n                if (can_move(ci, cj, ni, nj)) {\n                    s += dir_char[k];\n                    found = true;\n                    break;\n                }\n            }\n        }\n        if (!found) {\n            // This should not happen if route is valid\n            return \"\";\n        }\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    cin >> N;\n    h.resize(N-1);\n    for (int i = 0; i < N-1; i++) cin >> h[i];\n    v.resize(N);\n    for (int i = 0; i < N; i++) cin >> v[i];\n    d.assign(N, vector<int>(N));\n    \n    vector<pair<int,pair<int,int>>> dirt_cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> d[i][j];\n            dirt_cells.push_back({-d[i][j], {i, j}});\n        }\n    }\n    sort(dirt_cells.begin(), dirt_cells.end());\n    \n    // Step 1: Build base route using priority-based DFS\n    vector<pair<int,int>> base_route;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    \n    function<void(int,int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        base_route.push_back({i, j});\n        \n        // Collect reachable unvisited neighbors with priority\n        vector<pair<int,pair<int,int>>> neighbors;\n        for (int k = 0; k < 4; k++) {\n            int ni = i + dx[k], nj = j + dy[k];\n            if (can_move(i, j, ni, nj) && !visited[ni][nj]) {\n                neighbors.push_back({-d[ni][nj], {ni, nj}});\n            }\n        }\n        sort(neighbors.begin(), neighbors.end());\n        \n        for (auto& [_, next] : neighbors) {\n            auto [ni, nj] = next;\n            dfs(ni, nj);\n            base_route.push_back({i, j}); // Return to current node\n        }\n    };\n    \n    dfs(0, 0);\n    \n    // Step 2: Create working route\n    vector<pair<int,int>> current_route = base_route;\n    int MAX_LENGTH = 100000;\n    \n    // Step 3: Insert extra visits for high-dirt cells\n    // We'll insert additional visits to top priority cells\n    \n    // Build map of cell positions in route\n    map<pair<int,int>, vector<int>> pos_map;\n    for (size_t pos = 0; pos < current_route.size(); pos++) {\n        pos_map[current_route[pos]].push_back(pos);\n    }\n    \n    int insertions = 0;\n    int max_insertions = min(200, N * N / 2);\n    \n    for (auto& [neg_d, cell] : dirt_cells) {\n        if (insertions >= max_insertions) break;\n        if (current_route.size() >= MAX_LENGTH - 200) break;\n        \n        int di = cell.first, dj = cell.second;\n        int dirt_val = -neg_d;\n        \n        // Only add extra visits for cells with high dirt value\n        if (dirt_val < 300) continue;\n        \n        auto& positions = pos_map[{di, dj}];\n        if (positions.size() < 1) continue;\n        \n        // Calculate average gap between visits\n        int L = current_route.size();\n        int num_visits = positions.size();\n        double avg_gap = (double)L / num_visits;\n        \n        // If average gap is large, add extra visit\n        if (avg_gap > 80 && L < MAX_LENGTH - 100) {\n            // Find the largest gap\n            int max_gap = 0;\n            int insert_after = -1;\n            \n            for (size_t p = 0; p < positions.size(); p++) {\n                int curr = positions[p];\n                int next = positions[(p + 1) % positions.size()];\n                int gap;\n                if (next > curr) {\n                    gap = next - curr;\n                } else {\n                    gap = L - curr + next;\n                }\n                \n                if (gap > max_gap) {\n                    max_gap = gap;\n                    // We'll insert near the midpoint of this gap\n                    int midpoint = (curr + gap / 2) % L;\n                    \n                    // Find a point near midpoint that's close to target cell\n                    for (int delta = 0; delta <= 10; delta++) {\n                        int check_pos = (midpoint - delta + L) % L;\n                        auto [ci, cj] = current_route[check_pos];\n                        \n                        vector<vector<int>> dist = compute_distances(ci, cj);\n                        if (dist[di][dj] != -1 && dist[di][dj] <= 10) {\n                            insert_after = check_pos;\n                            break;\n                        }\n                    }\n                    \n                    if (insert_after >= 0) break;\n                }\n            }\n            \n            if (insert_after >= 0 && max_gap > 50) {\n                // Get insertion point\n                auto [si, sj] = current_route[insert_after];\n                \n                // Find path from insertion point to target cell and back\n                // We'll use BFS to find shortest paths\n                vector<vector<int>> dist_to = compute_distances(si, sj);\n                \n                if (dist_to[di][dj] != -1 && dist_to[di][dj] <= 15) {\n                    // Build path from si,sj to di,dj\n                    vector<pair<int,int>> path_to;\n                    int ci = di, cj = dj;\n                    while (ci != si || cj != sj) {\n                        path_to.push_back({ci, cj});\n                        // Find predecessor\n                        for (int k = 0; k < 4; k++) {\n                            int pi = ci - dx[k], pj = cj - dy[k];\n                            if (pi >= 0 && pi < N && pj >= 0 && pj < N && \n                                can_move(pi, pj, ci, cj) && \n                                dist_to[pi][pj] == dist_to[ci][cj] - 1) {\n                                ci = pi; cj = pj;\n                                break;\n                            }\n                        }\n                    }\n                    path_to.push_back({si, sj});\n                    reverse(path_to.begin(), path_to.end());\n                    \n                    // Build path back (reverse of path_to)\n                    vector<pair<int,int>> path_back = path_to;\n                    reverse(path_back.begin(), path_back.end());\n                    \n                    // Remove duplicate endpoints\n                    if (path_to.size() > 1) path_to.erase(path_to.begin()); // Remove start (already in route)\n                    if (path_back.size() > 1) path_back.pop_back(); // Remove end (will continue from there)\n                    \n                    int additional_moves = path_to.size() + path_back.size();\n                    if (current_route.size() + additional_moves <= MAX_LENGTH) {\n                        // Insert into route\n                        vector<pair<int,int>> new_route;\n                        for (int i = 0; i <= insert_after; i++) {\n                            new_route.push_back(current_route[i]);\n                        }\n                        for (auto& p : path_to) new_route.push_back(p);\n                        for (auto& p : path_back) new_route.push_back(p);\n                        for (size_t i = insert_after + 1; i < current_route.size(); i++) {\n                            new_route.push_back(current_route[i]);\n                        }\n                        \n                        current_route = new_route;\n                        insertions++;\n                        \n                        // Rebuild position map\n                        pos_map.clear();\n                        for (size_t pos = 0; pos < current_route.size(); pos++) {\n                            pos_map[current_route[pos]].push_back(pos);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Step 4: Ensure route ends at (0,0)\n    if (current_route.back().first != 0 || current_route.back().second != 0) {\n        int ci = current_route.back().first, cj = current_route.back().second;\n        vector<vector<int>> dist = compute_distances(ci, cj);\n        \n        if (dist[0][0] != -1) {\n            vector<pair<int,int>> return_path;\n            int x = 0, y = 0;\n            vector<pair<int,int>> rev_path;\n            while (x != ci || y != cj) {\n                rev_path.push_back({x, y});\n                for (int k = 0; k < 4; k++) {\n                    int px = x - dx[k], py = y - dy[k];\n                    if (px >= 0 && px < N && py >= 0 && py < N &&\n                        can_move(px, py, x, y) &&\n                        dist[px][py] == dist[x][y] - 1) {\n                        x = px; y = py;\n                        break;\n                    }\n                }\n            }\n            rev_path.push_back({ci, cj});\n            reverse(rev_path.begin(), rev_path.end());\n            \n            // Skip first element (already in route)\n            for (size_t i = 1; i < rev_path.size(); i++) {\n                current_route.push_back(rev_path[i]);\n            }\n        }\n    }\n    \n    // Step 5: Generate output string\n    string ans = route_to_string(current_route);\n    \n    // Validate and truncate if needed\n    if (ans.empty() || ans.size() > MAX_LENGTH) {\n        // Fallback: use simple DFS route\n        vector<pair<int,int>> fallback;\n        vector<vector<bool>> vis(N, vector<bool>(N, false));\n        \n        function<void(int,int)> simple_dfs = [&](int i, int j) {\n            vis[i][j] = true;\n            fallback.push_back({i, j});\n            for (int k = 0; k < 4; k++) {\n                int ni = i + dx[k], nj = j + dy[k];\n                if (can_move(i, j, ni, nj) && !vis[ni][nj]) {\n                    simple_dfs(ni, nj);\n                    fallback.push_back({i, j});\n                }\n            }\n        };\n        simple_dfs(0, 0);\n        ans = route_to_string(fallback);\n    }\n    \n    if (ans.size() > MAX_LENGTH) {\n        ans = ans.substr(0, MAX_LENGTH);\n    }\n    \n    cout << ans << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint si, sj;\nvector<pair<int,int>> pos[26];\nvector<string> targets;\nint dist[225][225];\nint letter_dist[26][26];\n\nint cell_id(int i, int j) { return i*N + j; }\n\nvoid bfs_dist() {\n    int di[] = {1,-1,0,0};\n    int dj[] = {0,0,1,-1};\n    for (int i = 0; i < N*N; i++)\n        for (int j = 0; j < N*N; j++)\n            dist[i][j] = 1e9;\n    \n    for (int i = 0; i < N*N; i++) {\n        int si = i/N, sj = i%N;\n        dist[i][i] = 0;\n        queue<pair<int,int>> q;\n        q.push({si,sj});\n        while (!q.empty()) {\n            auto [ci, cj] = q.front(); q.pop();\n            int cid = cell_id(ci,cj);\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nid = cell_id(ni,nj);\n                if (dist[i][nid] > dist[i][cid] + 1) {\n                    dist[i][nid] = dist[i][cid] + 1;\n                    q.push({ni,nj});\n                }\n            }\n        }\n    }\n    \n    for (int c1 = 0; c1 < 26; c1++) {\n        for (int c2 = 0; c2 < 26; c2++) {\n            int md = 1e9;\n            for (auto [i1, j1] : pos[c1])\n                for (auto [i2, j2] : pos[c2])\n                    md = min(md, abs(i1-i2) + abs(j1-j2));\n            letter_dist[c1][c2] = md;\n        }\n    }\n}\n\nint overlap(const string& a, const string& b) {\n    int max_len = min((int)a.size(), (int)b.size());\n    for (int len = max_len; len >= 0; len--) {\n        if (len == 0) return 0;\n        if (a.substr(a.size()-len) == b.substr(0, len))\n            return len;\n    }\n    return 0;\n}\n\nstring order_to_superstring(const vector<int>& order, const vector<string>& strs) {\n    if (order.empty()) return \"\";\n    string res = strs[order[0]];\n    for (int k = 1; k < (int)order.size(); k++) {\n        int ov = overlap(res, strs[order[k]]);\n        res += strs[order[k]].substr(ov);\n    }\n    return res;\n}\n\ndouble merge_score(const string& cur, const string& nxt, bool is_prepend) {\n    int ov;\n    if (is_prepend) ov = overlap(nxt, cur);\n    else ov = overlap(cur, nxt);\n    \n    if (is_prepend) {\n        if (ov == (int)nxt.size()) return ov * 20.0; // fully contained\n        char bridge = nxt[nxt.size() - ov - 1];\n        int d = letter_dist[bridge - 'A'][cur[0] - 'A'];\n        return ov * 10.0 - d * 2.0; // tuned weights\n    } else {\n        if (ov == (int)nxt.size()) return ov * 20.0;\n        char bridge = cur.back();\n        char next = nxt[ov];\n        int d = letter_dist[bridge - 'A'][next - 'A'];\n        return ov * 10.0 - d * 2.0;\n    }\n}\n\nvector<int> build_grid_aware_order(const vector<string>& strs, int start) {\n    int K = strs.size();\n    vector<bool> used(K, false);\n    vector<int> order;\n    string res = strs[start];\n    order.push_back(start);\n    used[start] = true;\n    \n    for (int step = 1; step < K; step++) {\n        int best_idx = -1;\n        double best_score = -1e9;\n        bool best_is_pre = true;\n        \n        for (int i = 0; i < K; i++) {\n            if (used[i]) continue;\n            double s_pre = merge_score(res, strs[i], true);\n            double s_app = merge_score(res, strs[i], false);\n            if (s_pre > best_score) { best_score = s_pre; best_idx = i; best_is_pre = true; }\n            if (s_app > best_score) { best_score = s_app; best_idx = i; best_is_pre = false; }\n        }\n        \n        used[best_idx] = true;\n        if (best_is_pre) {\n            int ov = overlap(strs[best_idx], res);\n            order.insert(order.begin(), best_idx);\n            res = strs[best_idx].substr(0, strs[best_idx].size() - ov) + res;\n        } else {\n            int ov = overlap(res, strs[best_idx]);\n            order.push_back(best_idx);\n            res += strs[best_idx].substr(ov);\n        }\n    }\n    return order;\n}\n\nunordered_map<string, int> cost_cache;\nint eval_cost(const string& s, int start_cell) {\n    auto it = cost_cache.find(s);\n    if (it != cost_cache.end()) return it->second;\n    \n    int L = s.size();\n    if (L == 0) return 0;\n    vector<int> dp_cur(225, 1e9);\n    for (auto [i, j] : pos[s[0]-'A']) {\n        dp_cur[cell_id(i,j)] = dist[start_cell][cell_id(i,j)] + 1;\n    }\n    for (int k = 1; k < L; k++) {\n        vector<int> dp_next(225, 1e9);\n        char c = s[k], pc = s[k-1];\n        for (auto [i, j] : pos[c-'A']) {\n            int cid = cell_id(i,j);\n            int best = 1e9;\n            for (auto [pi, pj] : pos[pc-'A']) {\n                int pid = cell_id(pi,pj);\n                if (dp_cur[pid] == 1e9) continue;\n                int nd = dp_cur[pid] + dist[pid][cid] + 1;\n                if (nd < best) best = nd;\n            }\n            dp_next[cid] = best;\n        }\n        dp_cur = dp_next;\n    }\n    int ans = 1e9;\n    for (auto [i, j] : pos[s.back()-'A']) {\n        ans = min(ans, dp_cur[cell_id(i,j)]);\n    }\n    cost_cache[s] = ans;\n    return ans;\n}\n\nvector<int> type_string(const string& s, int start_cell) {\n    int L = s.size();\n    vector<int> dp_cur(225, 1e9);\n    vector<vector<int>> prev(L, vector<int>(225, -1));\n    for (auto [i, j] : pos[s[0]-'A']) {\n        int cid = cell_id(i,j);\n        dp_cur[cid] = dist[start_cell][cid] + 1;\n    }\n    for (int k = 1; k < L; k++) {\n        vector<int> dp_next(225, 1e9);\n        char c = s[k], pc = s[k-1];\n        for (auto [i, j] : pos[c-'A']) {\n            int cid = cell_id(i,j);\n            for (auto [pi, pj] : pos[pc-'A']) {\n                int pid = cell_id(pi,pj);\n                if (dp_cur[pid] == 1e9) continue;\n                int nd = dp_cur[pid] + dist[pid][cid] + 1;\n                if (nd < dp_next[cid]) {\n                    dp_next[cid] = nd;\n                    prev[k][cid] = pid;\n                }\n            }\n        }\n        dp_cur = dp_next;\n    }\n    int best_end = -1;\n    for (auto [i, j] : pos[s.back()-'A']) {\n        int cid = cell_id(i,j);\n        if (best_end == -1 || dp_cur[cid] < dp_cur[best_end])\n            best_end = cid;\n    }\n    vector<int> path(L);\n    int cur = best_end;\n    for (int k = L-1; k >= 0; k--) {\n        path[k] = cur;\n        if (k > 0) cur = prev[k][cur];\n    }\n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    for (int i = 0; i < N; i++) {\n        string s; cin >> s;\n        for (int j = 0; j < N; j++) {\n            pos[s[j]-'A'].push_back({i,j});\n        }\n    }\n    targets.resize(M);\n    for (int i = 0; i < M; i++) cin >> targets[i];\n    \n    bfs_dist();\n    int start_cell = cell_id(si, sj);\n    \n    string best_super;\n    int best_cost = 1e9;\n    vector<int> best_order;\n    \n    auto process = [&](const string& sup, const vector<int>& order) {\n        int cost = eval_cost(sup, start_cell);\n        if (cost < best_cost) {\n            best_cost = cost;\n            best_super = sup;\n            best_order = order;\n        }\n    };\n    \n    // Grid-aware greedy from many starts\n    for (int start = 0; start < min(M, 60); start++) {\n        vector<int> order = build_grid_aware_order(targets, start);\n        string sup = order_to_superstring(order, targets);\n        process(sup, order);\n    }\n    \n    // Pure overlap greedy\n    for (int start = 0; start < min(M, 30); start++) {\n        vector<bool> used(M, false);\n        vector<int> order;\n        string res = targets[start];\n        order.push_back(start);\n        used[start] = true;\n        for (int step = 1; step < M; step++) {\n            int best_idx = -1, best_ov = -1;\n            bool is_pre = true;\n            for (int i = 0; i < M; i++) {\n                if (used[i]) continue;\n                int ov_pre = overlap(targets[i], res);\n                int ov_app = overlap(res, targets[i]);\n                if (ov_pre > best_ov) { best_ov = ov_pre; best_idx = i; is_pre = true; }\n                if (ov_app > best_ov) { best_ov = ov_app; best_idx = i; is_pre = false; }\n            }\n            used[best_idx] = true;\n            if (is_pre) {\n                order.insert(order.begin(), best_idx);\n                res = targets[best_idx].substr(0, targets[best_idx].size() - best_ov) + res;\n            } else {\n                order.push_back(best_idx);\n                res += targets[best_idx].substr(best_ov);\n            }\n        }\n        process(res, order);\n    }\n    \n    // Randomized variations\n    mt19937 rng(42);\n    for (int trial = 0; trial < 40; trial++) {\n        int start = rng() % M;\n        vector<bool> used(M, false);\n        string res = targets[start];\n        vector<int> order;\n        if (rng() % 2) {\n            order.push_back(start);\n            used[start] = true;\n            for (int step = 1; step < M; step++) {\n                vector<tuple<int,int>> cands;\n                for (int i = 0; i < M; i++) {\n                    if (used[i]) continue;\n                    cands.push_back({overlap(res, targets[i]), i});\n                }\n                sort(cands.rbegin(), cands.rend());\n                int pick = min((int)cands.size()-1, (int)(rng() % min(3, (int)cands.size())));\n                auto [ov, idx] = cands[pick];\n                used[idx] = true;\n                order.push_back(idx);\n                res += targets[idx].substr(ov);\n            }\n        } else {\n            order.push_back(start);\n            used[start] = true;\n            for (int step = 1; step < M; step++) {\n                vector<tuple<int,int>> cands;\n                for (int i = 0; i < M; i++) {\n                    if (used[i]) continue;\n                    cands.push_back({overlap(targets[i], res), i});\n                }\n                sort(cands.rbegin(), cands.rend());\n                int pick = min((int)cands.size()-1, (int)(rng() % min(3, (int)cands.size())));\n                auto [ov, idx] = cands[pick];\n                used[idx] = true;\n                order.insert(order.begin(), idx);\n                res = targets[idx].substr(0, targets[idx].size() - ov) + res;\n            }\n        }\n        process(res, order);\n    }\n    \n    // Local search: adjacent swaps + random swaps + relocate\n    mt19937 rng2(12345);\n    bool improved = true;\n    int iter = 0;\n    while (improved && iter < 800) {\n        improved = false;\n        iter++;\n        \n        // Adjacent swaps\n        for (int i = 0; i < M-1; i++) {\n            swap(best_order[i], best_order[i+1]);\n            string sup = order_to_superstring(best_order, targets);\n            int cost = eval_cost(sup, start_cell);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_super = sup;\n                improved = true;\n                break;\n            }\n            swap(best_order[i], best_order[i+1]);\n        }\n        if (improved) continue;\n        \n        // Random non-adjacent swaps\n        for (int t = 0; t < 500; t++) {\n            int a = rng2() % M;\n            int b = rng2() % M;\n            if (a == b) continue;\n            if (a > b) swap(a, b);\n            if (b - a > 50) continue;\n            swap(best_order[a], best_order[b]);\n            string sup = order_to_superstring(best_order, targets);\n            int cost = eval_cost(sup, start_cell);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_super = sup;\n                improved = true;\n                break;\n            }\n            swap(best_order[a], best_order[b]);\n        }\n        if (improved) continue;\n        \n        // Random segment reverse\n        for (int t = 0; t < 200; t++) {\n            int a = rng2() % M;\n            int b = rng2() % M;\n            if (a == b) continue;\n            if (a > b) swap(a, b);\n            if (b - a > 30) continue;\n            reverse(best_order.begin()+a, best_order.begin()+b+1);\n            string sup = order_to_superstring(best_order, targets);\n            int cost = eval_cost(sup, start_cell);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_super = sup;\n                improved = true;\n                break;\n            }\n            reverse(best_order.begin()+a, best_order.begin()+b+1);\n        }\n        if (improved) continue;\n        \n        // Relocate: move one element to a new position (limited)\n        for (int t = 0; t < 50; t++) {\n            int a = rng2() % M;\n            int b = rng2() % M;\n            if (a == b) continue;\n            int val = best_order[a];\n            best_order.erase(best_order.begin() + a);\n            best_order.insert(best_order.begin() + b, val);\n            string sup = order_to_superstring(best_order, targets);\n            int cost = eval_cost(sup, start_cell);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_super = sup;\n                improved = true;\n                break;\n            }\n            // revert\n            best_order.erase(best_order.begin() + b);\n            best_order.insert(best_order.begin() + a, val);\n        }\n    }\n    \n    // Final output\n    vector<int> output = type_string(best_super, start_cell);\n    for (int c : output) {\n        cout << c/N << \" \" << c%N << \"\\n\";\n    }\n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <set>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\nstruct Shape {\n    int d, h, w;\n    vector<pair<int,int>> cells;\n};\n\nint main() {\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n    \n    vector<Shape> shapes(M);\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        shapes[k].d = d;\n        shapes[k].cells.resize(d);\n        int mini = N, minj = N, maxi = 0, maxj = 0;\n        for (int t = 0; t < d; t++) {\n            cin >> shapes[k].cells[t].first >> shapes[k].cells[t].second;\n            mini = min(mini, shapes[k].cells[t].first);\n            minj = min(minj, shapes[k].cells[t].second);\n            maxi = max(maxi, shapes[k].cells[t].first);\n            maxj = max(maxj, shapes[k].cells[t].second);\n        }\n        shapes[k].h = maxi - mini + 1;\n        shapes[k].w = maxj - minj + 1;\n        for (auto &p : shapes[k].cells) {\n            p.first -= mini;\n            p.second -= minj;\n        }\n    }\n    \n    const int MAXQ = 2 * N * N;\n    int qcnt = 0;\n    \n    vector<vector<int>> val(N, vector<int>(N, -1));\n    set<pair<int,int>> known_oil;\n    vector<vector<bool>> drilled(N, vector<bool>(N, false));\n    \n    auto query_set = [&](const vector<pair<int,int>> &s) -> double {\n        if (qcnt >= MAXQ) return -1.0;\n        qcnt++;\n        cout << \"q \" << s.size();\n        for (auto &p : s) cout << \" \" << p.first << \" \" << p.second;\n        cout << endl;\n        double x;\n        cin >> x;\n        return x;\n    };\n    \n    auto query_one = [&](int i, int j) -> int {\n        if (qcnt >= MAXQ) return -1;\n        if (drilled[i][j]) return val[i][j];\n        qcnt++;\n        drilled[i][j] = true;\n        cout << \"q 1 \" << i << \" \" << j << endl;\n        int x;\n        cin >> x;\n        val[i][j] = x;\n        if (x > 0) known_oil.insert({i, j});\n        return x;\n    };\n    \n    auto submit = [&](const set<pair<int,int>> &ans) -> bool {\n        cout << \"a \" << ans.size();\n        for (auto &p : ans) cout << \" \" << p.first << \" \" << p.second;\n        cout << endl;\n        int r;\n        cin >> r;\n        return r == 1;\n    };\n    \n    auto est_v = [&](double obs, int k) -> double {\n        return max(0.0, (obs - k * eps) / (1.0 - 2.0 * eps));\n    };\n    \n    // Phase 1: Row and column scanning\n    vector<double> row_v(N), col_v(N);\n    for (int i = 0; i < N; i++) {\n        vector<pair<int,int>> row;\n        for (int j = 0; j < N; j++) row.push_back({i, j});\n        row_v[i] = est_v(query_set(row), N);\n    }\n    for (int j = 0; j < N; j++) {\n        vector<pair<int,int>> col;\n        for (int i = 0; i < N; i++) col.push_back({i, j});\n        col_v[j] = est_v(query_set(col), N);\n    }\n    \n    // Phase 2: Collect candidates (intersection of active rows/cols)\n    vector<pair<double, pair<int,int>>> candidates;\n    double total_v = 0;\n    for (int i = 0; i < N; i++) total_v += max(0.0, row_v[i]);\n    \n    for (int i = 0; i < N; i++) {\n        if (row_v[i] < 0.1) continue;\n        for (int j = 0; j < N; j++) {\n            if (col_v[j] < 0.1) continue;\n            double prob = (max(0.0, row_v[i]) * max(0.0, col_v[j])) / max(1.0, total_v);\n            if (prob > 0.05) {\n                candidates.push_back({prob, {i, j}});\n            }\n        }\n    }\n    \n    sort(candidates.rbegin(), candidates.rend());\n    \n    // Phase 3: Drill candidates in priority order\n    // When we find oil, use shape knowledge to drill remaining shape cells\n    for (auto &cp : candidates) {\n        if (qcnt + 5 >= MAXQ) break;\n        int i = cp.second.first, j = cp.second.second;\n        if (drilled[i][j]) continue;\n        \n        int v = query_one(i, j);\n        if (v > 0) {\n            // Check all shapes to see if this cell belongs to a placement\n            for (auto &s : shapes) {\n                for (auto &sc : s.cells) {\n                    int si = i - sc.first;\n                    int sj = j - sc.second;\n                    \n                    if (si >= 0 && sj >= 0 && si + s.h <= N && sj + s.w <= N) {\n                        // Check if this placement is consistent with known data\n                        bool ok = true;\n                        vector<pair<int,int>> unk;\n                        for (auto &c : s.cells) {\n                            int ni = si + c.first, nj = sj + c.second;\n                            if (drilled[ni][nj] && val[ni][nj] == 0) {\n                                ok = false;\n                                break;\n                            }\n                            if (!drilled[ni][nj]) {\n                                unk.push_back({ni, nj});\n                            }\n                        }\n                        if (ok && !unk.empty()) {\n                            // Drill remaining cells of this shape placement\n                            for (auto &p : unk) {\n                                if (qcnt + 2 >= MAXQ) break;\n                                query_one(p.first, p.second);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Phase 4: Build answer\n    set<pair<int,int>> ans = known_oil;\n    \n    // Include shape completions\n    for (auto &s : shapes) {\n        for (int i = 0; i + s.h <= N; i++) {\n            for (int j = 0; j + s.w <= N; j++) {\n                int matches = 0, conflicts = 0;\n                vector<pair<int,int>> cells;\n                for (auto &c : s.cells) {\n                    int ni = i + c.first, nj = j + c.second;\n                    cells.push_back({ni, nj});\n                    if (drilled[ni][nj]) {\n                        if (val[ni][nj] > 0) matches++;\n                        else conflicts++;\n                    }\n                }\n                if (matches > 0 && conflicts == 0) {\n                    for (auto &p : cells) ans.insert(p);\n                }\n            }\n        }\n    }\n    \n    if (submit(ans)) return 0;\n    \n    // Phase 5: Drill more if wrong\n    for (auto &cp : candidates) {\n        if (qcnt + 2 >= MAXQ) break;\n        if (!drilled[cp.second.first][cp.second.second]) {\n            query_one(cp.second.first, cp.second.second);\n        }\n    }\n    \n    ans = known_oil;\n    if (submit(ans)) return 0;\n    \n    // Phase 6: Drill everything\n    for (int i = 0; i < N && qcnt + 2 < MAXQ; i++)\n        for (int j = 0; j < N && qcnt + 2 < MAXQ; j++)\n            if (!drilled[i][j])\n                query_one(i, j);\n    \n    ans.clear();\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (drilled[i][j] && val[i][j] > 0)\n                ans.insert({i, j});\n    \n    submit(ans);\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <cstring>\n#include <functional>\n\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nlong long area(const Rect& r) {\n    return (long long)(r.i1 - r.i0) * (r.j1 - r.j0);\n}\n\n// Compute L_d cost between prev and curr layouts\nlong long partition_change_cost(const vector<Rect>& prev, const vector<Rect>& curr, int W) {\n    static vector<char> H_prev, H_curr, V_prev, V_curr;\n    H_prev.assign(W * W, 0);\n    H_curr.assign(W * W, 0);\n    V_prev.assign(W * W, 0);\n    V_curr.assign(W * W, 0);\n    \n    auto mark_rect = [W](vector<char>& H, vector<char>& V, const Rect& r) {\n        if (r.i0 > 0 && r.i0 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H[r.i0 * W + j] = 1;\n            }\n        }\n        if (r.i1 > 0 && r.i1 < W) {\n            for (int j = r.j0; j < r.j1; ++j) {\n                H[r.i1 * W + j] = 1;\n            }\n        }\n        if (r.j0 > 0 && r.j0 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V[i * W + r.j0] = 1;\n            }\n        }\n        if (r.j1 > 0 && r.j1 < W) {\n            for (int i = r.i0; i < r.i1; ++i) {\n                V[i * W + r.j1] = 1;\n            }\n        }\n    };\n    \n    if (!prev.empty()) {\n        for (const auto& r : prev) {\n            mark_rect(H_prev, V_prev, r);\n        }\n    }\n    for (const auto& r : curr) {\n        mark_rect(H_curr, V_curr, r);\n    }\n    \n    long long cost = 0;\n    for (int i = 1; i < W; ++i) {\n        for (int j = 0; j < W; ++j) {\n            if (H_prev[i * W + j] != H_curr[i * W + j]) cost++;\n        }\n    }\n    for (int i = 0; i < W; ++i) {\n        for (int j = 1; j < W; ++j) {\n            if (V_prev[i * W + j] != V_curr[i * W + j]) cost++;\n        }\n    }\n    return cost;\n}\n\n// Compute area deficit penalty\nlong long area_penalty(const vector<Rect>& rects, const vector<int>& demands) {\n    long long penalty = 0;\n    for (size_t k = 0; k < demands.size(); ++k) {\n        long long rect_area = area(rects[k]);\n        if (rect_area < demands[k]) {\n            penalty += 100 * (demands[k] - rect_area);\n        }\n    }\n    return penalty;\n}\n\n// Create layout for given demands using recursive bisection\n// Ensures each rectangle gets at least its demanded area\nvector<Rect> create_layout(const vector<int>& demands) {\n    int N = demands.size();\n    vector<Rect> rects(N);\n    \n    // Pair (demand, original_index) sorted by demand descending\n    vector<pair<long long, int>> slots;\n    for (int k = 0; k < N; ++k) {\n        slots.emplace_back(demands[k], k);\n    }\n    sort(slots.begin(), slots.end(), greater<pair<long long, int>>());\n    \n    function<void(int, int, int, int, int, int)> assign;\n    assign = [&](int start, int end, int i0, int j0, int i1, int j1) {\n        if (start >= end) return;\n        if (start + 1 == end) {\n            int idx = slots[start].second;\n            rects[idx] = {i0, j0, i1, j1};\n            return;\n        }\n        \n        // Total demand for this group\n        long long total_demand = 0;\n        for (int i = start; i < end; ++i) {\n            total_demand += slots[i].first;\n        }\n        \n        int height = i1 - i0;\n        int width = j1 - j0;\n        long long region_area = (long long)height * width;\n        \n        // Split along longer dimension\n        if (height >= width) {\n            // Horizontal split\n            // Find best split point that balances areas\n            long long best_penalty = 1LL << 60;\n            int best_split = start + 1;\n            \n            for (int split = start + 1; split < end; ++split) {\n                long long area_above = 0;\n                for (int i = start; i < split; ++i) area_above += slots[i].first;\n                long long area_below = total_demand - area_above;\n                \n                // Compute ideal split position\n                int ideal_split_i = i0 + (int)((area_above * height + total_demand/2) / total_demand);\n                if (ideal_split_i <= i0) ideal_split_i = i0 + 1;\n                if (ideal_split_i >= i1) ideal_split_i = i1 - 1;\n                \n                long long actual_above = (long long)(ideal_split_i - i0) * width;\n                long long actual_below = region_area - actual_above;\n                \n                long long penalty = 0;\n                if (actual_above < area_above) penalty += 100 * (area_above - actual_above);\n                if (actual_below < area_below) penalty += 100 * (area_below - actual_below);\n                \n                // Also prefer splits that make rectangles closer to square\n                double aspect_above = (double)(ideal_split_i - i0) / width;\n                double aspect_below = (double)(i1 - ideal_split_i) / width;\n                if (aspect_above < 1) aspect_above = 1.0 / aspect_above;\n                if (aspect_below < 1) aspect_below = 1.0 / aspect_below;\n                long long aspect_penalty = (long long)((aspect_above + aspect_below) * 10);\n                \n                if (penalty + aspect_penalty < best_penalty) {\n                    best_penalty = penalty + aspect_penalty;\n                    best_split = split;\n                }\n            }\n            \n            // Compute actual split position\n            long long area_above = 0;\n            for (int i = start; i < best_split; ++i) area_above += slots[i].first;\n            int split_i = i0 + (int)((area_above * height + total_demand/2) / total_demand);\n            if (split_i <= i0) split_i = i0 + 1;\n            if (split_i >= i1) split_i = i1 - 1;\n            \n            assign(start, best_split, i0, j0, split_i, j1);\n            assign(best_split, end, split_i, j0, i1, j1);\n        } else {\n            // Vertical split\n            long long best_penalty = 1LL << 60;\n            int best_split = start + 1;\n            \n            for (int split = start + 1; split < end; ++split) {\n                long long area_left = 0;\n                for (int i = start; i < split; ++i) area_left += slots[i].first;\n                long long area_right = total_demand - area_left;\n                \n                int ideal_split_j = j0 + (int)((area_left * width + total_demand/2) / total_demand);\n                if (ideal_split_j <= j0) ideal_split_j = j0 + 1;\n                if (ideal_split_j >= j1) ideal_split_j = j1 - 1;\n                \n                long long actual_left = (long long)height * (ideal_split_j - j0);\n                long long actual_right = region_area - actual_left;\n                \n                long long penalty = 0;\n                if (actual_left < area_left) penalty += 100 * (area_left - actual_left);\n                if (actual_right < area_right) penalty += 100 * (area_right - actual_right);\n                \n                double aspect_left = (double)height / (ideal_split_j - j0);\n                double aspect_right = (double)height / (j1 - ideal_split_j);\n                if (aspect_left < 1) aspect_left = 1.0 / aspect_left;\n                if (aspect_right < 1) aspect_right = 1.0 / aspect_right;\n                long long aspect_penalty = (long long)((aspect_left + aspect_right) * 10);\n                \n                if (penalty + aspect_penalty < best_penalty) {\n                    best_penalty = penalty + aspect_penalty;\n                    best_split = split;\n                }\n            }\n            \n            long long area_left = 0;\n            for (int i = start; i < best_split; ++i) area_left += slots[i].first;\n            int split_j = j0 + (int)((area_left * width + total_demand/2) / total_demand);\n            if (split_j <= j0) split_j = j0 + 1;\n            if (split_j >= j1) split_j = j1 - 1;\n            \n            assign(start, best_split, i0, j0, i1, split_j);\n            assign(best_split, end, i0, split_j, i1, j1);\n        }\n    };\n    \n    assign(0, N, 0, 0, 1000, 1000);\n    return rects;\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    // Precompute optimal layout for each day\n    vector<vector<Rect>> day_layouts(D);\n    for (int d = 0; d < D; ++d) {\n        day_layouts[d] = create_layout(a[d]);\n    }\n    \n    // Use DP-like approach: for each day, decide whether to keep previous layout or switch\n    vector<vector<Rect>> output_layouts(D);\n    output_layouts[0] = day_layouts[0];\n    \n    for (int d = 1; d < D; ++d) {\n        // Cost to keep previous layout\n        long long penalty_keep = area_penalty(output_layouts[d-1], a[d]);\n        \n        // Cost to switch to new optimal layout\n        long long change_cost = partition_change_cost(output_layouts[d-1], day_layouts[d], W);\n        long long penalty_new = area_penalty(day_layouts[d], a[d]);\n        \n        // Also consider switching to this day's layout might help future days\n        // Simple heuristic: look ahead one day\n        long long future_benefit = 0;\n        if (d + 1 < D) {\n            // If we switch now, estimate cost for day d+1\n            long long change_next_if_switch = partition_change_cost(day_layouts[d], day_layouts[d+1], W);\n            long long penalty_next_if_switch = area_penalty(day_layouts[d+1], a[d+1]);\n            long long cost_next_if_switch = change_next_if_switch + penalty_next_if_switch;\n            \n            // If we keep current, estimate cost for day d+1\n            long long change_next_if_keep = partition_change_cost(output_layouts[d-1], day_layouts[d+1], W);\n            long long penalty_next_if_keep = area_penalty(day_layouts[d+1], a[d+1]);\n            long long cost_next_if_keep = change_next_if_keep + penalty_next_if_keep;\n            \n            future_benefit = cost_next_if_keep - cost_next_if_switch;\n        }\n        \n        long long cost_keep = penalty_keep;\n        long long cost_switch = change_cost + penalty_new - future_benefit;\n        \n        if (cost_switch < cost_keep) {\n            output_layouts[d] = day_layouts[d];\n        } else {\n            output_layouts[d] = output_layouts[d-1];\n        }\n    }\n\n    // Output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            cout << output_layouts[d][k].i0 << \" \" << output_layouts[d][k].j0 << \" \"\n                 << output_layouts[d][k].i1 << \" \" << output_layouts[d][k].j1 << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cstdint>\n#include <tuple>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int MOD = 998244353;\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\n\nlong long score_board(const vector<vector<int>>& board) {\n    long long s = 0;\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            s += board[i][j] % MOD;\n    return s;\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<vector<int>> init_a(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> init_a[i][j];\n\n    vector<vector<vector<int>>> stamps(M, vector<vector<int>>(3, vector<int>(3)));\n    for (int s = 0; s < M; s++)\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                cin >> stamps[s][i][j];\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    long long global_best_score = 0;\n    vector<tuple<int,int,int>> global_best_ops;\n\n    auto start_time = chrono::steady_clock::now();\n    const int MAX_TRIES = 100;\n\n    for (int trial = 0; trial < MAX_TRIES; trial++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 1900) break;\n\n        // Shuffle stamp iteration order and position order for this trial\n        vector<int> stamp_order(M);\n        iota(stamp_order.begin(), stamp_order.end(), 0);\n        shuffle(stamp_order.begin(), stamp_order.end(), rng);\n\n        vector<int> row_order(N-2);\n        iota(row_order.begin(), row_order.end(), 0);\n        shuffle(row_order.begin(), row_order.end(), rng);\n\n        vector<int> col_order(N-2);\n        iota(col_order.begin(), col_order.end(), 0);\n        shuffle(col_order.begin(), col_order.end(), rng);\n\n        vector<vector<int>> board = init_a;\n        vector<tuple<int,int,int>> ops;\n\n        for (int step = 0; step < K; step++) {\n            long long best_gain = -1;\n            int best_m = -1, best_p = -1, best_q = -1;\n\n            for (int m_idx : stamp_order) {\n                for (int p : row_order) {\n                    for (int q : col_order) {\n                        long long gain = 0;\n                        for (int i = 0; i < 3; i++) {\n                            for (int j = 0; j < 3; j++) {\n                                int old = board[p+i][q+j] % MOD;\n                                int nv = (board[p+i][q+j] + stamps[m_idx][i][j]) % MOD;\n                                gain += nv - old;\n                            }\n                        }\n                        if (gain > best_gain) {\n                            best_gain = gain;\n                            best_m = m_idx;\n                            best_p = p;\n                            best_q = q;\n                        }\n                    }\n                }\n            }\n\n            if (best_m == -1) break;\n            ops.emplace_back(best_m, best_p, best_q);\n            for (int i = 0; i < 3; i++)\n                for (int j = 0; j < 3; j++)\n                    board[best_p+i][best_q+j] += stamps[best_m][i][j];\n        }\n\n        long long cur_score = score_board(board);\n        if (cur_score > global_best_score) {\n            global_best_score = cur_score;\n            global_best_ops = ops;\n        }\n    }\n\n    // Fallback to original deterministic if somehow empty\n    if (global_best_ops.empty()) {\n        vector<vector<int>> board = init_a;\n        for (int step = 0; step < K; step++) {\n            long long best_gain = -1;\n            int best_m = 0, best_p = 0, best_q = 0;\n            for (int m_idx = 0; m_idx < M; m_idx++) {\n                for (int p = 0; p <= N-3; p++) {\n                    for (int q = 0; q <= N-3; q++) {\n                        long long gain = 0;\n                        for (int i = 0; i < 3; i++)\n                            for (int j = 0; j < 3; j++) {\n                                int old = board[p+i][q+j] % MOD;\n                                int nv = (board[p+i][q+j] + stamps[m_idx][i][j]) % MOD;\n                                gain += nv - old;\n                            }\n                        if (gain > best_gain) {\n                            best_gain = gain;\n                            best_m = m_idx;\n                            best_p = p;\n                            best_q = q;\n                        }\n                    }\n                }\n            }\n            global_best_ops.emplace_back(best_m, best_p, best_q);\n            for (int i = 0; i < 3; i++)\n                for (int j = 0; j < 3; j++)\n                    board[best_p+i][best_q+j] += stamps[best_m][i][j];\n        }\n    }\n\n    cout << global_best_ops.size() << '\\n';\n    for (auto &[m_idx, p, q] : global_best_ops)\n        cout << m_idx << ' ' << p << ' ' << q << '\\n';\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct Pos { int x, y; };\nint target_gate(int cid) { return cid / N; }\n\nchar get_dir(int fx, int fy, int tx, int ty) {\n    if (tx == fx-1) return 'U';\n    if (tx == fx+1) return 'D';\n    if (ty == fy-1) return 'L';\n    if (ty == fy+1) return 'R';\n    return '.';\n}\n\nint 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    \n    int n; cin >> n;\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> A[i][j];\n    \n    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<queue<int>> recv_queue(N);\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            recv_queue[i].push(A[i][j]);\n    \n    int cx[N], cy[N];\n    bool holding[N];\n    int container[N];\n    bool bombed[N];\n    \n    for (int i = 0; i < N; i++) {\n        cx[i] = i; cy[i] = 0;\n        holding[i] = false;\n        container[i] = -1;\n        bombed[i] = false;\n    }\n    \n    int dispatched = 0;\n    vector<string> output(N);\n    int next_for_gate[5] = {0, 5, 10, 15, 20};\n    \n    auto bfs = [&](int sx, int sy, int ex, int ey) -> vector<pair<int,int>> {\n        vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1,-1}));\n        vector<vector<bool>> visited(N, vector<bool>(N, false));\n        queue<pair<int,int>> q;\n        q.push({sx, sy});\n        visited[sx][sy] = true;\n        \n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            if (x == ex && y == ey) {\n                vector<pair<int,int>> path;\n                while (x != sx || y != sy) {\n                    path.push_back({x, y});\n                    tie(x, y) = parent[x][y];\n                }\n                reverse(path.begin(), path.end());\n                return path;\n            }\n            \n            int dx[] = {-1, 1, 0, 0};\n            int dy[] = {0, 0, -1, 1};\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) continue;\n                if (visited[nx][ny]) continue;\n                \n                bool occupied = false;\n                for (int c = 0; c < N; c++)\n                    if (!bombed[c] && cx[c] == nx && cy[c] == ny) occupied = true;\n                if (occupied) continue;\n                \n                visited[nx][ny] = true;\n                parent[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n        return {};\n    };\n    \n    bool bombs_done = false;\n    \n    for (int turn = 0; turn < MAX_TURNS && dispatched < N * N; turn++) {\n        // Step 1: Spawn\n        for (int i = 0; i < N; i++) {\n            if (!recv_queue[i].empty() && grid[i][0] == -1) {\n                bool blocked = false;\n                for (int c = 0; c < N; c++)\n                    if (!bombed[c] && holding[c] && cx[c] == i && cy[c] == 0)\n                        blocked = true;\n                if (!blocked) {\n                    grid[i][0] = recv_queue[i].front();\n                    recv_queue[i].pop();\n                }\n            }\n        }\n        \n        vector<char> act(N, '.');\n        \n        // Bomb small cranes on turn 0\n        if (!bombs_done) {\n            bool can_bomb = true;\n            for (int i = 1; i < N; i++) if (!bombed[i] && holding[i]) can_bomb = false;\n            if (can_bomb) {\n                for (int i = 1; i < N; i++) if (!bombed[i]) act[i] = 'B';\n                bombs_done = true;\n            }\n        }\n        \n        // Large crane\n        if (!bombed[0]) {\n            if (holding[0]) {\n                int cid = container[0];\n                int tgt = target_gate(cid);\n                Pos target;\n                \n                // If next expected, deliver directly to dispatch\n                if (cid == next_for_gate[tgt] && grid[tgt][N-1] == -1) {\n                    target = {tgt, N-1};\n                } else {\n                    // Find staging spot\n                    target = {-1, -1};\n                    // Prefer staging in same row as target gate, columns N-2 or N-3\n                    if (grid[tgt][N-2] == -1) target = {tgt, N-2};\n                    else if (grid[tgt][N-3] == -1) target = {tgt, N-3};\n                    else if (grid[tgt][1] == -1) target = {tgt, 1};\n                    else {\n                        // Any empty non-dispatch spot\n                        for (int col = 1; col < N-1 && target.x == -1; col++)\n                            for (int row = 0; row < N && target.x == -1; row++)\n                                if (grid[row][col] == -1) target = {row, col};\n                    }\n                    if (target.x == -1) target = {tgt, N-1}; // Force dispatch\n                }\n                \n                if (cx[0] == target.x && cy[0] == target.y) {\n                    if (grid[target.x][target.y] == -1) act[0] = 'Q';\n                } else {\n                    auto path = bfs(cx[0], cy[0], target.x, target.y);\n                    if (!path.empty()) {\n                        act[0] = get_dir(cx[0], cy[0], path[0].first, path[0].second);\n                    }\n                }\n            } else {\n                // Find best container: heavily weight distance from current position\n                int best_score = -1e9;\n                Pos best = {-1, -1};\n                \n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (grid[i][j] == -1) continue;\n                        if (j == N-1) continue;\n                        \n                        int cid = grid[i][j];\n                        int tgt = target_gate(cid);\n                        int dist = manhattan(cx[0], cy[0], i, j);\n                        \n                        // Score: prioritize next-expected containers heavily\n                        int score = 0;\n                        \n                        if (cid == next_for_gate[tgt] && grid[tgt][N-1] == -1) {\n                            // This container is ready - super high priority\n                            score = 10000000 - dist * 10;\n                        } else {\n                            // General container\n                            // Weight: receiving gates important to unblock\n                            if (j == 0) score = 50000;\n                            else score = 30000;\n                            \n                            // Heavy distance penalty\n                            score -= dist * 200;\n                            \n                            // Small bonus for being close to target gate\n                            score -= manhattan(i, j, tgt, N-1) * 30;\n                        }\n                        \n                        if (score > best_score) {\n                            best_score = score;\n                            best = {i, j};\n                        }\n                    }\n                }\n                \n                if (best.x != -1) {\n                    if (cx[0] == best.x && cy[0] == best.y) {\n                        act[0] = 'P';\n                    } else {\n                        auto path = bfs(cx[0], cy[0], best.x, best.y);\n                        if (!path.empty()) {\n                            act[0] = get_dir(cx[0], cy[0], path[0].first, path[0].second);\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Execute\n        for (int i = 0; i < N; i++) {\n            if (bombed[i]) continue;\n            \n            if (act[i] == 'P') {\n                if (!holding[i] && grid[cx[i]][cy[i]] != -1) {\n                    holding[i] = true;\n                    container[i] = grid[cx[i]][cy[i]];\n                    grid[cx[i]][cy[i]] = -1;\n                }\n            } else if (act[i] == 'Q') {\n                if (holding[i] && grid[cx[i]][cy[i]] == -1) {\n                    grid[cx[i]][cy[i]] = container[i];\n                    holding[i] = false;\n                    container[i] = -1;\n                }\n            } else if (act[i] == 'B') {\n                if (!holding[i]) bombed[i] = true;\n            } else if (act[i] == 'U') cx[i]--;\n            else if (act[i] == 'D') cx[i]++;\n            else if (act[i] == 'L') cy[i]--;\n            else if (act[i] == 'R') cy[i]++;\n        }\n        \n        for (int i = 0; i < N; i++) output[i] += act[i];\n        \n        // Step 3: Auto-dispatch\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N-1] != -1) {\n                int cid = grid[i][N-1];\n                dispatched++;\n                grid[i][N-1] = -1;\n                \n                if (target_gate(cid) == i && cid == next_for_gate[i]) {\n                    next_for_gate[i]++;\n                    if (next_for_gate[i] >= (i+1)*N) next_for_gate[i] = (i+1)*N;\n                }\n            }\n        }\n    }\n    \n    int max_len = 0;\n    for (int i = 0; i < N; i++) max_len = max(max_len, (int)output[i].size());\n    for (int i = 0; i < N; i++)\n        while ((int)output[i].size() < max_len) output[i] += '.';\n    \n    for (int i = 0; i < N; i++) cout << output[i] << '\\n';\n    \n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            cin >> h[i][j];\n\n    const int BASE = 100;\n    int cx = 0, cy = 0, load = 0;\n    vector<string> ops;\n\n    auto mdist = [](int x1, int y1, int x2, int y2) {\n        return abs(x1 - x2) + abs(y1 - y2);\n    };\n\n    auto move_to = [&](int tx, int ty) {\n        while (cx < tx) { ops.push_back(\"D\"); cx++; }\n        while (cx > tx) { ops.push_back(\"U\"); cx--; }\n        while (cy < ty) { ops.push_back(\"R\"); cy++; }\n        while (cy > ty) { ops.push_back(\"L\"); cy--; }\n    };\n\n    auto deliver_load = [&]() {\n        // Collect up to 7 nearest negatives\n        vector<pair<int,pair<int,int>>> negs;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (h[i][j] < 0)\n                    negs.push_back({mdist(cx, cy, i, j), {i, j}});\n        sort(negs.begin(), negs.end());\n        int k = min((int)negs.size(), 7);\n        negs.resize(k);\n        \n        if (k == 1) {\n            auto [d, coords] = negs[0];\n            auto [ni, nj] = coords;\n            move_to(ni, nj);\n            int unload = min(load, -h[ni][nj]);\n            ops.push_back(\"-\" + to_string(unload));\n            h[ni][nj] += unload;\n            load -= unload;\n        } else if (k > 1) {\n            vector<int> perm(k);\n            iota(perm.begin(), perm.end(), 0);\n            int best_total_cost = 1e9;\n            vector<int> best_order;\n            \n            do {\n                int total = 0;\n                int sim_load = load;\n                int sx = cx, sy = cy;\n                for (int idx : perm) {\n                    auto [d, coords] = negs[idx];\n                    auto [ni, nj] = coords;\n                    total += mdist(sx, sy, ni, nj) * (BASE + sim_load);\n                    int need = -h[ni][nj];\n                    int deliver = min(sim_load, need);\n                    sim_load -= deliver;\n                    sx = ni; sy = nj;\n                    if (sim_load == 0) break;\n                }\n                if (total < best_total_cost) {\n                    best_total_cost = total;\n                    best_order = perm;\n                }\n            } while (next_permutation(perm.begin(), perm.end()));\n            \n            for (int idx : best_order) {\n                if (load == 0) break;\n                auto [d, coords] = negs[idx];\n                auto [ni, nj] = coords;\n                move_to(ni, nj);\n                int unload = min(load, -h[ni][nj]);\n                ops.push_back(\"-\" + to_string(unload));\n                h[ni][nj] += unload;\n                load -= unload;\n            }\n        }\n        // If there are still negatives and we have load, continue delivering\n        // (This handles the case where we visited some negatives but not all)\n        while (load > 0) {\n            int best_d = 1e9, ni = -1, nj = -1;\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (h[i][j] < 0) {\n                        int d = mdist(cx, cy, i, j);\n                        if (d < best_d) { best_d = d; ni = i; nj = j; }\n                    }\n            if (ni == -1) break;\n            move_to(ni, nj);\n            int unload = min(load, -h[ni][nj]);\n            ops.push_back(\"-\" + to_string(unload));\n            h[ni][nj] += unload;\n            load -= unload;\n        }\n    };\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (h[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n\n        if (load > 0) {\n            deliver_load();\n            continue;\n        }\n\n        // load == 0: choose the best starting positive\n        // Strategy: evaluate each positive as a \"seed\" for a multi-pickup trip\n        // We'll simulate: go to seed, then collect nearby positives greedily, then deliver\n        \n        int best_total_cost = 1e9;\n        int best_seed_x = -1, best_seed_y = -1;\n        \n        for (int seed_i = 0; seed_i < N; seed_i++) {\n            for (int seed_j = 0; seed_j < N; seed_j++) {\n                if (h[seed_i][seed_j] <= 0) continue;\n                \n                // Simulate a trip starting from this seed\n                int total_cost = mdist(cx, cy, seed_i, seed_j) * BASE;\n                int sim_load = h[seed_i][seed_j];\n                int sx = seed_i, sy = seed_j;\n                \n                // Make a copy of positive heights for simulation\n                vector<vector<int>> sim_pos(N, vector<int>(N, 0));\n                for (int i = 0; i < N; i++)\n                    for (int j = 0; j < N; j++)\n                        if (h[i][j] > 0)\n                            sim_pos[i][j] = h[i][j];\n                sim_pos[seed_i][seed_j] = 0;\n                \n                // Greedily collect nearby positives\n                while (true) {\n                    int best_pi = -1, best_pj = -1, best_d = 1e9;\n                    for (int i = 0; i < N; i++)\n                        for (int j = 0; j < N; j++)\n                            if (sim_pos[i][j] > 0) {\n                                int d = mdist(sx, sy, i, j);\n                                if (d < best_d) { best_d = d; best_pi = i; best_pj = j; }\n                            }\n                    if (best_pi == -1) break;\n                    \n                    // Decide if we should collect this positive\n                    // Heuristic: collect if distance <= 5 or if it's on the way to negatives\n                    // Also consider: the cost of detour vs benefit of not making separate trip\n                    int detour_cost = best_d * (BASE + sim_load);\n                    int future_empty_cost = best_d * BASE; // rough estimate of coming back later\n                    // We also save the delivery cost for this positive's soil separately\n                    // Simplified: collect if distance <= 5\n                    if (best_d <= 5) {\n                        total_cost += best_d * (BASE + sim_load);\n                        sim_load += sim_pos[best_pi][best_pj];\n                        sim_pos[best_pi][best_pj] = 0;\n                        sx = best_pi; sy = best_pj;\n                    } else {\n                        break;\n                    }\n                }\n                \n                // Now simulate delivering sim_load to negatives\n                // Use greedy nearest-negative delivery for simulation\n                int del_sx = sx, del_sy = sy;\n                int del_load = sim_load;\n                vector<vector<int>> sim_neg(N, vector<int>(N, 0));\n                for (int i = 0; i < N; i++)\n                    for (int j = 0; j < N; j++)\n                        if (h[i][j] < 0)\n                            sim_neg[i][j] = -h[i][j]; // store positive demand\n                \n                bool possible = true;\n                while (del_load > 0) {\n                    int best_ni = -1, best_nj = -1, best_d = 1e9;\n                    for (int i = 0; i < N; i++)\n                        for (int j = 0; j < N; j++)\n                            if (sim_neg[i][j] > 0) {\n                                int d = mdist(del_sx, del_sy, i, j);\n                                if (d < best_d) { best_d = d; best_ni = i; best_nj = j; }\n                            }\n                    if (best_ni == -1) { possible = false; break; }\n                    total_cost += best_d * (BASE + del_load);\n                    int deliver = min(del_load, sim_neg[best_ni][best_nj]);\n                    del_load -= deliver;\n                    sim_neg[best_ni][best_nj] -= deliver;\n                    del_sx = best_ni; del_sy = best_nj;\n                }\n                \n                if (!possible) continue;\n                \n                if (total_cost < best_total_cost) {\n                    best_total_cost = total_cost;\n                    best_seed_x = seed_i;\n                    best_seed_y = seed_j;\n                }\n            }\n        }\n\n        if (best_seed_x == -1) break;\n\n        // Execute the multi-pickup trip\n        // Move to seed\n        move_to(best_seed_x, best_seed_y);\n        int amount = h[best_seed_x][best_seed_y];\n        ops.push_back(\"+\" + to_string(amount));\n        load += amount;\n        h[best_seed_x][best_seed_y] = 0;\n\n        // Collect nearby positives (distance <= 5)\n        while (true) {\n            int best_pi = -1, best_pj = -1, best_d = 1e9;\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    if (h[i][j] > 0) {\n                        int d = mdist(cx, cy, i, j);\n                        if (d < best_d) { best_d = d; best_pi = i; best_pj = j; }\n                    }\n            if (best_pi == -1 || best_d > 5) break;\n            \n            move_to(best_pi, best_pj);\n            int amt = h[best_pi][best_pj];\n            ops.push_back(\"+\" + to_string(amt));\n            load += amt;\n            h[best_pi][best_pj] = 0;\n        }\n\n        // Deliver all load\n        deliver_load();\n    }\n\n    for (const auto &s : ops) cout << s << \"\\n\";\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <set>\n#include <queue>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int seed_count = 2 * N * (N - 1);\n    const int grid_size = N * N;\n    \n    vector<vector<int>> X(seed_count, vector<int>(M, 0));\n\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    // Track global maximums\n    vector<int> global_dim_max(M, 0);\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            global_dim_max[j] = max(global_dim_max[j], X[i][j]);\n        }\n    }\n\n    for (int t = 0; t < T; t++) {\n        // Compute seed values\n        vector<int> seed_val(seed_count, 0);\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                seed_val[i] += X[i][j];\n            }\n        }\n        \n        // Current max per dimension and carrier counts\n        vector<int> current_dim_max(M, 0);\n        vector<int> carrier_count(M, 0);\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                current_dim_max[j] = max(current_dim_max[j], X[i][j]);\n            }\n        }\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                if (X[i][j] == current_dim_max[j]) {\n                    carrier_count[j]++;\n                }\n            }\n        }\n        \n        // Score each seed\n        // Key insight: Reward seeds that carry rare maximum values heavily\n        vector<pair<long long, int>> scores;\n        for (int i = 0; i < seed_count; i++) {\n            long long score = (long long)seed_val[i] * 1000LL;\n            \n            // Heavy bonus for carrying rare maximums\n            for (int j = 0; j < M; j++) {\n                if (X[i][j] == current_dim_max[j]) {\n                    // The rarer the gene, the higher the bonus\n                    int rarity = max(1, seed_count - carrier_count[j]);\n                    score += (long long)rarity * rarity * 100LL;\n                }\n            }\n            \n            // Bonus for being close to max (potential to reach max after mating)\n            for (int j = 0; j < M; j++) {\n                if (current_dim_max[j] > 0 && X[i][j] >= current_dim_max[j] * 9 / 10) {\n                    score += 50LL;\n                }\n            }\n            \n            scores.push_back({score, i});\n        }\n        \n        sort(scores.begin(), scores.end(), greater<pair<long long, int>>());\n        \n        // Select top seeds\n        vector<int> selected;\n        set<int> selected_set;\n        for (int i = 0; i < grid_size && i < (int)scores.size(); i++) {\n            selected.push_back(scores[i].second);\n            selected_set.insert(scores[i].second);\n        }\n        \n        // Fill if needed\n        while ((int)selected.size() < grid_size) {\n            for (int i = 0; i < seed_count && (int)selected.size() < grid_size; i++) {\n                if (selected_set.find(i) == selected_set.end()) {\n                    selected.push_back(i);\n                    selected_set.insert(i);\n                }\n            }\n        }\n        selected.resize(grid_size);\n        \n        // Sort selected by value for placement\n        vector<pair<int, int>> sel_sorted;\n        for (int idx : selected) {\n            sel_sorted.push_back({seed_val[idx], idx});\n        }\n        sort(sel_sorted.begin(), sel_sorted.end(), greater<pair<int, int>>());\n        vector<int> sorted_seeds;\n        for (auto& p : sel_sorted) sorted_seeds.push_back(p.second);\n        \n        // Grid arrangement\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        \n        if (t < 2) {\n            // Early turns: Snake pattern for wide mixing\n            int pos = 0;\n            if (t == 0) {\n                // Horizontal snake\n                for (int i = 0; i < N; i++) {\n                    if (i % 2 == 0) {\n                        for (int j = 0; j < N; j++) {\n                            A[i][j] = sorted_seeds[pos++];\n                        }\n                    } else {\n                        for (int j = N - 1; j >= 0; j--) {\n                            A[i][j] = sorted_seeds[pos++];\n                        }\n                    }\n                }\n            } else {\n                // Vertical snake for different mixing pattern\n                for (int j = 0; j < N; j++) {\n                    if (j % 2 == 0) {\n                        for (int i = 0; i < N; i++) {\n                            A[i][j] = sorted_seeds[pos++];\n                        }\n                    } else {\n                        for (int i = N - 1; i >= 0; i--) {\n                            A[i][j] = sorted_seeds[pos++];\n                        }\n                    }\n                }\n            }\n        } else if (t < 4) {\n            // Middle turns: Checkerboard to maximize gene mixing\n            vector<int> group_a, group_b;\n            for (int i = 0; i < (int)sorted_seeds.size(); i++) {\n                if (i < 18) group_a.push_back(sorted_seeds[i]);\n                else group_b.push_back(sorted_seeds[i]);\n            }\n            \n            int pa = 0, pb = 0;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if ((i + j) % 2 == 0) {\n                        if (pa < (int)group_a.size()) A[i][j] = group_a[pa++];\n                        else if (pb < (int)group_b.size()) A[i][j] = group_b[pb++];\n                    } else {\n                        if (pb < (int)group_b.size()) A[i][j] = group_b[pb++];\n                        else if (pa < (int)group_a.size()) A[i][j] = group_a[pa++];\n                    }\n                }\n            }\n        } else if (t < 7) {\n            // Late-middle: Concentric pattern to concentrate good genes\n            vector<pair<int, int>> positions;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    positions.push_back({i, j});\n                }\n            }\n            \n            double cx = (N - 1) / 2.0, cy = (N - 1) / 2.0;\n            sort(positions.begin(), positions.end(), \n                 [cx, cy](const pair<int,int>& a, const pair<int,int>& b) {\n                     double da = pow(a.first - cx, 2) + pow(a.second - cy, 2);\n                     double db = pow(b.first - cx, 2) + pow(b.second - cy, 2);\n                     if (abs(da - db) < 1e-9) {\n                         return a.first * 10 + a.second < b.first * 10 + b.second;\n                     }\n                     return da < db;\n                 });\n            \n            for (int idx = 0; idx < (int)sorted_seeds.size(); idx++) {\n                A[positions[idx].first][positions[idx].second] = sorted_seeds[idx];\n            }\n        } else {\n            // Final turns: Maximize adjacency between top seeds via BFS\n            // Try multiple starting positions and pick the best\n            \n            auto compute_adjacency = [&](const vector<vector<int>>& grid) -> int {\n                set<int> top18;\n                for (int k = 0; k < 18 && k < (int)sorted_seeds.size(); k++) {\n                    top18.insert(sorted_seeds[k]);\n                }\n                int adj = 0;\n                for (int i = 0; i < N; i++) {\n                    for (int j = 0; j < N; j++) {\n                        if (top18.find(grid[i][j]) != top18.end()) {\n                            if (i > 0 && top18.find(grid[i-1][j]) != top18.end()) adj++;\n                            if (j > 0 && top18.find(grid[i][j-1]) != top18.end()) adj++;\n                        }\n                    }\n                }\n                return adj;\n            };\n            \n            int best_adj = -1;\n            vector<vector<int>> best_A;\n            \n            // Predefined starting positions\n            int starts[5][2] = {{N/2, N/2}, {1, 1}, {1, N-2}, {N/2, 1}, {1, N/2}};\n            \n            for (int s = 0; s < 5; s++) {\n                int si = starts[s][0], sj = starts[s][1];\n                if (si < 0 || si >= N || sj < 0 || sj >= N) continue;\n                \n                vector<vector<int>> tryA(N, vector<int>(N, -1));\n                queue<pair<int,int>> q;\n                set<int> placed;\n                \n                tryA[si][sj] = sorted_seeds[0];\n                placed.insert(si * N + sj);\n                q.push({si, sj});\n                int seed_idx = 1;\n                \n                const int di[] = {-1, 1, 0, 0};\n                const int dj[] = {0, 0, -1, 1};\n                \n                while (!q.empty() && seed_idx < (int)sorted_seeds.size()) {\n                    auto [i, j] = q.front();\n                    q.pop();\n                    \n                    for (int d = 0; d < 4; d++) {\n                        int ni = i + di[d];\n                        int nj = j + dj[d];\n                        if (ni >= 0 && ni < N && nj >= 0 && nj < N && \n                            placed.find(ni * N + nj) == placed.end()) {\n                            tryA[ni][nj] = sorted_seeds[seed_idx++];\n                            placed.insert(ni * N + nj);\n                            q.push({ni, nj});\n                        }\n                    }\n                }\n                \n                // Fill remaining\n                for (int i = 0; i < N && seed_idx < (int)sorted_seeds.size(); i++) {\n                    for (int j = 0; j < N && seed_idx < (int)sorted_seeds.size(); j++) {\n                        if (tryA[i][j] == -1) {\n                            tryA[i][j] = sorted_seeds[seed_idx++];\n                        }\n                    }\n                }\n                \n                int adj = compute_adjacency(tryA);\n                if (adj > best_adj) {\n                    best_adj = adj;\n                    best_A = tryA;\n                }\n            }\n            \n            A = best_A;\n        }\n        \n        // Safety: fill any remaining -1 positions\n        set<int> used_in_A;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (A[i][j] != -1) {\n                    used_in_A.insert(A[i][j]);\n                }\n            }\n        }\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (A[i][j] == -1) {\n                    for (int k = 0; k < seed_count; k++) {\n                        if (used_in_A.find(k) == used_in_A.end()) {\n                            A[i][j] = k;\n                            used_in_A.insert(k);\n                            break;\n                        }\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 << A[i][j];\n                if (j < N - 1) cout << \" \";\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read new seeds\n        for (int i = 0; i < seed_count; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                global_dim_max[j] = max(global_dim_max[j], X[i][j]);\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, V;\n    cin >> N >> M >> V;\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n    \n    // Tree: 2 vertices, edge length 1\n    cout << \"2\\n0 1\\n\";\n    int rx = 0, ry = 0;\n    cout << rx << \" \" << ry << \"\\n\";\n    \n    const int DX[4] = {0, 1, 0, -1};\n    const int DY[4] = {1, 0, -1, 0};\n    const char DIR[4] = {'R', 'D', 'L', 'U'};\n    \n    int dir1 = 0;\n    bool holding = false;\n    \n    mt19937 rng(42);\n    \n    for (int turn = 0; turn < 100; turn++) {  // Start with just 100 turns like sample\n        string S(4, '.');\n        \n        // Random move\n        int d = rng() % 4;\n        int nx = rx + DX[d], ny = ry + DY[d];\n        if (nx >= 0 && nx < N && ny >= 0 && ny < N) {\n            rx = nx; ry = ny;\n            S[0] = DIR[d];\n        }\n        \n        // Random rotate\n        int rot = rng() % 3;\n        if (rot == 1) {\n            S[1] = 'L';\n            dir1 = (dir1 + 3) % 4;\n        } else if (rot == 2) {\n            S[1] = 'R';\n            dir1 = (dir1 + 1) % 4;\n        }\n        \n        // Pick or place\n        int x = rx + DX[dir1], y = ry + DY[dir1];\n        if (x >= 0 && x < N && y >= 0 && y < N) {\n            if (s[x][y] == '1' && t[x][y] == '0' && !holding) {\n                S[3] = 'P';\n                s[x][y] = '0';\n                holding = true;\n            } else if (s[x][y] == '0' && t[x][y] == '1' && holding) {\n                S[3] = 'P';\n                s[x][y] = '1';\n                holding = false;\n            }\n        }\n        \n        cout << S << \"\\n\";\n    }\n    \n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_COORD = 100000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> N;\n    \n    vector<int> mx(N), my(N), sx(N), sy(N);\n    for (int i = 0; i < N; i++) cin >> mx[i] >> my[i];\n    for (int i = 0; i < N; i++) cin >> sx[i] >> sy[i];\n    \n    // Build compressed coordinates\n    vector<int> xVals = {0, MAX_COORD}, yVals = {0, MAX_COORD};\n    for (int i = 0; i < N; i++) {\n        xVals.push_back(mx[i]); xVals.push_back(sx[i]);\n        yVals.push_back(my[i]); yVals.push_back(sy[i]);\n    }\n    sort(xVals.begin(), xVals.end());\n    xVals.erase(unique(xVals.begin(), xVals.end()), xVals.end());\n    sort(yVals.begin(), yVals.end());\n    yVals.erase(unique(yVals.begin(), yVals.end()), yVals.end());\n    \n    vector<int> xs = xVals, ys = yVals;\n    if ((int)xs.size() > 500) {\n        vector<int> nx; int step = xs.size() / 500;\n        for (int i = 0; i < (int)xs.size(); i += step) nx.push_back(xs[i]);\n        if (nx.back() != xs.back()) nx.push_back(xs.back());\n        xs = nx;\n    }\n    if ((int)ys.size() > 500) {\n        vector<int> ny; int step = ys.size() / 500;\n        for (int i = 0; i < (int)ys.size(); i += step) ny.push_back(ys[i]);\n        if (ny.back() != ys.back()) ny.push_back(ys.back());\n        ys = ny;\n    }\n    \n    int X = xs.size(), Y = ys.size();\n    \n    vector<vector<int>> mPref(Y + 1, vector<int>(X + 1, 0));\n    vector<vector<int>> sPref(Y + 1, vector<int>(X + 1, 0));\n    \n    for (int i = 0; i < N; i++) {\n        int ix = lower_bound(xs.begin(), xs.end(), mx[i]) - xs.begin();\n        int iy = lower_bound(ys.begin(), ys.end(), my[i]) - ys.begin();\n        if (ix < X && iy < Y) mPref[iy + 1][ix + 1]++;\n    }\n    for (int i = 0; i < N; i++) {\n        int ix = lower_bound(xs.begin(), xs.end(), sx[i]) - xs.begin();\n        int iy = lower_bound(ys.begin(), ys.end(), sy[i]) - ys.begin();\n        if (ix < X && iy < Y) sPref[iy + 1][ix + 1]++;\n    }\n    \n    for (int i = 0; i < Y; i++)\n        for (int j = 0; j < X; j++) {\n            mPref[i+1][j+1] += mPref[i][j+1] + mPref[i+1][j] - mPref[i][j];\n            sPref[i+1][j+1] += sPref[i][j+1] + sPref[i+1][j] - sPref[i][j];\n        }\n    \n    auto scoreComp = [&](int ix1, int ix2, int iy1, int iy2) {\n        if (ix1 > ix2 || iy1 > iy2) return 0;\n        int m = mPref[iy2+1][ix2+1] - mPref[iy1][ix2+1] - mPref[iy2+1][ix1] + mPref[iy1][ix1];\n        int s = sPref[iy2+1][ix2+1] - sPref[iy1][ix2+1] - sPref[iy2+1][ix1] + sPref[iy1][ix1];\n        return m - s;\n    };\n    \n    // Find best initial rectangle\n    auto findRects = [&](int G, vector<tuple<int,int,int,int,int>> &out) {\n        int cw = (MAX_COORD + G - 1) / G, ch = (MAX_COORD + G - 1) / G;\n        vector<vector<int>> val(G, vector<int>(G, 0));\n        for (int i = 0; i < G; i++) {\n            for (int j = 0; j < G; j++) {\n                int ix1 = lower_bound(xs.begin(), xs.end(), j*cw) - xs.begin();\n                int ix2 = upper_bound(xs.begin(), xs.end(), min(MAX_COORD, (j+1)*cw)) - xs.begin() - 1;\n                int iy1 = lower_bound(ys.begin(), ys.end(), i*ch) - ys.begin();\n                int iy2 = upper_bound(ys.begin(), ys.end(), min(MAX_COORD, (i+1)*ch)) - ys.begin() - 1;\n                val[i][j] = scoreComp(ix1, ix2, iy1, iy2);\n            }\n        }\n        \n        vector<vector<int>> prefG(G+1, vector<int>(G+1, 0));\n        for (int i = 0; i < G; i++)\n            for (int j = 0; j < G; j++)\n                prefG[i+1][j+1] = val[i][j] + prefG[i][j+1] + prefG[i+1][j] - prefG[i][j];\n        \n        for (int r1 = 0; r1 < G; r1++) {\n            vector<int> rowSum(G, 0);\n            for (int r2 = r1; r2 < G; r2++) {\n                for (int c = 0; c < G; c++) rowSum[c] += val[r2][c];\n                int curr = 0, maxS = -1e9, cS = 0, cB = 0, cE = 0;\n                for (int c = 0; c < G; c++) {\n                    if (curr <= 0) { curr = rowSum[c]; cS = c; }\n                    else curr += rowSum[c];\n                    if (curr > maxS) { maxS = curr; cB = cS; cE = c; }\n                }\n                if (maxS > 0) out.push_back({r1, cB, r2, cE, maxS});\n            }\n        }\n    };\n    \n    vector<tuple<int,int,int,int,int>> allRects;\n    findRects(80, allRects);\n    findRects(50, allRects);\n    \n    sort(allRects.begin(), allRects.end(), \n         [](const auto &a, const auto &b) { return get<4>(a) > get<4>(b); });\n    if (allRects.size() > 25) allRects.resize(25);\n    \n    int bestScore = -1e9;\n    vector<pair<int,int>> bestPolygon;\n    \n    vector<int> iX, iY;\n    int stepX = max(1, X / 25), stepY = max(1, Y / 25);\n    for (int i = 0; i < X; i += stepX) iX.push_back(i);\n    for (int i = 0; i < Y; i += stepY) iY.push_back(i);\n    \n    // Helper to simplify and validate a polygon\n    auto processPolygon = [&](const vector<pair<int,int>> &v, int score) {\n        int sz = v.size();\n        vector<pair<int,int>> simp;\n        for (int i = 0; i < sz; i++) {\n            int p = (i-1+sz)%sz, n = (i+1)%sz;\n            if (!((v[p].first==v[i].first && v[i].first==v[n].first) ||\n                  (v[p].second==v[i].second && v[i].second==v[n].second)))\n                simp.push_back(v[i]);\n        }\n        if (simp.size() < 4) simp = v;\n        if ((int)simp.size() > 1000) return false;\n        \n        long long perim = 0;\n        for (int i = 0; i < (int)simp.size(); i++) {\n            int j = (i+1)%simp.size();\n            perim += abs(simp[i].first-simp[j].first) + abs(simp[i].second-simp[j].second);\n        }\n        if (perim > 400000) return false;\n        \n        if (score > bestScore) {\n            bestScore = score;\n            bestPolygon = simp;\n        }\n        return true;\n    };\n    \n    for (auto &[r1, c1, r2, c2, approxVal] : allRects) {\n        int G = (r2 < 50 && c2 < 50) ? 50 : 80;\n        int cw = (MAX_COORD + G - 1) / G, ch = (MAX_COORD + G - 1) / G;\n        \n        int ix1 = lower_bound(xs.begin(), xs.end(), c1 * cw) - xs.begin();\n        int ix2 = upper_bound(xs.begin(), xs.end(), min(MAX_COORD, (c2+1)*cw)) - xs.begin() - 1;\n        int iy1 = lower_bound(ys.begin(), ys.end(), r1 * ch) - ys.begin();\n        int iy2 = upper_bound(ys.begin(), ys.end(), min(MAX_COORD, (r2+1)*ch)) - ys.begin() - 1;\n        \n        if (ix1 >= ix2 || iy1 >= iy2) continue;\n        \n        int curScore = scoreComp(ix1, ix2, iy1, iy2);\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = ix1+1; i <= ix2 && !changed; i++) {\n                int s = scoreComp(i, ix2, iy1, iy2);\n                if (s > curScore) { curScore = s; ix1 = i; changed = true; }\n            }\n            for (int i = ix2-1; i >= ix1 && !changed; i--) {\n                int s = scoreComp(ix1, i, iy1, iy2);\n                if (s > curScore) { curScore = s; ix2 = i; changed = true; }\n            }\n            for (int i = iy1+1; i <= iy2 && !changed; i++) {\n                int s = scoreComp(ix1, ix2, i, iy2);\n                if (s > curScore) { curScore = s; iy1 = i; changed = true; }\n            }\n            for (int i = iy2-1; i >= iy1 && !changed; i--) {\n                int s = scoreComp(ix1, ix2, iy1, i);\n                if (s > curScore) { curScore = s; iy2 = i; changed = true; }\n            }\n        }\n        \n        int x1 = xs[ix1], x2 = xs[ix2], y1 = ys[iy1], y2 = ys[iy2];\n        \n        // Rectangle\n        processPolygon({{x1,y1},{x2,y1},{x2,y2},{x1,y2}}, curScore);\n        \n        // L-shapes\n        for (int icx : iX) {\n            int cx = xs[icx]; if (cx <= x1 || cx >= x2) continue;\n            for (int icy : iY) {\n                int cy = ys[icy]; if (cy <= y1 || cy >= y2) continue;\n                \n                int s = scoreComp(icx, ix2, iy1, iy2) + scoreComp(ix1, icx-1, icy, iy2);\n                if (s > curScore) processPolygon({{cx,cy},{x2,cy},{x2,y2},{x1,y2},{x1,y1},{cx,y1}}, s);\n                \n                s = scoreComp(ix1, icx, iy1, iy2) + scoreComp(icx+1, ix2, icy, iy2);\n                if (s > curScore) processPolygon({{cx,cy},{x1,cy},{x1,y2},{x2,y2},{x2,y1},{cx,y1}}, s);\n                \n                s = scoreComp(ix1, ix2, iy1, icy) + scoreComp(ix1, icx, icy+1, iy2);\n                if (s > curScore) processPolygon({{cx,cy},{x1,cy},{x1,y1},{x2,y1},{x2,y2},{cx,y2}}, s);\n                \n                s = scoreComp(ix1, ix2, iy1, icy) + scoreComp(icx, ix2, icy+1, iy2);\n                if (s > curScore) processPolygon({{cx,cy},{x2,cy},{x2,y1},{x1,y1},{x1,y2},{cx,y2}}, s);\n            }\n        }\n        \n        // C-shapes\n        for (int icy : iY) {\n            int cy = ys[icy]; if (cy <= y1 || cy >= y2) continue;\n            for (int icx1 : iX) {\n                int cx1 = xs[icx1]; if (cx1 <= x1 || cx1 >= x2) continue;\n                for (int icx2 : iX) {\n                    int cx2 = xs[icx2]; if (cx2 <= cx1 || cx2 >= x2) continue;\n                    int s = scoreComp(ix1, icx1, iy1, iy2) + \n                            scoreComp(icx2, ix2, iy1, iy2) + \n                            scoreComp(icx1, icx2-1, icy, iy2);\n                    if (s > curScore)\n                        processPolygon({{cx1,cy},{cx2,cy},{cx2,y1},{x2,y1},{x2,y2},\n                                      {x1,y2},{x1,y1},{cx1,y1}}, s);\n                }\n            }\n        }\n    }\n    \n    if (bestPolygon.empty()) {\n        bestPolygon = {{0,0},{100,0},{100,100},{0,100}};\n    }\n    \n    cout << bestPolygon.size() << \"\\n\";\n    for (auto [x,y] : bestPolygon) cout << x << \" \" << y << \"\\n\";\n    \n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T, sigma;\nvector<long long> est_w, est_h;\n\nstruct Placement {\n    int p, r, d;\n    int b;\n};\n\npair<long long, long long> query(const vector<Placement>& placements) {\n    cout << placements.size() << \"\\n\";\n    for (const auto& pl : placements) {\n        cout << pl.p << \" \" << pl.r << \" \" << (pl.d == 0 ? \"U\" : \"L\") << \" \" << pl.b << \"\\n\";\n    }\n    cout.flush();\n    long long W, H;\n    cin >> W >> H;\n    return {W, H};\n}\n\n// Strategy 1: Shelf packing using U operations\n// Start new shelf with b=-1, continue shelf with b=prev\nvector<Placement> shelf_packing(double shelf_width_limit_ratio) {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long>> placed;\n    \n    long long current_shelf_y = 0;\n    long long current_shelf_x = 0;\n    long long current_shelf_h = 0;\n    long long max_W = 0;\n    \n    for (int idx = 0; idx < N; idx++) {\n        long long w0 = est_w[idx], h0 = est_h[idx];\n        \n        // Try both rotations, pick better one\n        int best_rot = 0;\n        long long best_w = w0, best_h = h0;\n        long long best_marginal = LLONG_MAX;\n        int best_ref = -1;\n        long long best_x = 0, best_y = 0;\n        \n        for (int rot : {0, 1}) {\n            long long w = w0, h = h0;\n            if (rot == 1) swap(w, h);\n            \n            // Option A: Start new shelf (U, b=-1)\n            {\n                long long x = 0, y = 0;\n                for (const auto& [px, py, pw, ph] : placed) {\n                    if (x < px + pw && x + w > px) y = max(y, py + ph);\n                }\n                long long new_W = max(max_W, x + w);\n                long long new_H = max({current_shelf_y + current_shelf_h, y + h});\n                long long marginal = (new_W - max_W) + (new_H - max(current_shelf_y + current_shelf_h, 0LL));\n                if (marginal < best_marginal) {\n                    best_marginal = marginal;\n                    best_rot = rot; best_w = w; best_h = h;\n                    best_ref = -1;\n                    best_x = x; best_y = y;\n                }\n            }\n            \n            // Option B: Continue current shelf (U, b=last_placed)\n            if (!placed.empty()) {\n                int last_pos = (int)placed.size() - 1;\n                long long x = get<0>(placed[last_pos]) + get<2>(placed[last_pos]);\n                long long y = 0;\n                for (const auto& [px, py, pw, ph] : placed) {\n                    if (x < px + pw && x + w > px) y = max(y, py + ph);\n                }\n                long long new_W = max(max_W, x + w);\n                long long new_H = max(current_shelf_y + current_shelf_h, y + h);\n                long long marginal = (new_W - max_W) + (new_H - max(current_shelf_y + current_shelf_h, 0LL));\n                \n                // Check if it fits on current shelf (y should match shelf bottom)\n                if (y == current_shelf_y + current_shelf_h && marginal < best_marginal) {\n                    best_marginal = marginal;\n                    best_rot = rot; best_w = w; best_h = h;\n                    best_ref = last_pos;\n                    best_x = x; best_y = y;\n                }\n            }\n            \n            // Option C: U with reference to any placed rect that fits well\n            for (int pi = 0; pi < (int)placed.size(); pi++) {\n                long long x = get<0>(placed[pi]) + get<2>(placed[pi]);\n                long long y = 0;\n                for (const auto& [px, py, pw, ph] : placed) {\n                    if (x < px + pw && x + w > px) y = max(y, py + ph);\n                }\n                long long new_W = max(max_W, x + w);\n                long long new_H = max(current_shelf_y + current_shelf_h, y + h);\n                long long marginal = (new_W - max_W) + (new_H - max(current_shelf_y + current_shelf_h, 0LL));\n                if (marginal < best_marginal) {\n                    best_marginal = marginal;\n                    best_rot = rot; best_w = w; best_h = h;\n                    best_ref = pi;\n                    best_x = x; best_y = y;\n                }\n            }\n        }\n        \n        Placement p;\n        p.p = idx; p.r = best_rot; p.d = 0; p.b = best_ref; // Always U\n        placements.push_back(p);\n        placed.emplace_back(best_x, best_y, best_w, best_h);\n        max_W = max(max_W, best_x + best_w);\n        if (best_ref == -1) {\n            // New shelf started\n            current_shelf_y = best_y;\n            current_shelf_h = best_h;\n            current_shelf_x = best_w;\n        } else {\n            current_shelf_h = max(current_shelf_h, best_y + best_h - current_shelf_y);\n            current_shelf_x = max(current_shelf_x, best_x + best_w);\n        }\n    }\n    \n    return placements;\n}\n\n// Strategy 2: Column packing using L operations\nvector<Placement> column_packing() {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long>> placed;\n    \n    long long max_W = 0, max_H = 0;\n    \n    for (int idx = 0; idx < N; idx++) {\n        long long w0 = est_w[idx], h0 = est_h[idx];\n        \n        int best_rot = 0;\n        long long best_w = w0, best_h = h0;\n        long long best_sum = LLONG_MAX;\n        int best_ref = -1;\n        long long best_x = 0, best_y = 0;\n        \n        for (int rot : {0, 1}) {\n            long long w = w0, h = h0;\n            if (rot == 1) swap(w, h);\n            \n            // L with b=-1\n            {\n                long long y = 0, x = 0;\n                for (const auto& [px, py, pw, ph] : placed) {\n                    if (y < py + ph && y + h > py) x = max(x, px + pw);\n                }\n                long long nW = max(max_W, x + w);\n                long long nH = max(max_H, y + h);\n                if (nW + nH < best_sum) {\n                    best_sum = nW + nH;\n                    best_rot = rot; best_w = w; best_h = h;\n                    best_ref = -1; best_x = x; best_y = y;\n                }\n            }\n            \n            // L with reference to placed\n            for (int pi = 0; pi < (int)placed.size(); pi++) {\n                long long y = get<1>(placed[pi]) + get<3>(placed[pi]);\n                long long x = 0;\n                for (const auto& [px, py, pw, ph] : placed) {\n                    if (y < py + ph && y + h > py) x = max(x, px + pw);\n                }\n                long long nW = max(max_W, x + w);\n                long long nH = max(max_H, y + h);\n                if (nW + nH < best_sum) {\n                    best_sum = nW + nH;\n                    best_rot = rot; best_w = w; best_h = h;\n                    best_ref = pi; best_x = x; best_y = y;\n                }\n            }\n        }\n        \n        Placement p;\n        p.p = idx; p.r = best_rot; p.d = 1; p.b = best_ref; // Always L\n        placements.push_back(p);\n        placed.emplace_back(best_x, best_y, best_w, best_h);\n        max_W = max(max_W, best_x + best_w);\n        max_H = max(max_H, best_y + best_h);\n    }\n    \n    return placements;\n}\n\n// Strategy 3: Smart hybrid - choose U or L based on rectangle shape\nvector<Placement> hybrid_packing() {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long>> placed;\n    long long max_W = 0, max_H = 0;\n    \n    for (int idx = 0; idx < N; idx++) {\n        long long w0 = est_w[idx], h0 = est_h[idx];\n        \n        int best_rot = 0, best_dir = 0, best_ref = -1;\n        long long best_w = w0, best_h = h0;\n        long long best_sum = LLONG_MAX;\n        long long best_x = 0, best_y = 0;\n        \n        for (int rot : {0, 1}) {\n            long long w = w0, h = h0;\n            if (rot == 1) swap(w, h);\n            \n            // Prefer U for wide rectangles, L for tall ones\n            vector<int> dirs;\n            if (w >= h) dirs = {0, 1}; // Try U first\n            else dirs = {1, 0}; // Try L first\n            \n            for (int dir : dirs) {\n                // b=-1\n                {\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (x < px + pw && x + w > px) y = max(y, py + ph);\n                        }\n                    } else {\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (y < py + ph && y + h > py) x = max(x, px + pw);\n                        }\n                    }\n                    long long nW = max(max_W, x + w);\n                    long long nH = max(max_H, y + h);\n                    if (nW + nH < best_sum) {\n                        best_sum = nW + nH;\n                        best_rot = rot; best_dir = dir; best_ref = -1;\n                        best_w = w; best_h = h; best_x = x; best_y = y;\n                    }\n                }\n                \n                // b=placed\n                for (int pi = 0; pi < (int)placed.size(); pi++) {\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        x = get<0>(placed[pi]) + get<2>(placed[pi]);\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (x < px + pw && x + w > px) y = max(y, py + ph);\n                        }\n                    } else {\n                        y = get<1>(placed[pi]) + get<3>(placed[pi]);\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (y < py + ph && y + h > py) x = max(x, px + pw);\n                        }\n                    }\n                    long long nW = max(max_W, x + w);\n                    long long nH = max(max_H, y + h);\n                    if (nW + nH < best_sum) {\n                        best_sum = nW + nH;\n                        best_rot = rot; best_dir = dir; best_ref = pi;\n                        best_w = w; best_h = h; best_x = x; best_y = y;\n                    }\n                }\n            }\n        }\n        \n        Placement p;\n        p.p = idx; p.r = best_rot; p.d = best_dir; p.b = best_ref;\n        placements.push_back(p);\n        placed.emplace_back(best_x, best_y, best_w, best_h);\n        max_W = max(max_W, best_x + best_w);\n        max_H = max(max_H, best_y + best_h);\n    }\n    \n    return placements;\n}\n\n// Strategy 4: Greedy with all options (original approach)\nvector<Placement> greedy_all_options(int dir_bias) {\n    vector<Placement> placements;\n    vector<tuple<long long, long long, long long, long long>> placed;\n    long long cur_W = 0, cur_H = 0;\n    \n    for (int idx = 0; idx < N; idx++) {\n        long long w0 = est_w[idx], h0 = est_h[idx];\n        \n        int best_rot = 0, best_dir = 0, best_ref = -1;\n        long long best_x = 0, best_y = 0, best_w = 0, best_h = 0;\n        long long best_sum = LLONG_MAX;\n        \n        for (int rot : {0, 1}) {\n            long long w = w0, h = h0;\n            if (rot == 1) swap(w, h);\n            \n            vector<int> dirs;\n            if (dir_bias == 1) dirs = {0, 1};\n            else if (dir_bias == -1) dirs = {1, 0};\n            else dirs = {0, 1};\n            \n            for (int dir : dirs) {\n                // b=-1\n                {\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (x < px + pw && x + w > px) y = max(y, py + ph);\n                        }\n                    } else {\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (y < py + ph && y + h > py) x = max(x, px + pw);\n                        }\n                    }\n                    long long nW = max(cur_W, x + w);\n                    long long nH = max(cur_H, y + h);\n                    if (nW + nH < best_sum) {\n                        best_sum = nW + nH;\n                        best_rot = rot; best_dir = dir; best_ref = -1;\n                        best_x = x; best_y = y; best_w = w; best_h = h;\n                    }\n                }\n                \n                // b=placed\n                for (int pi = 0; pi < (int)placed.size(); pi++) {\n                    long long x = 0, y = 0;\n                    if (dir == 0) {\n                        x = get<0>(placed[pi]) + get<2>(placed[pi]);\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (x < px + pw && x + w > px) y = max(y, py + ph);\n                        }\n                    } else {\n                        y = get<1>(placed[pi]) + get<3>(placed[pi]);\n                        for (const auto& [px, py, pw, ph] : placed) {\n                            if (y < py + ph && y + h > py) x = max(x, px + pw);\n                        }\n                    }\n                    long long nW = max(cur_W, x + w);\n                    long long nH = max(cur_H, y + h);\n                    if (nW + nH < best_sum) {\n                        best_sum = nW + nH;\n                        best_rot = rot; best_dir = dir; best_ref = pi;\n                        best_x = x; best_y = y; best_w = w; best_h = h;\n                    }\n                }\n            }\n        }\n        \n        Placement p;\n        p.p = idx; p.r = best_rot; p.d = best_dir; p.b = best_ref;\n        placements.push_back(p);\n        placed.emplace_back(best_x, best_y, best_w, best_h);\n        cur_W = max(cur_W, best_x + best_w);\n        cur_H = max(cur_H, best_y + best_h);\n    }\n    \n    return placements;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    cin >> N >> T >> sigma;\n    est_w.resize(N);\n    est_h.resize(N);\n    \n    for (int i = 0; i < N; i++) {\n        cin >> est_w[i] >> est_h[i];\n    }\n    \n    auto time_limit = chrono::milliseconds(2950);\n    long long best_score = LLONG_MAX;\n    \n    // Strategy list\n    struct Strategy {\n        string name;\n        function<vector<Placement>()> func;\n    };\n    \n    vector<Strategy> strategies;\n    \n    // Add shelf packing with different parameters\n    strategies.push_back({\"shelf\", []() { return shelf_packing(1.0); }});\n    strategies.push_back({\"shelf_wide\", []() { return shelf_packing(2.0); }});\n    \n    // Column packing\n    strategies.push_back({\"column\", column_packing});\n    \n    // Hybrid\n    strategies.push_back({\"hybrid\", hybrid_packing});\n    \n    // Greedy with different biases\n    strategies.push_back({\"greedy_U\", []() { return greedy_all_options(1); }});\n    strategies.push_back({\"greedy_L\", []() { return greedy_all_options(-1); }});\n    strategies.push_back({\"greedy_neutral\", []() { return greedy_all_options(0); }});\n    \n    // Track best per strategy\n    vector<long long> strat_best(strategies.size(), LLONG_MAX);\n    \n    for (int turn = 0; turn < T; turn++) {\n        auto elapsed = chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - start_time);\n        if (elapsed > time_limit) break;\n        \n        int si = turn % strategies.size();\n        vector<Placement> placements = strategies[si].func();\n        \n        auto [W, H] = query(placements);\n        \n        vector<bool> used(N, false);\n        for (const auto& pl : placements) used[pl.p] = true;\n        long long penalty = 0;\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) penalty += est_w[i] + est_h[i];\n        }\n        long long score = W + H + penalty;\n        \n        if (score < strat_best[si]) strat_best[si] = score;\n        if (score < best_score) best_score = score;\n    }\n    \n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nstruct Xor128 {\n    unsigned x,y,z,w;\n    Xor128(unsigned s=123456789):x(s),y(362436069),z(521288629),w(88675123){}\n    unsigned next(){unsigned t=x^(x<<11);x=y;y=z;z=w;return w=w^(w>>19)^t^(t>>8);}\n    double prob(){return next()/4294967295.0;}\n};\n\nint main(){\n    auto start=steady_clock::now();\n    ios::sync_with_stdio(false);cin.tie(nullptr);\n    int N,M,H;cin>>N>>M>>H;\n    vector<int> A(N);\n    for(int i=0;i<N;++i)cin>>A[i];\n    vector<pair<int,int>> edges(M);\n    for(int i=0;i<M;++i)cin>>edges[i].first>>edges[i].second;\n    for(int i=0;i<N;++i){int x,y;cin>>x>>y;}\n\n    vector<vector<int>> adj(N);\n    for(auto&e:edges){\n        adj[e.first].push_back(e.second);\n        adj[e.second].push_back(e.first);\n    }\n\n    vector<vector<int>> ch(N);\n    vector<int> depth(N,-1), maxSubDepth(N,0);\n    auto rebuildAndValidate=[&](const vector<int>& par)->pair<bool,long long>{\n        for(int i=0;i<N;++i)ch[i].clear();\n        for(int i=0;i<N;++i)if(par[i]!=-1)ch[par[i]].push_back(i);\n        fill(depth.begin(),depth.end(),-1);\n        queue<int> q;\n        for(int i=0;i<N;++i)if(par[i]==-1){depth[i]=0;q.push(i);}\n        int cnt=0;\n        vector<int> order;\n        while(!q.empty()){\n            int v=q.front();q.pop();cnt++;\n            if(depth[v]>H)return {false,0};\n            order.push_back(v);\n            for(int c:ch[v]){\n                if(depth[c]!=-1)return {false,0};\n                depth[c]=depth[v]+1;\n                q.push(c);\n            }\n        }\n        if(cnt!=N)return {false,0};\n        fill(maxSubDepth.begin(),maxSubDepth.end(),0);\n        for(int i=N-1;i>=0;--i){\n            int v=order[i];\n            int mx=0;\n            for(int c:ch[v])mx=max(mx,maxSubDepth[c]+1);\n            maxSubDepth[v]=mx;\n        }\n        long long sc=1;\n        for(int i=0;i<N;++i)sc+=(depth[i]+1LL)*A[i];\n        return {true,sc};\n    };\n\n    Xor128 rng(12345);\n    vector<int> bestParent(N,-1);\n    long long bestScore=-1;\n\n    for(int trial=0;trial<12;++trial){\n        vector<int> parent(N,-1);\n        vector<int> order(N);iota(order.begin(),order.end(),0);\n        if(trial==0)sort(order.begin(),order.end(),[&](int i,int j){return A[i]>A[j];});\n        else shuffle(order.begin(),order.end(),mt19937(rng.next()));\n        vector<bool> placed(N,false);\n        vector<int> tmpD(N,0);\n        for(int u:order){\n            int bestp=-1,bestd=-1;\n            for(int p:adj[u])if(placed[p]&&tmpD[p]<H){\n                if(tmpD[p]>bestd){bestd=tmpD[p];bestp=p;}\n            }\n            if(bestp!=-1){parent[u]=bestp;tmpD[u]=bestd+1;}\n            else{parent[u]=-1;tmpD[u]=0;}\n            placed[u]=true;\n        }\n        auto [ok,sc]=rebuildAndValidate(parent);\n        if(ok&&sc>bestScore){bestScore=sc;bestParent=parent;}\n    }\n\n    vector<int> curParent=bestParent;\n    long long curScore=bestScore;\n    rebuildAndValidate(curParent);\n\n    double T0=250.0,T1=0.2;\n    int maxIter=110000;\n    for(int iter=0;iter<maxIter;++iter){\n        if(steady_clock::now()-start>milliseconds(1900))break;\n        double progress=(double)iter/maxIter;\n        double T=T0*pow(T1/T0,progress);\n        int type=rng.next()%10;\n        vector<int> newPar=curParent;\n        if(type<7){\n            int u=rng.next()%N;\n            if(adj[u].empty())continue;\n            int oldp=newPar[u];\n            int oldd=depth[u];\n            vector<int> cand;\n            for(int p:adj[u])if(p!=oldp&&p!=u){\n                if(depth[p]+1+maxSubDepth[u]<=H) cand.push_back(p);\n            }\n            if(cand.empty())continue;\n            // prefer deeper new parent\n            int bestp=cand[0];int bestd=depth[bestp];\n            for(int p:cand)if(depth[p]>bestd){bestd=depth[p];bestp=p;}\n            newPar[u]=bestp;\n        }else{\n            int u=rng.next()%N;\n            if(newPar[u]==-1)continue;\n            int oldp=newPar[u];\n            vector<int> cand;\n            for(int p:adj[u])if(p!=oldp&&p!=u){\n                if(depth[p]+1+maxSubDepth[u]<=H) cand.push_back(p);\n            }\n            if(cand.empty())continue;\n            int p=cand[rng.next()%cand.size()];\n            newPar[u]=p;\n        }\n        auto [ok,newSc]=rebuildAndValidate(newPar);\n        if(ok){\n            long long delta=newSc-curScore;\n            if(delta>=0||rng.prob()<exp(delta/T)){\n                curScore=newSc;curParent=newPar;\n                if(curScore>bestScore){bestScore=curScore;bestParent=curParent;}\n            }\n        }\n    }\n\n    // final greedy\n    for(int phase=0;phase<5;++phase){\n        if(steady_clock::now()-start>milliseconds(1950))break;\n        vector<int> order(N);iota(order.begin(),order.end(),0);\n        shuffle(order.begin(),order.end(),mt19937(rng.next()));\n        for(int u:order){\n            int oldp=curParent[u];\n            long long bestGain=0;\n            int bestp=oldp;\n            for(int p:adj[u]){\n                if(p==u||p==oldp)continue;\n                curParent[u]=p;\n                auto [ok,sc]=rebuildAndValidate(curParent);\n                if(ok){\n                    long long gain=sc-curScore;\n                    if(gain>bestGain){bestGain=gain;bestp=p;}\n                }\n            }\n            if(bestp!=oldp){\n                curParent[u]=bestp;\n                auto [ok,sc]=rebuildAndValidate(curParent);\n                curScore=sc;\n                if(curScore>bestScore){bestScore=curScore;bestParent=curParent;}\n                break;\n            }else{\n                curParent[u]=oldp;\n            }\n        }\n    }\n\n    for(int i=0;i<N;++i){\n        if(i)cout<<' ';\n        cout<<bestParent[i];\n    }\n    cout<<'\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\nusing pii = pair<int,int>;\nusing namespace chrono;\n\nint N;\nvector<string> orig_board;\nvector<pii> oni_pos;\nvector<unordered_map<char,int>> dist;\nint M;\n\nint compute_cost(const vector<char>& assign) {\n    map<pair<int,char>, int> max_d;\n    for (int k = 0; k < M; k++) {\n        char dir = assign[k];\n        int idx = (dir == 'L' || dir == 'R') ? oni_pos[k].first : oni_pos[k].second;\n        int d = dist[k].at(dir);\n        auto key = make_pair(idx, dir);\n        if (d > max_d[key]) max_d[key] = d;\n    }\n    int total = 0;\n    for (auto& [key, d] : max_d) total += 2 * d;\n    return total;\n}\n\nvector<char> local_search(vector<char> assign, int& cost) {\n    cost = compute_cost(assign);\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        // Try 1-opt moves\n        for (int k = 0; k < M; k++) {\n            char old_dir = assign[k];\n            for (auto& [new_dir, _] : dist[k]) {\n                if (new_dir == old_dir) continue;\n                assign[k] = new_dir;\n                int new_cost = compute_cost(assign);\n                if (new_cost < cost) {\n                    cost = new_cost;\n                    improved = true;\n                    break;\n                } else {\n                    assign[k] = old_dir;\n                }\n            }\n            if (improved) break;\n        }\n        if (!improved) {\n            // Try 2-opt: swap assignments of two Oni\n            for (int k1 = 0; k1 < M && !improved; k1++) {\n                for (int k2 = k1+1; k2 < M && !improved; k2++) {\n                    char d1 = assign[k1], d2 = assign[k2];\n                    // Check if swapping is valid\n                    if (dist[k1].count(d2) && dist[k2].count(d1)) {\n                        assign[k1] = d2;\n                        assign[k2] = d1;\n                        int new_cost = compute_cost(assign);\n                        if (new_cost < cost) {\n                            cost = new_cost;\n                            improved = true;\n                            break;\n                        } else {\n                            assign[k1] = d1;\n                            assign[k2] = d2;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return assign;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto start_time = high_resolution_clock::now();\n    \n    cin >> N;\n    orig_board.resize(N);\n    for (int i = 0; i < N; i++) cin >> orig_board[i];\n    \n    // Collect Oni positions\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            if (orig_board[i][j] == 'x') oni_pos.push_back({i, j});\n    M = oni_pos.size();\n    \n    if (M == 0) return 0;\n    \n    // Determine valid directions for each Oni\n    dist.resize(M);\n    for (int k = 0; k < M; k++) {\n        int i = oni_pos[k].first, j = oni_pos[k].second;\n        \n        bool up_ok = true;\n        for (int r = 0; r < i; r++) if (orig_board[r][j] == 'o') up_ok = false;\n        if (up_ok) dist[k]['U'] = i + 1;\n        \n        bool down_ok = true;\n        for (int r = i+1; r < N; r++) if (orig_board[r][j] == 'o') down_ok = false;\n        if (down_ok) dist[k]['D'] = N - i;\n        \n        bool left_ok = true;\n        for (int c = 0; c < j; c++) if (orig_board[i][c] == 'o') left_ok = false;\n        if (left_ok) dist[k]['L'] = j + 1;\n        \n        bool right_ok = true;\n        for (int c = j+1; c < N; c++) if (orig_board[i][c] == 'o') right_ok = false;\n        if (right_ok) dist[k]['R'] = N - j;\n    }\n    \n    // Initial assignment: best individual direction\n    vector<char> best_assign(M);\n    for (int k = 0; k < M; k++) {\n        int best_d = 1e9;\n        char best_c = 0;\n        for (auto& [c, d] : dist[k]) {\n            if (d < best_d) { best_d = d; best_c = c; }\n        }\n        best_assign[k] = best_c;\n    }\n    int best_cost = compute_cost(best_assign);\n    best_assign = local_search(best_assign, best_cost);\n    \n    // Try multiple random starts within time limit\n    mt19937 rng(42);\n    int trials = 0;\n    while (true) {\n        auto now = high_resolution_clock::now();\n        if (duration_cast<milliseconds>(now - start_time).count() > 1500) break;\n        \n        // Generate random assignment\n        vector<char> assign(M);\n        for (int k = 0; k < M; k++) {\n            int idx = rng() % dist[k].size();\n            auto it = dist[k].begin();\n            advance(it, idx);\n            assign[k] = it->first;\n        }\n        int cost;\n        assign = local_search(assign, cost);\n        \n        if (cost < best_cost) {\n            best_cost = cost;\n            best_assign = assign;\n        }\n        trials++;\n    }\n    \n    // Execute the best assignment\n    vector<string> b = orig_board;\n    vector<pair<char,int>> ops;\n    \n    auto shiftRowLeft = [&](int i) {\n        ops.push_back({'L', i});\n        for (int j = 0; j < N-1; j++) b[i][j] = b[i][j+1];\n        b[i][N-1] = '.';\n    };\n    auto shiftRowRight = [&](int i) {\n        ops.push_back({'R', i});\n        for (int j = N-1; j > 0; j--) b[i][j] = b[i][j-1];\n        b[i][0] = '.';\n    };\n    auto shiftColUp = [&](int j) {\n        ops.push_back({'U', j});\n        for (int i = 0; i < N-1; i++) b[i][j] = b[i+1][j];\n        b[N-1][j] = '.';\n    };\n    auto shiftColDown = [&](int j) {\n        ops.push_back({'D', j});\n        for (int i = N-1; i > 0; i--) b[i][j] = b[i-1][j];\n        b[0][j] = '.';\n    };\n    \n    while (true) {\n        // Find remaining Oni\n        vector<int> remaining;\n        for (int k = 0; k < M; k++) {\n            int i = oni_pos[k].first, j = oni_pos[k].second;\n            if (b[i][j] == 'x') remaining.push_back(k);\n        }\n        if (remaining.empty()) break;\n        \n        // Group by assignment\n        map<pair<int,char>, vector<int>> groups;\n        for (int k : remaining) {\n            char dir = best_assign[k];\n            int idx = (dir == 'L' || dir == 'R') ? oni_pos[k].first : oni_pos[k].second;\n            groups[{idx, dir}].push_back(k);\n        }\n        \n        // Find best group by efficiency\n        pair<int,char> best_key;\n        double best_eff = -1;\n        int best_dist = 0;\n        \n        for (auto& [key, members] : groups) {\n            int idx = key.first;\n            char dir = key.second;\n            int max_d = 0;\n            for (int k : members) {\n                int d = dist[k].at(dir);\n                max_d = max(max_d, d);\n            }\n            double eff = (double)members.size() / (2.0 * max_d);\n            if (eff > best_eff) {\n                best_eff = eff;\n                best_key = key;\n                best_dist = max_d;\n            }\n        }\n        \n        auto [idx, dir] = best_key;\n        if (dir == 'L') {\n            for (int s = 0; s < best_dist; s++) shiftRowLeft(idx);\n            for (int s = 0; s < best_dist; s++) shiftRowRight(idx);\n        } else if (dir == 'R') {\n            for (int s = 0; s < best_dist; s++) shiftRowRight(idx);\n            for (int s = 0; s < best_dist; s++) shiftRowLeft(idx);\n        } else if (dir == 'U') {\n            for (int s = 0; s < best_dist; s++) shiftColUp(idx);\n            for (int s = 0; s < best_dist; s++) shiftColDown(idx);\n        } else if (dir == 'D') {\n            for (int s = 0; s < best_dist; s++) shiftColDown(idx);\n            for (int s = 0; s < best_dist; s++) shiftColUp(idx);\n        }\n    }\n    \n    for (auto [d, p] : ops)\n        cout << d << ' ' << p << '\\n';\n    \n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\nusing namespace chrono;\n\nconst int N = 100;\nconst int L = 500000;\n\nint T[N];\nint best_a[N], best_b[N];\nlong long best_error;\n\n// Fast evaluation using fixed-point iteration\n// Returns true if converged, false if cycling\nbool evaluate(const int a[], const int b[], int cnt[]) {\n    // Initialize cnt with targets as starting guess\n    for (int i = 0; i < N; ++i) cnt[i] = T[i];\n    \n    int iter;\n    for (iter = 0; iter < 200; ++iter) {\n        int new_cnt[N] = {0};\n        new_cnt[0] = 1; // Start at node 0\n        \n        for (int i = 0; i < N; ++i) {\n            if (cnt[i] > 0) {\n                int odd_visits = (cnt[i] + 1) / 2;  // ceil(cnt/2)\n                int even_visits = cnt[i] / 2;        // floor(cnt/2)\n                new_cnt[a[i]] += odd_visits;\n                new_cnt[b[i]] += even_visits;\n            }\n        }\n        \n        // Check convergence\n        bool converged = true;\n        int total = 0;\n        for (int i = 0; i < N; ++i) {\n            total += new_cnt[i];\n            if (abs(new_cnt[i] - cnt[i]) > 1) converged = false;\n        }\n        \n        memcpy(cnt, new_cnt, sizeof(int) * N);\n        \n        // Normalize to L\n        if (total != L && total > 0) {\n            long long scale = (long long)L * 1000000 / total;\n            for (int i = 0; i < N; ++i) {\n                cnt[i] = (int)((long long)cnt[i] * scale / 1000000);\n            }\n            // Fix rounding\n            int sum = 0;\n            for (int i = 0; i < N; ++i) sum += cnt[i];\n            cnt[0] += L - sum;\n        }\n        \n        if (converged && iter > 5) break;\n    }\n    return true;\n}\n\n// Full simulation for verification\nvoid full_simulate(const int a[], const int b[], int cnt[]) {\n    memset(cnt, 0, sizeof(int) * N);\n    int cur = 0;\n    for (int week = 0; week < L; ++week) {\n        cnt[cur]++;\n        cur = (cnt[cur] & 1) ? a[cur] : b[cur];\n    }\n}\n\nlong long calc_error(const int cnt[]) {\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += abs(cnt[i] - T[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) cin >> T[i];\n    \n    auto start_time = steady_clock::now();\n    const double time_limit = 1.98;\n    mt19937 rng(12345);\n    uniform_int_distribution<int> rand_emp(0, N-1);\n    uniform_real_distribution<double> rand_real(0.0, 1.0);\n    \n    best_error = 1e18;\n    \n    // Weighted initialization\n    vector<int> weighted;\n    for (int i = 0; i < N; ++i) {\n        int times = max(1, T[i] / 10);\n        for (int t = 0; t < min(times, 300); ++t) {\n            weighted.push_back(i);\n        }\n    }\n    \n    int a[N], b[N];\n    int cnt[N];\n    int saved_a[N], saved_b[N], saved_cnt[N];\n    int total_evals = 0;\n    \n    // Main loop\n    while (true) {\n        auto now = steady_clock::now();\n        if (duration<double>(now - start_time).count() > time_limit) break;\n        \n        // Initialize\n        if (total_evals < 50) {\n            int init_type = total_evals % 5;\n            if (init_type == 0) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = weighted[rand() % weighted.size()];\n                    b[i] = weighted[rand() % weighted.size()];\n                }\n            } else if (init_type == 1) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = rand_emp(rng);\n                    b[i] = rand_emp(rng);\n                }\n            } else if (init_type == 2) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = (i + 1) % N;\n                    b[i] = (i + 2) % N;\n                }\n            } else if (init_type == 3) {\n                for (int i = 0; i < N; ++i) {\n                    a[i] = i;\n                    b[i] = (i + 1) % N;\n                }\n            } else {\n                // Point to nodes with high T\n                int top5[5];\n                vector<pair<int,int>> sorted;\n                for (int j = 0; j < N; ++j) sorted.push_back({T[j], j});\n                sort(sorted.rbegin(), sorted.rend());\n                for (int j = 0; j < 5; ++j) top5[j] = sorted[j].second;\n                for (int i = 0; i < N; ++i) {\n                    a[i] = top5[rand() % 5];\n                    b[i] = top5[rand() % 5];\n                }\n            }\n        } else {\n            // Mutate best solution\n            memcpy(a, best_a, sizeof(a));\n            memcpy(b, best_b, sizeof(b));\n            int num_mutations = 5 + rand() % 25;\n            for (int m = 0; m < num_mutations; ++m) {\n                int i = rand_emp(rng);\n                if (rand() % 2) a[i] = rand_emp(rng);\n                else b[i] = rand_emp(rng);\n            }\n        }\n        \n        // Evaluate using fixed-point iteration (fast)\n        evaluate(a, b, cnt);\n        long long current_error = calc_error(cnt);\n        total_evals++;\n        \n        // Verify with full simulation occasionally\n        if (total_evals % 50 == 0 || current_error < best_error) {\n            full_simulate(a, b, cnt);\n            current_error = calc_error(cnt);\n        }\n        \n        if (current_error < best_error) {\n            best_error = current_error;\n            memcpy(best_a, a, sizeof(a));\n            memcpy(best_b, b, sizeof(b));\n        }\n        \n        // Local search\n        double temp = 300.0;\n        int streak = 0;\n        \n        for (int iter = 0; iter < 1000; ++iter) {\n            auto now2 = steady_clock::now();\n            if (duration<double>(now2 - start_time).count() > time_limit) break;\n            \n            memcpy(saved_a, a, sizeof(a));\n            memcpy(saved_b, b, sizeof(b));\n            memcpy(saved_cnt, cnt, sizeof(cnt));\n            \n            // Pick node to mutate\n            int i;\n            if (rand_real(rng) < 0.5) {\n                i = rand_emp(rng);\n            } else {\n                // Weighted by error\n                int total_err = 0;\n                for (int j = 0; j < N; ++j) total_err += abs(cnt[j] - T[j]);\n                if (total_err > 0) {\n                    int r = rand() % total_err;\n                    int cum = 0;\n                    for (int j = 0; j < N; ++j) {\n                        cum += abs(cnt[j] - T[j]);\n                        if (r < cum) { i = j; break; }\n                    }\n                }\n            }\n            \n            if (rand() % 2) a[i] = rand_emp(rng);\n            else b[i] = rand_emp(rng);\n            \n            total_evals++;\n            evaluate(a, b, cnt);\n            long long new_error = calc_error(cnt);\n            \n            if (new_error <= current_error || \n                rand_real(rng) < exp((current_error - new_error) / temp)) {\n                current_error = new_error;\n                streak = 0;\n                if (new_error < best_error) {\n                    // Verify with full simulation\n                    full_simulate(a, b, cnt);\n                    new_error = calc_error(cnt);\n                    if (new_error < best_error) {\n                        best_error = new_error;\n                        memcpy(best_a, a, sizeof(a));\n                        memcpy(best_b, b, sizeof(b));\n                    }\n                }\n            } else {\n                memcpy(a, saved_a, sizeof(a));\n                memcpy(b, saved_b, sizeof(b));\n                memcpy(cnt, saved_cnt, sizeof(cnt));\n                streak++;\n            }\n            \n            if (streak > 30) {\n                temp *= 0.9;\n                streak = 0;\n            }\n            temp *= 0.999;\n            if (temp < 0.01) break;\n        }\n    }\n    \n    // Output best\n    for (int i = 0; i < N; ++i) {\n        cout << best_a[i] << \" \" << best_b[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc045":"#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        return parent[x] == x ? x : parent[x] = find(parent[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]) 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    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<long long> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n    }\n    \n    vector<long long> estX(N), estY(N);\n    for (int i = 0; i < N; ++i) {\n        estX[i] = (lx[i] + rx[i]) / 2;\n        estY[i] = (ly[i] + ry[i]) / 2;\n    }\n    \n    // ---------- Balanced k-means clustering ----------\n    // Initialize M cluster centers via k-means++\n    vector<long long> cx(M), cy(M);\n    vector<bool> chosen(N, false);\n    mt19937 rng(42);\n    uniform_int_distribution<int> dist(0, N-1);\n    int first = dist(rng);\n    chosen[first] = true;\n    cx[0] = estX[first]; cy[0] = estY[first];\n    for (int k = 1; k < M; ++k) {\n        vector<long long> min_dist2(N, LLONG_MAX);\n        for (int i = 0; i < N; ++i) {\n            if (chosen[i]) continue;\n            long long dx = estX[i] - cx[k-1];\n            long long dy = estY[i] - cy[k-1];\n            min_dist2[i] = min(min_dist2[i], dx*dx + dy*dy);\n        }\n        long long sum = 0;\n        for (int i = 0; i < N; ++i) if (!chosen[i]) sum += min_dist2[i];\n        uniform_int_distribution<long long> dsum(0, sum==0?0:sum-1);\n        long long rnd = dsum(rng);\n        int selected = -1;\n        for (int i = 0; i < N; ++i) {\n            if (chosen[i]) continue;\n            rnd -= min_dist2[i];\n            if (rnd < 0) { selected = i; break; }\n        }\n        if (selected == -1) selected = 0;\n        chosen[selected] = true;\n        cx[k] = estX[selected]; cy[k] = estY[selected];\n    }\n    \n    // Capacitated assignment: sort all pairs (city, cluster) by distance, assign greedily\n    vector<int> group_of_city(N, -1);\n    vector<int> pos_in_group_city(N, -1);\n    vector<vector<int>> groups(M);\n    for (int iter = 0; iter < 3; ++iter) {\n        // Build distances from each city to each center\n        vector<tuple<long long, int, int>> pairs; // dist2, city, cluster\n        for (int i = 0; i < N; ++i) {\n            for (int k = 0; k < M; ++k) {\n                long long dx = estX[i] - cx[k];\n                long long dy = estY[i] - cy[k];\n                pairs.emplace_back(dx*dx + dy*dy, i, k);\n            }\n        }\n        sort(pairs.begin(), pairs.end());\n        vector<int> cap(M);\n        for (int k = 0; k < M; ++k) cap[k] = G[k];\n        vector<vector<int>> temp_groups(M);\n        for (auto &tup : pairs) {\n            int city = get<1>(tup);\n            int clust = get<2>(tup);\n            if (group_of_city[city] != -1) continue; // already assigned in this iteration\n            if (cap[clust] > 0) {\n                group_of_city[city] = clust;\n                temp_groups[clust].push_back(city);\n                cap[clust]--;\n            }\n        }\n        // Update centers\n        for (int k = 0; k < M; ++k) {\n            long long sx = 0, sy = 0;\n            for (int c : temp_groups[k]) {\n                sx += estX[c]; sy += estY[c];\n            }\n            if (!temp_groups[k].empty()) {\n                cx[k] = sx / temp_groups[k].size();\n                cy[k] = sy / temp_groups[k].size();\n            }\n        }\n        groups = move(temp_groups);\n        // reset group_of_city for next iteration\n        fill(group_of_city.begin(), group_of_city.end(), -1);\n    }\n    // Final assignment is in 'groups', but they aren't occupied in order yet. We'll just use them as groups.\n    // Sort each group by Morton order for spatial coherence\n    auto morton = [](long long x, long long y) -> unsigned long long {\n        auto interleave = [](unsigned int a) -> unsigned long long {\n            unsigned long long b = a;\n            b = (b | (b << 16)) & 0x0000FFFF0000FFFFULL;\n            b = (b | (b << 8))  & 0x00FF00FF00FF00FFULL;\n            b = (b | (b << 4))  & 0x0F0F0F0F0F0F0F0FULL;\n            b = (b | (b << 2))  & 0x3333333333333333ULL;\n            b = (b | (b << 1))  & 0x5555555555555555ULL;\n            return b;\n        };\n        unsigned int ix = (unsigned int)max(0LL, min(10000LL, x));\n        unsigned int iy = (unsigned int)max(0LL, min(10000LL, y));\n        return interleave(ix) | (interleave(iy) << 1);\n    };\n    for (int g = 0; g < M; ++g) {\n        sort(groups[g].begin(), groups[g].end(), [&](int a, int b) {\n            return morton(estX[a], estY[a]) < morton(estX[b], estY[b]);\n        });\n        for (int j = 0; j < G[g]; ++j) {\n            int city = groups[g][j];\n            group_of_city[city] = g;\n            pos_in_group_city[city] = j;\n        }\n    }\n    \n    vector<vector<pair<int,int>>> final_edges(M);\n    vector<DSU> dsu;\n    dsu.reserve(M);\n    for (int g = 0; g < M; ++g) dsu.emplace_back(G[g]);\n    \n    int queries_used = 0;\n    \n    // Phase 1: sliding window with dynamic step based on group size vs query budget\n    // Allocate queries proportionally to group size (with minimum 1 for size>2)\n    int total_queries = Q;\n    vector<int> group_queries(M, 0);\n    int sum_sizes = N;\n    int rem_queries = total_queries;\n    for (int g = 0; g < M; ++g) {\n        int sz = G[g];\n        if (sz <= 2) continue;\n        int alloc = max(1, (int)((long long)total_queries * sz / sum_sizes));\n        group_queries[g] = alloc;\n        rem_queries -= alloc;\n    }\n    // distribute remaining to largest groups\n    for (int g = 0; g < M && rem_queries > 0; ++g) {\n        if (G[g] > 2) {\n            group_queries[g]++;\n            rem_queries--;\n        }\n    }\n    \n    for (int g = 0; g < M && queries_used < Q; ++g) {\n        int sz = G[g];\n        if (sz <= 2) {\n            if (sz == 2) {\n                final_edges[g].emplace_back(0, 1);\n                dsu[g].unite(0, 1);\n            }\n            continue;\n        }\n        int max_q = group_queries[g];\n        int step = L - 2;\n        if (step < 1) step = 1;\n        // Adjust step to not exceed available queries\n        int max_windows = (sz - 1 + step - 1) / step; // rough count\n        if (max_windows > max_q) {\n            step = (sz - 1 + max_q - 1) / max_q; // increase step to fit budget\n            if (step < 1) step = 1;\n        }\n        for (int start = 0; start + 1 < sz && queries_used < Q; start += step) {\n            int end = min(start + L, sz);\n            if (end - start < 2) break;\n            \n            cout << \"? \" << end - start;\n            for (int j = start; j < end; ++j) cout << \" \" << groups[g][j];\n            cout << \"\\n\";\n            cout.flush();\n            ++queries_used;\n            \n            for (int j = 0; j < (end - start) - 1; ++j) {\n                int a, b;\n                cin >> a >> b;\n                int pa = pos_in_group_city[a];\n                int pb = pos_in_group_city[b];\n                if (pa < start || pa >= end || pb < start || pb >= end) continue;\n                if (dsu[g].unite(pa, pb))\n                    final_edges[g].emplace_back(pa, pb);\n            }\n        }\n    }\n    \n    // Phase 2: remaining queries for component connection (same as before)\n    while (queries_used < Q) {\n        int best_g = -1, best_cnt = 0;\n        for (int g = 0; g < M; ++g) {\n            int sz = G[g];\n            if (sz <= 2) continue;\n            unordered_map<int, vector<int>> comps;\n            for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n            int cnt = comps.size();\n            if (cnt > best_cnt && cnt > 1) {\n                best_cnt = cnt;\n                best_g = g;\n            }\n        }\n        if (best_g == -1) break;\n        \n        int g = best_g;\n        int sz = G[g];\n        unordered_map<int, vector<int>> comps;\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        vector<int> reps;\n        for (auto &kv : comps) {\n            reps.push_back(kv.second.front());\n            if ((int)reps.size() == L) break;\n        }\n        if (reps.size() < 2) break;\n        \n        cout << \"? \" << reps.size();\n        for (int r : reps) cout << \" \" << groups[g][r];\n        cout << \"\\n\";\n        cout.flush();\n        ++queries_used;\n        \n        for (int j = 0; j < (int)reps.size() - 1; ++j) {\n            int a, b;\n            cin >> a >> b;\n            int pa = pos_in_group_city[a];\n            int pb = pos_in_group_city[b];\n            if (dsu[g].unite(pa, pb))\n                final_edges[g].emplace_back(pa, pb);\n        }\n    }\n    \n    cout << \"!\\n\";\n    cout.flush();\n    \n    // Phase 3: post-query component MST (unchanged logic)\n    for (int g = 0; g < M; ++g) {\n        if (G[g] <= 1) continue;\n        const auto &cities = groups[g];\n        int sz = cities.size();\n        \n        unordered_map<int, vector<int>> comps;\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        if (comps.size() == 1) continue;\n        \n        vector<int> comp_ids;\n        for (auto &kv : comps) comp_ids.push_back(kv.first);\n        int C = comp_ids.size();\n        \n        vector<tuple<long long, int, int>> comp_edges;\n        for (int i = 0; i < C; ++i) {\n            for (int j = i+1; j < C; ++j) {\n                long long best = LLONG_MAX;\n                for (int u : comps[comp_ids[i]]) {\n                    long long xu = estX[cities[u]], yu = estY[cities[u]];\n                    for (int v : comps[comp_ids[j]]) {\n                        long long dx = xu - estX[cities[v]];\n                        long long dy = yu - estY[cities[v]];\n                        long long d2 = dx*dx + dy*dy;\n                        if (d2 < best) best = d2;\n                    }\n                }\n                comp_edges.emplace_back(best, i, j);\n            }\n        }\n        sort(comp_edges.begin(), comp_edges.end());\n        DSU comp_dsu(C);\n        for (auto &e : comp_edges) {\n            int i = get<1>(e), j = get<2>(e);\n            if (comp_dsu.unite(i, j)) {\n                int u = -1, v = -1;\n                long long best_d2 = LLONG_MAX;\n                for (int a : comps[comp_ids[i]]) {\n                    long long xa = estX[cities[a]], ya = estY[cities[a]];\n                    for (int b : comps[comp_ids[j]]) {\n                        long long dx = xa - estX[cities[b]];\n                        long long dy = ya - estY[cities[b]];\n                        long long d2 = dx*dx + dy*dy;\n                        if (d2 < best_d2) {\n                            best_d2 = d2;\n                            u = a; v = b;\n                        }\n                    }\n                }\n                if (u != -1 && v != -1) {\n                    dsu[g].unite(u, v);\n                    final_edges[g].emplace_back(u, v);\n                }\n            }\n        }\n        \n        comps.clear();\n        for (int i = 0; i < sz; ++i) comps[dsu[g].find(i)].push_back(i);\n        if (comps.size() > 1) {\n            vector<tuple<long long, int, int>> cand;\n            vector<int> keys;\n            for (auto &kv : comps) keys.push_back(kv.first);\n            for (size_t ci = 0; ci < keys.size(); ++ci) {\n                for (size_t cj = ci+1; cj < keys.size(); ++cj) {\n                    for (int u : comps[keys[ci]]) {\n                        for (int v : comps[keys[cj]]) {\n                            long long dx = estX[cities[u]] - estX[cities[v]];\n                            long long dy = estY[cities[u]] - estY[cities[v]];\n                            long long d2 = dx*dx + dy*dy;\n                            cand.emplace_back(d2, u, v);\n                        }\n                    }\n                }\n            }\n            sort(cand.begin(), cand.end());\n            for (auto &e : cand) {\n                int u = get<1>(e), v = get<2>(e);\n                if (dsu[g].unite(u, v))\n                    final_edges[g].emplace_back(u, v);\n            }\n        }\n    }\n    \n    // Output\n    for (int g = 0; g < M; ++g) {\n        for (int i = 0; i < G[g]; ++i) {\n            if (i) cout << \" \";\n            cout << groups[g][i];\n        }\n        cout << \"\\n\";\n        for (auto &e : final_edges[g]) {\n            cout << groups[g][e.first] << \" \" << groups[g][e.second] << \"\\n\";\n        }\n    }\n    \n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nvector<string> blocks;\nvector<pair<int,int>> targets;\nvector<pair<char,char>> actions;\nint cur_x, cur_y;\n\nbool valid(int x, int y) { return x>=0 && x<N && y>=0 && y<N; }\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char dc[4] = {'U', 'D', 'L', 'R'};\n\npair<int,int> slide(int x, int y, int d) {\n    while (true) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (!valid(nx, ny) || blocks[nx][ny] == '#') break;\n        x = nx; y = ny;\n    }\n    return {x, y};\n}\n\nvector<pair<char,char>> bfs(int sx, int sy, int gx, int gy) {\n    vector dist(N, vector<int>(N, 1e9));\n    vector act(N, vector<pair<char,char>>(N, {'?','?'}));\n    vector prev(N, vector<pair<int,int>>(N, {-1,-1}));\n    queue<pair<int,int>> q;\n    dist[sx][sy] = 0;\n    q.push({sx, sy});\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        if (x == gx && y == gy) break;\n        // moves\n        for (int k=0; k<4; k++) {\n            int nx = x + dx[k], ny = y + dy[k];\n            if (valid(nx, ny) && blocks[nx][ny] == '.' && dist[nx][ny] > dist[x][y] + 1) {\n                dist[nx][ny] = dist[x][y] + 1;\n                act[nx][ny] = {'M', dc[k]};\n                prev[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n        // slides\n        for (int k=0; k<4; k++) {\n            auto [nx, ny] = slide(x, y, k);\n            if ((nx != x || ny != y) && dist[nx][ny] > dist[x][y] + 1) {\n                dist[nx][ny] = dist[x][y] + 1;\n                act[nx][ny] = {'S', dc[k]};\n                prev[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n    }\n    vector<pair<char,char>> path;\n    int x = gx, y = gy;\n    while (!(x == sx && y == sy)) {\n        auto a = act[x][y];\n        path.push_back(a);\n        auto p = prev[x][y];\n        x = p.first; y = p.second;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid move(char d) {\n    int k = string(\"UDLR\").find(d);\n    actions.push_back({'M', d});\n    cur_x += dx[k]; cur_y += dy[k];\n}\n\nvoid slide_action(char d) {\n    int k = string(\"UDLR\").find(d);\n    actions.push_back({'S', d});\n    while (true) {\n        int nx = cur_x + dx[k], ny = cur_y + dy[k];\n        if (!valid(nx, ny) || blocks[nx][ny] == '#') break;\n        cur_x = nx; cur_y = ny;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    blocks.assign(N, string(N, '.'));\n    targets.resize(M);\n    for (int i=0; i<M; i++) cin >> targets[i].first >> targets[i].second;\n    cur_x = targets[0].first;\n    cur_y = targets[0].second;\n    for (int t=1; t<M; t++) {\n        int tx = targets[t].first, ty = targets[t].second;\n        vector<pair<char,char>> path = bfs(cur_x, cur_y, tx, ty);\n        for (auto [a, d] : path) {\n            if (a == 'M') move(d);\n            else slide_action(d);\n        }\n    }\n    for (auto [a,d] : actions) cout << a << ' ' << d << '\\n';\n    return 0;\n}"}}}