{"model_name":"qwen3.5-397b-a17b","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    int area() const { return (x2 - x1) * (y2 - y1); }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n};\n\n// Check if a rectangle contains the desired point\nbool canPlace(const Rect& rect, int x, int y) {\n    return rect.contains(x, y);\n}\n\n// Try to create a rectangle with target area containing point (x,y)\nRect makeRect(int x1, int y1, int x2, int y2, int x, int y, long long targetArea) {\n    Rect rect = {x1, y1, x2, y2};\n    long long area = rect.area();\n    \n    if (area <= 0) return rect;\n    \n    // Adjust dimensions to match target area while containing (x,y)\n    int width = x2 - x1;\n    int height = y2 - y1;\n    \n    if (width <= 0 || height <= 0) return rect;\n    \n    // Try to adjust height to match area\n    long long newHeight = (targetArea + width - 1) / width;\n    newHeight = max(1LL, min((long long)height, newHeight));\n    \n    // Ensure point is contained\n    int newY1 = max(x1, min(y1, y - (int)newHeight + 1));\n    int newY2 = min(y2, newY1 + (int)newHeight);\n    \n    if (newY2 - newY1 < 1) {\n        newY1 = max(x1, y - (int)newHeight + 1);\n        newY2 = min(y2, y + 1);\n    }\n    \n    return {x1, newY1, x2, newY2};\n}\n\n// Recursive space partitioning\nvoid partition(vector<Company>& comps, int idx, int end, Rect space) {\n    if (idx >= end) return;\n    if (idx == end - 1) {\n        // Last company gets remaining space\n        comps[idx].a = space.x1;\n        comps[idx].b = space.y1;\n        comps[idx].c = space.x2;\n        comps[idx].d = space.y2;\n        return;\n    }\n    \n    // Calculate total area needed for remaining companies\n    long long totalArea = 0;\n    for (int i = idx; i < end; i++) {\n        totalArea += comps[i].r;\n    }\n    \n    if (totalArea == 0) return;\n    \n    // Find split point\n    long long leftArea = 0;\n    int split = idx;\n    for (int i = idx; i < end - 1; i++) {\n        leftArea += comps[i].r;\n        if (leftArea * 2 >= totalArea) {\n            split = i + 1;\n            break;\n        }\n    }\n    \n    int width = space.x2 - space.x1;\n    int height = space.y2 - space.y1;\n    \n    if (width <= 0 || height <= 0) return;\n    \n    // Decide split direction based on aspect ratio and point positions\n    double aspectRatio = (double)width / height;\n    bool splitVertically = aspectRatio > 1.0;\n    \n    // Check if all points in left group are on one side\n    int leftMidX = 0, leftMidY = 0;\n    int rightMidX = 0, rightMidY = 0;\n    for (int i = idx; i < split; i++) {\n        leftMidX += comps[i].x;\n        leftMidY += comps[i].y;\n    }\n    for (int i = split; i < end; i++) {\n        rightMidX += comps[i].x;\n        rightMidY += comps[i].y;\n    }\n    leftMidX /= (split - idx);\n    leftMidY /= (split - idx);\n    rightMidX /= (end - split);\n    rightMidY /= (end - split);\n    \n    // Choose split direction that separates the groups better\n    int xDiff = abs(leftMidX - rightMidX);\n    int yDiff = abs(leftMidY - rightMidY);\n    splitVertically = (xDiff >= yDiff);\n    \n    Rect leftSpace, rightSpace;\n    \n    if (splitVertically) {\n        // Split horizontally (vertical line)\n        long long leftRatio = leftArea * space.area() / totalArea;\n        int splitX = space.x1 + max(1, min(space.x2 - space.x1 - 1, \n                      (int)((long long)width * leftArea / totalArea)));\n        \n        // Ensure split contains points properly\n        bool leftHasPoint = false, rightHasPoint = false;\n        for (int i = idx; i < split; i++) {\n            if (comps[i].x < splitX) leftHasPoint = true;\n        }\n        for (int i = split; i < end; i++) {\n            if (comps[i].x >= splitX) rightHasPoint = true;\n        }\n        \n        if (!leftHasPoint || !rightHasPoint) {\n            // Adjust split to ensure points are contained\n            int maxXLeft = -1, minXRight = 10001;\n            for (int i = idx; i < split; i++) maxXLeft = max(maxXLeft, comps[i].x);\n            for (int i = split; i < end; i++) minXRight = min(minXRight, comps[i].x);\n            splitX = max(space.x1 + 1, min(space.x2 - 1, (maxXLeft + minXRight + 1) / 2));\n        }\n        \n        leftSpace = {space.x1, space.y1, splitX, space.y2};\n        rightSpace = {splitX, space.y1, space.x2, space.y2};\n    } else {\n        // Split vertically (horizontal line)\n        int splitY = space.y1 + max(1, min(space.y2 - space.y1 - 1,\n                      (int)((long long)height * leftArea / totalArea)));\n        \n        bool leftHasPoint = false, rightHasPoint = false;\n        for (int i = idx; i < split; i++) {\n            if (comps[i].y < splitY) leftHasPoint = true;\n        }\n        for (int i = split; i < end; i++) {\n            if (comps[i].y >= splitY) rightHasPoint = true;\n        }\n        \n        if (!leftHasPoint || !rightHasPoint) {\n            int maxYLeft = -1, minYRight = 10001;\n            for (int i = idx; i < split; i++) maxYLeft = max(maxYLeft, comps[i].y);\n            for (int i = split; i < end; i++) minYRight = min(minYRight, comps[i].y);\n            splitY = max(space.y1 + 1, min(space.y2 - 1, (maxYLeft + minYRight + 1) / 2));\n        }\n        \n        leftSpace = {space.x1, space.y1, space.x2, splitY};\n        rightSpace = {space.x1, splitY, space.x2, space.y2};\n    }\n    \n    partition(comps, idx, split, leftSpace);\n    partition(comps, split, end, rightSpace);\n}\n\n// Local optimization to improve area matching\nvoid optimize(vector<Company>& comps) {\n    int n = comps.size();\n    bool improved = true;\n    int iterations = 0;\n    const int MAX_ITER = 1000;\n    \n    while (improved && iterations < MAX_ITER) {\n        improved = false;\n        iterations++;\n        \n        for (int i = 0; i < n; i++) {\n            for (int j = i + 1; j < n; j++) {\n                // Try to swap area between adjacent rectangles\n                if (comps[i].c <= comps[j].a || comps[j].c <= comps[i].a ||\n                    comps[i].d <= comps[j].b || comps[j].d <= comps[i].b) {\n                    continue; // Not adjacent\n                }\n                \n                // Check if we can improve by adjusting boundaries\n                int currentScoreI = 0, currentScoreJ = 0;\n                int areaI = (comps[i].c - comps[i].a) * (comps[i].d - comps[i].b);\n                int areaJ = (comps[j].c - comps[j].a) * (comps[j].d - comps[j].b);\n                \n                auto calcScore = [](int desired, int actual) -> double {\n                    if (actual <= 0) return 0.0;\n                    double ratio = (double)min(desired, actual) / max(desired, actual);\n                    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n                };\n                \n                currentScoreI = calcScore(comps[i].r, areaI) * 1000000;\n                currentScoreJ = calcScore(comps[j].r, areaJ) * 1000000;\n                \n                // Try small adjustments\n                for (int dx = -10; dx <= 10; dx += 5) {\n                    for (int dy = -10; dy <= 10; dy += 5) {\n                        if (dx == 0 && dy == 0) continue;\n                        \n                        // Try adjusting company i\n                        int newA = comps[i].a, newB = comps[i].b;\n                        int newC = comps[i].c, newD = comps[i].d;\n                        \n                        // Simple boundary adjustment\n                        if (dx > 0 && newC + dx <= 10000) {\n                            newC += dx;\n                        } else if (dx < 0 && newA - dx <= newC - 1) {\n                            newA += dx;\n                        }\n                        if (dy > 0 && newD + dy <= 10000) {\n                            newD += dy;\n                        } else if (dy < 0 && newB - dy <= newD - 1) {\n                            newB += dy;\n                        }\n                        \n                        if (newC - newA < 1 || newD - newB < 1) continue;\n                        if (!canPlace({newA, newB, newC, newD}, comps[i].x, comps[i].y)) continue;\n                        \n                        int newAreaI = (newC - newA) * (newD - newB);\n                        int newScoreI = calcScore(comps[i].r, newAreaI) * 1000000;\n                        \n                        if (newScoreI > currentScoreI) {\n                            comps[i].a = newA;\n                            comps[i].b = newB;\n                            comps[i].c = newC;\n                            comps[i].d = newD;\n                            improved = true;\n                        }\n                    }\n                }\n            }\n        }\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<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n    }\n    \n    // Sort by space-filling curve (Morton order approximation)\n    sort(companies.begin(), companies.end(), [](const Company& a, const Company& b) {\n        // Interleave bits for Morton order\n        auto morton = [](int x, int y) -> long long {\n            long long result = 0;\n            for (int i = 0; i < 14; i++) {\n                result |= ((long long)(x & (1 << i)) << i);\n                result |= ((long long)(y & (1 << i)) << (i + 1));\n            }\n            return result;\n        };\n        return morton(a.x, a.y) < morton(b.x, b.y);\n    });\n    \n    // Partition space\n    Rect fullSpace = {0, 0, 10000, 10000};\n    partition(companies, 0, n, fullSpace);\n    \n    // Local optimization\n    optimize(companies);\n    \n    // Ensure all rectangles are valid and contain their points\n    for (int i = 0; i < n; i++) {\n        // Ensure minimum size\n        if (companies[i].c - companies[i].a < 1) {\n            companies[i].c = companies[i].a + 1;\n        }\n        if (companies[i].d - companies[i].b < 1) {\n            companies[i].d = companies[i].b + 1;\n        }\n        \n        // Ensure point is contained\n        if (!canPlace({companies[i].a, companies[i].b, companies[i].c, companies[i].d}, \n                      companies[i].x, companies[i].y)) {\n            // Adjust to contain point\n            companies[i].a = min(companies[i].a, companies[i].x);\n            companies[i].b = min(companies[i].b, companies[i].y);\n            companies[i].c = max(companies[i].c, companies[i].x + 1);\n            companies[i].d = max(companies[i].d, companies[i].y + 1);\n        }\n        \n        // Ensure bounds\n        companies[i].a = max(0, min(9999, companies[i].a));\n        companies[i].b = max(0, min(9999, companies[i].b));\n        companies[i].c = max(1, min(10000, companies[i].c));\n        companies[i].d = max(1, min(10000, companies[i].d));\n        \n        if (companies[i].a >= companies[i].c) companies[i].c = companies[i].a + 1;\n        if (companies[i].b >= companies[i].d) companies[i].d = companies[i].b + 1;\n    }\n    \n    // Output in original order\n    vector<tuple<int,int,int,int>> result(n);\n    for (const auto& comp : companies) {\n        result[comp.id] = {comp.a, comp.b, comp.c, comp.d};\n    }\n    \n    for (int i = 0; i < n; i++) {\n        auto [a, b, c, d] = result[i];\n        cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#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;\n    cin >> si >> sj;\n    \n    vector<vector<int>> t(50, vector<int>(50));\n    int max_tile = 0;\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> t[i][j];\n            max_tile = max(max_tile, t[i][j]);\n        }\n    }\n    \n    vector<vector<int>> p(50, vector<int>(50));\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> p[i][j];\n        }\n    }\n    \n    // Directions: U, D, L, R\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    const char dc[] = {'U', 'D', 'L', 'R'};\n    \n    string best_path = \"\";\n    int best_score = 0;\n    \n    // Seed random number generator\n    mt19937 rng(42);\n    \n    // Multiple iterations with different strategies\n    for (int iter = 0; iter < 5000; iter++) {\n        vector<bool> tile_visited(max_tile + 1, false);\n        string path = \"\";\n        int ci = si, cj = sj;\n        int score = p[ci][cj];\n        tile_visited[t[ci][cj]] = true;\n        \n        // Temperature for simulated annealing-like behavior\n        double temp = 1.0 - (double)iter / 5000;\n        double randomness = 0.3 * temp;\n        \n        while (true) {\n            vector<pair<int, int>> candidates; // {value, direction}\n            \n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n                if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                    if (!tile_visited[t[ni][nj]]) {\n                        candidates.push_back({p[ni][nj], d});\n                    }\n                }\n            }\n            \n            if (candidates.empty()) break;\n            \n            // Sort by value descending\n            sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n                return a.first > b.first;\n            });\n            \n            // Select candidate with weighted probability\n            int pick_idx = 0;\n            if (candidates.size() > 1) {\n                double r = (double)rng() / rng.max();\n                if (r < randomness) {\n                    // Random selection from top candidates\n                    pick_idx = rng() % min(3, (int)candidates.size());\n                } else {\n                    // Greedy selection with some bias\n                    double r2 = (double)rng() / rng.max();\n                    if (r2 < 0.7) {\n                        pick_idx = 0;\n                    } else if (r2 < 0.9 && candidates.size() > 1) {\n                        pick_idx = 1;\n                    } else if (candidates.size() > 2) {\n                        pick_idx = 2;\n                    }\n                }\n            }\n            \n            int d = candidates[pick_idx].second;\n            path += dc[d];\n            ci += di[d];\n            cj += dj[d];\n            score += p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n        }\n        \n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n        }\n    }\n    \n    // Additional focused search from best path's endpoint\n    for (int iter = 0; iter < 2000; iter++) {\n        vector<bool> tile_visited(max_tile + 1, false);\n        string path = \"\";\n        int ci = si, cj = sj;\n        int score = p[ci][cj];\n        tile_visited[t[ci][cj]] = true;\n        \n        // More aggressive exploration\n        double aggression = 0.5 + 0.5 * ((double)rng() / rng.max());\n        \n        while (true) {\n            vector<tuple<int, int, int>> candidates; // {value, remaining_neighbors, direction}\n            \n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n                if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                    if (!tile_visited[t[ni][nj]]) {\n                        int neighbors = 0;\n                        for (int d2 = 0; d2 < 4; d2++) {\n                            int nn_i = ni + di[d2];\n                            int nn_j = nj + dj[d2];\n                            if (nn_i >= 0 && nn_i < 50 && nn_j >= 0 && nn_j < 50) {\n                                if (!tile_visited[t[nn_i][nn_j]]) {\n                                    neighbors++;\n                                }\n                            }\n                        }\n                        candidates.push_back({p[ni][nj], neighbors, d});\n                    }\n                }\n            }\n            \n            if (candidates.empty()) break;\n            \n            // Sort by value, then by remaining neighbors (prefer paths with more options)\n            sort(candidates.begin(), candidates.end(), [](const tuple<int,int,int>& a, const tuple<int,int,int>& b) {\n                if (get<0>(a) != get<0>(b)) return get<0>(a) > get<0>(b);\n                return get<1>(a) > get<1>(b);\n            });\n            \n            int pick_idx = 0;\n            if (candidates.size() > 1 && (double)rng() / rng.max() < aggression * 0.3) {\n                pick_idx = rng() % min(3, (int)candidates.size());\n            }\n            \n            int d = get<2>(candidates[pick_idx]);\n            path += dc[d];\n            ci += di[d];\n            cj += dj[d];\n            score += p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n        }\n        \n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <functional>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Edge weights\n// h_w[i][j] is weight between (i, j) and (i, j+1)\n// v_w[i][j] is weight between (i, j) and (i+1, j)\ndouble h_w[H][W-1];\ndouble v_w[H-1][W];\nint h_n[H][W-1];\nint v_n[H-1][W];\n\n// Initialize weights\nvoid init() {\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W-1; ++j) {\n            h_w[i][j] = 5000.0;\n            h_n[i][j] = 10; // Pseudo-count to stabilize early updates\n        }\n    }\n    for (int i = 0; i < H-1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_w[i][j] = 5000.0;\n            v_n[i][j] = 10;\n        }\n    }\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nstring dijkstra(int sr, int sc, int tr, int tc) {\n    // Dijkstra with UCB exploration bonus\n    // Static variable to keep track of total queries for UCB calculation\n    static int total_visits = 0;\n    total_visits++;\n    \n    vector<vector<double>> dist(H, vector<double>(W, 1e18));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> dir_from(H, vector<char>(W, 0));\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    \n    dist[sr][sc] = 0;\n    pq.push({0.0, sr, sc});\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char dchar[] = {'U', 'D', 'L', 'R'};\n    \n    double beta = 200.0; // Exploration parameter\n    \n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        \n        int r = top.r;\n        int c = top.c;\n        double d = top.dist;\n        \n        if (d > dist[r][c]) continue;\n        if (r == tr && c == tc) break;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                double weight = 0;\n                int n = 0;\n                \n                if (i == 0) { // U\n                    weight = v_w[r-1][c];\n                    n = v_n[r-1][c];\n                } else if (i == 1) { // D\n                    weight = v_w[r][c];\n                    n = v_n[r][c];\n                } else if (i == 2) { // L\n                    weight = h_w[r][c-1];\n                    n = h_n[r][c-1];\n                } else if (i == 3) { // R\n                    weight = h_w[r][c];\n                    n = h_n[r][c];\n                }\n                \n                // UCB bonus: subtract bonus to encourage exploring uncertain edges\n                double bonus = beta * sqrt(log(total_visits + 1) / (n + 1));\n                double cost = weight - bonus;\n                if (cost < 1.0) cost = 1.0; // Ensure positive cost for Dijkstra\n                \n                if (dist[r][c] + cost < dist[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + cost;\n                    parent[nr][nc] = {r, c};\n                    dir_from[nr][nc] = dchar[i];\n                    pq.push({dist[nr][nc], nr, nc});\n                }\n            }\n        }\n    }\n    \n    // Reconstruct path\n    string path = \"\";\n    int cr = tr, cc = tc;\n    while (cr != sr || cc != sc) {\n        char d = dir_from[cr][cc];\n        path += d;\n        int pr = parent[cr][cc].first;\n        int pc = parent[cr][cc].second;\n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid update_weights(const string& path, int sr, int sc, int observed_len) {\n    int cr = sr, cc = sc;\n    double est_len = 0;\n    \n    struct EdgeRef {\n        bool is_h;\n        int r, c;\n    };\n    vector<EdgeRef> path_edges;\n    \n    for (char d : path) {\n        int nr = cr, nc = cc;\n        if (d == 'U') { nr--; }\n        else if (d == 'D') { nr++; }\n        else if (d == 'L') { nc--; }\n        else if (d == 'R') { nc++; }\n        \n        double w = 0;\n        int n = 0;\n        bool is_h = false;\n        int r = 0, c = 0;\n        \n        if (d == 'U') {\n            w = v_w[cr-1][cc];\n            n = v_n[cr-1][cc];\n            is_h = false; r = cr-1; c = cc;\n        } else if (d == 'D') {\n            w = v_w[cr][cc];\n            n = v_n[cr][cc];\n            is_h = false; r = cr; c = cc;\n        } else if (d == 'L') {\n            w = h_w[cr][cc-1];\n            n = h_n[cr][cc-1];\n            is_h = true; r = cr; c = cc-1;\n        } else if (d == 'R') {\n            w = h_w[cr][cc];\n            n = h_n[cr][cc];\n            is_h = true; r = cr; c = cc;\n        }\n        \n        est_len += w;\n        path_edges.push_back({is_h, r, c});\n        \n        cr = nr;\n        cc = nc;\n    }\n    \n    if (path_edges.empty()) return;\n    \n    // Distribute error evenly among edges in the path\n    double error = observed_len - est_len;\n    double step = error / path_edges.size();\n    \n    for (auto& edge : path_edges) {\n        if (edge.is_h) {\n            int n = h_n[edge.r][edge.c];\n            double eta = 1.0 / (n + 1); // Decaying learning rate\n            h_w[edge.r][edge.c] += eta * step;\n            h_n[edge.r][edge.c]++;\n            // Clamp weights to valid range\n            if (h_w[edge.r][edge.c] < 1000) h_w[edge.r][edge.c] = 1000;\n            if (h_w[edge.r][edge.c] > 9000) h_w[edge.r][edge.c] = 9000;\n        } else {\n            int n = v_n[edge.r][edge.c];\n            double eta = 1.0 / (n + 1);\n            v_w[edge.r][edge.c] += eta * step;\n            v_n[edge.r][edge.c]++;\n            // Clamp weights to valid range\n            if (v_w[edge.r][edge.c] < 1000) v_w[edge.r][edge.c] = 1000;\n            if (v_w[edge.r][edge.c] > 9000) v_w[edge.r][edge.c] = 9000;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    init();\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        string path = dijkstra(si, sj, ti, tj);\n        cout << path << \"\\n\" << flush;\n        \n        int observed;\n        cin >> observed;\n        \n        update_weights(path, si, sj, observed);\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPHABET = 8;\n\nint countMatches(const vector<string>& grid, const vector<string>& strings) {\n    int matches = 0;\n    for (const string& s : strings) {\n        bool found = false;\n        int len = s.length();\n        \n        // Check horizontal\n        for (int i = 0; i < N && !found; i++) {\n            for (int j = 0; j < N && !found; j++) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[i][(j + k) % N];\n                    if (c != '.' && c != s[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) found = true;\n            }\n        }\n        \n        // Check vertical\n        for (int i = 0; i < N && !found; i++) {\n            for (int j = 0; j < N && !found; j++) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[(i + k) % N][j];\n                    if (c != '.' && c != s[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) found = true;\n            }\n        }\n        \n        if (found) matches++;\n    }\n    return matches;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N_in, M;\n    cin >> N_in >> M;\n    \n    vector<string> strings(M);\n    for (int i = 0; i < M; i++) {\n        cin >> strings[i];\n    }\n    \n    // Initialize grid with '.'\n    vector<string> grid(N, string(N, '.'));\n    \n    // Sort strings by length (longer first - more constrained)\n    vector<pair<int, int>> indexed(M);\n    for (int i = 0; i < M; i++) {\n        indexed[i] = {-(int)strings[i].length(), i};\n    }\n    sort(indexed.begin(), indexed.end());\n    \n    // Greedy placement\n    for (auto& p : indexed) {\n        int idx = p.second;\n        const string& s = strings[idx];\n        int len = s.length();\n        \n        // Try all positions and orientations\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                // Try horizontal\n                bool canPlaceH = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[i][(j + k) % N];\n                    if (c != '.' && c != s[k]) {\n                        canPlaceH = false;\n                        break;\n                    }\n                }\n                if (canPlaceH) {\n                    for (int k = 0; k < len; k++) {\n                        grid[i][(j + k) % N] = s[k];\n                    }\n                    goto next_string;\n                }\n                \n                // Try vertical\n                bool canPlaceV = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[(i + k) % N][j];\n                    if (c != '.' && c != s[k]) {\n                        canPlaceV = false;\n                        break;\n                    }\n                }\n                if (canPlaceV) {\n                    for (int k = 0; k < len; k++) {\n                        grid[(i + k) % N][j] = s[k];\n                    }\n                    goto next_string;\n                }\n            }\n        }\n        next_string:;\n    }\n    \n    // Count initial matches\n    int matches = countMatches(grid, strings);\n    \n    // Simulated annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double temp = 100.0;\n    double cooling = 0.99995;\n    int iterations = 800000;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        char old = grid[i][j];\n        \n        // Choose new character\n        char newChar;\n        if (old == '.') {\n            newChar = 'A' + (rng() % ALPHABET);\n        } else {\n            if (rng() % 3 == 0) {\n                newChar = '.';\n            } else {\n                newChar = 'A' + (rng() % ALPHABET);\n            }\n        }\n        \n        if (newChar == old) continue;\n        \n        grid[i][j] = newChar;\n        int newMatches = countMatches(grid, strings);\n        \n        double delta = newMatches - matches;\n        \n        // Accept if better, or with probability based on temperature\n        if (delta > 0 || (delta == 0 && newChar != '.') || \n            exp(delta / temp) > (double)(rng() % 1000000) / 1000000.0) {\n            matches = newMatches;\n        } else {\n            grid[i][j] = old;\n        }\n        \n        temp *= cooling;\n    }\n    \n    // If all strings match, fill remaining '.' to maximize score\n    if (matches == M) {\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] = 'A' + (rng() % ALPHABET);\n                }\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << grid[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <set>\n\nusing namespace std;\n\n// Constants\nconst int MAX_N = 70;\nconst int MAX_SEGMENTS = 600; // Sufficiently large\nconst long long INF = 1e18;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<Point> road_squares;\nint segment_h[MAX_N][MAX_N];\nint segment_v[MAX_N][MAX_N];\nint num_h_segments = 0;\nint num_v_segments = 0;\nint total_road_squares = 0;\n\nvector<Point> key_points;\nmap<Point, int> point_to_idx;\nint num_key_points = 0;\nint start_idx = -1;\n\n// APSP data\nlong long dist_mat[300][300];\nbitset<MAX_SEGMENTS> coverage_mat[300][300];\nvector<Point> path_mat[300][300]; // Reconstruct path\n\n// Directions\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\n\nbool is_road(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N && grid[r][c] != '#';\n}\n\nint get_cost(int r, int c) {\n    return grid[r][c] - '0';\n}\n\nvoid identify_segments() {\n    // Initialize\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            segment_h[i][j] = -1;\n            segment_v[i][j] = -1;\n        }\n    }\n\n    // Horizontal\n    for(int i=0; i<N; ++i) {\n        int j = 0;\n        while(j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            int start_j = j;\n            while(j < N && grid[i][j] != '#') {\n                j++;\n            }\n            // Segment from (i, start_j) to (i, j-1)\n            for(int k=start_j; k<j; ++k) {\n                segment_h[i][k] = num_h_segments;\n            }\n            num_h_segments++;\n        }\n    }\n\n    // Vertical\n    for(int j=0; j<N; ++j) {\n        int i = 0;\n        while(i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            int start_i = i;\n            while(i < N && grid[i][j] != '#') {\n                i++;\n            }\n            for(int k=start_i; k<i; ++k) {\n                segment_v[k][j] = num_v_segments;\n            }\n            num_v_segments++;\n        }\n    }\n}\n\nvoid identify_key_points() {\n    // Degree != 2 or Start Point\n    set<Point> kp_set;\n    kp_set.insert({si, sj});\n\n    for(const auto& p : road_squares) {\n        int degree = 0;\n        for(int d=0; d<4; ++d) {\n            int nr = p.r + dr[d];\n            int nc = p.c + dc[d];\n            if(is_road(nr, nc)) degree++;\n        }\n        if(degree != 2) {\n            kp_set.insert(p);\n        }\n    }\n    \n    // If very few key points (e.g. simple cycle), add more to ensure connectivity representation\n    if(kp_set.size() < 2 && road_squares.size() > 2) {\n        // Add a point far from start\n        Point best = road_squares[0];\n        int max_d = -1;\n        for(const auto& p : road_squares) {\n            int d = abs(p.r - si) + abs(p.c - sj);\n            if(d > max_d) {\n                max_d = d;\n                best = p;\n            }\n        }\n        kp_set.insert(best);\n    }\n\n    for(const auto& p : kp_set) {\n        point_to_idx[p] = num_key_points;\n        key_points.push_back(p);\n        if(p.r == si && p.c == sj) {\n            start_idx = num_key_points;\n        }\n        num_key_points++;\n    }\n}\n\nvoid compute_apsp() {\n    // Initialize\n    for(int i=0; i<num_key_points; ++i) {\n        for(int j=0; j<num_key_points; ++j) {\n            dist_mat[i][j] = INF;\n            // coverage_mat[i][j].reset(); \n        }\n    }\n\n    // Run Dijkstra from each key point\n    // We need to compute coverage for the path.\n    // Since we need path reconstruction, we store parent pointers in Dijkstra.\n    // However, storing parent for every node for every source is memory heavy.\n    // Instead, we can just store the full path in path_mat after Dijkstra.\n    \n    // To optimize, we run Dijkstra on the full grid graph but only care about distances to Key Points.\n    // But we need coverage of the path.\n    \n    for(int src_idx = 0; src_idx < num_key_points; ++src_idx) {\n        Point src = key_points[src_idx];\n        \n        // Dijkstra state\n        // dist[r][c], cov[r][c]\n        // Use flat arrays for speed\n        static long long d_grid[MAX_N][MAX_N];\n        static bitset<MAX_SEGMENTS> c_grid[MAX_N][MAX_N];\n        static Point parent_grid[MAX_N][MAX_N];\n        static bool visited[MAX_N][MAX_N];\n\n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                d_grid[i][j] = INF;\n                visited[i][j] = false;\n            }\n        }\n\n        priority_queue<pair<long long, Point>, vector<pair<long long, Point>>, greater<pair<long long, Point>>> pq;\n        \n        d_grid[src.r][src.c] = 0;\n        // Coverage of starting point\n        if(segment_h[src.r][src.c] != -1) c_grid[src.r][src.c].set(segment_h[src.r][src.c]);\n        if(segment_v[src.r][src.c] != -1) c_grid[src.r][src.c].set(segment_v[src.r][src.c]);\n        \n        pq.push({0, src});\n        parent_grid[src.r][src.c] = {-1, -1};\n\n        while(!pq.empty()) {\n            long long cost = pq.top().first;\n            Point u = pq.top().second;\n            pq.pop();\n\n            if(visited[u.r][u.c]) continue;\n            visited[u.r][u.c] = true;\n\n            // If u is a key point, record it\n            if(point_to_idx.count(u)) {\n                int v_idx = point_to_idx[u];\n                dist_mat[src_idx][v_idx] = cost;\n                coverage_mat[src_idx][v_idx] = c_grid[u.r][u.c];\n                // Reconstruct path\n                vector<Point> path;\n                Point curr = u;\n                while(curr.r != -1) {\n                    path.push_back(curr);\n                    if(curr.r == src.r && curr.c == src.c) break;\n                    curr = parent_grid[curr.r][curr.c];\n                }\n                reverse(path.begin(), path.end());\n                path_mat[src_idx][v_idx] = path;\n            }\n\n            for(int d=0; d<4; ++d) {\n                int nr = u.r + dr[d];\n                int nc = u.c + dc[d];\n                if(is_road(nr, nc)) {\n                    long long new_cost = cost + get_cost(nr, nc);\n                    bitset<MAX_SEGMENTS> new_cov = c_grid[u.r][u.c];\n                    if(segment_h[nr][nc] != -1) new_cov.set(segment_h[nr][nc]);\n                    if(segment_v[nr][nc] != -1) new_cov.set(segment_v[nr][nc]);\n\n                    bool update = false;\n                    if(new_cost < d_grid[nr][nc]) {\n                        update = true;\n                    } else if(new_cost == d_grid[nr][nc]) {\n                        if(new_cov.count() > c_grid[nr][nc].count()) {\n                            update = true;\n                        }\n                    }\n\n                    if(update) {\n                        d_grid[nr][nc] = new_cost;\n                        c_grid[nr][nc] = new_cov;\n                        parent_grid[nr][nc] = u;\n                        pq.push({new_cost, {nr, nc}});\n                    }\n                }\n            }\n        }\n    }\n}\n\n// SA State\nvector<int> current_path; // Indices of key points\nlong long current_dist = 0;\nbitset<MAX_SEGMENTS> current_cov;\nlong long best_dist = INF;\nvector<int> best_path;\n\nlong long calc_path_dist(const vector<int>& path) {\n    long long d = 0;\n    for(size_t i=0; i<path.size()-1; ++i) {\n        d += dist_mat[path[i]][path[i+1]];\n    }\n    return d;\n}\n\nbitset<MAX_SEGMENTS> calc_path_cov(const vector<int>& path) {\n    bitset<MAX_SEGMENTS> c;\n    for(size_t i=0; i<path.size()-1; ++i) {\n        c |= coverage_mat[path[i]][path[i+1]];\n    }\n    return c;\n}\n\nvoid update_state() {\n    current_dist = calc_path_dist(current_path);\n    current_cov = calc_path_cov(current_path);\n}\n\nlong long energy() {\n    long long uncovered = total_road_squares; // Upper bound\n    // Count covered squares? \n    // We have segment coverage. We need to estimate covered squares.\n    // Actually, we can just count covered segments? No, score depends on squares.\n    // But covering a segment covers all squares in it.\n    // To be precise, we should count squares.\n    // But for SA energy, segment coverage is a good proxy.\n    // Let's use uncovered segments count * large weight + dist.\n    // Wait, to ensure v=r, we need to be precise.\n    // Let's compute exact covered squares for the best solution, but for SA use segments.\n    // Actually, bitset stores segment IDs.\n    // We can precompute which squares belong to which segments.\n    // But that's slow to check every time.\n    // Heuristic: Maximize segment coverage count.\n    // Since every square belongs to 1 H and 1 V segment, covering all segments implies covering all squares.\n    // Covering all squares implies covering all segments? Yes.\n    // So maximizing covered segments is equivalent to maximizing covered squares.\n    // Total segments = num_h_segments + num_v_segments.\n    \n    long long covered_segs = current_cov.count();\n    long long total_segs = num_h_segments + num_v_segments;\n    long long penalty = (total_segs - covered_segs) * 1000000LL;\n    return penalty + current_dist;\n}\n\nvoid solve_sa() {\n    // Initial path: Start -> Start\n    current_path = {start_idx, start_idx};\n    update_state();\n    best_dist = current_dist;\n    best_path = current_path;\n\n    // Greedy insertion to get initial coverage\n    // This helps SA start from a feasible region\n    /* \n       Disabled for now to let SA explore, but might be needed for time.\n       Given 3s, SA should find it.\n       But to ensure v=r, I will add a post-processing fix.\n    */\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 2.8; // Leave 0.2s for output\n\n    int iter = 0;\n    double temp = 10000.0;\n    double cooling = 0.9995;\n\n    while(true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        // Move\n        vector<int> next_path = current_path;\n        int type = rng() % 4;\n        \n        if(next_path.size() > 2) {\n            if(type == 0) {\n                // 2-opt\n                int i = 1 + rng() % (next_path.size() - 2);\n                int j = i + 1 + rng() % (next_path.size() - 1 - i);\n                if(j >= next_path.size() - 1) j = next_path.size() - 2;\n                reverse(next_path.begin() + i, next_path.begin() + j + 1);\n            } else if(type == 1) {\n                // Swap\n                int i = 1 + rng() % (next_path.size() - 2);\n                int j = 1 + rng() % (next_path.size() - 2);\n                swap(next_path[i], next_path[j]);\n            } else if(type == 2) {\n                // Insert\n                int idx = 1 + rng() % (next_path.size() - 1);\n                int kp = rng() % num_key_points;\n                next_path.insert(next_path.begin() + idx, kp);\n            } else {\n                // Remove\n                if(next_path.size() > 3) {\n                    int idx = 1 + rng() % (next_path.size() - 2);\n                    next_path.erase(next_path.begin() + idx);\n                }\n            }\n        } else {\n            // Path is just start->start. Must insert.\n            int kp = rng() % num_key_points;\n            next_path.insert(next_path.begin() + 1, kp);\n        }\n\n        // Ensure start and end are correct\n        next_path.front() = start_idx;\n        next_path.back() = start_idx;\n\n        long long next_dist = calc_path_dist(next_path);\n        // Optimization: Incremental coverage update is hard. Recalculate.\n        // Bitset OR is fast.\n        bitset<MAX_SEGMENTS> next_cov;\n        for(size_t i=0; i<next_path.size()-1; ++i) {\n            next_cov |= coverage_mat[next_path[i]][next_path[i+1]];\n        }\n\n        long long current_energy = energy();\n        \n        // Calculate next energy manually to avoid full update if not needed\n        long long covered_segs = next_cov.count();\n        long long total_segs = num_h_segments + num_v_segments;\n        long long next_penalty = (total_segs - covered_segs) * 1000000LL;\n        long long next_energy = next_penalty + next_dist;\n\n        double delta = (double)(next_energy - current_energy);\n        bool accept = false;\n        if(delta < 0) accept = true;\n        else {\n            double prob = exp(-delta / temp);\n            if((double)rng() / rng.max() < prob) accept = true;\n        }\n\n        if(accept) {\n            current_path = next_path;\n            current_dist = next_dist;\n            current_cov = next_cov;\n            if(next_penalty == 0) {\n                if(next_dist < best_dist) {\n                    best_dist = next_dist;\n                    best_path = current_path;\n                }\n            } else {\n                // If not full coverage, still track best coverage\n                // But primarily we want to minimize energy\n            }\n        }\n        \n        // Update best if full coverage\n        if(covered_segs == total_segs) {\n             if(next_dist < best_dist) {\n                best_dist = next_dist;\n                best_path = next_path;\n            }\n        }\n\n        temp *= cooling;\n        iter++;\n    }\n}\n\nvoid greedy_fix() {\n    // Check if best_path covers all segments\n    bitset<MAX_SEGMENTS> cov;\n    for(size_t i=0; i<best_path.size()-1; ++i) {\n        cov |= coverage_mat[best_path[i]][best_path[i+1]];\n    }\n    long long total_segs = num_h_segments + num_v_segments;\n    if(cov.count() == total_segs) return;\n\n    // Try to insert points to cover missing segments\n    // Identify missing segments\n    vector<int> missing_segs;\n    for(int i=0; i<total_segs; ++i) {\n        if(!cov.test(i)) missing_segs.push_back(i);\n    }\n\n    // For each missing segment, find a road square that covers it and is closest to current path\n    // This is O(Missing * RoadSquares * PathLen). Might be slow.\n    // Optimize: Just pick one missing segment, find best insertion, repeat.\n    \n    int fix_iter = 0;\n    while(cov.count() < total_segs && fix_iter < 100) {\n        int best_seg = missing_segs[0]; // Pick first missing\n        // Find best square to cover best_seg\n        // A square covers best_seg if it is in that segment.\n        // We need to find a square (r, c) such that segment_h[r][c] == best_seg OR segment_v[r][c] == best_seg.\n        // And minimize dist to path.\n        \n        // Since we only have APSP for Key Points, we should insert a Key Point if possible.\n        // If the segment has no Key Points, we might need to insert a non-Key Point.\n        // But let's assume Key Points are sufficient.\n        // Find a Key Point that covers best_seg.\n        \n        int best_kp = -1;\n        long long min_insert_cost = INF;\n        int best_pos = -1;\n\n        for(int kp=0; kp<num_key_points; ++kp) {\n            Point p = key_points[kp];\n            bool covers = false;\n            if(segment_h[p.r][p.c] == best_seg) covers = true;\n            if(segment_v[p.r][p.c] == best_seg) covers = true;\n            \n            if(covers) {\n                // Find best insertion point in best_path\n                for(size_t i=0; i<best_path.size()-1; ++i) {\n                    int u = best_path[i];\n                    int v = best_path[i+1];\n                    long long cost = dist_mat[u][kp] + dist_mat[kp][v] - dist_mat[u][v];\n                    if(cost < min_insert_cost) {\n                        min_insert_cost = cost;\n                        best_kp = kp;\n                        best_pos = i + 1;\n                    }\n                }\n            }\n        }\n        \n        if(best_kp != -1) {\n            best_path.insert(best_path.begin() + best_pos, best_kp);\n            // Update cov\n            // Recalculate full cov\n            cov.reset();\n            for(size_t i=0; i<best_path.size()-1; ++i) {\n                cov |= coverage_mat[best_path[i]][best_path[i+1]];\n            }\n            // Update missing_segs\n            missing_segs.clear();\n            for(int i=0; i<total_segs; ++i) {\n                if(!cov.test(i)) missing_segs.push_back(i);\n            }\n        } else {\n            // No Key Point covers this segment?\n            // This implies the segment consists only of degree-2 nodes.\n            // We need to pick one node from that segment.\n            // Find any road square in that segment.\n            Point target = {-1, -1};\n            for(const auto& p : road_squares) {\n                if(segment_h[p.r][p.c] == best_seg || segment_v[p.r][p.c] == best_seg) {\n                    target = p;\n                    break;\n                }\n            }\n            if(target.r != -1) {\n                // We need to add this point to Key Points and recompute APSP?\n                // Too expensive.\n                // Instead, just insert it into the path by splitting an edge.\n                // Find edge (u, v) in path such that target is on the path between u and v?\n                // Or just connect to nearest Key Point.\n                // Let's find nearest Key Point to target.\n                long long min_d = INF;\n                int nearest_kp = -1;\n                for(int kp=0; kp<num_key_points; ++kp) {\n                    // We don't have dist from KP to arbitrary point.\n                    // We can run BFS from target to find nearest KP.\n                    // But time is tight.\n                    // Fallback: Just add a random KP that is close?\n                    // Given the generation, this case is rare.\n                    // I will skip this complex case and hope Key Points cover everything.\n                    // If not, score will be lower but valid.\n                    break; \n                }\n                break; // Avoid infinite loop\n            } else {\n                break;\n            }\n        }\n        fix_iter++;\n    }\n}\n\nvoid output_solution() {\n    string res = \"\";\n    Point curr = {si, sj};\n    for(size_t i=0; i<best_path.size()-1; ++i) {\n        int u = best_path[i];\n        int v = best_path[i+1];\n        const auto& segment = path_mat[u][v];\n        // segment[0] is u, segment[end] is v\n        for(size_t k=1; k<segment.size(); ++k) {\n            Point next = segment[k];\n            if(next.r == curr.r + 1) res += 'D';\n            else if(next.r == curr.r - 1) res += 'U';\n            else if(next.c == curr.c + 1) res += 'R';\n            else if(next.c == curr.c - 1) res += 'L';\n            curr = next;\n        }\n    }\n    cout << res << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if(!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for(int i=0; i<N; ++i) {\n        cin >> grid[i];\n    }\n\n    // Collect road squares\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                total_road_squares++;\n            }\n        }\n    }\n\n    identify_segments();\n    identify_key_points();\n    compute_apsp();\n\n    solve_sa();\n    greedy_fix();\n    output_solution();\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <numeric>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    \n    // Read initial input\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    // Read task difficulties\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    // Read dependencies\n    vector<vector<int>> deps(N);\n    vector<vector<int>> rev_deps(N);\n    vector<int> in_degree(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        deps[v].push_back(u);\n        rev_deps[u].push_back(v);\n        in_degree[v]++;\n    }\n    \n    // Skill estimates (start with reasonable guess based on task difficulty distribution)\n    vector<vector<double>> s_est(M, vector<double>(K, 35.0));\n    vector<int> s_obs_count(M, 0);\n    \n    // Task status: -1 = not started, 0 = in progress, 1 = completed\n    vector<int> task_status(N, -1);\n    \n    // Member tracking\n    vector<int> member_task(M, -1);\n    vector<int> member_start_day(M, -1);\n    \n    // Observations for learning: (task_id, observed_days)\n    vector<vector<pair<int, int>>> member_obs(M);\n    \n    // Task priority (estimated remaining tasks in dependency chain)\n    vector<int> task_priority(N, 0);\n    \n    // Calculate task priorities using reverse topological order\n    for (int i = N - 1; i >= 0; i--) {\n        task_priority[i] = 1;\n        for (int next : rev_deps[i]) {\n            task_priority[i] = max(task_priority[i], task_priority[next] + 1);\n        }\n    }\n    \n    int day = 0;\n    int completed_count = 0;\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(42);\n    \n    while (true) {\n        day++;\n        \n        // Read completion information\n        int n_completed;\n        cin >> n_completed;\n        \n        if (n_completed == -1) {\n            break;\n        }\n        \n        vector<int> completed_members(n_completed);\n        for (int i = 0; i < n_completed; i++) {\n            cin >> completed_members[i];\n            completed_members[i]--;\n        }\n        \n        // Process completions and update skill estimates\n        for (int member : completed_members) {\n            if (member_task[member] >= 0) {\n                int task = member_task[member];\n                int days_taken = day - member_start_day[member];\n                \n                task_status[task] = 1;\n                completed_count++;\n                \n                // Record observation\n                member_obs[member].push_back({task, days_taken});\n                s_obs_count[member]++;\n                \n                // Update skill estimate using observed data\n                // w = sum(max(0, d_k - s_k)) \u2248 days_taken (when w > 0)\n                // We try to adjust s_k to reduce the gap\n                if (days_taken > 1 && s_obs_count[member] <= 50) {\n                    // Early learning phase - more aggressive updates\n                    double learning_rate = 0.3 / min(10, s_obs_count[member]);\n                    \n                    for (int k = 0; k < K; k++) {\n                        double deficit = max(0.0, (double)d[task][k] - s_est[member][k]);\n                        // If task took long, increase skill estimate for skills where there was deficit\n                        if (deficit > 0) {\n                            s_est[member][k] += learning_rate * deficit * 0.5;\n                        }\n                        // Cap skill estimates reasonably\n                        s_est[member][k] = min(80.0, max(5.0, s_est[member][k]));\n                    }\n                }\n                \n                member_task[member] = -1;\n                member_start_day[member] = -1;\n            }\n        }\n        \n        // Check if all tasks completed\n        if (completed_count >= N) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Find ready tasks (all dependencies completed, not started)\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == -1) {\n                bool all_deps_done = true;\n                for (int dep : deps[i]) {\n                    if (task_status[dep] != 1) {\n                        all_deps_done = false;\n                        break;\n                    }\n                }\n                if (all_deps_done) {\n                    ready_tasks.push_back(i);\n                }\n            }\n        }\n        \n        // Find idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n        \n        if (idle_members.empty() || ready_tasks.empty()) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Calculate estimated completion time for each (member, task) pair\n        vector<vector<double>> est_time(M, vector<double>(N, 1e9));\n        for (int member : idle_members) {\n            for (int task : ready_tasks) {\n                double w = 0;\n                for (int k = 0; k < K; k++) {\n                    w += max(0.0, (double)d[task][k] - s_est[member][k]);\n                }\n                est_time[member][task] = (w == 0) ? 1.0 : max(1.0, w);\n            }\n        }\n        \n        // Greedy assignment: match tasks to members minimizing estimated time\n        // Prioritize high-priority tasks and good skill matches\n        vector<pair<int, int>> assignments;\n        vector<bool> task_assigned(ready_tasks.size(), false);\n        vector<bool> member_used(idle_members.size(), false);\n        \n        // Create assignment candidates with scores\n        vector<tuple<double, int, int, int>> candidates; // (score, priority, member_idx, task_idx)\n        for (size_t mi = 0; mi < idle_members.size(); mi++) {\n            for (size_t ti = 0; ti < ready_tasks.size(); ti++) {\n                int member = idle_members[mi];\n                int task = ready_tasks[ti];\n                double score = est_time[member][task] - task_priority[task] * 0.1;\n                candidates.push_back({score, task_priority[task], (int)mi, (int)ti});\n            }\n        }\n        \n        // Sort by score (lower is better)\n        sort(candidates.begin(), candidates.end());\n        \n        // Assign greedily\n        for (auto& [score, priority, mi, ti] : candidates) {\n            if (member_used[mi] || task_assigned[ti]) continue;\n            \n            int member = idle_members[mi];\n            int task = ready_tasks[ti];\n            \n            assignments.push_back({member + 1, task + 1});\n            member_used[mi] = true;\n            task_assigned[ti] = true;\n            \n            member_task[member] = task;\n            member_start_day[member] = day;\n            task_status[task] = 0;\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n        \n        // Output skill predictions for visualization (optional)\n        if (day % 50 == 1) {\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 << endl;\n            }\n            cout.flush();\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <random>\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n    int order_id; // -1 for office, order index for pickup/delivery\n    bool is_pickup;\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    const int OFFICE_X = 400, OFFICE_Y = 400;\n    const int NUM_ORDERS = 1000;\n    const int SELECT_COUNT = 50;\n    \n    // Read input\n    vector<Order> orders(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n    }\n    \n    mt19937 rng(42);\n    \n    // Score each order for selection\n    // Lower score = better (closer to office, shorter pickup-delivery)\n    vector<pair<double, int>> order_scores;\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n        int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n        int return_dist = manhattan(orders[i].cx, orders[i].cy, OFFICE_X, OFFICE_Y);\n        // Weight pickup-delivery distance more heavily\n        double score = pickup_dist + 2.0 * delivery_dist + return_dist;\n        // Add some randomness for diversity\n        score += uniform_real_distribution<double>(0, 50)(rng);\n        order_scores.push_back({score, i});\n    }\n    \n    // Select 50 orders with best scores\n    sort(order_scores.begin(), order_scores.end());\n    vector<int> selected;\n    vector<bool> is_selected(NUM_ORDERS, false);\n    for (int i = 0; i < SELECT_COUNT; i++) {\n        selected.push_back(order_scores[i].second);\n        is_selected[order_scores[i].second] = true;\n    }\n    \n    // Build initial route: office -> pickups (sorted by angle) -> deliveries (sorted by angle) -> office\n    auto get_angle = [&](int x, int y) {\n        return atan2(y - OFFICE_Y, x - OFFICE_X);\n    };\n    \n    vector<pair<double, int>> pickups, deliveries;\n    for (int idx : selected) {\n        pickups.push_back({get_angle(orders[idx].ax, orders[idx].ay), idx});\n        deliveries.push_back({get_angle(orders[idx].cx, orders[idx].cy), idx});\n    }\n    sort(pickups.begin(), pickups.end());\n    sort(deliveries.begin(), deliveries.end());\n    \n    vector<Point> route;\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    for (auto& p : pickups) {\n        int idx = p.second;\n        route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n    }\n    for (auto& p : deliveries) {\n        int idx = p.second;\n        route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n    }\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    // Calculate total distance\n    auto calc_distance = [&]() -> long long {\n        long long 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    // Check if route is valid (pickup before delivery for each order)\n    auto is_valid_route = [&]() -> bool {\n        vector<bool> picked(SELECT_COUNT, false);\n        map<int, int> order_to_pos;\n        for (int i = 0; i < SELECT_COUNT; i++) {\n            order_to_pos[selected[i]] = i;\n        }\n        \n        for (size_t i = 0; i < route.size(); i++) {\n            if (route[i].order_id == -1) continue;\n            int order_pos = order_to_pos[route[i].order_id];\n            if (route[i].is_pickup) {\n                picked[order_pos] = true;\n            } else {\n                if (!picked[order_pos]) return false;\n            }\n        }\n        return true;\n    };\n    \n    // Simulated Annealing for route optimization\n    long long best_distance = calc_distance();\n    vector<Point> best_route = route;\n    \n    double temperature = 10000.0;\n    double cooling_rate = 0.9995;\n    int iterations = 0;\n    const int MAX_ITERATIONS = 150000;\n    \n    auto try_swap = [&](int i, int j) -> bool {\n        if (i >= route.size() - 1 || j >= route.size() - 1) return false;\n        if (i == 0 || j == 0 || i == (int)route.size() - 1 || j == (int)route.size() - 1) return false;\n        if (route[i].order_id == -1 || route[j].order_id == -1) return false;\n        \n        // Check if swap violates precedence\n        vector<Point> new_route = route;\n        swap(new_route[i], new_route[j]);\n        \n        // Validate new route\n        vector<bool> picked(NUM_ORDERS, false);\n        for (size_t k = 0; k < new_route.size(); k++) {\n            if (new_route[k].order_id == -1) continue;\n            if (new_route[k].is_pickup) {\n                picked[new_route[k].order_id] = true;\n            } else {\n                if (!picked[new_route[k].order_id]) return false;\n            }\n        }\n        return true;\n    };\n    \n    while (iterations < MAX_ITERATIONS && temperature > 0.1) {\n        iterations++;\n        \n        // Try 2-opt move\n        int i = uniform_int_distribution<int>(1, route.size() - 3)(rng);\n        int j = uniform_int_distribution<int>(i + 1, route.size() - 2)(rng);\n        \n        vector<Point> new_route = route;\n        reverse(new_route.begin() + i, new_route.begin() + j + 1);\n        \n        // Validate new route\n        bool valid = true;\n        vector<bool> picked(NUM_ORDERS, false);\n        for (size_t k = 0; k < new_route.size(); k++) {\n            if (new_route[k].order_id == -1) continue;\n            if (new_route[k].is_pickup) {\n                picked[new_route[k].order_id] = true;\n            } else {\n                if (!picked[new_route[k].order_id]) {\n                    valid = false;\n                    break;\n                }\n            }\n        }\n        \n        if (valid) {\n            long long new_distance = 0;\n            for (size_t k = 0; k + 1 < new_route.size(); k++) {\n                new_distance += manhattan(new_route[k].x, new_route[k].y, new_route[k+1].x, new_route[k+1].y);\n            }\n            \n            double delta = new_distance - best_distance;\n            if (delta < 0 || exp(-delta / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                route = new_route;\n                if (new_distance < best_distance) {\n                    best_distance = new_distance;\n                    best_route = route;\n                }\n            }\n        }\n        \n        // Try relocating a pickup-delivery pair\n        if (uniform_int_distribution<int>(0, 9)(rng) < 3) {\n            int order_idx = uniform_int_distribution<int>(0, SELECT_COUNT - 1)(rng);\n            int order_id = selected[order_idx];\n            \n            // Find positions of pickup and delivery\n            int pickup_pos = -1, delivery_pos = -1;\n            for (size_t k = 0; k < route.size(); k++) {\n                if (route[k].order_id == order_id) {\n                    if (route[k].is_pickup) pickup_pos = k;\n                    else delivery_pos = k;\n                }\n            }\n            \n            if (pickup_pos > 0 && delivery_pos < (int)route.size() - 1) {\n                // Try moving the pair to a new position\n                int new_pos = uniform_int_distribution<int>(1, route.size() - 2)(rng);\n                if (new_pos != pickup_pos && new_pos != delivery_pos) {\n                    vector<Point> new_route2;\n                    vector<Point> pair_points;\n                    pair_points.push_back(route[pickup_pos]);\n                    pair_points.push_back(route[delivery_pos]);\n                    \n                    for (size_t k = 0; k < route.size(); k++) {\n                        if (k == (size_t)pickup_pos || k == (size_t)delivery_pos) continue;\n                        if (k == (size_t)new_pos) {\n                            new_route2.push_back(pair_points[0]);\n                            new_route2.push_back(pair_points[1]);\n                        }\n                        new_route2.push_back(route[k]);\n                    }\n                    if (new_pos >= (int)route.size() - 2) {\n                        new_route2.push_back(pair_points[0]);\n                        new_route2.push_back(pair_points[1]);\n                    }\n                    \n                    // Validate\n                    bool valid2 = true;\n                    vector<bool> picked2(NUM_ORDERS, false);\n                    for (size_t k = 0; k < new_route2.size(); k++) {\n                        if (new_route2[k].order_id == -1) continue;\n                        if (new_route2[k].is_pickup) {\n                            picked2[new_route2[k].order_id] = true;\n                        } else {\n                            if (!picked2[new_route2[k].order_id]) {\n                                valid2 = false;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if (valid2 && new_route2.size() == route.size()) {\n                        long long new_distance2 = 0;\n                        for (size_t k = 0; k + 1 < new_route2.size(); k++) {\n                            new_distance2 += manhattan(new_route2[k].x, new_route2[k].y, new_route2[k+1].x, new_route2[k+1].y);\n                        }\n                        \n                        if (new_distance2 < best_distance) {\n                            route = new_route2;\n                            best_distance = new_distance2;\n                            best_route = route;\n                        } else if (exp(-(new_distance2 - best_distance) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                            route = new_route2;\n                        }\n                    }\n                }\n            }\n        }\n        \n        temperature *= cooling_rate;\n    }\n    \n    // Try order swapping (replace selected orders with better ones)\n    for (int swap_iter = 0; swap_iter < 100; swap_iter++) {\n        int remove_idx = uniform_int_distribution<int>(0, SELECT_COUNT - 1)(rng);\n        int remove_order = selected[remove_idx];\n        \n        // Find a better unselected order\n        vector<pair<double, int>> candidates;\n        for (int i = 0; i < NUM_ORDERS; i++) {\n            if (!is_selected[i]) {\n                int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n                int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n                double score = pickup_dist + 2.0 * delivery_dist;\n                candidates.push_back({score, i});\n            }\n        }\n        sort(candidates.begin(), candidates.end());\n        \n        for (int try_idx = 0; try_idx < min(10, (int)candidates.size()); try_idx++) {\n            int add_order = candidates[try_idx].second;\n            \n            // Try swapping\n            vector<int> new_selected = selected;\n            new_selected[remove_idx] = add_order;\n            is_selected[remove_order] = false;\n            is_selected[add_order] = true;\n            \n            // Rebuild route\n            vector<pair<double, int>> new_pickups, new_deliveries;\n            for (int idx : new_selected) {\n                new_pickups.push_back({get_angle(orders[idx].ax, orders[idx].ay), idx});\n                new_deliveries.push_back({get_angle(orders[idx].cx, orders[idx].cy), idx});\n            }\n            sort(new_pickups.begin(), new_pickups.end());\n            sort(new_deliveries.begin(), new_deliveries.end());\n            \n            vector<Point> new_route;\n            new_route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n            for (auto& p : new_pickups) {\n                int idx = p.second;\n                new_route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n            }\n            for (auto& p : new_deliveries) {\n                int idx = p.second;\n                new_route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n            }\n            new_route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n            \n            long long new_dist = 0;\n            for (size_t k = 0; k + 1 < new_route.size(); k++) {\n                new_dist += manhattan(new_route[k].x, new_route[k].y, new_route[k+1].x, new_route[k+1].y);\n            }\n            \n            if (new_dist < best_distance) {\n                selected = new_selected;\n                route = new_route;\n                best_distance = new_dist;\n                best_route = route;\n                break;\n            } else {\n                is_selected[remove_order] = true;\n                is_selected[add_order] = false;\n            }\n        }\n    }\n    \n    // Final route optimization with lower temperature\n    route = best_route;\n    temperature = 1000.0;\n    cooling_rate = 0.999;\n    iterations = 0;\n    const int FINAL_ITERATIONS = 50000;\n    \n    while (iterations < FINAL_ITERATIONS && temperature > 0.1) {\n        iterations++;\n        \n        int i = uniform_int_distribution<int>(1, route.size() - 3)(rng);\n        int j = uniform_int_distribution<int>(i + 1, route.size() - 2)(rng);\n        \n        vector<Point> new_route = route;\n        reverse(new_route.begin() + i, new_route.begin() + j + 1);\n        \n        bool valid = true;\n        vector<bool> picked(NUM_ORDERS, false);\n        for (size_t k = 0; k < new_route.size(); k++) {\n            if (new_route[k].order_id == -1) continue;\n            if (new_route[k].is_pickup) {\n                picked[new_route[k].order_id] = true;\n            } else {\n                if (!picked[new_route[k].order_id]) {\n                    valid = false;\n                    break;\n                }\n            }\n        }\n        \n        if (valid) {\n            long long new_distance = 0;\n            for (size_t k = 0; k + 1 < new_route.size(); k++) {\n                new_distance += manhattan(new_route[k].x, new_route[k].y, new_route[k+1].x, new_route[k+1].y);\n            }\n            \n            if (new_distance < best_distance) {\n                route = new_route;\n                best_distance = new_distance;\n                best_route = route;\n            } else if (exp(-(new_distance - best_distance) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                route = new_route;\n            }\n        }\n        \n        temperature *= cooling_rate;\n    }\n    \n    // Output\n    cout << SELECT_COUNT;\n    for (int idx : selected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << endl;\n    \n    cout << best_route.size();\n    for (auto& p : best_route) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\n// Union-Find data structure for tracking connected components\nstruct UnionFind {\n    vector<int> parent;\n    vector<int> rank;\n    int components;\n    \n    UnionFind(int n) : parent(n), rank(n, 0), components(n) {\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]);  // Path compression\n        }\n        return parent[x];\n    }\n    \n    bool unite(int x, int y) {\n        int px = find(x);\n        int py = find(y);\n        if (px == py) return false;\n        \n        // Union by rank\n        if (rank[px] < rank[py]) swap(px, py);\n        parent[py] = px;\n        if (rank[px] == rank[py]) rank[px]++;\n        components--;\n        return true;\n    }\n    \n    bool same(int x, int y) {\n        return find(x) == find(y);\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 edge endpoints\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    \n    UnionFind uf(N);\n    int edges_selected = 0;\n    \n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first;\n        int v = edges[i].second;\n        \n        // Compute expected distance d_i from coordinates\n        double dx = coords[u].first - coords[v].first;\n        double dy = coords[u].second - coords[v].second;\n        double d = round(sqrt(dx * dx + dy * dy));\n        \n        // Check if edge connects different components\n        bool different_components = !uf.same(u, v);\n        \n        bool accept = false;\n        \n        if (different_components) {\n            // Base threshold for inter-component edges\n            // Expected value is 2*d, so 2.4*d is reasonably selective\n            double threshold = 2.4 * d;\n            \n            // Calculate urgency based on remaining edges and components\n            int components_left = uf.components;\n            int edges_left = M - i;\n            int needed = components_left - 1;  // Edges needed to connect all\n            \n            // Urgency ratio: how critical is it to accept edges now?\n            double urgency = (double)needed / max(1, edges_left);\n            \n            // Adjust threshold based on urgency\n            if (urgency > 0.4) {\n                // High urgency: accept almost any inter-component edge\n                threshold = 3.0 * d;\n            } else if (urgency > 0.25) {\n                // Medium-high urgency\n                threshold = 2.7 * d;\n            } else if (urgency > 0.15) {\n                // Medium urgency\n                threshold = 2.5 * d;\n            } else if (urgency > 0.08) {\n                // Low urgency\n                threshold = 2.4 * d;\n            }\n            \n            // If we've selected many edges already, be more selective\n            // Target is N-1 = 399 edges for a tree\n            if (edges_selected > N - 1 + 100) {\n                threshold = 2.2 * d;\n            } else if (edges_selected > N - 1 + 50) {\n                threshold = 2.3 * d;\n            }\n            \n            if (l <= threshold) {\n                accept = true;\n            }\n        } else {\n            // For intra-component edges, only accept if very cheap\n            // These might replace more expensive edges in our spanning tree\n            // Threshold is lower since these are less valuable\n            if (l < d * 1.3) {\n                accept = true;\n            }\n        }\n        \n        // Emergency mode: force connectivity near the end\n        // Last 150 edges: be very aggressive about connecting components\n        if (i >= M - 150 && uf.components > 1 && different_components) {\n            accept = true;\n        }\n        \n        // Final emergency: last 50 edges, must connect if possible\n        if (i >= M - 50 && uf.components > 1 && different_components) {\n            accept = true;\n        }\n        \n        if (accept) {\n            cout << 1 << \"\\n\";\n            uf.unite(u, v);\n            edges_selected++;\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        \n        cout.flush();  // Critical: flush after each output\n    }\n    \n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <cstring>\n\nusing namespace std;\n\n// Structure to represent a position\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\n// Global variables\nint N, M;\nvector<Pos> pets;\nvector<int> pet_types;\nvector<Pos> humans;\nbool walls[32][32]; // Global wall state\nint pet_sum[32][32]; // Prefix sum of pet positions\n\n// Target zone\nint target_r1, target_r2, target_c1, target_c2;\nbool zone_locked = false; // If true, don't search for new zone for a while\nint turns_since_rezone = 0;\n\n// Check bounds\nbool in_grid(int r, int c) {\n    return r >= 0 && r < 30 && c >= 0 && c < 30;\n}\n\n// Update prefix sum of pet positions\nvoid update_pet_sum() {\n    int grid[32][32] = {0};\n    for(const auto& p : pets) {\n        if (in_grid(p.r, p.c)) {\n            grid[p.r][p.c]++;\n        }\n    }\n    // Compute 2D prefix sum\n    // pet_sum[i][j] stores sum of grid[0..i-1][0..j-1]\n    memset(pet_sum, 0, sizeof(pet_sum));\n    for(int i=0; i<30; ++i) {\n        for(int j=0; j<30; ++j) {\n            pet_sum[i+1][j+1] = grid[i][j] + pet_sum[i][j+1] + pet_sum[i+1][j] - pet_sum[i][j];\n        }\n    }\n}\n\n// Count pets in rectangle [r1, r2] x [c1, c2] (0-based inclusive)\nint count_pets(int r1, int c1, int r2, int c2) {\n    if (r1 > r2 || c1 > c2) return 0;\n    // Clamp to grid\n    r1 = max(0, r1); c1 = max(0, c1);\n    r2 = min(29, r2); c2 = min(29, c2);\n    return pet_sum[r2+1][c2+1] - pet_sum[r1][c2+1] - pet_sum[r2+1][c1] + pet_sum[r1][c1];\n}\n\n// Evaluate a zone\nint evaluate_zone(int r1, int r2, int c1, int c2) {\n    if (r1 > r2 || c1 > c2) return -2000000;\n    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n    \n    // Critical: No pets inside\n    if (count_pets(r1, c1, r2, c2) > 0) {\n        return -1000000; \n    }\n    \n    // Penalty for pets adjacent to perimeter (makes building hard)\n    int pets_adjacent = 0;\n    for(const auto& p : pets) {\n        // Check if pet is at Manhattan distance 1 from any cell on perimeter\n        int closest_r = max(r1, min(r2, p.r));\n        int closest_c = max(c1, min(c2, p.c));\n        int dist = abs(p.r - closest_r) + abs(p.c - closest_c);\n        if (dist == 1) {\n            pets_adjacent++;\n        }\n    }\n    \n    return area - pets_adjacent * 10;\n}\n\nvoid find_best_zone() {\n    int best_score = -2000000;\n    int best_r1 = 5, best_r2 = 24, best_c1 = 5, best_c2 = 24;\n    \n    // Search all rectangles\n    for (int r1 = 0; r1 < 30; ++r1) {\n        for (int r2 = r1; r2 < 30; ++r2) {\n            for (int c1 = 0; c1 < 30; ++c1) {\n                for (int c2 = c1; c2 < 30; ++c2) {\n                    int score = evaluate_zone(r1, r2, c1, c2);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1;\n                        best_r2 = r2;\n                        best_c1 = c1;\n                        best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n    \n    target_r1 = best_r1;\n    target_r2 = best_r2;\n    target_c1 = best_c1;\n    target_c2 = best_c2;\n    \n    // If we found a valid zone (no pets inside), lock it for a while\n    if (best_score > -500000) {\n        zone_locked = true;\n        turns_since_rezone = 0;\n    } else {\n        zone_locked = false;\n    }\n}\n\n// Get perimeter cells of the target zone\nvector<Pos> get_perimeter() {\n    vector<Pos> cells;\n    for (int c = target_c1; c <= target_c2; ++c) {\n        cells.push_back({target_r1, c});\n        if (target_r2 != target_r1) cells.push_back({target_r2, c});\n    }\n    for (int r = target_r1 + 1; r < target_r2; ++r) {\n        cells.push_back({r, target_c1});\n        if (target_c2 != target_c1) cells.push_back({r, target_c2});\n    }\n    return cells;\n}\n\n// Check if building at (r, c) is safe (no pet adjacent)\nbool can_build(int r, int c) {\n    if (!in_grid(r, c)) return false;\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    for (const auto& p : pets) {\n        for (int k = 0; k < 4; ++k) {\n            if (p.r + dr[k] == r && p.c + dc[k] == c) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// BFS for human movement avoiding walls\nPos get_next_move(Pos start, Pos target, const bool grid[32][32]) {\n    if (start == target) return start;\n    \n    queue<Pos> q;\n    q.push(start);\n    int dist[32][32];\n    Pos parent[32][32];\n    for(int i=0; i<32; ++i) for(int j=0; j<32; ++j) {\n        dist[i][j] = -1;\n        parent[i][j] = {-1, -1};\n    }\n    \n    dist[start.r][start.c] = 0;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    \n    while(!q.empty()){\n        Pos cur = q.front(); q.pop();\n        if (cur == target) break;\n        \n        for(int k=0; k<4; ++k){\n            int nr = cur.r + dr[k];\n            int nc = cur.c + dc[k];\n            if(in_grid(nr, nc) && !grid[nr][nc] && dist[nr][nc] == -1){\n                dist[nr][nc] = dist[cur.r][cur.c] + 1;\n                parent[nr][nc] = cur;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if (dist[target.r][target.c] == -1) return start;\n    \n    Pos curr = target;\n    while(parent[curr.r][curr.c] != start){\n        curr = parent[curr.r][curr.c];\n        if (curr.r == -1) return start;\n    }\n    return curr;\n}\n\nchar get_action_char(Pos from, Pos to) {\n    if (from == to) return '.';\n    if (to.r < from.r) return 'U';\n    if (to.r > from.r) return 'D';\n    if (to.c < from.c) return 'L';\n    if (to.c > from.c) return 'R';\n    return '.';\n}\n\nchar get_build_char(Pos from, Pos wall_pos) {\n    if (wall_pos.r < from.r) return 'u';\n    if (wall_pos.r > from.r) return 'd';\n    if (wall_pos.c < from.c) return 'l';\n    if (wall_pos.c > from.c) return 'r';\n    return '.';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N)) return 0;\n    pets.resize(N);\n    pet_types.resize(N);\n    for(int i=0; i<N; ++i){\n        cin >> pets[i].r >> pets[i].c >> pet_types[i];\n        pets[i].r--; pets[i].c--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for(int i=0; i<M; ++i){\n        cin >> humans[i].r >> humans[i].c;\n        humans[i].r--; humans[i].c--;\n    }\n    \n    memset(walls, 0, sizeof(walls));\n    \n    update_pet_sum();\n    find_best_zone();\n    \n    vector<Pos> perimeter = get_perimeter();\n    \n    for(int turn=0; turn<300; ++turn){\n        if (turn > 0) {\n            for(int i=0; i<N; ++i){\n                string s;\n                cin >> s;\n                if (s == \".\") continue;\n                for(char c : s){\n                    if (c == 'U') pets[i].r--;\n                    else if (c == 'D') pets[i].r++;\n                    else if (c == 'L') pets[i].c--;\n                    else if (c == 'R') pets[i].c++;\n                }\n            }\n            update_pet_sum();\n        }\n        \n        bool need_rezone = false;\n        if (!zone_locked) {\n            turns_since_rezone++;\n            if (turns_since_rezone >= 50) need_rezone = true;\n        }\n        \n        if (count_pets(target_r1, target_c1, target_r2, target_c2) > 0) {\n            need_rezone = true;\n            zone_locked = false;\n        }\n        \n        if (need_rezone) {\n            find_best_zone();\n            perimeter = get_perimeter();\n            turns_since_rezone = 0;\n        }\n        \n        bool temp_walls[32][32];\n        memcpy(temp_walls, walls, sizeof(walls));\n        \n        vector<char> human_actions(M, '.');\n        vector<Pos> next_human_pos(M);\n        vector<Pos> old_humans = humans;\n        \n        vector<int> buildable_indices;\n        for(size_t i=0; i<perimeter.size(); ++i){\n            if (!walls[perimeter[i].r][perimeter[i].c]) {\n                if (can_build(perimeter[i].r, perimeter[i].c)) {\n                    buildable_indices.push_back(i);\n                }\n            }\n        }\n        \n        vector<bool> segment_taken(perimeter.size(), false);\n        \n        for(int i=0; i<M; ++i){\n            int best_seg = -1;\n            int min_dist = 10000;\n            \n            for(int idx : buildable_indices){\n                if (segment_taken[idx]) continue;\n                int d = abs(humans[i].r - perimeter[idx].r) + abs(humans[i].c - perimeter[idx].c);\n                if (d < min_dist) {\n                    min_dist = d;\n                    best_seg = idx;\n                }\n            }\n            \n            Pos target;\n            if (best_seg != -1) {\n                segment_taken[best_seg] = true;\n                target = perimeter[best_seg];\n                \n                int dist = abs(humans[i].r - target.r) + abs(humans[i].c - target.c);\n                if (dist == 1) {\n                    if (can_build(target.r, target.c) && !temp_walls[target.r][target.c]) {\n                        human_actions[i] = get_build_char(humans[i], target);\n                        temp_walls[target.r][target.c] = true;\n                        next_human_pos[i] = humans[i];\n                    } else {\n                        Pos next = get_next_move(humans[i], target, temp_walls);\n                        human_actions[i] = get_action_char(humans[i], next);\n                        next_human_pos[i] = next;\n                    }\n                } else {\n                    Pos next = get_next_move(humans[i], target, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                }\n            } else {\n                bool all_built = true;\n                for(const auto& p : perimeter) {\n                    if (!walls[p.r][p.c]) {\n                        all_built = false;\n                        break;\n                    }\n                }\n                \n                if (all_built) {\n                    Pos center = {(target_r1 + target_r2)/2, (target_c1 + target_c2)/2};\n                    Pos next = get_next_move(humans[i], center, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                } else {\n                    human_actions[i] = '.';\n                    next_human_pos[i] = humans[i];\n                }\n            }\n        }\n        \n        string out = \"\";\n        for(int i=0; i<M; ++i) out += human_actions[i];\n        cout << out << endl;\n        \n        for(int i=0; i<M; ++i){\n            humans[i] = next_human_pos[i];\n            char act = human_actions[i];\n            if (act == 'u') walls[old_humans[i].r - 1][old_humans[i].c] = true;\n            else if (act == 'd') walls[old_humans[i].r + 1][old_humans[i].c] = true;\n            else if (act == 'l') walls[old_humans[i].r][old_humans[i].c - 1] = true;\n            else if (act == 'r') walls[old_humans[i].r][old_humans[i].c + 1] = true;\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables for grid and parameters\nint SI, SJ, TI, TJ;\ndouble P;\nvector<string> H; // 20 x 19\nvector<string> V; // 19 x 20\n\n// Directions\nconst int DI[4] = {-1, 1, 0, 0}; // U, D, L, R\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIRS[4] = {'U', 'D', 'L', 'R'};\n\n// Check if move is valid\ninline bool can_move(int r, int c, int dir) {\n    int nr = r + DI[dir];\n    int nc = c + DJ[dir];\n    if (nr < 0 || nr >= 20 || nc < 0 || nc >= 20) return false;\n    \n    if (dir == 0) { // U\n        if (r == 0) return false;\n        return V[r-1][c] == '0';\n    } else if (dir == 1) { // D\n        if (r == 19) return false;\n        return V[r][c] == '0';\n    } else if (dir == 2) { // L\n        if (c == 0) return false;\n        return H[r][c-1] == '0';\n    } else if (dir == 3) { // R\n        if (c == 19) return false;\n        return H[r][c] == '0';\n    }\n    return false;\n}\n\n// Calculate Expected Score for a given path string\ndouble calc_score(const string& path) {\n    // Static buffers to avoid allocation overhead\n    static double dp[20][20];\n    static double next_dp[20][20];\n    static int visited_token[20][20];\n    static int token = 0;\n    \n    // Reset dp for active cells from previous call is not needed if we manage active list\n    // But we need to ensure dp is clean for the start.\n    // Since we only access dp[r][c] for (r,c) in active, we just need to set dp[SI][SJ] = 1.0\n    // and ensure others are 0.\n    // To be safe and simple, we clear dp array. 400 doubles is fast.\n    for(int i=0; i<20; ++i) {\n        for(int j=0; j<20; ++j) {\n            dp[i][j] = 0.0;\n        }\n    }\n    \n    dp[SI][SJ] = 1.0;\n    \n    vector<pair<int, int>> active;\n    active.reserve(400);\n    active.push_back({SI, SJ});\n    \n    double expected_S = 0.0;\n    int L = path.length();\n    \n    for (int t = 0; t < L; ++t) {\n        token++;\n        int dir_idx = 0;\n        char c = path[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        vector<pair<int, int>> next_active;\n        next_active.reserve(400);\n        double prob_reach_now = 0.0;\n        \n        for (auto& p : active) {\n            int r = p.first;\n            int c = p.second;\n            double prob = dp[r][c];\n            \n            bool valid = can_move(r, c, dir_idx);\n            if (!valid) {\n                if (visited_token[r][c] != token) {\n                    visited_token[r][c] = token;\n                    next_dp[r][c] = 0.0;\n                    next_active.push_back({r, c});\n                }\n                next_dp[r][c] += prob;\n            } else {\n                int nr = r + DI[dir_idx];\n                int nc = c + DJ[dir_idx];\n                \n                // Stay\n                if (visited_token[r][c] != token) {\n                    visited_token[r][c] = token;\n                    next_dp[r][c] = 0.0;\n                    next_active.push_back({r, c});\n                }\n                next_dp[r][c] += prob * P;\n                \n                // Move\n                if (nr == TI && nc == TJ) {\n                    prob_reach_now += prob * (1.0 - P);\n                } else {\n                    if (visited_token[nr][nc] != token) {\n                        visited_token[nr][nc] = token;\n                        next_dp[nr][nc] = 0.0;\n                        next_active.push_back({nr, nc});\n                    }\n                    next_dp[nr][nc] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        expected_S += (401.0 - (t + 1)) * prob_reach_now;\n        \n        active = next_active;\n        for (auto& p : active) {\n            dp[p.first][p.second] = next_dp[p.first][p.second];\n        }\n        \n        if (active.empty()) break;\n    }\n    return expected_S;\n}\n\nint main() {\n    // Optimize I/O\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> SI >> SJ >> TI >> TJ >> P)) return 0;\n    \n    H.resize(20);\n    for (int i = 0; i < 20; ++i) cin >> H[i];\n    \n    V.resize(19);\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>>> parent(20, vector<pair<int, int>>(20, {-1, -1}));\n    vector<vector<int>> parent_dir(20, vector<int>(20, -1));\n    \n    queue<pair<int, int>> q;\n    q.push({SI, SJ});\n    dist[SI][SJ] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        if (r == TI && c == TJ) break;\n        \n        for (int d = 0; d < 4; ++d) {\n            if (can_move(r, c, d)) {\n                int nr = r + DI[d];\n                int nc = c + DJ[d];\n                if (dist[nr][nc] == -1) {\n                    dist[nr][nc] = dist[r][c] + 1;\n                    parent[nr][nc] = {r, c};\n                    parent_dir[nr][nc] = d;\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    \n    // Reconstruct path\n    string path = \"\";\n    int cr = TI, cc = TJ;\n    // If target not reachable (should not happen per problem statement)\n    if (dist[TI][TJ] != -1) {\n        while (cr != SI || cc != SJ) {\n            int d = parent_dir[cr][cc];\n            path += DIRS[d];\n            auto p = parent[cr][cc];\n            cr = p.first;\n            cc = p.second;\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    // Initial solution: repeat path to fill 200\n    string current_sol = \"\";\n    if (path.empty()) {\n        // Fallback if start==target or error, though constraints prevent start==target\n        current_sol = \"D\"; \n    }\n    while (current_sol.length() < 200) {\n        current_sol += path;\n    }\n    if (current_sol.length() > 200) {\n        current_sol = current_sol.substr(0, 200);\n    }\n    \n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double current_score = calc_score(current_sol);\n    double best_score = current_score;\n    string best_sol = current_sol;\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    \n    double temp = 1000.0;\n    double cooling_rate = 0.9999;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        // Propose move\n        string next_sol = current_sol;\n        int idx = uniform_int_distribution<int>(0, 199)(rng);\n        int new_dir = uniform_int_distribution<int>(0, 3)(rng);\n        next_sol[idx] = DIRS[new_dir];\n        \n        double next_score = calc_score(next_sol);\n        \n        double delta = next_score - current_score;\n        \n        if (delta > 0 || exp(delta / temp) > uniform_real_distribution<double>(0, 1)(rng)) {\n            current_sol = next_sol;\n            current_score = next_score;\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_sol = current_sol;\n            }\n        }\n        \n        temp *= cooling_rate;\n    }\n    \n    cout << best_sol << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entry_direction] = exit_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\n// -1 means cannot enter from that direction\nconst int to_table[8][4] = {\n    {1, 0, -1, -1},  // tile 0\n    {3, -1, -1, 0},  // tile 1\n    {-1, -1, 3, 2},  // tile 2\n    {-1, 2, 1, -1},  // tile 3\n    {1, 0, 3, 2},    // tile 4\n    {3, 2, 1, 0},    // tile 5\n    {2, -1, 0, -1},  // tile 6\n    {-1, 3, -1, 1},  // tile 7\n};\n\nconst int di[4] = {0, -1, 0, 1};  // left, up, right, down\nconst int dj[4] = {-1, 0, 1, 0};\n\nint tiles[N][N];\nint rotation[N][N];\nint best_rotation[N][N];\n\n// Get effective tile type after rotation\ninline int get_tile(int i, int j) {\n    return (tiles[i][j] + rotation[i][j]) % 8;\n}\n\n// Trace a loop starting from position (si, sj) with entry direction sd\n// Returns the length of the loop, or 0 if not a valid loop\nint trace_loop(int si, int sj, int sd) {\n    int i = si, j = sj, d = sd;\n    int length = 0;\n    const int max_len = N * N * 4 + 10;\n    \n    do {\n        int tile = get_tile(i, j);\n        int d2 = to_table[tile][d];\n        \n        if (d2 == -1) return 0;\n        \n        i += di[d2];\n        j += dj[d2];\n        \n        if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n        \n        d = (d2 + 2) % 4;\n        length++;\n        \n        if (length > max_len) return 0;\n        \n    } while (!(i == si && j == sj && d == sd));\n    \n    return length;\n}\n\n// Find all loops and return the two longest lengths\npair<int, int> find_two_longest_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    \n    int max1 = 0, max2 = 0;\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                if (!visited[i][j][d]) {\n                    int len = trace_loop(i, j, d);\n                    \n                    if (len > 0) {\n                        // Mark all states in this loop as visited\n                        int ci = i, cj = j, cd = d;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2];\n                            cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == i && cj == j && cd == d));\n                        \n                        if (len > max1) {\n                            max2 = max1;\n                            max1 = len;\n                        } else if (len > max2) {\n                            max2 = len;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    return {max1, max2};\n}\n\n// Calculate score\nlong long calculate_score() {\n    auto [l1, l2] = find_two_longest_loops();\n    return (long long)l1 * l2;\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        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            tiles[i][j] = s[j] - '0';\n            rotation[i][j] = 0;\n        }\n    }\n    \n    // Initialize with random rotations\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            rotation[i][j] = uniform_int_distribution<>(0, 3)(rng);\n        }\n    }\n    \n    long long best_score = calculate_score();\n    memcpy(best_rotation, rotation, sizeof(rotation));\n    \n    long long current_score = best_score;\n    \n    // Simulated annealing\n    double temperature = 10000.0;\n    double cooling_rate = 0.99995;\n    int iterations = 0;\n    int max_iterations = 2000000;\n    int no_improve_count = 0;\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    while (iterations < max_iterations && temperature > 0.001) {\n        // Check time limit (leave some margin)\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.8) break;\n        \n        // Pick random tile\n        int i = uniform_int_distribution<>(0, N-1)(rng);\n        int j = uniform_int_distribution<>(0, N-1)(rng);\n        \n        // Try changing rotation\n        int old_rot = rotation[i][j];\n        int new_rot = (old_rot + uniform_int_distribution<>(1, 3)(rng)) % 4;\n        rotation[i][j] = new_rot;\n        \n        long long new_score = calculate_score();\n        \n        // Accept or reject using Metropolis criterion\n        double delta = (double)(new_score - current_score);\n        bool accept = false;\n        \n        if (delta > 0) {\n            accept = true;\n        } else if (temperature > 0.001) {\n            double prob = exp(delta / temperature);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n                no_improve_count = 0;\n            } else {\n                no_improve_count++;\n            }\n        } else {\n            rotation[i][j] = old_rot;  // revert\n        }\n        \n        // Adaptive cooling: cool faster if no improvement\n        if (no_improve_count > 10000) {\n            cooling_rate = 0.9999;\n        }\n        \n        temperature *= cooling_rate;\n        iterations++;\n        \n        // Periodic restart if stuck\n        if (no_improve_count > 50000 && temperature < 1.0) {\n            temperature = 100.0;\n            no_improve_count = 0;\n            // Randomize some tiles\n            for (int k = 0; k < 100; k++) {\n                int ri = uniform_int_distribution<>(0, N-1)(rng);\n                int rj = uniform_int_distribution<>(0, N-1)(rng);\n                rotation[ri][rj] = uniform_int_distribution<>(0, 3)(rng);\n            }\n            current_score = calculate_score();\n        }\n    }\n    \n    // Output best rotation\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << best_rotation[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nvector<string> board;\nint empty_r, empty_c;\nstring moves = \"\";\n\n// Direction vectors: U, D, L, R\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nint get_tile(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N) return -1;\n    if (board[r][c] == '0') return 0;\n    return hex_to_int(board[r][c]);\n}\n\nbool has_connection(int tile_val, int d) {\n    if (tile_val == 0) return false;\n    const int mask[] = {2, 8, 1, 4};\n    return (tile_val & mask[d]) != 0;\n}\n\nbool tiles_connect(int r1, int c1, int r2, int c2) {\n    int t1 = get_tile(r1, c1);\n    int t2 = get_tile(r2, c2);\n    if (t1 == 0 || t2 == 0) return false;\n    \n    if (r2 == r1 + 1) return has_connection(t1, 1) && has_connection(t2, 0);\n    if (r2 == r1 - 1) return has_connection(t1, 0) && has_connection(t2, 1);\n    if (c2 == c1 + 1) return has_connection(t1, 3) && has_connection(t2, 2);\n    if (c2 == c1 - 1) return has_connection(t1, 2) && has_connection(t2, 3);\n    return false;\n}\n\nvoid make_move(int d) {\n    int nr = empty_r + dr[d];\n    int nc = empty_c + dc[d];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return;\n    if ((int)moves.size() >= T) return;\n    \n    swap(board[empty_r][empty_c], board[nr][nc]);\n    empty_r = nr;\n    empty_c = nc;\n    moves += dir_char[d];\n}\n\nvoid move_empty_to(int target_r, int target_c) {\n    while (empty_r != target_r || empty_c != target_c) {\n        if ((int)moves.size() >= T - 10) break;\n        \n        int best_d = -1;\n        int best_dist = 1e9;\n        \n        for (int d = 0; d < 4; d++) {\n            int nr = empty_r + dr[d];\n            int nc = empty_c + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                int dist = abs(nr - target_r) + abs(nc - target_c);\n                if (dist < best_dist) {\n                    best_dist = dist;\n                    best_d = d;\n                }\n            }\n        }\n        \n        if (best_d == -1) break;\n        make_move(best_d);\n    }\n}\n\nint calculate_tree_size() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int max_size = 0;\n    const int dr2[] = {-1, 1, 0, 0};\n    const int dc2[] = {0, 0, -1, 1};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0' || visited[i][j]) continue;\n            \n            int size = 0;\n            queue<pair<int,int>> q;\n            q.push({i, j});\n            visited[i][j] = true;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front();\n                q.pop();\n                size++;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr2[d];\n                    int nc = c + dc2[d];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && \n                        !visited[nr][nc] && board[nr][nc] != '0') {\n                        if (tiles_connect(r, c, nr, nc)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n            }\n            max_size = max(max_size, size);\n        }\n    }\n    return max_size;\n}\n\nstruct TileInfo {\n    int value;\n    int r, c;\n    bool placed;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    \n    vector<TileInfo> tiles;\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            } else {\n                tiles.push_back({hex_to_int(board[i][j]), i, j, false});\n            }\n        }\n    }\n    \n    // Target positions in snake pattern (excluding bottom-right for empty)\n    vector<pair<int,int>> targets;\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)) targets.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (!(i == N-1 && j == N-1)) targets.push_back({i, j});\n            }\n        }\n    }\n    \n    // Sort tiles by connection count (descending)\n    sort(tiles.begin(), tiles.end(), [](const TileInfo& a, const TileInfo& b) {\n        int ca = __builtin_popcount(a.value), cb = __builtin_popcount(b.value);\n        return ca > cb;\n    });\n    \n    // Place tiles one by one\n    for (int ti = 0; ti < (int)tiles.size() && ti < (int)targets.size(); ti++) {\n        if ((int)moves.size() >= T - 50) break;\n        \n        int tr = targets[ti].first;\n        int tc = targets[ti].second;\n        \n        // Find best unplaced tile for this position\n        int best_idx = -1;\n        int best_score = -1e9;\n        \n        for (int i = ti; i < (int)tiles.size(); i++) {\n            if (tiles[i].placed) continue;\n            \n            int score = 0;\n            \n            // Check connections with placed neighbors\n            for (int d = 0; d < 4; d++) {\n                int pr = tr + dr[d];\n                int pc = tc + dc[d];\n                if (pr >= 0 && pr < N && pc >= 0 && pc < N) {\n                    for (int j = 0; j < ti; j++) {\n                        if (tiles[j].placed && tiles[j].r == pr && tiles[j].c == pc) {\n                            // Check if they would connect\n                            int t1_val = tiles[j].value;\n                            int t2_val = tiles[i].value;\n                            bool conn = false;\n                            if (d == 0) conn = has_connection(t2_val, 0) && has_connection(t1_val, 1);\n                            if (d == 1) conn = has_connection(t2_val, 1) && has_connection(t1_val, 0);\n                            if (d == 2) conn = has_connection(t2_val, 2) && has_connection(t1_val, 3);\n                            if (d == 3) conn = has_connection(t2_val, 3) && has_connection(t1_val, 2);\n                            if (conn) score += 20;\n                            break;\n                        }\n                    }\n                }\n            }\n            \n            // Penalty for distance\n            int dist = abs(tiles[i].r - tr) + abs(tiles[i].c - tc);\n            score -= dist;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_idx = i;\n            }\n        }\n        \n        if (best_idx == -1) continue;\n        \n        // Move this tile to target position\n        int tile_r = tiles[best_idx].r;\n        int tile_c = tiles[best_idx].c;\n        \n        while (tile_r != tr || tile_c != tc) {\n            if ((int)moves.size() >= T - 30) break;\n            \n            // Move empty to appropriate position to push tile\n            if (tile_r < tr) {\n                // Move tile down: empty should be below tile\n                move_empty_to(tile_r + 1, tile_c);\n                if (empty_r == tile_r + 1 && empty_c == tile_c && tile_r + 1 < N) {\n                    make_move(0); // Empty moves up, tile moves down\n                    tile_r++;\n                }\n            } else if (tile_r > tr) {\n                move_empty_to(tile_r - 1, tile_c);\n                if (empty_r == tile_r - 1 && empty_c == tile_c && tile_r - 1 >= 0) {\n                    make_move(1); // Empty moves down, tile moves up\n                    tile_r--;\n                }\n            } else if (tile_c < tc) {\n                move_empty_to(tile_r, tile_c + 1);\n                if (empty_r == tile_r && empty_c == tile_c + 1 && tile_c + 1 < N) {\n                    make_move(2); // Empty moves left, tile moves right\n                    tile_c++;\n                }\n            } else if (tile_c > tc) {\n                move_empty_to(tile_r, tile_c - 1);\n                if (empty_r == tile_r && empty_c == tile_c - 1 && tile_c - 1 >= 0) {\n                    make_move(3); // Empty moves right, tile moves left\n                    tile_c--;\n                }\n            }\n            \n            // Safety check\n            if (tile_r == tiles[best_idx].r && tile_c == tiles[best_idx].c) {\n                // Couldn't move, try different approach\n                move_empty_to(tr, tc);\n                break;\n            }\n        }\n        \n        // Update tile position in our tracking\n        // Find the tile at target position\n        int actual_val = get_tile(tr, tc);\n        for (int i = 0; i < (int)tiles.size(); i++) {\n            if (!tiles[i].placed && tiles[i].value == actual_val) {\n                tiles[i].r = tr;\n                tiles[i].c = tc;\n                tiles[i].placed = true;\n                break;\n            }\n        }\n    }\n    \n    // Move empty to bottom-right\n    move_empty_to(N-1, N-1);\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\n#include <Eigen/Dense>\nusing namespace std;\n\nstruct Point {\n    long long x, y;\n    double angle;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\nstruct Strawberry {\n    int id;\n    long long x, y;\n    int assigned_group = -1;\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> lines;\n\n// Check which side of line a point is on\n// Returns: 1 if left, -1 if right, 0 if on line\nint sideOfLine(const Line& l, long long x, long long y) {\n    __int128 dx1 = l.qx - l.px;\n    __int128 dy1 = l.qy - l.py;\n    __int128 dx2 = x - l.px;\n    __int128 dy2 = y - l.py;\n    __int128 cross = dx1 * dy2 - dy1 * dx2;\n    if (cross > 0) return 1;\n    if (cross < 0) return -1;\n    return 0;\n}\n\n// Check if strawberry is on any cut line\nbool isCut(int idx) {\n    for (const auto& l : lines) {\n        if (sideOfLine(l, strawberries[idx].x, strawberries[idx].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\n// Get region assignment for each strawberry\nvector<int> getRegions() {\n    vector<int> region(N);\n    for (int i = 0; i < N; i++) {\n        if (isCut(i)) {\n            region[i] = -1;\n            continue;\n        }\n        long long signature = 0;\n        for (int j = 0; j < (int)lines.size(); j++) {\n            int s = sideOfLine(lines[j], strawberries[i].x, strawberries[i].y);\n            if (s == 1) signature |= (1LL << j);\n        }\n        region[i] = signature;\n    }\n    return region;\n}\n\n// Calculate score\nint calculateScore() {\n    auto regions = getRegions();\n    map<int, int> pieceCount;\n    for (int i = 0; i < N; i++) {\n        if (regions[i] >= 0) {\n            pieceCount[regions[i]]++;\n        }\n    }\n    \n    int score = 0;\n    for (int d = 1; d <= 10; d++) {\n        int b_d = 0;\n        for (auto& [region, count] : pieceCount) {\n            if (count == d) b_d++;\n        }\n        score += min(a[d], b_d);\n    }\n    return score;\n}\n\n// Distance squared between two points\nlong long distSq(long long x1, long long y1, long long x2, long long y2) {\n    __int128 dx = x1 - x2;\n    __int128 dy = y1 - y2;\n    return (long long)(dx * dx + dy * dy);\n}\n\n// Create a line that separates two groups of strawberries\nLine createSeparatingLine(const vector<int>& group1, const vector<int>& group2) {\n    if (group1.empty() || group2.empty()) {\n        return Line{0, 0, 1, 0};\n    }\n    \n    // Find centroids\n    long long cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0;\n    for (int idx : group1) {\n        cx1 += strawberries[idx].x;\n        cy1 += strawberries[idx].y;\n    }\n    for (int idx : group2) {\n        cx2 += strawberries[idx].x;\n        cy2 += strawberries[idx].y;\n    }\n    cx1 /= group1.size();\n    cy1 /= group1.size();\n    cx2 /= group2.size();\n    cy2 /= group2.size();\n    \n    // Line perpendicular to line connecting centroids, passing through midpoint\n    long long mx = (cx1 + cx2) / 2;\n    long long my = (cy1 + cy2) / 2;\n    long long dx = cx2 - cx1;\n    long long dy = cy2 - cy1;\n    \n    // Perpendicular direction\n    long long px = mx - dy;\n    long long py = my + dx;\n    long long qx = mx + dy;\n    long long qy = my - dx;\n    \n    // Ensure points are different\n    if (px == qx && py == qy) {\n        qx++;\n    }\n    \n    return Line{px, py, qx, qy};\n}\n\n// Cluster strawberries using greedy approach\nvector<vector<int>> clusterStrawberries() {\n    vector<vector<int>> clusters;\n    vector<bool> used(N, false);\n    \n    // Create demand list\n    vector<int> demands;\n    for (int d = 1; d <= 10; d++) {\n        for (int i = 0; i < a[d]; i++) {\n            demands.push_back(d);\n        }\n    }\n    sort(demands.rbegin(), demands.rend()); // Larger groups first\n    \n    for (int demand : demands) {\n        if ((int)clusters.size() >= K + 1) break; // Can't create more pieces than regions\n        \n        // Find best unassigned strawberry as seed\n        int bestSeed = -1;\n        double bestMinDist = -1;\n        \n        for (int i = 0; i < N; i++) {\n            if (used[i]) continue;\n            double minDist = 1e18;\n            for (int j = 0; j < N; j++) {\n                if (i == j || used[j]) continue;\n                double d = sqrt(distSq(strawberries[i].x, strawberries[i].y, \n                                       strawberries[j].x, strawberries[j].y));\n                minDist = min(minDist, d);\n            }\n            if (minDist > bestMinDist) {\n                bestMinDist = minDist;\n                bestSeed = i;\n            }\n        }\n        \n        if (bestSeed == -1) break;\n        \n        // Grow cluster from seed\n        vector<int> cluster;\n        vector<pair<double, int>> candidates;\n        \n        for (int i = 0; i < N; i++) {\n            if (!used[i]) {\n                double d = sqrt(distSq(strawberries[bestSeed].x, strawberries[bestSeed].y,\n                                       strawberries[i].x, strawberries[i].y));\n                candidates.push_back({d, i});\n            }\n        }\n        sort(candidates.begin(), candidates.end());\n        \n        for (int i = 0; i < (int)candidates.size() && (int)cluster.size() < demand; i++) {\n            cluster.push_back(candidates[i].second);\n            used[candidates[i].second] = true;\n        }\n        \n        if (!cluster.empty()) {\n            clusters.push_back(cluster);\n        }\n    }\n    \n    // Assign remaining strawberries to existing clusters or create singletons\n    for (int i = 0; i < N; i++) {\n        if (!used[i]) {\n            // Find nearest cluster\n            int bestCluster = -1;\n            double bestDist = 1e18;\n            for (int c = 0; c < (int)clusters.size(); c++) {\n                if ((int)clusters[c].size() < 10) {\n                    for (int idx : clusters[c]) {\n                        double d = sqrt(distSq(strawberries[i].x, strawberries[i].y,\n                                               strawberries[idx].x, strawberries[idx].y));\n                        if (d < bestDist) {\n                            bestDist = d;\n                            bestCluster = c;\n                        }\n                    }\n                }\n            }\n            if (bestCluster >= 0 && (int)clusters[bestCluster].size() < 10) {\n                clusters[bestCluster].push_back(i);\n                used[i] = true;\n            } else {\n                clusters.push_back({i});\n                used[i] = true;\n            }\n        }\n    }\n    \n    return clusters;\n}\n\n// Generate lines to separate clusters\nvoid generateLines(const vector<vector<int>>& clusters) {\n    lines.clear();\n    \n    // For each pair of adjacent clusters, create a separating line\n    for (int i = 0; i < (int)clusters.size() && (int)lines.size() < K; i++) {\n        for (int j = i + 1; j < (int)clusters.size() && (int)lines.size() < K; j++) {\n            // Check if clusters are already separated by existing lines\n            bool alreadySeparated = true;\n            for (int idx1 : clusters[i]) {\n                for (int idx2 : clusters[j]) {\n                    bool same = true;\n                    for (const auto& l : lines) {\n                        int s1 = sideOfLine(l, strawberries[idx1].x, strawberries[idx1].y);\n                        int s2 = sideOfLine(l, strawberries[idx2].x, strawberries[idx2].y);\n                        if (s1 != 0 && s2 != 0 && s1 != s2) {\n                            same = false;\n                            break;\n                        }\n                    }\n                    if (same) {\n                        alreadySeparated = false;\n                        break;\n                    }\n                }\n                if (!alreadySeparated) break;\n            }\n            \n            if (!alreadySeparated) {\n                Line l = createSeparatingLine(clusters[i], clusters[j]);\n                \n                // Check if line cuts any strawberry\n                bool cutsStrawberry = false;\n                for (int k = 0; k < N; k++) {\n                    if (sideOfLine(l, strawberries[k].x, strawberries[k].y) == 0) {\n                        cutsStrawberry = true;\n                        break;\n                    }\n                }\n                \n                if (!cutsStrawberry && (int)lines.size() < K) {\n                    lines.push_back(l);\n                }\n            }\n        }\n    }\n}\n\n// Try to improve solution by adjusting lines\nvoid optimize() {\n    int baseScore = calculateScore();\n    \n    for (int iter = 0; iter < 100; iter++) {\n        if ((int)lines.size() >= K) break;\n        \n        // Try adding a random line\n        int i1 = rand() % N;\n        int i2 = rand() % N;\n        if (i1 == i2) continue;\n        \n        Line newLine = createSeparatingLine({i1}, {i2});\n        \n        // Check if it cuts any strawberry\n        bool cutsStrawberry = false;\n        for (int k = 0; k < N; k++) {\n            if (sideOfLine(newLine, strawberries[k].x, strawberries[k].y) == 0) {\n                cutsStrawberry = true;\n                break;\n            }\n        }\n        \n        if (!cutsStrawberry) {\n            lines.push_back(newLine);\n            int newScore = calculateScore();\n            if (newScore < baseScore) {\n                lines.pop_back();\n            } else {\n                baseScore = newScore;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        strawberries[i].id = i;\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Cluster strawberries\n    auto clusters = clusterStrawberries();\n    \n    // Generate separating lines\n    generateLines(clusters);\n    \n    // Optimize\n    optimize();\n    \n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const auto& l : lines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nstruct Rect {\n    Point p[4]; // p[0] is target (new dot), p[1..3] are existing\n    long long weight;\n    int perimeter_len;\n    \n    // For sorting\n    bool operator<(const Rect& other) const {\n        if (weight != other.weight) return weight > other.weight;\n        return perimeter_len < other.perimeter_len;\n    }\n};\n\nint N, M;\nvector<Point> initial_dots;\nvector<vector<bool>> has_dot;\nvector<vector<bool>> used_h;\nvector<vector<bool>> used_v;\nvector<vector<bool>> used_d1;\nvector<vector<bool>> used_d2;\n\nlong long total_weight_S = 0;\nvector<vector<long long>> weights;\n\nvoid init_weights() {\n    double c = (N - 1) / 2.0;\n    weights.assign(N, vector<long long>(N));\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (long long)round(pow(x - c, 2) + pow(y - c, 2) + 1);\n            weights[x][y] = w;\n            total_weight_S += w;\n        }\n    }\n}\n\nbool is_inside(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\nbool check_perimeter_dots(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps == 0) return true;\n    int sx = (dx > 0) - (dx < 0);\n    int sy = (dy > 0) - (dy < 0);\n    \n    for (int i = 1; i < steps; ++i) {\n        int cx = x1 + i * sx;\n        int cy = y1 + i * sy;\n        if (has_dot[cx][cy]) return false;\n    }\n    return true;\n}\n\nbool check_rect_dots(const Rect& r) {\n    for (int i = 0; i < 4; ++i) {\n        Point p1 = r.p[i];\n        Point p2 = r.p[(i + 1) % 4];\n        if (!check_perimeter_dots(p1.x, p1.y, p2.x, p2.y)) return false;\n    }\n    return true;\n}\n\nbool process_edges(const Rect& r, bool mark) {\n    for (int i = 0; i < 4; ++i) {\n        int x1 = r.p[i].x, y1 = r.p[i].y;\n        int x2 = r.p[(i + 1) % 4].x, y2 = r.p[(i + 1) % 4].y;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx > 0) - (dx < 0);\n        int sy = (dy > 0) - (dy < 0);\n        \n        for (int i = 0; i < steps; ++i) {\n            int cx = x1 + i * sx;\n            int cy = y1 + i * sy;\n            int nx = cx + sx;\n            int ny = cy + sy;\n            \n            bool used = false;\n            if (sx == 1 && sy == 0) { \n                if (used_h[cx][cy]) used = true;\n                else if (mark) used_h[cx][cy] = true;\n            } else if (sx == 0 && sy == 1) { \n                if (used_v[cx][cy]) used = true;\n                else if (mark) used_v[cx][cy] = true;\n            } else if (sx == 1 && sy == 1) { \n                if (used_d1[cx][cy]) used = true;\n                else if (mark) used_d1[cx][cy] = true;\n            } else if (sx == 1 && sy == -1) { \n                if (used_d2[cx][cy]) used = true;\n                else if (mark) used_d2[cx][cy] = true;\n            } else {\n                return false; \n            }\n            if (used) return false;\n        }\n    }\n    return true;\n}\n\nvector<Rect> generate_candidates(const vector<Point>& active_dots, mt19937& rng) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    // Iterate all pairs of existing dots\n    for (int i = 0; i < S; ++i) {\n        for (int j = i + 1; j < S; ++j) {\n            Point A = active_dots[i];\n            Point B = active_dots[j];\n            \n            // Case 1: A, B are diagonal\n            // Axis aligned\n            if (A.x != B.x && A.y != B.y) {\n                Point C1 = {A.x, B.y};\n                Point C2 = {B.x, A.y};\n                // Target C1, Source C2\n                if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && has_dot[C2.x][C2.y]) {\n                    Rect r; r.p[0]=C1; r.p[1]=C2; r.p[2]=B; r.p[3]=A;\n                    cands.push_back(r);\n                }\n                // Target C2, Source C1\n                if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && has_dot[C1.x][C1.y]) {\n                    Rect r; r.p[0]=C2; r.p[1]=C1; r.p[2]=A; r.p[3]=B;\n                    cands.push_back(r);\n                }\n            }\n            // 45-deg diagonal (Diagonals are H or V)\n            if (A.x == B.x) {\n                if ((A.y + B.y) % 2 == 0) {\n                    int my = (A.y + B.y) / 2;\n                    int dist = abs(A.y - B.y) / 2;\n                    Point C = {A.x - dist, my};\n                    Point D = {A.x + dist, my};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; cands.push_back(r);\n                    }\n                }\n            }\n            if (A.y == B.y) {\n                if ((A.x + B.x) % 2 == 0) {\n                    int mx = (A.x + B.x) / 2;\n                    int dist = abs(A.x - B.x) / 2;\n                    Point C = {mx, A.y - dist};\n                    Point D = {mx, A.y + dist};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; cands.push_back(r);\n                    }\n                }\n            }\n            \n            // Case 2: A, B are side. Need 3rd dot C to form corner.\n            // Iterate all C to find valid corners. O(M^3) total.\n            // Optimization: Only check C that forms right angle.\n            // We can iterate all C. M is small (<=300). M^3 = 2.7e7. Acceptable for initialization.\n            // But inside loop we call this every step? No, we only call this for NEW candidates.\n            // To avoid O(M^3) every step, we rely on the fact that we only need to pair the NEW dot with existing.\n            // But this function generates ALL candidates from scratch.\n            // For the main loop, we should use an incremental approach or accept O(M^3) if M is small.\n            // Given 5s, let's try to be efficient.\n            // Actually, for the main loop, we can just call this function.\n            // If it's too slow, we limit restarts.\n            // Let's optimize: Only iterate C if it forms a right angle with A, B.\n            // But checking all C is simplest.\n            // Let's add this loop.\n            for (int k = 0; k < S; ++k) {\n                if (k == i || k == j) continue;\n                Point C = active_dots[k];\n                // Check if A, B, C form a corner of a rect\n                // 3 permutations: Corner at A, B, or C.\n                // Corner at A: AB perp AC.\n                {\n                    long long dx1 = B.x - A.x, dy1 = B.y - A.y;\n                    long long dx2 = C.x - A.x, dy2 = C.y - A.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {B.x + C.x - A.x, B.y + C.y - A.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=A; r.p[2]=B; r.p[3]=C; cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at B: BA perp BC.\n                {\n                    long long dx1 = A.x - B.x, dy1 = A.y - B.y;\n                    long long dx2 = C.x - B.x, dy2 = C.y - B.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + C.x - B.x, A.y + C.y - B.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=B; r.p[2]=A; r.p[3]=C; cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at C: CA perp CB.\n                {\n                    long long dx1 = A.x - C.x, dy1 = A.y - C.y;\n                    long long dx2 = B.x - C.x, dy2 = B.y - C.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + B.x - C.x, A.y + B.y - C.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return cands;\n}\n\nstruct Solution {\n    vector<Rect> ops;\n    long long score;\n};\n\nSolution solve_one(mt19937& rng) {\n    // Reset state\n    has_dot.assign(N, vector<bool>(N, false));\n    used_h.assign(N, vector<bool>(N, false));\n    used_v.assign(N, vector<bool>(N, false));\n    used_d1.assign(N, vector<bool>(N, false));\n    used_d2.assign(N, vector<bool>(N, false));\n    \n    vector<Point> active_dots = initial_dots;\n    for (auto& p : active_dots) has_dot[p.x][p.y] = true;\n    \n    vector<Rect> ops;\n    // Initial candidates\n    vector<Rect> candidates = generate_candidates(active_dots, rng);\n    \n    while (true) {\n        // Filter valid candidates\n        vector<Rect> valid_cands;\n        valid_cands.reserve(candidates.size());\n        for (auto& r : candidates) {\n            if (!has_dot[r.p[0].x][r.p[0].y] && // Target empty\n                has_dot[r.p[1].x][r.p[1].y] && has_dot[r.p[2].x][r.p[2].y] && has_dot[r.p[3].x][r.p[3].y] && // Sources have dots\n                check_rect_dots(r) && // No other dots on perimeter\n                process_edges(r, false) // Edges free\n               ) {\n                r.weight = get_weight(r.p[0].x, r.p[0].y);\n                // Calculate perimeter len\n                int len = 0;\n                for(int i=0; i<4; ++i) {\n                    len += max(abs(r.p[i].x - r.p[(i+1)%4].x), abs(r.p[i].y - r.p[(i+1)%4].y));\n                }\n                r.perimeter_len = len;\n                valid_cands.push_back(r);\n            }\n        }\n        \n        if (valid_cands.empty()) break;\n        \n        // Sort and pick\n        // Add some noise to break ties and explore\n        for(auto& r : valid_cands) {\n            r.weight += (rng() % 100); \n        }\n        sort(valid_cands.begin(), valid_cands.end());\n        \n        Rect best = valid_cands[0];\n        \n        // Apply\n        ops.push_back(best);\n        has_dot[best.p[0].x][best.p[0].y] = true;\n        active_dots.push_back(best.p[0]);\n        process_edges(best, true);\n        \n        // Update candidates:\n        // 1. Remove invalid ones (done by filtering next iter)\n        // 2. Add new ones involving the new dot.\n        // To do this efficiently, we can just regenerate all candidates?\n        // Regenerating all is O(M^3). M grows.\n        // Instead, generate only those involving the new dot.\n        // But generate_candidates iterates all pairs.\n        // Let's just regenerate all candidates if M is small, else incremental.\n        // Given M <= 300, O(M^3) is 2.7e7. Doing this 100 times is 2.7e9. Too slow.\n        // We MUST use incremental.\n        // But implementing incremental generation of \"3 dots including new one\" is complex.\n        // Compromise: Regenerate candidates only every K steps or if list is small?\n        // Or just rely on the fact that valid_cands shrinks.\n        // If we don't add new candidates, we stop early.\n        // We MUST add new candidates.\n        // Let's create a function `generate_candidates_with_new_dot(new_dot, active_dots)`\n        // This is O(M^2).\n        // We will use this.\n        \n        vector<Rect> new_cands;\n        Point new_dot = best.p[0];\n        int S = active_dots.size() - 1; // Exclude new_dot itself for pairing\n        for (int i = 0; i < S; ++i) {\n            Point A = active_dots[i];\n            Point B = new_dot; // One source is the new dot\n            \n            // We need 3 sources. So we need one more source C from active_dots.\n            // So we iterate C. O(M^2).\n            for (int k = 0; k < S; ++k) {\n                if (k == i) continue;\n                Point C = active_dots[k];\n                // Check corners with A, B, C\n                // Corner at A\n                {\n                    long long dx1 = B.x - A.x, dy1 = B.y - A.y;\n                    long long dx2 = C.x - A.x, dy2 = C.y - A.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {B.x + C.x - A.x, B.y + C.y - A.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=A; r.p[2]=B; r.p[3]=C; new_cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at B\n                {\n                    long long dx1 = A.x - B.x, dy1 = A.y - B.y;\n                    long long dx2 = C.x - B.x, dy2 = C.y - B.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + C.x - B.x, A.y + C.y - B.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=B; r.p[2]=A; r.p[3]=C; new_cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at C\n                {\n                    long long dx1 = A.x - C.x, dy1 = A.y - C.y;\n                    long long dx2 = B.x - C.x, dy2 = B.y - C.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + B.x - C.x, A.y + B.y - C.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Also check diagonal cases with new_dot\n            // A, new_dot diagonal\n            if (A.x != B.x && A.y != B.y) {\n                Point C1 = {A.x, B.y};\n                Point C2 = {B.x, A.y};\n                if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && has_dot[C2.x][C2.y]) {\n                    Rect r; r.p[0]=C1; r.p[1]=C2; r.p[2]=B; r.p[3]=A; new_cands.push_back(r);\n                }\n                if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && has_dot[C1.x][C1.y]) {\n                    Rect r; r.p[0]=C2; r.p[1]=C1; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                }\n            }\n             if (A.x == B.x) {\n                if ((A.y + B.y) % 2 == 0) {\n                    int my = (A.y + B.y) / 2;\n                    int dist = abs(A.y - B.y) / 2;\n                    Point C = {A.x - dist, my};\n                    Point D = {A.x + dist, my};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; new_cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                    }\n                }\n            }\n            if (A.y == B.y) {\n                if ((A.x + B.x) % 2 == 0) {\n                    int mx = (A.x + B.x) / 2;\n                    int dist = abs(A.x - B.x) / 2;\n                    Point C = {mx, A.y - dist};\n                    Point D = {mx, A.y + dist};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; new_cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                    }\n                }\n            }\n        }\n        \n        // Merge new_cands into candidates\n        candidates.insert(candidates.end(), new_cands.begin(), new_cands.end());\n    }\n    \n    Solution sol;\n    sol.ops = ops;\n    long long current_weight_sum = 0;\n    for(int x=0; x<N; ++x) for(int y=0; y<N; ++y) if(has_dot[x][y]) current_weight_sum += weights[x][y];\n    \n    // Score calculation\n    // round(1e6 * N*N / M * current_weight_sum / S)\n    double score_d = 1e6 * (double)N * N / M * (double)current_weight_sum / total_weight_S;\n    sol.score = (long long)round(score_d);\n    \n    return sol;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> initial_dots[i].x >> initial_dots[i].y;\n    }\n    \n    init_weights();\n    \n    Solution best_sol;\n    best_sol.score = -1;\n    \n    auto start = chrono::steady_clock::now();\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 4.8) break;\n        \n        Solution sol = solve_one(rng);\n        if (sol.score > best_sol.score) {\n            best_sol = sol;\n        }\n        iterations++;\n    }\n    \n    cout << best_sol.ops.size() << \"\\n\";\n    for (const auto& op : best_sol.ops) {\n        cout << op.p[0].x << \" \" << op.p[0].y << \" \"\n             << op.p[1].x << \" \" << op.p[1].y << \" \"\n             << op.p[2].x << \" \" << op.p[2].y << \" \"\n             << op.p[3].x << \" \" << op.p[3].y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <utility>\n\nusing namespace std;\n\n// Grid type: 10x10 integers\nusing Grid = array<array<int, 10>, 10>;\n\n// Function to calculate the sum of squares of connected component sizes\n// This is the numerator of the score function, which we want to maximize.\nlong long calculate_score(const Grid& g) {\n    long long score = 0;\n    bool visited[10][10] = {};\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                // Use a vector as a queue for BFS\n                vector<pair<int, int>> q;\n                q.reserve(100); \n                q.push_back({r, c});\n                visited[r][c] = true;\n                size++;\n                \n                int head = 0;\n                while(head < (int)q.size()){\n                    auto [cr, cc] = q[head++];\n                    for(int i=0; i<4; ++i){\n                        int nr = cr + dr[i];\n                        int nc = cc + dc[i];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                            if(!visited[nr][nc] && g[nr][nc] == flavor){\n                                visited[nr][nc] = true;\n                                size++;\n                                q.push_back({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Function to apply tilt and return the new grid\nGrid apply_tilt(const Grid& g, char dir) {\n    Grid ng;\n    // Initialize new grid with 0\n    for(auto& row : ng) row.fill(0);\n\n    if (dir == 'L' || dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            vector<int> row_vals;\n            row_vals.reserve(10);\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) row_vals.push_back(g[r][c]);\n            }\n            if (dir == 'L') {\n                for (int i = 0; i < (int)row_vals.size(); ++i) ng[r][i] = row_vals[i];\n            } else { // 'R'\n                int idx = 9;\n                for (int i = (int)row_vals.size() - 1; i >= 0; --i) ng[r][idx--] = row_vals[i];\n            }\n        }\n    } else { // 'F' or 'B'\n        for (int c = 0; c < 10; ++c) {\n            vector<int> col_vals;\n            col_vals.reserve(10);\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) col_vals.push_back(g[r][c]);\n            }\n            if (dir == 'F') {\n                for (int i = 0; i < (int)col_vals.size(); ++i) ng[i][c] = col_vals[i];\n            } else { // 'B'\n                int idx = 9;\n                for (int i = (int)col_vals.size() - 1; i >= 0; --i) ng[idx--][c] = col_vals[i];\n            }\n        }\n    }\n    return ng;\n}\n\nint main() {\n    // Optimize I/O operations\n    cin.tie(NULL);\n    ios_base::sync_with_stdio(false);\n\n    // Read flavors\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) {\n        cin >> f[i];\n    }\n\n    // Initialize empty grid\n    Grid grid;\n    for(auto& row : grid) row.fill(0);\n\n    // Process 100 turns\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        // Place the t-th candy (f[t]) into the p-th empty cell\n        int count = 0;\n        bool placed = false;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    count++;\n                    if (count == p) {\n                        grid[r][c] = f[t];\n                        placed = true;\n                        break;\n                    }\n                }\n            }\n            if (placed) break;\n        }\n\n        // For the last turn, the board is full, tilt doesn't change anything.\n        // We output 'F' for consistency, though it could be skipped.\n        if (t == 99) {\n            cout << \"F\" << endl;\n            break;\n        }\n\n        // Evaluate all 4 possible tilts\n        char best_dir = 'F';\n        long long best_score = -1;\n        char dirs[] = {'F', 'B', 'L', 'R'};\n\n        for (char d : dirs) {\n            Grid ng = apply_tilt(grid, d);\n            long long sc = calculate_score(ng);\n            // Greedy choice: maximize sum of squares of component sizes\n            if (sc > best_score) {\n                best_score = sc;\n                best_dir = d;\n            }\n        }\n\n        // Output the best direction and update the grid\n        cout << best_dir << endl;\n        grid = apply_tilt(grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n#include <Eigen/Dense>\n\nusing namespace std;\n\nint M;\ndouble epsilon;\nint N;\nvector<string> graphs;\nvector<vector<int>> graph_degrees;\nvector<int> graph_edge_counts;\nvector<vector<double>> graph_eigenvalues;\n\n// Parse graph string to adjacency matrix\nvector<vector<int>> parseGraph(const string& s, int n) {\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    int idx = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            adj[i][j] = adj[j][i] = s[idx++] - '0';\n        }\n    }\n    return adj;\n}\n\n// Convert adjacency matrix to graph string\nstring toGraphString(const vector<vector<int>>& adj, int n) {\n    string s;\n    s.reserve(n * (n - 1) / 2);\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Count edges\nint countEdges(const string& s) {\n    return count(s.begin(), s.end(), '1');\n}\n\n// Compute degree sequence (sorted)\nvector<int> degreeSequence(const vector<vector<int>>& adj, int n) {\n    vector<int> deg(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            deg[i] += adj[i][j];\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute eigenvalues of adjacency matrix\nvector<double> computeEigenvalues(const vector<vector<int>>& adj, int n) {\n    Eigen::MatrixXd A(n, n);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            A(i, j) = adj[i][j];\n        }\n    }\n    Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> solver(A);\n    vector<double> evals;\n    evals.reserve(n);\n    for (int i = 0; i < n; i++) {\n        evals.push_back(solver.eigenvalues()[i]);\n    }\n    sort(evals.begin(), evals.end(), greater<double>());\n    return evals;\n}\n\n// Compute distance between two degree sequences\ndouble degreeDistance(const vector<int>& d1, const vector<int>& d2) {\n    double dist = 0;\n    for (size_t i = 0; i < d1.size(); i++) {\n        dist += abs(d1[i] - d2[i]);\n    }\n    return dist;\n}\n\n// Compute distance between eigenvalue vectors\ndouble eigenDistance(const vector<double>& e1, const vector<double>& e2) {\n    double dist = 0;\n    for (size_t i = 0; i < e1.size(); i++) {\n        dist += abs(e1[i] - e2[i]);\n    }\n    return dist;\n}\n\n// Generate a graph with target edge density and some structure\nstring generateGraph(int n, double density, int seed) {\n    mt19937 rng(seed);\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    int target_edges = (int)(n * (n - 1) / 2 * density);\n    \n    // Create a base structure (random graph with target density)\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    }\n    shuffle(edges.begin(), edges.end(), rng);\n    \n    int added = 0;\n    for (auto& [u, v] : edges) {\n        if (added >= target_edges) break;\n        adj[u][v] = adj[v][u] = 1;\n        added++;\n    }\n    \n    return toGraphString(adj, n);\n}\n\n// Generate graphs with varying structures for better distinguishability\nvector<string> generateGraphs(int m, int n, double eps) {\n    vector<string> result;\n    result.reserve(m);\n    \n    // Strategy: Create graphs with different edge densities and structures\n    double min_density = 0.1;\n    double max_density = 0.9;\n    double density_step = (max_density - min_density) / max(1, m - 1);\n    \n    for (int k = 0; k < m; k++) {\n        double density = min_density + density_step * k;\n        // Add some variation to make graphs more distinguishable\n        string g = generateGraph(n, density, k * 1000 + n);\n        result.push_back(g);\n    }\n    \n    return result;\n}\n\n// Compute signature for a graph (for matching)\nstruct GraphSignature {\n    int edge_count;\n    vector<int> degree_seq;\n    vector<double> eigenvalues_top;  // Top 10 eigenvalues\n    \n    GraphSignature() {}\n    \n    GraphSignature(const string& s, int n) {\n        edge_count = countEdges(s);\n        auto adj = parseGraph(s, n);\n        degree_seq = degreeSequence(adj, n);\n        auto evals = computeEigenvalues(adj, n);\n        // Use top min(10, n) eigenvalues\n        int top_k = min(10, n);\n        eigenvalues_top.assign(evals.begin(), evals.begin() + top_k);\n    }\n};\n\n// Compute distance between signatures\ndouble signatureDistance(const GraphSignature& s1, const GraphSignature& s2, double eps) {\n    double dist = 0;\n    \n    // Edge count distance (normalized)\n    double edge_dist = abs(s1.edge_count - s2.edge_count);\n    dist += edge_dist * 0.3;\n    \n    // Degree sequence distance\n    double deg_dist = degreeDistance(s1.degree_seq, s2.degree_seq);\n    dist += deg_dist * 0.4;\n    \n    // Eigenvalue distance\n    double eigen_dist = eigenDistance(s1.eigenvalues_top, s2.eigenvalues_top);\n    dist += eigen_dist * 0.3;\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> M >> epsilon;\n    \n    // Choose N based on M and epsilon\n    // Larger M or higher epsilon needs larger N\n    // Score = 10^9 * 0.9^E / N, so we want small N but also small E\n    int base_n = 30;\n    if (M > 50) base_n = 40;\n    if (M > 80) base_n = 50;\n    if (epsilon > 0.2) base_n += 10;\n    if (epsilon > 0.3) base_n += 10;\n    N = min(100, max(4, base_n));\n    \n    // Generate graphs\n    graphs = generateGraphs(M, N, epsilon);\n    \n    // Precompute signatures for all graphs\n    vector<GraphSignature> signatures(M);\n    for (int i = 0; i < M; i++) {\n        signatures[i] = GraphSignature(graphs[i], N);\n    }\n    \n    // Output N and graphs\n    cout << N << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << graphs[i] << \"\\n\";\n    }\n    cout.flush();\n    \n    // Process 100 queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        GraphSignature h_sig(h, N);\n        \n        // Find best match\n        int best_idx = 0;\n        double best_dist = 1e18;\n        \n        for (int i = 0; i < M; i++) {\n            double dist = signatureDistance(h_sig, signatures[i], epsilon);\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_idx = i;\n            }\n        }\n        \n        cout << best_idx << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nconst long long INF = 1e18;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, int>>> adj(N + 1); // to, edge_index\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\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 (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Conflict matrix W\n    // Use 1D array for cache efficiency\n    // W[i * M + j] stores co-occurrence count of edge i and edge j\n    vector<long long> W(M * M, 0);\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Sample paths to build W\n    int num_sources = 1000;\n    int num_targets = 5;\n    \n    // To avoid bias, we can shuffle vertices\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 1);\n    shuffle(vertices.begin(), vertices.end(), rng);\n\n    auto start_time = chrono::steady_clock::now();\n\n    for (int s_idx = 0; s_idx < num_sources; ++s_idx) {\n        int s = vertices[s_idx % N];\n        \n        // Dijkstra\n        vector<long long> dist(N + 1, INF);\n        vector<int> par_edge(N + 1, -1);\n        vector<int> par_node(N + 1, -1);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n            for (auto [v, eid] : adj[u]) {\n                if (dist[u] + edges[eid].w < dist[v]) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    par_node[v] = u;\n                    par_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        // Pick random targets\n        for (int t_idx = 0; t_idx < num_targets; ++t_idx) {\n            int t = vertices[(s_idx * num_targets + t_idx) % N];\n            if (t == s) continue;\n            if (dist[t] == INF) continue;\n\n            // Reconstruct path\n            vector<int> path_edges;\n            int curr = t;\n            while (curr != s) {\n                int eid = par_edge[curr];\n                path_edges.push_back(eid);\n                curr = par_node[curr];\n            }\n\n            // Update W\n            int L = path_edges.size();\n            for (int i = 0; i < L; ++i) {\n                for (int j = i + 1; j < L; ++j) { // j starts from i+1 to avoid self and duplicate\n                    int u = path_edges[i];\n                    int v = path_edges[j];\n                    W[u * M + v]++;\n                    W[v * M + u]++;\n                }\n            }\n        }\n        \n        // Time check for W construction (limit to ~3 seconds)\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 3000) {\n            break; \n        }\n    }\n\n    // Initial Assignment\n    // Calculate degree in conflict graph\n    vector<long long> edge_conflict(M, 0);\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            edge_conflict[i] += W[i * M + j];\n        }\n    }\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 edge_conflict[a] > edge_conflict[b];\n    });\n\n    vector<int> assignment(M, -1);\n    vector<int> day_size(D, 0);\n    vector<vector<int>> day_edges(D);\n    \n    // Greedy assignment\n    for (int e : order) {\n        int best_day = -1;\n        long long min_cost = -1;\n        \n        for (int k = 0; k < D; ++k) {\n            if (day_size[k] < K) {\n                long long cost = 0;\n                for (int other : day_edges[k]) {\n                    cost += W[e * M + other];\n                }\n                if (best_day == -1 || cost < min_cost) {\n                    min_cost = cost;\n                    best_day = k;\n                }\n            }\n        }\n        \n        if (best_day != -1) {\n            assignment[e] = best_day;\n            day_edges[best_day].push_back(e);\n            day_size[best_day]++;\n        }\n    }\n\n    // Prepare for Local Search\n    // Maintain C[k][e] = sum_{j in S_k} W[e][j]\n    // Flattened: C[k * M + e]\n    vector<long long> C(D * M, 0);\n    \n    for (int k = 0; k < D; ++k) {\n        for (int e : day_edges[k]) {\n            for (int other = 0; other < M; ++other) {\n                C[k * M + other] += W[e * M + other];\n            }\n        }\n    }\n    \n    // Current total cost\n    long long current_total_cost = 0;\n    for (int k = 0; k < D; ++k) {\n        for (int i : day_edges[k]) {\n            for (int j : day_edges[k]) {\n                if (i < j) current_total_cost += W[i * M + j];\n            }\n        }\n    }\n    \n    long long best_total_cost = current_total_cost;\n    vector<int> best_assignment = assignment;\n\n    // Local Search\n    auto ls_start = chrono::steady_clock::now();\n    int moves = 0;\n    int max_moves = 500000;\n    \n    vector<int> day_size_ls = day_size;\n    \n    while (moves < max_moves) {\n        auto now = chrono::steady_clock::now();\n        // Limit LS to ~2.5 seconds\n        if (chrono::duration_cast<chrono::milliseconds>(now - ls_start).count() > 2500) break;\n        \n        // Pick random edge\n        int e = uniform_int_distribution<>(0, M - 1)(rng);\n        int k_old = assignment[e];\n        \n        // Find best new day\n        int k_new = -1;\n        long long best_delta = 0;\n        \n        for (int k = 0; k < D; ++k) {\n            if (k == k_old) continue;\n            if (day_size_ls[k] >= K) continue;\n            \n            // Delta = Cost(new) - Cost(old)\n            long long delta = C[k * M + e] - C[k_old * M + e];\n            if (k_new == -1 || delta < best_delta) {\n                best_delta = delta;\n                k_new = k;\n            }\n        }\n        \n        if (k_new != -1 && best_delta < 0) {\n            // Move e\n            assignment[e] = k_new;\n            day_size_ls[k_old]--;\n            day_size_ls[k_new]++;\n            \n            // Update C\n            for (int other = 0; other < M; ++other) {\n                long long w_val = W[e * M + other];\n                C[k_old * M + other] -= w_val;\n                C[k_new * M + other] += w_val;\n            }\n            \n            current_total_cost += best_delta;\n            if (current_total_cost < best_total_cost) {\n                best_total_cost = current_total_cost;\n                best_assignment = assignment;\n            }\n            moves++;\n        } else {\n            moves++;\n        }\n    }\n\n    // Output\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;\n\nstruct Block {\n    vector<tuple<int,int,int>> cells;\n    int id;\n};\n\nint D;\nvector<string> f1, r1, f2, r2;\nvector<vector<vector<bool>>> valid1, valid2;\nvector<vector<vector<int>>> b1, b2;\nvector<Block> blocks;\nvector<vector<vector<bool>>> used1, used2;\n\n// Check if position is valid for silhouette i\nbool isValid(int i, int x, int y, int z) {\n    if (i == 0) return valid1[x][y][z];\n    return valid2[x][y][z];\n}\n\n// Check if position is used in solution i\nbool isUsed(int i, int x, int y, int z) {\n    if (i == 0) return used1[x][y][z];\n    return used2[x][y][z];\n}\n\n// Mark position as used in solution i\nvoid markUsed(int i, int x, int y, int z, int blockId) {\n    if (i == 0) {\n        used1[x][y][z] = true;\n        b1[x][y][z] = blockId;\n    } else {\n        used2[x][y][z] = true;\n        b2[x][y][z] = blockId;\n    }\n}\n\n// Get neighbors (6 directions)\nvector<tuple<int,int,int>> getNeighbors(int x, int y, int z) {\n    vector<tuple<int,int,int>> neighbors;\n    int dx[] = {1, -1, 0, 0, 0, 0};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {0, 0, 0, 0, 1, -1};\n    \n    for (int d = 0; d < 6; d++) {\n        int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n        if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D) {\n            neighbors.emplace_back(nx, ny, nz);\n        }\n    }\n    return neighbors;\n}\n\n// Grow a connected block from a seed position\nBlock growBlock(int seedX, int seedY, int seedZ, int solution, int maxCells = 8) {\n    Block block;\n    block.id = blocks.size() + 1;\n    \n    queue<tuple<int,int,int>> q;\n    set<tuple<int,int,int>> inBlock;\n    \n    q.emplace(seedX, seedY, seedZ);\n    inBlock.emplace(seedX, seedY, seedZ);\n    \n    while (!q.empty() && (int)inBlock.size() < maxCells) {\n        auto [x, y, z] = q.front();\n        q.pop();\n        \n        for (auto [nx, ny, nz] : getNeighbors(x, y, z)) {\n            if (inBlock.count({nx, ny, nz})) continue;\n            if (!isValid(solution, nx, ny, nz)) continue;\n            if (isUsed(solution, nx, ny, nz)) continue;\n            \n            inBlock.emplace(nx, ny, nz);\n            q.emplace(nx, ny, nz);\n            \n            if ((int)inBlock.size() >= maxCells) break;\n        }\n    }\n    \n    for (auto& cell : inBlock) {\n        block.cells.push_back(cell);\n    }\n    \n    return block;\n}\n\n// Try to place a block in both solutions (checking if shape matches)\nbool canPlaceInBoth(const Block& block, int x1, int y1, int z1, int x2, int y2, int z2) {\n    // Check if block can be placed at position (x1,y1,z1) in solution 1\n    // and at position (x2,y2,z2) in solution 2 with same relative shape\n    \n    int dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;\n    \n    for (auto [x, y, z] : block.cells) {\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) return false;\n        if (!isValid(1, nx, ny, nz)) return false;\n        if (isUsed(1, nx, ny, nz)) return false;\n    }\n    \n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    f1.resize(D); r1.resize(D);\n    f2.resize(D); r2.resize(D);\n    \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    // Initialize validity arrays\n    valid1.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    valid2.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    b1.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    b2.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    used1.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    used2.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    // Compute valid positions\n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') {\n                    valid1[x][y][z] = true;\n                }\n                if (f2[z][x] == '1' && r2[z][y] == '1') {\n                    valid2[x][y][z] = true;\n                }\n            }\n        }\n    }\n    \n    // Count valid positions\n    int count1 = 0, count2 = 0, common = 0;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z]) count1++;\n                if (valid2[x][y][z]) count2++;\n                if (valid1[x][y][z] && valid2[x][y][z]) common++;\n            }\n        }\n    }\n    \n    // Strategy: Create larger blocks for common positions first\n    // Then fill remaining positions with medium-sized blocks\n    \n    int blockId = 0;\n    \n    // Phase 1: Create blocks for common positions (try to reuse in both solutions)\n    vector<tuple<int,int,int>> commonPositions;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && valid2[x][y][z]) {\n                    commonPositions.emplace_back(x, y, z);\n                }\n            }\n        }\n    }\n    \n    // Sort by number of valid neighbors (prioritize positions with more connections)\n    sort(commonPositions.begin(), commonPositions.end(), [&](auto& a, auto& b) {\n        auto [x1, y1, z1] = a;\n        auto [x2, y2, z2] = b;\n        int c1 = 0, c2 = 0;\n        for (auto [nx, ny, nz] : getNeighbors(x1, y1, z1)) {\n            if (valid1[nx][ny][nz] && valid2[nx][ny][nz]) c1++;\n        }\n        for (auto [nx, ny, nz] : getNeighbors(x2, y2, z2)) {\n            if (valid1[nx][ny][nz] && valid2[nx][ny][nz]) c2++;\n        }\n        return c1 > c2;\n    });\n    \n    // Create blocks for common positions\n    for (auto [x, y, z] : commonPositions) {\n        if (isUsed(0, x, y, z) || isUsed(1, x, y, z)) continue;\n        \n        // Try to create a larger block\n        int targetSize = min(6, max(3, common / 20 + 2));\n        Block block = growBlock(x, y, z, 0, targetSize);\n        \n        if (block.cells.empty()) continue;\n        \n        blockId++;\n        block.id = blockId;\n        \n        // Place in solution 1\n        for (auto [cx, cy, cz] : block.cells) {\n            markUsed(0, cx, cy, cz, blockId);\n        }\n        \n        // Try to place same block in solution 2 at same position\n        bool placed2 = false;\n        for (auto [cx, cy, cz] : block.cells) {\n            if (valid2[cx][cy][cz] && !isUsed(1, cx, cy, cz)) {\n                placed2 = true;\n            } else {\n                placed2 = false;\n                break;\n            }\n        }\n        \n        if (placed2) {\n            for (auto [cx, cy, cz] : block.cells) {\n                markUsed(1, cx, cy, cz, blockId);\n            }\n        }\n        \n        blocks.push_back(block);\n    }\n    \n    // Phase 2: Fill remaining positions in solution 1\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && !isUsed(0, x, y, z)) {\n                    int targetSize = min(4, max(2, count1 / 50 + 1));\n                    Block block = growBlock(x, y, z, 0, targetSize);\n                    \n                    if (block.cells.empty()) {\n                        block.cells.emplace_back(x, y, z);\n                    }\n                    \n                    blockId++;\n                    block.id = blockId;\n                    \n                    for (auto [cx, cy, cz] : block.cells) {\n                        markUsed(0, cx, cy, cz, blockId);\n                    }\n                    \n                    blocks.push_back(block);\n                }\n            }\n        }\n    }\n    \n    // Phase 3: Fill remaining positions in solution 2\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid2[x][y][z] && !isUsed(1, x, y, z)) {\n                    int targetSize = min(4, max(2, count2 / 50 + 1));\n                    Block block = growBlock(x, y, z, 1, targetSize);\n                    \n                    if (block.cells.empty()) {\n                        block.cells.emplace_back(x, y, z);\n                    }\n                    \n                    blockId++;\n                    block.id = blockId;\n                    \n                    for (auto [cx, cy, cz] : block.cells) {\n                        markUsed(1, cx, cy, cz, blockId);\n                    }\n                    \n                    blocks.push_back(block);\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << blockId << \"\\n\";\n    \n    // Output b1\n    bool first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b1[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    // Output b2\n    first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b2[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <tuple>\n#include <iomanip>\n\nusing namespace std;\n\n// Global data\nint N, M, K;\nvector<pair<int, int>> vertices;\nvector<tuple<int, int, int>> edges;\nvector<pair<int, int>> residents;\nvector<vector<int>> adj;\n\n// Solution\nvector<int> P;\nvector<int> B;\n\n// Precomputed: residents near each vertex (within 5000 distance)\nvector<vector<pair<int, long long>>> vertexResidents;\n\ninline long long dist2(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\ninline bool isCovered(int k, int i, int p) {\n    long long d2 = dist2(vertices[i].first, vertices[i].second, \n                         residents[k].first, residents[k].second);\n    return d2 <= 1LL * p * p;\n}\n\nvector<bool> getReachable() {\n    vector<bool> reachable(N, false);\n    vector<int> q;\n    q.reserve(N);\n    q.push_back(0);\n    reachable[0] = true;\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (int ej : adj[u]) {\n            if (B[ej]) {\n                int v = (get<0>(edges[ej]) == u) ? get<1>(edges[ej]) : get<0>(edges[ej]);\n                if (!reachable[v]) {\n                    reachable[v] = true;\n                    q.push_back(v);\n                }\n            }\n        }\n    }\n    return reachable;\n}\n\npair<int, vector<bool>> getCoverage() {\n    vector<bool> reachable = getReachable();\n    vector<bool> residentCovered(K, false);\n    int count = 0;\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i] || P[i] == 0) continue;\n        for (auto& [k, d2] : vertexResidents[i]) {\n            if (!residentCovered[k] && 1LL * P[i] * P[i] >= d2) {\n                residentCovered[k] = true;\n                count++;\n            }\n        }\n    }\n    \n    return {count, residentCovered};\n}\n\ninline long long calculateCost() {\n    long long cost = 0;\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    for (int j = 0; j < M; j++) {\n        if (B[j]) {\n            cost += get<2>(edges[j]);\n        }\n    }\n    return cost;\n}\n\nvoid precompute() {\n    vertexResidents.assign(N, vector<pair<int, long long>>());\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            long long d2 = dist2(vertices[i].first, vertices[i].second,\n                                residents[k].first, residents[k].second);\n            if (d2 <= 25000000LL) {\n                vertexResidents[i].push_back({k, d2});\n            }\n        }\n    }\n}\n\nvoid buildInitialTree() {\n    fill(B.begin(), B.end(), 0);\n    fill(P.begin(), P.end(), 0);\n    \n    vector<bool> visited(N, false);\n    vector<int> q;\n    q.reserve(N);\n    q.push_back(0);\n    visited[0] = true;\n    \n    vector<int> parentEdge(N, -1);\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (int ej : adj[u]) {\n            int v = (get<0>(edges[ej]) == u) ? get<1>(edges[ej]) : get<0>(edges[ej]);\n            if (!visited[v]) {\n                visited[v] = true;\n                parentEdge[v] = ej;\n                q.push_back(v);\n            }\n        }\n    }\n    \n    for (int i = 1; i < N; i++) {\n        if (parentEdge[i] >= 0) {\n            B[parentEdge[i]] = 1;\n        }\n    }\n}\n\nvoid optimizeP() {\n    vector<bool> reachable = getReachable();\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i]) {\n            P[i] = 0;\n        }\n    }\n    \n    for (int iter = 0; iter < 3; iter++) {\n        auto [covered, residentCovered] = getCoverage();\n        \n        if (covered == K) {\n            for (int i = 0; i < N; i++) {\n                if (!reachable[i] || P[i] == 0) continue;\n                \n                int oldP = P[i];\n                int lo = 0, hi = P[i];\n                while (lo < hi) {\n                    int mid = (lo + hi) / 2;\n                    P[i] = mid;\n                    auto [c, rc] = getCoverage();\n                    if (c == K) {\n                        hi = mid;\n                    } else {\n                        lo = mid + 1;\n                    }\n                }\n                P[i] = lo;\n                \n                auto [c, rc] = getCoverage();\n                if (c < K) {\n                    P[i] = oldP;\n                }\n            }\n        } else {\n            for (int k = 0; k < K; k++) {\n                if (residentCovered[k]) continue;\n                \n                int bestI = -1;\n                int bestNeeded = 5001;\n                long long bestCostIncrease = 1LL << 60;\n                \n                for (int i = 0; i < N; i++) {\n                    if (!reachable[i]) continue;\n                    \n                    long long d2 = dist2(vertices[i].first, vertices[i].second,\n                                        residents[k].first, residents[k].second);\n                    if (d2 > 25000000LL) continue;\n                    \n                    int needed = (int)ceil(sqrt(d2));\n                    if (needed > 5000) continue;\n                    \n                    int newP = max(P[i], needed);\n                    long long costIncrease = 1LL * newP * newP - 1LL * P[i] * P[i];\n                    \n                    if (costIncrease < bestCostIncrease) {\n                        bestCostIncrease = costIncrease;\n                        bestI = i;\n                        bestNeeded = needed;\n                    }\n                }\n                \n                if (bestI >= 0) {\n                    P[bestI] = max(P[bestI], bestNeeded);\n                }\n            }\n        }\n    }\n}\n\nvoid localSearch(double timeLimit) {\n    auto startTime = chrono::high_resolution_clock::now();\n    \n    auto [bestCovered, bestResidentCovered] = getCoverage();\n    long long bestCost = calculateCost();\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int noImprove = 0;\n    while (true) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        \n        if (elapsed > timeLimit) break;\n        if (noImprove > 5000 && bestCovered == K) break;\n        \n        double temp = max(0.01, 1.0 - elapsed / timeLimit);\n        \n        int edgeIdx = uniform_int_distribution<int>(0, M - 1)(rng);\n        int oldB = B[edgeIdx];\n        B[edgeIdx] = 1 - oldB;\n        \n        auto [newCovered, newResidentCovered] = getCoverage();\n        long long newCost = calculateCost();\n        \n        bool accept = false;\n        if (newCovered > bestCovered) {\n            accept = true;\n        } else if (newCovered == bestCovered) {\n            if (newCost < bestCost) {\n                accept = true;\n            } else if (bestCovered == K) {\n                double delta = (double)(newCost - bestCost);\n                double prob = exp(-delta / (50000.0 * temp));\n                if (uniform_real_distribution<double>(0, 1)(rng) < prob) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept) {\n            if (newCovered > bestCovered || (newCovered == bestCovered && newCost < bestCost)) {\n                bestCovered = newCovered;\n                bestResidentCovered = newResidentCovered;\n                bestCost = newCost;\n                noImprove = 0;\n            }\n            if (noImprove % 20 == 0) {\n                optimizeP();\n                auto [c, rc] = getCoverage();\n                long long cost = calculateCost();\n                if (c > bestCovered || (c == bestCovered && cost < bestCost)) {\n                    bestCovered = c;\n                    bestResidentCovered = rc;\n                    bestCost = cost;\n                    noImprove = 0;\n                }\n            }\n        } else {\n            B[edgeIdx] = oldB;\n            noImprove++;\n        }\n        \n        if (elapsed > timeLimit * 0.7 && bestCovered < K) {\n            for (int tryCount = 0; tryCount < 3; tryCount++) {\n                int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n                if (B[e1] == 0) {\n                    B[e1] = 1;\n                    auto [c, rc] = getCoverage();\n                    if (c >= bestCovered) {\n                        bestCovered = c;\n                        bestResidentCovered = rc;\n                        bestCost = calculateCost();\n                        noImprove = 0;\n                    } else {\n                        B[e1] = 0;\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    vertices.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> vertices[i].first >> vertices[i].second;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    for (int j = 0; j < M; j++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back(j);\n        adj[v].push_back(j);\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].first >> residents[k].second;\n    }\n    \n    P.resize(N, 0);\n    B.resize(M, 0);\n    \n    precompute();\n    buildInitialTree();\n    optimizeP();\n    localSearch(1.95);\n    optimizeP();\n    \n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\n\nstruct Coord {\n    int x, y;\n    bool operator==(const Coord& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Coord& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n};\n\nint grid[N][N];\nCoord pos[TOTAL_BALLS];\n\n// 6 adjacent directions\nconst int DX[6] = {-1, -1, 0, 0, 1, 1};\nconst int DY[6] = {-1, 0, -1, 1, 0, 1};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvector<Coord> getAdjacent(int x, int y) {\n    vector<Coord> adj;\n    for (int i = 0; i < 6; i++) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (isValid(nx, ny)) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\nbool areAdjacent(Coord c1, Coord c2) {\n    for (int i = 0; i < 6; i++) {\n        int nx = c1.x + DX[i];\n        int ny = c1.y + DY[i];\n        if (nx == c2.x && ny == c2.y) return true;\n    }\n    return false;\n}\n\n// BFS with heuristic (A* like)\nvector<Coord> findPath(Coord start, Coord end, const vector<vector<bool>>& blocked) {\n    if (start == end) return {start};\n    \n    priority_queue<tuple<int, int, Coord>, vector<tuple<int, int, Coord>>, greater<>> pq;\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<Coord>> parent(N, vector<Coord>(N, {-1, -1}));\n    \n    auto heuristic = [](Coord a, Coord b) {\n        return abs(a.x - b.x) + abs(a.y - b.y);\n    };\n    \n    dist[start.x][start.y] = 0;\n    pq.push({heuristic(start, end), 0, start});\n    \n    while (!pq.empty()) {\n        auto [f, d, curr] = pq.top();\n        pq.pop();\n        \n        if (d > dist[curr.x][curr.y]) continue;\n        if (curr == end) {\n            vector<Coord> path;\n            Coord c = end;\n            while (c != start) {\n                path.push_back(c);\n                c = parent[c.x][c.y];\n            }\n            path.push_back(start);\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto& next : getAdjacent(curr.x, curr.y)) {\n            if (blocked[next.x][next.y]) continue;\n            int nd = d + 1;\n            if (nd < dist[next.x][next.y]) {\n                dist[next.x][next.y] = nd;\n                parent[next.x][next.y] = curr;\n                pq.push({nd + heuristic(next, end), nd, next});\n            }\n        }\n    }\n    \n    return {};\n}\n\nvector<tuple<int,int,int,int>> operations;\n\nvoid swapBalls(Coord c1, Coord c2) {\n    if (c1 == c2 || !areAdjacent(c1, c2)) return;\n    if (operations.size() >= 10000) return;\n    \n    operations.push_back({c1.x, c1.y, c2.x, c2.y});\n    \n    int val1 = grid[c1.x][c1.y];\n    int val2 = grid[c2.x][c2.y];\n    \n    grid[c1.x][c1.y] = val2;\n    grid[c2.x][c2.y] = val1;\n    \n    pos[val1] = c2;\n    pos[val2] = c1;\n}\n\nvoid moveBall(int value, Coord target) {\n    Coord current = pos[value];\n    \n    while (current != target && operations.size() < 9500) {\n        vector<vector<bool>> blocked(N, vector<bool>(N, false));\n        // Block positions of balls that are already in place (smaller values)\n        for (int v = 0; v < value; v++) {\n            blocked[pos[v].x][pos[v].y] = true;\n        }\n        blocked[target.x][target.y] = false; // Allow target\n        \n        auto path = findPath(current, target, blocked);\n        if (path.size() < 2) {\n            // Try without blocking\n            vector<vector<bool>> empty(N, vector<bool>(N, false));\n            path = findPath(current, target, empty);\n        }\n        \n        if (path.size() < 2) break;\n        \n        Coord next = path[1];\n        swapBalls(current, next);\n        current = pos[value];\n    }\n}\n\nint countViolations() {\n    int E = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (grid[x][y] > grid[x + 1][y]) E++;\n            if (grid[x][y] > grid[x + 1][y + 1]) E++;\n        }\n    }\n    return E;\n}\n\nvoid fixViolations() {\n    bool improved = true;\n    while (improved && operations.size() < 10000) {\n        improved = false;\n        for (int x = 0; x < N - 1 && operations.size() < 10000; x++) {\n            for (int y = 0; y <= x && operations.size() < 10000; y++) {\n                // Check violation with left child\n                if (grid[x][y] > grid[x + 1][y]) {\n                    if (areAdjacent({x, y}, {x + 1, y})) {\n                        swapBalls({x, y}, {x + 1, y});\n                        improved = true;\n                    }\n                }\n                // Check violation with right child\n                if (grid[x][y] > grid[x + 1][y + 1]) {\n                    if (areAdjacent({x, y}, {x + 1, y + 1})) {\n                        swapBalls({x, y}, {x + 1, y + 1});\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n            pos[grid[x][y]] = {x, y};\n        }\n    }\n    \n    // Create sorted list of balls with their target positions\n    vector<pair<int, Coord>> balls(TOTAL_BALLS);\n    int idx = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            balls[idx++] = {grid[x][y], {x, y}};\n        }\n    }\n    \n    // Sort by value - smaller values should go to top\n    sort(balls.begin(), balls.end());\n    \n    // Target positions in tier order\n    vector<Coord> targets(TOTAL_BALLS);\n    idx = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            targets[idx++] = {x, y};\n        }\n    }\n    \n    // Move balls to target positions (smallest first)\n    for (int i = 0; i < TOTAL_BALLS && operations.size() < 9000; i++) {\n        int value = balls[i].first;\n        Coord target = targets[i];\n        moveBall(value, target);\n    }\n    \n    // Fix remaining violations\n    fixViolations();\n    \n    // Output\n    cout << operations.size() << \"\\n\";\n    for (auto& op : operations) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = 4;\n\nstruct Container {\n    int id;\n    int r, c;\n};\n\nint grid[D][D];  // -1: empty, -2: obstacle, >=0: container id\nint dist_from_entrance[D][D];\nvector<pair<int, int>> empty_squares;\nvector<Container> containers;\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\nbool isValid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D && grid[r][c] != -2;\n}\n\n// BFS to find all reachable empty squares from entrance\nvector<vector<bool>> computeReachable() {\n    vector<vector<bool>> reachable(D, vector<bool>(D, false));\n    queue<pair<int, int>> q;\n    \n    q.push({ENTRANCE_R, ENTRANCE_C});\n    reachable[ENTRANCE_R][ENTRANCE_C] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && grid[nr][nc] == -1 && !reachable[nr][nc]) {\n                reachable[nr][nc] = true;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return reachable;\n}\n\n// Check if container at (r, c) is reachable (adjacent to reachable empty square)\nbool isContainerReachable(int r, int c) {\n    for (int i = 0; i < 4; i++) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        \n        if (isValid(nr, nc) && grid[nr][nc] == -1) {\n            auto reachable = computeReachable();\n            if (reachable[nr][nc]) return true;\n        }\n    }\n    return false;\n}\n\n// Check if placing container maintains connectivity for all existing containers\nbool canPlace(int r, int c) {\n    if (!isValid(r, c) || grid[r][c] != -1) return false;\n    \n    grid[r][c] = -3;  // Temporarily occupied\n    \n    bool ok = true;\n    for (const auto& cont : containers) {\n        if (!isContainerReachable(cont.r, cont.c)) {\n            ok = false;\n            break;\n        }\n    }\n    \n    grid[r][c] = -1;\n    return ok;\n}\n\nvoid computeDistances() {\n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            dist_from_entrance[i][j] = 1e9;\n        }\n    }\n    \n    queue<pair<int, int>> q;\n    q.push({ENTRANCE_R, ENTRANCE_C});\n    dist_from_entrance[ENTRANCE_R][ENTRANCE_C] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && dist_from_entrance[nr][nc] > dist_from_entrance[r][c] + 1) {\n                dist_from_entrance[nr][nc] = dist_from_entrance[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            grid[i][j] = -1;\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -2;\n    }\n    \n    computeDistances();\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            if (grid[i][j] == -1 && !(i == ENTRANCE_R && j == ENTRANCE_C)) {\n                empty_squares.push_back({i, j});\n            }\n        }\n    }\n    \n    sort(empty_squares.begin(), empty_squares.end(), [](const pair<int, int>& a, const pair<int, int>& b) {\n        return dist_from_entrance[a.first][a.second] < dist_from_entrance[b.first][b.second];\n    });\n    \n    int total_containers = D * D - 1 - N;\n    \n    for (int d = 0; d < total_containers; d++) {\n        int container_id;\n        cin >> container_id;\n        \n        int best_r = -1, best_c = -1;\n        int best_score = 1e9;\n        \n        for (const auto& [r, c] : empty_squares) {\n            if (grid[r][c] == -1 && canPlace(r, c)) {\n                int score = dist_from_entrance[r][c] * 100;\n                if (container_id < total_containers / 2) {\n                    score -= 50;  // Prefer closer for smaller IDs\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        grid[best_r][best_c] = container_id;\n        containers.push_back({container_id, best_r, best_c});\n        \n        cout << best_r << \" \" << best_c << endl;\n    }\n    \n    // Retrieval: output in order 0, 1, 2, ...\n    vector<bool> retrieved(total_containers, false);\n    vector<pair<int, int>> output_order;\n    \n    for (int target_id = 0; target_id < total_containers; target_id++) {\n        for (auto& cont : containers) {\n            if (cont.id == target_id && !retrieved[target_id]) {\n                if (isContainerReachable(cont.r, cont.c)) {\n                    output_order.push_back({cont.r, cont.c});\n                    retrieved[target_id] = true;\n                    grid[cont.r][cont.c] = -1;  // Remove container\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Output any remaining\n    for (auto& cont : containers) {\n        if (!retrieved[cont.id]) {\n            output_order.push_back({cont.r, cont.c});\n        }\n    }\n    \n    for (const auto& [r, c] : output_order) {\n        cout << r << \" \" << c << endl;\n    }\n    \n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <atcoder/all>\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nint grid[N][N];\nint adj[M + 1][M + 1];  // adjacency matrix\nint color_count[M + 1]; // count of each color\n\n// Check if a color region is connected using BFS\nbool check_connectivity(int c) {\n    vector<pair<int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == c) {\n                cells.push_back({i, j});\n            }\n        }\n    }\n    if (cells.empty()) return c == 0; // color 0 can be empty (connects through outside)\n    \n    // BFS from first cell\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    queue<pair<int, int>> q;\n    q.push(cells[0]);\n    visited[cells[0].first][cells[0].second] = true;\n    int count = 1;\n    \n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\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                !visited[ni][nj] && grid[ni][nj] == c) {\n                visited[ni][nj] = true;\n                count++;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return count == (int)cells.size();\n}\n\n// Check if all color regions are connected\nbool check_all_connectivity() {\n    for (int c = 1; c <= m; c++) {\n        if (!check_connectivity(c)) return false;\n    }\n    // Color 0 connectivity through outside is automatic if other colors are connected\n    return true;\n}\n\n// Build adjacency matrix from current grid\nvoid build_adjacency() {\n    memset(adj, 0, sizeof(adj));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    // Boundary touches color 0\n                    adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Get current adjacency from grid\nvoid get_current_adjacency(int cur_adj[M + 1][M + 1]) {\n    memset(cur_adj, 0, sizeof(int) * (M + 1) * (M + 1));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        cur_adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    cur_adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Check if adjacency is preserved\nbool check_adjacency_preserved() {\n    int cur_adj[M + 1][M + 1];\n    get_current_adjacency(cur_adj);\n    \n    for (int c1 = 0; c1 <= m; c1++) {\n        for (int c2 = c1 + 1; c2 <= m; c2++) {\n            if (adj[c1][c2] != cur_adj[c1][c2]) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Count color 0 squares\nint count_zeros() {\n    int cnt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == 0) cnt++;\n        }\n    }\n    return cnt;\n}\n\n// Try to fill a 0 cell with a color\nbool try_fill_zero(int i, int j, int c) {\n    if (grid[i][j] != 0) return false;\n    \n    int old = grid[i][j];\n    grid[i][j] = c;\n    \n    // Check connectivity\n    if (!check_connectivity(c)) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    // Check adjacency preservation\n    if (!check_adjacency_preserved()) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    return true;\n}\n\n// Get colors adjacent to position (i, j)\nvector<int> get_adjacent_colors(int i, int j) {\n    vector<int> colors;\n    vector<bool> seen(M + 1, false);\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\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            int c = grid[ni][nj];\n            if (c != 0 && !seen[c]) {\n                seen[c] = true;\n                colors.push_back(c);\n            }\n        } else {\n            if (!seen[0]) {\n                seen[0] = true;\n                colors.push_back(0);\n            }\n        }\n    }\n    return colors;\n}\n\n// Check if filling (i,j) with color c would create unwanted adjacency\nbool would_create_bad_adjacency(int i, int j, int c) {\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int d = 0; d < 4; d++) {\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        int neighbor_c;\n        if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n            neighbor_c = grid[ni][nj];\n        } else {\n            neighbor_c = 0;\n        }\n        \n        if (neighbor_c != c && neighbor_c != 0) {\n            // Check if c and neighbor_c should be adjacent\n            if (!adj[min(c, neighbor_c)][max(c, neighbor_c)]) {\n                return true; // Would create unwanted adjacency\n            }\n        }\n    }\n    return false;\n}\n\n// Check if filling (i,j) with color c would miss required adjacency\nbool would_miss_adjacency(int i, int j, int c) {\n    // This is harder to check locally, skip for now\n    return false;\n}\n\n// Greedy fill zeros\nvoid greedy_fill() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        vector<tuple<int, int, int>> candidates;\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    vector<int> adj_colors = get_adjacent_colors(i, j);\n                    for (int c : adj_colors) {\n                        if (c == 0) continue;\n                        if (!would_create_bad_adjacency(i, j, c)) {\n                            candidates.push_back({i, j, c});\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try candidates in random order\n        shuffle(candidates.begin(), candidates.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count()));\n        \n        for (auto [i, j, c] : candidates) {\n            if (grid[i][j] == 0 && try_fill_zero(i, j, c)) {\n                changed = true;\n                break; // Restart to be safe\n            }\n        }\n    }\n}\n\n// Simulated annealing style local search\nvoid local_search() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 5000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find a 0 cell\n        vector<pair<int, int>> zeros;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    zeros.push_back({i, j});\n                }\n            }\n        }\n        \n        if (zeros.empty()) break;\n        \n        auto [i, j] = zeros[rng() % zeros.size()];\n        vector<int> adj_colors = get_adjacent_colors(i, j);\n        \n        if (adj_colors.empty()) continue;\n        \n        int c = adj_colors[rng() % adj_colors.size()];\n        if (c == 0) continue;\n        \n        if (try_fill_zero(i, j, c)) {\n            // Success, continue\n        }\n    }\n}\n\n// Compact regions by moving boundary cells\nvoid compact_regions() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 3000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find boundary cells (colored cells adjacent to 0)\n        vector<tuple<int, int, int>> boundaries; // i, j, color\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0) {\n                    int di[] = {0, 0, 1, -1};\n                    int dj[] = {1, -1, 0, 0};\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 && grid[ni][nj] == 0) {\n                            boundaries.push_back({i, j, grid[i][j]});\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (boundaries.empty()) break;\n        \n        auto [i, j, c] = boundaries[rng() % boundaries.size()];\n        \n        // Try to expand into adjacent 0\n        int di[] = {0, 0, 1, -1};\n        int dj[] = {1, -1, 0, 0};\n        \n        vector<pair<int, int>> adjacent_zeros;\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 && grid[ni][nj] == 0) {\n                adjacent_zeros.push_back({ni, nj});\n            }\n        }\n        \n        if (adjacent_zeros.empty()) continue;\n        \n        auto [ni, nj] = adjacent_zeros[rng() % adjacent_zeros.size()];\n        \n        if (!would_create_bad_adjacency(ni, nj, c)) {\n            int old = grid[ni][nj];\n            grid[ni][nj] = c;\n            \n            if (check_connectivity(c) && check_adjacency_preserved()) {\n                // Keep the change\n            } else {\n                grid[ni][nj] = old;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    \n    int zeros = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> grid[i][j];\n            if (grid[i][j] == 0) zeros++;\n            color_count[grid[i][j]]++;\n        }\n    }\n    \n    // Build target adjacency from input\n    build_adjacency();\n    \n    // Phase 1: Greedy fill\n    greedy_fill();\n    \n    // Phase 2: Local search\n    local_search();\n    \n    // Phase 3: Compact regions\n    compact_regions();\n    \n    // Phase 4: Final greedy pass\n    greedy_fill();\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cout << grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Estimate weights through comparisons\n    // Use a reference-based approach: compare each item against a reference set\n    vector<double> estimated_weight(N, 1.0);\n    vector<int> win_count(N, 0);\n    vector<int> lose_count(N, 0);\n    \n    // Phase 1: Pairwise comparisons to build relative ranking\n    // Use tournament-style comparisons\n    int queries_used = 0;\n    \n    // First, do pairwise comparisons between items\n    // Compare item i vs item j by putting them on opposite sides\n    for (int i = 0; i < N && queries_used < Q; i++) {\n        for (int j = i + 1; j < N && queries_used < Q; j++) {\n            // Compare single items\n            cout << \"1 1 \" << i << \" \" << j << endl;\n            queries_used++;\n            \n            string result;\n            cin >> result;\n            \n            if (result == \">\") {\n                win_count[i]++;\n                lose_count[j]++;\n            } else if (result == \"<\") {\n                lose_count[i]++;\n                win_count[j]++;\n            }\n            // \"=\" means equal, no change\n        }\n    }\n    \n    // Calculate estimated weights based on win/loss ratio\n    for (int i = 0; i < N; i++) {\n        int total = win_count[i] + lose_count[i];\n        if (total > 0) {\n            estimated_weight[i] = 1.0 + (double)win_count[i] / total;\n        }\n    }\n    \n    // If we have remaining queries, do more refined comparisons\n    // Compare items against groups to get better estimates\n    while (queries_used < Q) {\n        // Pick two random items to compare\n        static mt19937 rng(42);\n        int i = rng() % N;\n        int j = rng() % N;\n        if (i == j) continue;\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        if (result == \">\") {\n            estimated_weight[i] += 0.1;\n            estimated_weight[j] -= 0.05;\n        } else if (result == \"<\") {\n            estimated_weight[i] -= 0.05;\n            estimated_weight[j] += 0.1;\n        }\n    }\n    \n    // Phase 2: Partition items into D sets\n    // Use greedy approach: sort by estimated weight, assign to lightest bin\n    \n    // Create indices sorted by estimated weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return estimated_weight[a] > estimated_weight[b];\n    });\n    \n    // Initialize D bins\n    vector<vector<int>> bins(D);\n    vector<double> bin_weight(D, 0.0);\n    \n    // Greedy assignment: assign heaviest items first to lightest bin\n    for (int idx : indices) {\n        // Find bin with minimum current weight\n        int min_bin = 0;\n        for (int d = 1; d < D; d++) {\n            if (bin_weight[d] < bin_weight[min_bin]) {\n                min_bin = d;\n            }\n        }\n        bins[min_bin].push_back(idx);\n        bin_weight[min_bin] += estimated_weight[idx];\n    }\n    \n    // Phase 3: Local optimization to reduce variance\n    // Try swapping items between bins to reduce variance\n    auto calc_variance = [&]() -> double {\n        double mean = 0.0;\n        for (double w : bin_weight) mean += w;\n        mean /= D;\n        double var = 0.0;\n        for (double w : bin_weight) {\n            double diff = w - mean;\n            var += diff * diff;\n        }\n        return var / D;\n    };\n    \n    // Local search optimization\n    bool improved = true;\n    int max_iterations = 1000;\n    int iteration = 0;\n    \n    while (improved && iteration < max_iterations) {\n        improved = false;\n        iteration++;\n        \n        double current_var = calc_variance();\n        \n        // Try swapping pairs of items between different bins\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = d1 + 1; d2 < D && !improved; d2++) {\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    for (int j = 0; j < (int)bins[d2].size() && !improved; j++) {\n                        int item1 = bins[d1][i];\n                        int item2 = bins[d2][j];\n                        \n                        // Calculate new weights if we swap\n                        double new_w1 = bin_weight[d1] - estimated_weight[item1] + estimated_weight[item2];\n                        double new_w2 = bin_weight[d2] - estimated_weight[item2] + estimated_weight[item1];\n                        \n                        // Check if this reduces variance\n                        double mean = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            if (d == d1) mean += new_w1;\n                            else if (d == d2) mean += new_w2;\n                            else mean += bin_weight[d];\n                        }\n                        mean /= D;\n                        \n                        double new_var = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                            double diff = w - mean;\n                            new_var += diff * diff;\n                        }\n                        new_var /= D;\n                        \n                        if (new_var < current_var - 1e-9) {\n                            // Perform swap\n                            swap(bins[d1][i], bins[d2][j]);\n                            bin_weight[d1] = new_w1;\n                            bin_weight[d2] = new_w2;\n                            improved = true;\n                            current_var = new_var;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Also try moving single items\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = 0; d2 < D && !improved; d2++) {\n                if (d1 == d2) continue;\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    int item = bins[d1][i];\n                    \n                    double new_w1 = bin_weight[d1] - estimated_weight[item];\n                    double new_w2 = bin_weight[d2] + estimated_weight[item];\n                    \n                    double mean = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        if (d == d1) mean += new_w1;\n                        else if (d == d2) mean += new_w2;\n                        else mean += bin_weight[d];\n                    }\n                    mean /= D;\n                    \n                    double new_var = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                        double diff = w - mean;\n                        new_var += diff * diff;\n                    }\n                    new_var /= D;\n                    \n                    if (new_var < current_var - 1e-9) {\n                        bins[d1].erase(bins[d1].begin() + i);\n                        bins[d2].push_back(item);\n                        bin_weight[d1] = new_w1;\n                        bin_weight[d2] = new_w2;\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Create output assignment\n    vector<int> assignment(N);\n    for (int d = 0; d < D; d++) {\n        for (int item : bins[d]) {\n            assignment[item] = d;\n        }\n    }\n    \n    // Output final assignment\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    int boxes_per_stack = n / m;\n    \n    // stacks[i] contains boxes from bottom to top\n    vector<vector<int>> stacks(m);\n    // pos[v] = {stack_index, height_index} for box v\n    vector<pair<int, int>> pos(n + 1);\n    \n    for (int i = 0; i < m; i++) {\n        stacks[i].resize(boxes_per_stack);\n        for (int j = 0; j < boxes_per_stack; j++) {\n            cin >> stacks[i][j];\n            pos[stacks[i][j]] = {i, j};\n        }\n    }\n    \n    vector<pair<int, int>> operations;\n    int total_energy = 0;\n    \n    // Remove boxes 1 to n in order\n    for (int v = 1; v <= n; v++) {\n        auto [stack_idx, height_idx] = pos[v];\n        \n        // Check if box v is at the top of its stack\n        if (height_idx == (int)stacks[stack_idx].size() - 1) {\n            // Box is at top, can remove directly\n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1}; // Mark as removed\n        } else {\n            // Need to move boxes above v to other stacks\n            int boxes_to_move = stacks[stack_idx].size() - 1 - height_idx;\n            \n            // Move each box above v to another stack\n            for (int h = stacks[stack_idx].size() - 1; h > height_idx; h--) {\n                int box_to_move = stacks[stack_idx][h];\n                \n                // Find best destination stack (prefer fewer boxes, not current stack)\n                int best_stack = -1;\n                int min_size = n + 1;\n                \n                for (int s = 0; s < m; s++) {\n                    if (s != stack_idx && (int)stacks[s].size() < min_size) {\n                        min_size = stacks[s].size();\n                        best_stack = s;\n                    }\n                }\n                \n                if (best_stack == -1) {\n                    // Fallback: any stack except current\n                    for (int s = 0; s < m; s++) {\n                        if (s != stack_idx) {\n                            best_stack = s;\n                            break;\n                        }\n                    }\n                }\n                \n                // Move box_to_move and all above it (just this box since we're at top)\n                operations.push_back({box_to_move, best_stack + 1});\n                total_energy += 2; // 1 box + 1 = 2 energy\n                \n                // Update stacks\n                stacks[best_stack].push_back(box_to_move);\n                stacks[stack_idx].pop_back();\n                pos[box_to_move] = {best_stack, (int)stacks[best_stack].size() - 1};\n            }\n            \n            // Now box v should be at top\n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        }\n    }\n    \n    // Output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring result;\n\n// Direction vectors: R, D, L, U\nconst int DI[4] = {0, 1, 0, -1};\nconst int DJ[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nbool canMove(int i, int j, int dir) {\n    int ni = i + DI[dir];\n    int nj = j + DJ[dir];\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    if (dir == 0) { // Right\n        return v[i][j] == '0';\n    } else if (dir == 1) { // Down\n        return h[i][j] == '0';\n    } else if (dir == 2) { // Left\n        return v[i][nj] == '0';\n    } else { // Up\n        return h[ni][j] == '0';\n    }\n}\n\n// BFS to find shortest path from (si,sj) to (ti,tj)\nvector<int> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parentDir(N, vector<int>(N, -1));\n    \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();\n        q.pop();\n        \n        if (i == ti && j == tj) break;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    parent[ni][nj] = {i, j};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (dist[ti][tj] == -1) return {};\n    \n    vector<int> path;\n    int ci = ti, cj = tj;\n    while (ci != si || cj != sj) {\n        path.push_back(parentDir[ci][cj]);\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// DFS to build spanning tree and initial tour\nvoid dfsTour(int i, int j, vector<vector<bool>>& treeVisited) {\n    treeVisited[i][j] = true;\n    \n    for (int dir = 0; dir < 4; dir++) {\n        if (canMove(i, j, dir)) {\n            int ni = i + DI[dir];\n            int nj = j + DJ[dir];\n            if (!treeVisited[ni][nj]) {\n                result += DIR_CHAR[dir];\n                dfsTour(ni, nj, treeVisited);\n                result += DIR_CHAR[(dir + 2) % 4]; // Return\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    h.resize(N - 1);\n    for (int i = 0; i < N - 1; i++) {\n        cin >> h[i];\n    }\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> v[i];\n    }\n    \n    d.resize(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    }\n    \n    // Create initial tour using DFS spanning tree\n    vector<vector<bool>> treeVisited(N, vector<bool>(N, false));\n    dfsTour(0, 0, treeVisited);\n    \n    // Calculate total dirt sum for prioritization\n    long long totalDirt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            totalDirt += d[i][j];\n        }\n    }\n    \n    // Identify high-priority cells (top 30% by dirt value)\n    vector<tuple<int, int, int>> cells; // (dirt, i, j)\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cells.push_back({d[i][j], i, j});\n        }\n    }\n    sort(cells.begin(), cells.end(), greater<tuple<int,int,int>>());\n    \n    // Budget for extra visits (keep under 10^5)\n    int maxLen = 100000;\n    int currentLen = result.size();\n    int budget = maxLen - currentLen - 1000; // Leave some margin\n    \n    // Add extra visits to high-priority cells\n    // Strategy: Insert visits to top cells by going from current position and back\n    int posI = 0, posJ = 0;\n    \n    for (auto& [dirt, ti, tj] : cells) {\n        if (budget <= 10) break;\n        \n        // Only add extra visits for high-dirt cells\n        if (dirt < totalDirt / (N * N) * 1.5) break;\n        \n        // Find path from current position to target and back\n        vector<int> pathTo = bfsPath(posI, posJ, ti, tj);\n        if (pathTo.empty()) continue;\n        \n        vector<int> pathBack = bfsPath(ti, tj, posI, posJ);\n        if (pathBack.empty()) continue;\n        \n        int pathLen = pathTo.size() + pathBack.size();\n        if (pathLen > budget) continue;\n        \n        // Insert the round trip\n        for (int dir : pathTo) {\n            result += DIR_CHAR[dir];\n            posI += DI[dir];\n            posJ += DJ[dir];\n        }\n        for (int dir : pathBack) {\n            result += DIR_CHAR[dir];\n            posI += DI[dir];\n            posJ += DJ[dir];\n        }\n        \n        budget -= pathLen;\n    }\n    \n    // Ensure we end at (0,0)\n    if (posI != 0 || posJ != 0) {\n        vector<int> pathHome = bfsPath(posI, posJ, 0, 0);\n        for (int dir : pathHome) {\n            result += DIR_CHAR[dir];\n        }\n    }\n    \n    // Verify all cells are visited\n    vector<vector<bool>> allVisited(N, vector<bool>(N, false));\n    int ci = 0, cj = 0;\n    allVisited[ci][cj] = true;\n    for (char c : result) {\n        int dir;\n        if (c == 'R') dir = 0;\n        else if (c == 'D') dir = 1;\n        else if (c == 'L') dir = 2;\n        else dir = 3;\n        ci += DI[dir];\n        cj += DJ[dir];\n        allVisited[ci][cj] = true;\n    }\n    \n    // If any cell not visited, do a final sweep\n    bool allGood = true;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!allVisited[i][j]) {\n                allGood = false;\n                break;\n            }\n        }\n        if (!allGood) break;\n    }\n    \n    if (!allGood) {\n        // Fallback: rebuild with guaranteed coverage\n        result.clear();\n        vector<vector<bool>> treeVisited2(N, vector<bool>(N, false));\n        dfsTour(0, 0, treeVisited2);\n    }\n    \n    cout << result << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    int N, M;\n    cin >> N >> M;\n    \n    int si, sj;\n    cin >> si >> sj;\n    \n    vector<string> A(N);\n    for (int i = 0; i < N; i++) {\n        cin >> A[i];\n    }\n    \n    vector<string> t(M);\n    for (int i = 0; i < M; i++) {\n        cin >> t[i];\n    }\n    \n    // Map each character to all its positions on grid\n    vector<vector<pair<int,int>>> charPos(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            charPos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    // Precompute overlap between all pairs of words\n    // overlap[i][j] = max overlap when word j follows word i\n    vector<vector<int>> overlap(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) continue;\n            int maxOv = 0;\n            for (int ov = 1; ov < 5; ov++) {\n                if (t[i].substr(5 - ov) == t[j].substr(0, ov)) {\n                    maxOv = ov;\n                }\n            }\n            overlap[i][j] = maxOv;\n        }\n    }\n    \n    // Greedy word ordering with multiple random starts\n    string bestString = \"\";\n    vector<int> bestOrder;\n    \n    int numTrials = min(50, M);\n    mt19937 rng(42);\n    \n    for (int trial = 0; trial < numTrials; trial++) {\n        vector<bool> used(M, false);\n        vector<int> order;\n        \n        // Start with random word\n        int start = (trial < M) ? trial : (int)(rng() % M);\n        order.push_back(start);\n        used[start] = true;\n        \n        string current = t[start];\n        \n        // Greedily add remaining words\n        for (int i = 1; i < M; i++) {\n            int bestNext = -1;\n            int bestOverlap = -1;\n            int bestAdded = INT_MAX;\n            \n            for (int j = 0; j < M; j++) {\n                if (!used[j]) {\n                    int ov = overlap[order.back()][j];\n                    int added = 5 - ov;\n                    // Prefer higher overlap, then fewer added chars\n                    if (ov > bestOverlap || (ov == bestOverlap && added < bestAdded)) {\n                        bestOverlap = ov;\n                        bestNext = j;\n                        bestAdded = added;\n                    }\n                }\n            }\n            \n            if (bestNext != -1) {\n                used[bestNext] = true;\n                order.push_back(bestNext);\n                current += t[bestNext].substr(bestOverlap);\n            }\n        }\n        \n        // Keep best (shortest) string\n        if (bestString.empty() || current.size() < bestString.size()) {\n            bestString = current;\n            bestOrder = order;\n        }\n    }\n    \n    // Now construct the path on the grid\n    // For each character, choose position minimizing movement cost\n    vector<pair<int,int>> path;\n    int curI = si, curJ = sj;\n    long long totalCost = 0;\n    \n    for (char c : bestString) {\n        int charIdx = c - 'A';\n        \n        // Find the position that minimizes movement cost\n        int bestI = -1, bestJ = -1;\n        int minCost = INT_MAX;\n        \n        for (auto [ni, nj] : charPos[charIdx]) {\n            int cost = abs(ni - curI) + abs(nj - curJ) + 1;\n            if (cost < minCost) {\n                minCost = cost;\n                bestI = ni;\n                bestJ = nj;\n            }\n        }\n        \n        path.push_back({bestI, bestJ});\n        totalCost += minCost;\n        curI = bestI;\n        curJ = bestJ;\n    }\n    \n    // Try to optimize by considering future characters (lookahead)\n    // Simple 2-step lookahead optimization\n    if (bestString.size() >= 2) {\n        vector<pair<int,int>> optPath = path;\n        \n        for (int pos = 1; pos < (int)bestString.size() - 1; pos++) {\n            int charIdx = bestString[pos] - 'A';\n            int nextCharIdx = bestString[pos + 1] - 'A';\n            \n            int curBestI = optPath[pos].first;\n            int curBestJ = optPath[pos].second;\n            \n            int prevI = optPath[pos - 1].first;\n            int prevJ = optPath[pos - 1].second;\n            \n            // Try all positions for current character\n            for (auto [ni, nj] : charPos[charIdx]) {\n                int cost1 = abs(ni - prevI) + abs(nj - prevJ) + 1;\n                \n                // Find best next position given this choice\n                int minCost2 = INT_MAX;\n                for (auto [ni2, nj2] : charPos[nextCharIdx]) {\n                    int cost2 = abs(ni2 - ni) + abs(nj2 - nj) + 1;\n                    minCost2 = min(minCost2, cost2);\n                }\n                \n                int totalLookahead = cost1 + minCost2;\n                int origCost1 = abs(curBestI - prevI) + abs(curBestJ - prevJ) + 1;\n                \n                int origCost2 = INT_MAX;\n                for (auto [ni2, nj2] : charPos[nextCharIdx]) {\n                    int cost2 = abs(ni2 - curBestI) + abs(nj2 - curBestJ) + 1;\n                    origCost2 = min(origCost2, cost2);\n                }\n                \n                if (totalLookahead < origCost1 + origCost2) {\n                    optPath[pos] = {ni, nj};\n                }\n            }\n        }\n        \n        path = optPath;\n    }\n    \n    // Verify we haven't exceeded operation limit\n    if ((int)path.size() > 5000) {\n        path.resize(5000);\n    }\n    \n    // Output\n    for (auto [i, j] : path) {\n        cout << i << \" \" << j << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <iomanip>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Global constants\nconst double EPS = 1e-9;\n\nstruct Field {\n    int id;\n    vector<pair<int, int>> shape;\n    int h, w;\n    vector<pair<int, int>> valid_positions;\n};\n\nint N, M;\ndouble epsilon;\nvector<Field> fields;\nvector<vector<double>> probs; // probs[k * N * N + r * N + c]\nvector<vector<int>> drill_results; // -1 if not drilled\nvector<double> row_obs;\nvector<double> col_obs;\n\n// Helper to get probability index\ninline int idx(int k, int r, int c) {\n    return k * N * N + r * N + c;\n}\n\n// Initialize probabilities uniformly over valid positions\nvoid init_probs() {\n    probs.assign(M * N * N, 0.0);\n    for (int k = 0; k < M; ++k) {\n        double count = fields[k].valid_positions.size();\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] = 1.0 / count;\n        }\n    }\n}\n\n// Calculate marginal probability that field k covers (i, j)\ndouble get_marginal(int k, int i, int j) {\n    double p = 0.0;\n    for (auto [r, c] : fields[k].valid_positions) {\n        // Check if (i, j) is covered by field k at (r, c)\n        // Shape coords are (di, dj). Grid coords (r+di, c+dj).\n        // So (i, j) covered if (i-r, j-c) is in shape.\n        int di = i - r;\n        int dj = j - c;\n        // Since shape is stored as list, we need to check efficiently.\n        // Given small shape size, linear scan is fine.\n        // But we can precompute a grid for each field?\n        // N is small, shape size is small.\n        // Let's iterate shape.\n        for (auto [si, sj] : fields[k].shape) {\n            if (r + si == i && c + sj == j) {\n                p += probs[idx(k, r, c)];\n                break;\n            }\n        }\n    }\n    return p;\n}\n\n// Precompute coverage for faster marginal calculation\n// covered[k][r][c][i][j] is bool. Too much memory?\n// M * N * N * N * N = 20 * 160000 = 3.2M bools. ~3MB. Fine.\n// Actually we can just store for each (k, r, c) the list of covered (i, j).\n// Or for each (k, i, j) the list of (r, c) that cover it.\n// Let's use: covers[k][i][j] -> vector of (r, c) indices.\nvector<vector<vector<vector<pair<int, int>>>>> cover_map;\n\nvoid build_cover_map() {\n    cover_map.assign(M, vector<vector<vector<pair<int, int>>>>(N, vector<vector<pair<int, int>>>(N)));\n    for (int k = 0; k < M; ++k) {\n        for (auto [r, c] : fields[k].valid_positions) {\n            for (auto [si, sj] : fields[k].shape) {\n                int i = r + si;\n                int j = c + sj;\n                if (i >= 0 && i < N && j >= 0 && j < N) {\n                    cover_map[k][i][j].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\ndouble get_marginal_fast(int k, int i, int j) {\n    double p = 0.0;\n    for (auto [r, c] : cover_map[k][i][j]) {\n        p += probs[idx(k, r, c)];\n    }\n    return p;\n}\n\n// Update probabilities based on row/col observations\nvoid update_row_col() {\n    // Row observations\n    for (int i = 0; i < N; ++i) {\n        double Y = row_obs[i];\n        double sigma_sq = N * epsilon * (1.0 - epsilon);\n        double sigma = sqrt(sigma_sq);\n        \n        // For each field, update its distribution\n        for (int k = 0; k < M; ++k) {\n            // Calculate expected contribution from other fields\n            double E_rest = 0.0;\n            for (int j = 0; j < M; ++j) {\n                if (j == k) continue;\n                for (int col = 0; col < N; ++col) {\n                    E_rest += get_marginal_fast(j, i, col);\n                }\n            }\n            \n            // Update probs for field k\n            vector<double> new_probs;\n            new_probs.reserve(fields[k].valid_positions.size());\n            double sum_p = 0.0;\n            \n            for (auto [r, c] : fields[k].valid_positions) {\n                // Count cells of field k in row i\n                int v_k = 0;\n                for (auto [si, sj] : fields[k].shape) {\n                    if (r + si == i) v_k++;\n                }\n                \n                double V_pred = v_k + E_rest;\n                double mu = N * epsilon + V_pred * (1.0 - 2.0 * epsilon);\n                double diff = Y - mu;\n                double likelihood = exp(-0.5 * diff * diff / sigma_sq);\n                \n                double p = probs[idx(k, r, c)] * likelihood;\n                new_probs.push_back(p);\n                sum_p += p;\n            }\n            \n            // Normalize\n            if (sum_p < EPS) sum_p = EPS;\n            int p_idx = 0;\n            for (auto [r, c] : fields[k].valid_positions) {\n                probs[idx(k, r, c)] = new_probs[p_idx++] / sum_p;\n            }\n        }\n    }\n    \n    // Col observations\n    for (int j = 0; j < N; ++j) {\n        double Y = col_obs[j];\n        double sigma_sq = N * epsilon * (1.0 - epsilon);\n        double sigma = sqrt(sigma_sq);\n        \n        for (int k = 0; k < M; ++k) {\n            double E_rest = 0.0;\n            for (int i = 0; i < M; ++i) {\n                if (i == k) continue;\n                for (int row = 0; row < N; ++row) {\n                    E_rest += get_marginal_fast(i, row, j);\n                }\n            }\n            \n            vector<double> new_probs;\n            new_probs.reserve(fields[k].valid_positions.size());\n            double sum_p = 0.0;\n            \n            for (auto [r, c] : fields[k].valid_positions) {\n                int v_k = 0;\n                for (auto [si, sj] : fields[k].shape) {\n                    if (c + sj == j) v_k++;\n                }\n                \n                double V_pred = v_k + E_rest;\n                double mu = N * epsilon + V_pred * (1.0 - 2.0 * epsilon);\n                double diff = Y - mu;\n                double likelihood = exp(-0.5 * diff * diff / sigma_sq);\n                \n                double p = probs[idx(k, r, c)] * likelihood;\n                new_probs.push_back(p);\n                sum_p += p;\n            }\n            \n            if (sum_p < EPS) sum_p = EPS;\n            int p_idx = 0;\n            for (auto [r, c] : fields[k].valid_positions) {\n                probs[idx(k, r, c)] = new_probs[p_idx++] / sum_p;\n            }\n        }\n    }\n}\n\n// Update probabilities based on drill result at (i, j) with value V\nvoid update_drill(int i, int j, int V) {\n    // Get marginals q_k = P(field k covers (i, j))\n    vector<double> q(M);\n    for (int k = 0; k < M; ++k) {\n        q[k] = get_marginal_fast(k, i, j);\n    }\n    \n    // DP to find distribution of sum S = sum X_k\n    // dp[s] = P(sum = s)\n    // We need P(S=V | X_k=1) and P(S=V | X_k=0)\n    // P(X_k=1 | S=V) = P(S=V | X_k=1) * q[k] / P(S=V)\n    // P(S=V | X_k=1) = P(S_{-k} = V-1)\n    // P(S=V | X_k=0) = P(S_{-k} = V)\n    \n    // Compute distribution of S_{-k} for each k?\n    // That's O(M^3). M=20 -> 8000. Fast.\n    // Or compute total S dist, then remove k?\n    // Removing is division, risky with 0.\n    // Recomputing for each k is safer and fast enough.\n    \n    vector<double> new_q(M);\n    \n    for (int k = 0; k < M; ++k) {\n        // DP for sum of other fields\n        vector<double> dp(V + 2, 0.0); // Max sum needed is V\n        dp[0] = 1.0;\n        \n        for (int other = 0; other < M; ++other) {\n            if (other == k) continue;\n            double p = q[other];\n            // Update dp in reverse\n            for (int s = V; s >= 0; --s) {\n                double val = dp[s] * (1.0 - p);\n                if (s > 0) val += dp[s-1] * p;\n                dp[s] = val;\n            }\n        }\n        \n        double prob_S_V_given_1 = (V > 0) ? dp[V-1] : 0.0;\n        double prob_S_V_given_0 = dp[V];\n        \n        double num_1 = prob_S_V_given_1 * q[k];\n        double num_0 = prob_S_V_given_0 * (1.0 - q[k]);\n        double denom = num_1 + num_0;\n        \n        if (denom < EPS) {\n            // Contradiction or very unlikely. Keep old q?\n            // Should not happen if beliefs are not 0/1.\n            new_q[k] = q[k];\n        } else {\n            new_q[k] = num_1 / denom;\n        }\n    }\n    \n    // Update probs for each field to match new_q\n    for (int k = 0; k < M; ++k) {\n        double old_q = q[k];\n        double target_q = new_q[k];\n        \n        if (abs(old_q - target_q) < EPS) continue;\n        \n        double f1 = (old_q > EPS) ? (target_q / old_q) : 1.0;\n        double f0 = (old_q < 1.0 - EPS) ? ((1.0 - target_q) / (1.0 - old_q)) : 1.0;\n        \n        double sum_p = 0.0;\n        // Apply factors\n        for (auto [r, c] : cover_map[k][i][j]) {\n            probs[idx(k, r, c)] *= f1;\n            sum_p += probs[idx(k, r, c)];\n        }\n        for (auto [r, c] : fields[k].valid_positions) {\n            // Check if NOT in cover_map\n            bool covers = false;\n            for (auto [si, sj] : fields[k].shape) {\n                if (r + si == i && c + sj == j) {\n                    covers = true;\n                    break;\n                }\n            }\n            if (!covers) {\n                probs[idx(k, r, c)] *= f0;\n                sum_p += probs[idx(k, r, c)];\n            }\n        }\n        \n        // Renormalize\n        // Wait, sum_p calculated above is sum of ALL probs for field k?\n        // Yes, because we iterated all valid positions (union of covers and not covers).\n        // But I iterated cover_map then valid_positions.\n        // cover_map is subset of valid_positions.\n        // So I double counted if I'm not careful.\n        // Better: iterate valid_positions once.\n        \n        sum_p = 0.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            bool covers = false;\n            for (auto [si, sj] : fields[k].shape) {\n                if (r + si == i && c + sj == j) {\n                    covers = true;\n                    break;\n                }\n            }\n            // probs already multiplied\n            sum_p += probs[idx(k, r, c)];\n        }\n        \n        if (sum_p < EPS) sum_p = EPS;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] /= sum_p;\n        }\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    cin >> N >> M >> epsilon;\n    \n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        fields[k].id = k;\n        int d;\n        cin >> d;\n        fields[k].shape.resize(d);\n        int min_i = N, min_j = N, max_i = -1, max_j = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> fields[k].shape[i].first >> fields[k].shape[i].second;\n            min_i = min(min_i, fields[k].shape[i].first);\n            min_j = min(min_j, fields[k].shape[i].second);\n            max_i = max(max_i, fields[k].shape[i].first);\n            max_j = max(max_j, fields[k].shape[i].second);\n        }\n        // The problem says shape is translated so min coords are 0.\n        // So min_i, min_j should be 0.\n        // Valid positions for top-left (r, c):\n        // r + max_i < N => r <= N - 1 - max_i\n        // c + max_j < N => c <= N - 1 - max_j\n        fields[k].h = max_i + 1;\n        fields[k].w = max_j + 1;\n        for (int r = 0; r <= N - fields[k].h; ++r) {\n            for (int c = 0; c <= N - fields[k].w; ++c) {\n                fields[k].valid_positions.push_back({r, c});\n            }\n        }\n    }\n    \n    build_cover_map();\n    init_probs();\n    \n    drill_results.assign(N, vector<int>(N, -1));\n    row_obs.assign(N, 0.0);\n    col_obs.assign(N, 0.0);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // 1. Query Rows\n    for (int i = 0; i < N; ++i) {\n        cout << \"q \" << N;\n        for (int j = 0; j < N; ++j) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        cin >> row_obs[i];\n    }\n    \n    // 2. Query Cols\n    for (int j = 0; j < N; ++j) {\n        cout << \"q \" << N;\n        for (int i = 0; i < N; ++i) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        cin >> col_obs[j];\n    }\n    \n    // 3. Update beliefs\n    update_row_col();\n    \n    // 4. Iterative Drilling\n    int ops_count = 2 * N;\n    int max_ops = 2 * N * N;\n    \n    while (ops_count < max_ops) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.5) break; // Safety margin\n        \n        // Find square with max entropy\n        int best_i = -1, best_j = -1;\n        double max_entropy = -1.0;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drill_results[i][j] != -1) continue;\n                \n                double p_oil = 0.0;\n                // P(v > 0) = 1 - Prod(1 - q_k)\n                double p_empty = 1.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal_fast(k, i, j);\n                    p_empty *= (1.0 - q);\n                }\n                p_oil = 1.0 - p_empty;\n                \n                if (p_oil < EPS) p_oil = EPS;\n                if (p_oil > 1.0 - EPS) p_oil = 1.0 - EPS;\n                \n                double H = -p_oil * log2(p_oil) - (1.0 - p_oil) * log2(1.0 - p_oil);\n                if (H > max_entropy) {\n                    max_entropy = H;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1 || max_entropy < 0.3) break; // Low uncertainty\n        \n        // Drill\n        cout << \"q 1 \" << best_i << \" \" << best_j << endl;\n        int val;\n        cin >> val;\n        drill_results[best_i][best_j] = val;\n        ops_count++;\n        \n        // Update\n        update_drill(best_i, best_j, val);\n    }\n    \n    // 5. Construct Answer\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool has_oil = false;\n            if (drill_results[i][j] != -1) {\n                if (drill_results[i][j] > 0) has_oil = true;\n            } else {\n                double p_empty = 1.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal_fast(k, i, j);\n                    p_empty *= (1.0 - q);\n                }\n                if (p_empty < 0.5) has_oil = true;\n            }\n            \n            if (has_oil) {\n                ans.push_back({i, j});\n            }\n        }\n    }\n    \n    // 6. Guess\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    \n    int resp;\n    cin >> resp;\n    // If resp == 0, we could continue, but we exit.\n    // In a contest, we should ideally handle resp==0, but with this strategy we aim for 1.\n    // If 0, we get penalty but program ends.\n    // To be robust, we could loop, but time limit.\n    // Given the heuristic nature, we assume 1.\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int W = 1000;\nconst double TIME_LIMIT = 2.8; // seconds\n\nstruct Rect {\n    int r0, c0, r1, c1;\n};\n\nstruct Node {\n    int id;\n    bool is_leaf;\n    int left = -1, right = -1; // children indices\n    int res_id = -1; // reservation id if leaf\n    long long target_area = 0;\n    \n    // Layout info\n    int r0, c0, r1, c1; // coordinates\n    int cut_pos = 0; // relative cut position (width for V, height for H)\n    int cut_type = 0; // 0: V, 1: H\n    \n    // Previous day info for cost calculation\n    int prev_cut_pos = 0;\n    int prev_cut_type = 0;\n};\n\nstruct Solver {\n    int D, N;\n    vector<vector<int>> A; // A[d][k]\n    vector<Node> tree;\n    vector<Rect> prev_day_rects; // rects for each reservation k\n    mt19937 rng;\n    \n    // Timing\n    chrono::steady_clock::time_point start_time;\n    \n    Solver() {\n        rng.seed(42);\n    }\n    \n    void run() {\n        start_time = chrono::steady_clock::now();\n        \n        int W_in;\n        if (!(cin >> W_in >> D >> N)) return;\n        // W_in is always 1000\n        \n        A.resize(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        prev_day_rects.resize(N);\n        \n        // Initialize Tree\n        // We create a balanced binary tree with N leaves\n        // Nodes 0 to 2N-2. Leaves are N-1 to 2N-2.\n        tree.resize(2 * N - 1);\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].id = i;\n            if (i >= N - 1) {\n                tree[i].is_leaf = true;\n                tree[i].res_id = i - (N - 1); // temporary mapping\n            } else {\n                tree[i].is_leaf = false;\n                tree[i].left = 2 * i + 1;\n                tree[i].right = 2 * i + 2;\n                // Alternate cut types for balance\n                tree[i].cut_type = (i % 2); \n            }\n        }\n        \n        // Initial assignment for Day 0\n        // Sort reservations by area and assign to leaves\n        // But leaves are fixed in tree structure. We assign res_id to leaves.\n        // To make it simple, we just assign res_id 0..N-1 to leaves 0..N-1 (in leaf index order)\n        // But we should sort to match areas?\n        // For Day 0, there is no previous geometry, so any assignment is fine.\n        // We'll sort A[0] and assign largest to largest capacity leaves?\n        // Since tree is balanced, all leaves have similar capacity potential.\n        // Let's just assign in order.\n        vector<int> p(N);\n        iota(p.begin(), p.end(), 0);\n        // Sort p based on A[0][p[i]]\n        sort(p.begin(), p.end(), [&](int i, int j) {\n            return A[0][i] < A[0][j];\n        });\n        \n        // Assign sorted reservations to leaves in order\n        // Leaves are tree[N-1] ... tree[2N-2]\n        for (int i = 0; i < N; ++i) {\n            tree[N - 1 + i].res_id = p[i];\n            tree[N - 1 + i].target_area = A[0][p[i]];\n        }\n        \n        // Layout Day 0\n        layout(0, 0, 0, W, W);\n        \n        // Store prev info\n        update_prev_info();\n        store_rects(0);\n        \n        // Output Day 0\n        output_day(0);\n        \n        // Subsequent days\n        for (int d = 1; d < D; ++d) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            \n            solve_day(d);\n            output_day(d);\n        }\n    }\n    \n    void solve_day(int d) {\n        // 1. Re-assign reservations to leaves based on area rank\n        // Calculate current area of each leaf\n        vector<pair<long long, int>> leaf_areas; // area, leaf_index\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            long long area = (long long)(tree[leaf_idx].r1 - tree[leaf_idx].r0) * (tree[leaf_idx].c1 - tree[leaf_idx].c0);\n            leaf_areas.push_back({area, leaf_idx});\n        }\n        sort(leaf_areas.begin(), leaf_areas.end());\n        \n        // Sort new requests\n        vector<pair<int, int>> requests; // area, original_k\n        for (int k = 0; k < N; ++k) {\n            requests.push_back({A[d][k], k});\n        }\n        sort(requests.begin(), requests.end());\n        \n        // Match\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = leaf_areas[i].second;\n            int k = requests[i].second;\n            tree[leaf_idx].res_id = k;\n            tree[leaf_idx].target_area = A[d][k];\n        }\n        \n        // 2. Local Search\n        vector<Node> best_tree = tree;\n        double best_cost = calc_approx_cost();\n        \n        int iterations = 10000;\n        // Adjust iterations based on remaining time\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = TIME_LIMIT - elapsed;\n        double time_per_day = TIME_LIMIT / D;\n        if (remaining < time_per_day * 0.5) {\n            iterations = 2000;\n        } else if (remaining > time_per_day * 2) {\n            iterations = 20000;\n        }\n        \n        for (int iter = 0; iter < iterations; ++iter) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            \n            // Mutate\n            // Pick a random internal node\n            int node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n            int mutation_type = uniform_int_distribution<>(0, 2)(rng);\n            \n            // Save state\n            Node saved_node = tree[node_idx];\n            vector<Node> saved_children;\n            if (!tree[node_idx].is_leaf) {\n                saved_children.push_back(tree[tree[node_idx].left]);\n                saved_children.push_back(tree[tree[node_idx].right]);\n            }\n            \n            bool valid = true;\n            if (mutation_type == 0) {\n                // Swap children\n                swap(tree[node_idx].left, tree[node_idx].right);\n            } else if (mutation_type == 1) {\n                // Flip cut type\n                tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n            } else {\n                // Swap children and flip cut type\n                swap(tree[node_idx].left, tree[node_idx].right);\n                tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n            }\n            \n            // Layout and Calc Cost\n            layout(0, 0, 0, W, W);\n            double cost = calc_approx_cost();\n            \n            // Acceptance (Hill Climbing with some randomness)\n            // Simple HC: accept if better\n            // SA: accept if worse with prob\n            // Given time, let's use simple HC with restart if stuck?\n            // Or just HC.\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_tree = tree;\n            } else {\n                // Revert\n                tree[node_idx] = saved_node;\n                if (!tree[node_idx].is_leaf) {\n                    tree[tree[node_idx].left] = saved_children[0];\n                    tree[tree[node_idx].right] = saved_children[1];\n                }\n                // Restore layout to consistent state (though we will overwrite next iter or end)\n                // Actually, we should restore layout to match reverted tree for next iter cost calc?\n                // No, next iter will mutate again and re-layout.\n                // But we need `tree` to be consistent for `calc_approx_cost` if we don't revert layout?\n                // `calc_approx_cost` uses `tree` nodes' `prev_cut_pos` which is static.\n                // It uses `tree` nodes' `cut_pos` which is set by `layout`.\n                // So we must layout after revert to have valid `cut_pos`.\n                layout(0, 0, 0, W, W);\n            }\n        }\n        \n        tree = best_tree;\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n        store_rects(d);\n    }\n    \n    void layout(int u, int r0, int c0, int r1, int c1) {\n        tree[u].r0 = r0; tree[u].c0 = c0; tree[u].r1 = r1; tree[u].c1 = c1;\n        if (tree[u].is_leaf) return;\n        \n        int left = tree[u].left;\n        int right = tree[u].right;\n        long long area_l = get_subtree_area(left);\n        long long area_r = get_subtree_area(right);\n        long long total = area_l + area_r;\n        \n        if (total == 0) {\n            // Should not happen given constraints\n            tree[u].cut_pos = (tree[u].cut_type == 0) ? (c1 - c0) / 2 : (r1 - r0) / 2;\n        } else {\n            if (tree[u].cut_type == 0) { // V-cut\n                // Split width\n                // Use integer division with rounding\n                // w_l = round(W * area_l / total)\n                long long w = c1 - c0;\n                long long w_l = (w * area_l + total / 2) / total;\n                if (w_l < 1) w_l = 1;\n                if (w_l > w - 1) w_l = w - 1;\n                tree[u].cut_pos = c0 + w_l;\n                \n                layout(left, r0, c0, r1, tree[u].cut_pos);\n                layout(right, r0, tree[u].cut_pos, r1, c1);\n            } else { // H-cut\n                // Split height\n                long long h = r1 - r0;\n                long long h_l = (h * area_l + total / 2) / total;\n                if (h_l < 1) h_l = 1;\n                if (h_l > h - 1) h_l = h - 1;\n                tree[u].cut_pos = r0 + h_l;\n                \n                layout(left, r0, c0, tree[u].cut_pos, c1);\n                layout(right, tree[u].cut_pos, c0, r1, c1);\n            }\n        }\n    }\n    \n    long long get_subtree_area(int u) {\n        if (tree[u].is_leaf) return tree[u].target_area;\n        return get_subtree_area(tree[u].left) + get_subtree_area(tree[u].right);\n    }\n    \n    double calc_approx_cost() {\n        double cost = 0;\n        for (int i = 0; i < N - 1; ++i) { // Internal nodes\n            if (tree[i].cut_type != tree[i].prev_cut_type) {\n                // Type changed\n                int span_old = (tree[i].prev_cut_type == 0) ? (tree[i].r1 - tree[i].r0) : (tree[i].c1 - tree[i].c0);\n                // Note: r1, c1 etc are from CURRENT layout. \n                // We should use PREVIOUS layout dimensions for old span?\n                // We don't store previous dimensions per node easily.\n                // Approximation: use current span.\n                int span_new = (tree[i].cut_type == 0) ? (tree[i].r1 - tree[i].r0) : (tree[i].c1 - tree[i].c0);\n                cost += span_old + span_new;\n            } else {\n                int pos_diff = abs(tree[i].cut_pos - tree[i].prev_cut_pos);\n                int span = (tree[i].cut_type == 0) ? (tree[i].r1 - tree[i].r0) : (tree[i].c1 - tree[i].c0);\n                cost += 2.0 * pos_diff * span;\n            }\n        }\n        return cost;\n    }\n    \n    void update_prev_info() {\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].prev_cut_pos = tree[i].cut_pos;\n            tree[i].prev_cut_type = tree[i].cut_type;\n        }\n    }\n    \n    void store_rects(int d) {\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            prev_day_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n    }\n    \n    void output_day(int d) {\n        // We need to output in order of k=0..N-1\n        // But we stored rects in prev_day_rects[k]\n        // Wait, for day d, we just computed rects.\n        // We should output the rects we just computed.\n        // store_rects saves them for NEXT day's cost calc.\n        // But we need to output current day's rects.\n        // They are in tree leaves now.\n        vector<Rect> current_rects(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            current_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n        \n        for (int k = 0; k < N; ++k) {\n            cout << current_rects[k].r0 << \" \" << current_rects[k].c0 << \" \" \n                 << current_rects[k].r1 << \" \" << current_rects[k].c1 << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver solver;\n    solver.run();\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long MOD = 998244353;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, K;\n    cin >> N >> M >> K;\n    \n    // Read initial board\n    vector<vector<long long>> a(N, vector<long long>(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    // Read stamps\n    vector<vector<vector<long long>>> s(M, vector<vector<long long>>(3, vector<long long>(3)));\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> s[m][i][j];\n            }\n        }\n    }\n    \n    // Current board state (actual values, not modded)\n    vector<vector<long long>> board = a;\n    \n    // Operations: (stamp_id, p, q)\n    vector<tuple<int, int, int>> operations;\n    operations.reserve(K);\n    \n    // Precompute all possible operation effects\n    struct OpInfo {\n        int m, p, q;\n        long long improvement;\n    };\n    \n    // Greedy selection for K operations\n    for (int op = 0; op < K; op++) {\n        long long best_improvement = LLONG_MIN;\n        int best_m = 0, best_p = 0, best_q = 0;\n        \n        // Try all possible operations\n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    // Calculate improvement if we add this operation\n                    long long improvement = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            long long old_val = board[p + i][q + j];\n                            long long old_mod = old_val % MOD;\n                            long long new_val = old_val + s[m][i][j];\n                            long long new_mod = new_val % MOD;\n                            improvement += new_mod - old_mod;\n                        }\n                    }\n                    \n                    if (improvement > best_improvement) {\n                        best_improvement = improvement;\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n        \n        // Apply the best operation\n        operations.push_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] += s[best_m][i][j];\n            }\n        }\n    }\n    \n    // Output\n    cout << operations.size() << \"\\n\";\n    for (const auto& [m, p, q] : operations) {\n        cout << m << \" \" << p << \" \" << q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct State {\n    int container[N][N]; // -1 if empty, otherwise container number\n    int crane_row[5];    // current row of each crane\n    int crane_col[5];    // current col of each crane\n    int crane_holding[5]; // -1 if not holding, otherwise container number\n    int next_receive[5]; // next container index to receive at each gate\n    vector<int> dispatched[5]; // containers dispatched from each gate\n};\n\nint get_target_row(int container_num) {\n    return container_num / N;\n}\n\nint get_target_col(int container_num) {\n    return N - 1;\n}\n\nbool can_move_small(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return false;\n    return state.container[row][col] == -1;\n}\n\nbool can_move_large(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return true;\n    return true; // Large crane can move over containers\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\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    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            state.container[i][j] = -1;\n        }\n        state.crane_row[i] = i;\n        state.crane_col[i] = 0;\n        state.crane_holding[i] = -1;\n        state.next_receive[i] = 0;\n        state.dispatched[i].clear();\n    }\n    \n    // Output strings for each crane\n    vector<string> actions(N, \"\");\n    \n    // Track which containers need to be dispatched from each gate\n    vector<vector<int>> target_containers(N);\n    for (int c = 0; c < N * N; c++) {\n        target_containers[c / N].push_back(c);\n    }\n    \n    // Simple greedy strategy: move containers from left to right\n    // Large crane (0) handles row 0, small cranes handle their rows\n    // Use columns 1-3 as buffer\n    \n    int turn = 0;\n    int total_dispatched = 0;\n    \n    while (turn < MAX_TURNS && total_dispatched < N * N) {\n        string turn_actions(N, '.');\n        bool any_action = false;\n        \n        // Step 1: Receive containers (simulated - happens automatically)\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && \n                state.container[i][0] == -1 && \n                state.crane_holding[0] == -1) { // Check if crane 0 not blocking\n                // Container arrives at gate\n                // This happens automatically in the simulation\n            }\n        }\n        \n        // Step 2: Plan crane actions\n        for (int c = 0; c < N; c++) {\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            int holding = state.crane_holding[c];\n            \n            char action = '.';\n            \n            if (holding == -1) {\n                // Not holding - try to pick up a container\n                if (state.container[r][col] != -1) {\n                    // Pick up container\n                    action = 'P';\n                    any_action = true;\n                } else {\n                    // Move towards containers or dispatch gates\n                    bool is_large = (c == 0);\n                    \n                    // Priority: go to left side to pick up, then right to dispatch\n                    int target_col = 0;\n                    int target_row = r;\n                    \n                    // Look for containers to pick up\n                    bool found_container = false;\n                    for (int j = 0; j < N && !found_container; j++) {\n                        for (int i = 0; i < N && !found_container; i++) {\n                            if (state.container[i][j] != -1) {\n                                int container = state.container[i][j];\n                                int target_r = get_target_row(container);\n                                if (c == target_r || (c == 0 && target_r == 0)) {\n                                    target_row = i;\n                                    target_col = j;\n                                    found_container = true;\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (!found_container) {\n                        // Go to left side to wait for new containers\n                        target_col = 0;\n                    }\n                    \n                    // Move towards target\n                    if (col < target_col) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_col) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_row) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_row) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            } else {\n                // Holding a container - try to dispatch it\n                int target_r = get_target_row(holding);\n                int target_c = get_target_col(holding);\n                \n                if (r == target_r && col == target_c) {\n                    // At dispatch gate - release\n                    action = 'Q';\n                    any_action = true;\n                } else {\n                    // Move towards dispatch gate\n                    bool is_large = (c == 0);\n                    \n                    if (col < target_c) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_c) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_r) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_r) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            }\n            \n            turn_actions[c] = action;\n        }\n        \n        // If no actions, break to avoid infinite loop\n        if (!any_action && total_dispatched < N * N) {\n            // Try to do something - at least move cranes\n            for (int c = 0; c < N; c++) {\n                if (state.crane_col[c] < N - 1) {\n                    turn_actions[c] = 'R';\n                }\n            }\n        }\n        \n        // Apply actions (simplified simulation)\n        for (int c = 0; c < N; c++) {\n            char action = turn_actions[c];\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            \n            if (action == 'P' && state.crane_holding[c] == -1 && state.container[r][col] != -1) {\n                state.crane_holding[c] = state.container[r][col];\n                state.container[r][col] = -1;\n            } else if (action == 'Q' && state.crane_holding[c] != -1 && state.container[r][col] == -1) {\n                state.container[r][col] = state.crane_holding[c];\n                state.crane_holding[c] = -1;\n            } else if (action == 'R' && col < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col + 1] == -1) {\n                    state.crane_col[c]++;\n                }\n            } else if (action == 'L' && col > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col - 1] == -1) {\n                    state.crane_col[c]--;\n                }\n            } else if (action == 'D' && r < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r + 1][col] == -1) {\n                    state.crane_row[c]++;\n                }\n            } else if (action == 'U' && r > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r - 1][col] == -1) {\n                    state.crane_row[c]--;\n                }\n            }\n        }\n        \n        // Step 3: Dispatch containers at right edge\n        for (int i = 0; i < N; i++) {\n            if (state.container[i][N - 1] != -1) {\n                int container = state.container[i][N - 1];\n                state.dispatched[i].push_back(container);\n                state.container[i][N - 1] = -1;\n                total_dispatched++;\n            }\n        }\n        \n        // Simulate container arrival at left edge\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && state.container[i][0] == -1) {\n                // Check if any crane is holding at this position\n                bool crane_blocking = false;\n                for (int c = 0; c < N; c++) {\n                    if (state.crane_row[c] == i && state.crane_col[c] == 0 && state.crane_holding[c] != -1) {\n                        crane_blocking = true;\n                        break;\n                    }\n                }\n                if (!crane_blocking) {\n                    state.container[i][0] = A[i][state.next_receive[i]];\n                    state.next_receive[i]++;\n                }\n            }\n        }\n        \n        // Record actions\n        for (int c = 0; c < N; c++) {\n            actions[c] += turn_actions[c];\n        }\n        \n        turn++;\n        \n        // Safety break\n        if (turn >= 5000) break;\n    }\n    \n    // Pad all strings to same length\n    size_t max_len = 0;\n    for (int i = 0; i < N; i++) {\n        max_len = max(max_len, actions[i].size());\n    }\n    for (int i = 0; i < N; i++) {\n        while (actions[i].size() < max_len) {\n            actions[i] += '.';\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << actions[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Structure to represent a cell with non-zero height\nstruct Cell {\n    int r, c;\n    int h;\n    int id;\n};\n\nint N;\nvector<vector<int>> H;\nvector<string> ops;\nint curr_r, curr_c;\nlong long current_load;\n\n// Helper to record an operation\nvoid add_op(const string& s) {\n    ops.push_back(s);\n}\n\n// Helper to move the truck to a target coordinate and record moves\nvoid move_to(int tr, int tc) {\n    while (curr_r < tr) {\n        add_op(\"D\");\n        curr_r++;\n    }\n    while (curr_r > tr) {\n        add_op(\"U\");\n        curr_r--;\n    }\n    while (curr_c < tc) {\n        add_op(\"R\");\n        curr_c++;\n    }\n    while (curr_c > tc) {\n        add_op(\"L\");\n        curr_c--;\n    }\n}\n\n// Manhattan distance\nint dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    H.assign(N, vector<int>(N));\n    vector<Cell> sources;\n    vector<Cell> sinks;\n\n    // Read input and classify cells into sources (h > 0) and sinks (h < 0)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n            if (H[i][j] > 0) {\n                sources.push_back({i, j, H[i][j], i * N + j});\n            } else if (H[i][j] < 0) {\n                sinks.push_back({i, j, H[i][j], i * N + j});\n            }\n        }\n    }\n\n    curr_r = 0;\n    curr_c = 0;\n    current_load = 0;\n\n    // Continue until all sources are processed and truck is empty\n    // Note: If sources are empty, current_load must be 0 eventually because sum(h) = 0.\n    // However, we might have loaded soil from the last source and need to deliver it.\n    while (!sources.empty() || current_load > 0) {\n        if (current_load == 0) {\n            // Truck is empty, need to pick up soil from a source.\n            // Heuristic: Select source u that minimizes:\n            // 100 * dist(curr, u) + (100 + h[u]) * dist(u, centroid_of_sinks)\n            // This balances travel cost to source and estimated distribution cost.\n            \n            // Calculate weighted centroid of sinks\n            long long sum_demand = 0;\n            long long sum_r = 0;\n            long long sum_c = 0;\n            for (const auto& s : sinks) {\n                long long d = -s.h;\n                sum_demand += d;\n                sum_r += d * s.r;\n                sum_c += d * s.c;\n            }\n            \n            int centroid_r = 0;\n            int centroid_c = 0;\n            if (sum_demand > 0) {\n                centroid_r = (int)(sum_r / sum_demand);\n                centroid_c = (int)(sum_c / sum_demand);\n            }\n\n            int best_idx = -1;\n            long long best_score = -1;\n\n            for (int i = 0; i < (int)sources.size(); ++i) {\n                int d1 = dist(curr_r, curr_c, sources[i].r, sources[i].c);\n                int d2 = dist(sources[i].r, sources[i].c, centroid_r, centroid_c);\n                // Cost estimate\n                long long score = 100LL * d1 + (100LL + sources[i].h) * d2;\n                \n                if (best_idx == -1 || score < best_score) {\n                    best_score = score;\n                    best_idx = i;\n                }\n            }\n\n            // Pick the best source\n            Cell u = sources[best_idx];\n            // Remove from sources list efficiently\n            sources[best_idx] = sources.back();\n            sources.pop_back();\n\n            // Move to source and load all soil\n            move_to(u.r, u.c);\n            long long amount = u.h;\n            add_op(\"+\" + to_string(amount));\n            current_load += amount;\n            H[u.r][u.c] = 0;\n        }\n\n        if (current_load > 0) {\n            // Truck has soil, need to deliver to a sink.\n            // Heuristic: Go to the nearest sink to minimize loaded travel cost.\n            int best_idx = -1;\n            int min_d = 1e9;\n\n            for (int i = 0; i < (int)sinks.size(); ++i) {\n                int d = dist(curr_r, curr_c, sinks[i].r, sinks[i].c);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n\n            Cell v = sinks[best_idx];\n            \n            // Move to sink and unload as much as possible\n            move_to(v.r, v.c);\n            long long amount = min(current_load, (long long)-v.h);\n            add_op(\"-\" + to_string(amount));\n            current_load -= amount;\n            H[v.r][v.c] += amount;\n            \n            // If sink is satisfied (height becomes 0), remove from list\n            if (H[v.r][v.c] == 0) {\n                sinks[best_idx] = sinks.back();\n                sinks.pop_back();\n            }\n        }\n    }\n\n    // Output all operations\n    for (const auto& op : ops) {\n        cout << op << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::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); // 60 seeds\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    vector<int> values(seed_count, 0);\n    \n    // Read initial seeds\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n            values[i] += X[i][j];\n        }\n    }\n    \n    // Calculate neighbor count for each position\n    vector<vector<int>> neighbor_count(N, vector<int>(N, 0));\n    int di[] = {-1, 1, 0, 0};\n    int dj[] = {0, 0, -1, 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 ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    neighbor_count[i][j]++;\n                }\n            }\n        }\n    }\n    \n    // Create position list sorted by neighbor count (descending)\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    // Track which seeds have been used recently\n    vector<bool> used_recently(seed_count, false);\n    int use_cooldown = 3; // Seeds can't be reused for this many turns\n    vector<int> last_used(seed_count, -use_cooldown);\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (int t = 0; t < T; t++) {\n        // Create indices sorted by value (with diversity consideration)\n        vector<int> indices(seed_count);\n        iota(indices.begin(), indices.end(), 0);\n        \n        // Sort by value, but penalize recently used seeds\n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            int val_a = values[a];\n            int val_b = values[b];\n            // Penalize recently used seeds\n            if (t - last_used[a] < use_cooldown) val_a -= 50;\n            if (t - last_used[b] < use_cooldown) val_b -= 50;\n            if (val_a != val_b) return val_a > val_b;\n            return a < b; // Tie-break by index for determinism\n        });\n        \n        // Sort positions by neighbor count (descending)\n        sort(positions.begin(), positions.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n            if (neighbor_count[a.first][a.second] != neighbor_count[b.first][b.second]) {\n                return neighbor_count[a.first][a.second] > neighbor_count[b.first][b.second];\n            }\n            // Secondary sort: prefer center positions\n            int dist_a = abs(a.first - N/2) + abs(a.second - N/2);\n            int dist_b = abs(b.first - N/2) + abs(b.second - N/2);\n            return dist_a < dist_b;\n        });\n        \n        // Assign seeds to positions\n        vector<vector<int>> A(N, vector<int>(N));\n        vector<bool> seed_used(seed_count, false);\n        \n        for (int p = 0; p < N * N; p++) {\n            int i = positions[p].first;\n            int j = positions[p].second;\n            \n            // Find best unused seed\n            for (int idx : indices) {\n                if (!seed_used[idx]) {\n                    A[i][j] = idx;\n                    seed_used[idx] = true;\n                    last_used[idx] = t;\n                    break;\n                }\n            }\n        }\n        \n        // Output the placement\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            values[i] = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                values[i] += X[i][j];\n            }\n        }\n        \n        // Output debug info as comments\n        int max_val = *max_element(values.begin(), values.end());\n        cerr << \"# Turn \" << t << \" max_value: \" << max_val << endl;\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Structure to represent a point on the grid\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\n// Manhattan distance\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\n// Structure to represent a transport task\nstruct Pair {\n    Point s, t;\n    int id;\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M_in, V;\n    if (!(cin >> N >> M_in >> V)) return 0;\n\n    vector<string> S_grid(N), T_grid(N);\n    vector<Point> starts, targets;\n\n    // Read grid configurations\n    for (int i = 0; i < N; ++i) cin >> S_grid[i];\n    for (int i = 0; i < N; ++i) cin >> T_grid[i];\n\n    // Extract start and target coordinates\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (S_grid[i][j] == '1') starts.push_back({i, j});\n            if (T_grid[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n\n    // Filter out takoyaki that are already at target positions\n    vector<bool> s_used(starts.size(), false);\n    vector<bool> t_used(targets.size(), false);\n    \n    // Match identical positions first (cost 0)\n    for (size_t i = 0; i < starts.size(); ++i) {\n        for (size_t j = 0; j < targets.size(); ++j) {\n            if (!s_used[i] && !t_used[j] && starts[i] == targets[j]) {\n                s_used[i] = true;\n                t_used[j] = true;\n                break;\n            }\n        }\n    }\n\n    vector<Point> S_rem, T_rem;\n    for (size_t i = 0; i < starts.size(); ++i) if (!s_used[i]) S_rem.push_back(starts[i]);\n    for (size_t i = 0; i < targets.size(); ++i) if (!t_used[i]) T_rem.push_back(targets[i]);\n\n    int M = S_rem.size();\n    \n    // Output Arm Design: Star Graph\n    // Root 0, Leaves 1 to V-1, Edge Length 1\n    // This allows up to V-1 simultaneous pickups/dropoffs near the root\n    int V_prime = V;\n    cout << V_prime << \"\\n\";\n    for (int i = 1; i < V_prime; ++i) {\n        cout << 0 << \" \" << 1 << \"\\n\";\n    }\n    // Initial root position (0,0), will move immediately in simulation\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    if (M == 0) {\n        // No moves needed\n        cout << 0 << \"\\n\";\n        return 0;\n    }\n\n    // Greedy Matching between remaining Starts and Targets\n    vector<Pair> pairs;\n    vector<bool> t_matched(T_rem.size(), false);\n    for (int i = 0; i < M; ++i) {\n        int best_j = -1;\n        int min_d = 1e9;\n        for (int j = 0; j < (int)T_rem.size(); ++j) {\n            if (!t_matched[j]) {\n                int d = dist(S_rem[i], T_rem[j]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_j = j;\n                }\n            }\n        }\n        if (best_j != -1) {\n            pairs.push_back({S_rem[i], T_rem[best_j], i});\n            t_matched[best_j] = true;\n        }\n    }\n\n    // Sort pairs to improve spatial locality (reduce travel distance between tasks)\n    // Using a coarse grid hash for clustering\n    sort(pairs.begin(), pairs.end(), [](const Pair& a, const Pair& b) {\n        int ma = (a.s.r / 5) * 10 + (a.s.c / 5);\n        int mb = (b.s.r / 5) * 10 + (b.s.c / 5);\n        if (ma != mb) return ma < mb;\n        return dist(a.s, a.t) < dist(b.s, b.t);\n    });\n\n    // Simulation State\n    int cur_r = 0, cur_c = 0;\n    // Move to a valid neighbor of the first start position\n    {\n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n        for(int k=0; k<4; ++k) {\n            int nr = pairs[0].s.r + dr[k];\n            int nc = pairs[0].s.c + dc[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                cur_r = nr; cur_c = nc;\n                break;\n            }\n        }\n    }\n\n    // Finger state: holding[u] = index in pairs, -1 if none\n    // finger_dir[u]: 0:R, 1:U, 2:L, 3:D\n    vector<int> holding(V_prime, -1);\n    vector<int> finger_dir(V_prime, 0); \n\n    vector<string> commands;\n    // We process tasks in batches to allow potential parallelism, \n    // but here we implement robust 1-by-1 transport ordered by proximity.\n    int batch_size = V_prime - 1; \n    \n    int pair_idx = 0;\n    while (pair_idx < M) {\n        int end_idx = min(pair_idx + batch_size, M);\n        \n        // Collect indices for current batch\n        vector<int> batch_indices;\n        for(int i=pair_idx; i<end_idx; ++i) batch_indices.push_back(i);\n        \n        // Order batch by nearest neighbor from current position to minimize travel\n        vector<bool> visited_batch(batch_indices.size(), false);\n        vector<int> ordered_batch;\n        int curr_r = cur_r, curr_c = cur_c;\n        \n        for(int k=0; k<(int)batch_indices.size(); ++k) {\n            int best_k = -1;\n            int min_d = 1e9;\n            for(int j=0; j<(int)batch_indices.size(); ++j) {\n                if(!visited_batch[j]) {\n                    int d = dist({curr_r, curr_c}, pairs[batch_indices[j]].s);\n                    if(d < min_d) {\n                        min_d = d;\n                        best_k = j;\n                    }\n                }\n            }\n            if(best_k != -1) {\n                visited_batch[best_k] = true;\n                ordered_batch.push_back(batch_indices[best_k]);\n                // Update heuristic current position to target of this task\n                // This encourages chaining pickups and dropoffs efficiently\n                curr_r = pairs[batch_indices[best_k]].t.r;\n                curr_c = pairs[batch_indices[best_k]].t.c;\n            }\n        }\n        \n        // Execute transport for each pair in the ordered batch\n        for (int idx : ordered_batch) {\n            Point s = pairs[idx].s;\n            Point t = pairs[idx].t;\n            \n            // 1. Move root to a neighbor of s\n            int best_nr = -1, best_nc = -1;\n            int min_move_dist = 1e9;\n            int dr[] = {0, 0, 1, -1};\n            int dc[] = {1, -1, 0, 0};\n            \n            for(int k=0; k<4; ++k) {\n                int nr = s.r + dr[k];\n                int nc = s.c + dc[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d < min_move_dist) {\n                        min_move_dist = d;\n                        best_nr = nr;\n                        best_nc = nc;\n                    }\n                }\n            }\n            \n            // Generate move commands\n            while (cur_r != best_nr || cur_c != best_nc) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                commands.push_back(cmd);\n            }\n            \n            // 2. Pick up takoyaki\n            // Find a free finger (since we do 1-by-1, one is always free)\n            int finger = -1;\n            for(int u=1; u<V_prime; ++u) {\n                if(holding[u] == -1) {\n                    finger = u;\n                    break;\n                }\n            }\n            \n            // Determine target direction for finger to point to s\n            int target_dir = -1;\n            if (s.r == cur_r && s.c == cur_c + 1) target_dir = 0; // R\n            else if (s.r == cur_r - 1 && s.c == cur_c) target_dir = 1; // U\n            else if (s.r == cur_r && s.c == cur_c - 1) target_dir = 2; // L\n            else if (s.r == cur_r + 1 && s.c == cur_c) target_dir = 3; // D\n            \n            if (target_dir != -1 && finger != -1) {\n                // Rotate finger to target direction\n                while (finger_dir[finger] != target_dir) {\n                    string rot_cmd(2 * V_prime, '.');\n                    int d = (target_dir - finger_dir[finger] + 4) % 4;\n                    if (d == 1) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    } else if (d == 3) {\n                        rot_cmd[finger] = 'R';\n                        finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n                    } else if (d == 2) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    }\n                    commands.push_back(rot_cmd);\n                }\n                \n                // Grab\n                string grab_cmd(2 * V_prime, '.');\n                grab_cmd[V_prime + finger] = 'P';\n                commands.push_back(grab_cmd);\n                holding[finger] = idx;\n            }\n            \n            // 3. Move root to a neighbor of t\n            best_nr = -1, best_nc = -1;\n            min_move_dist = 1e9;\n            for(int k=0; k<4; ++k) {\n                int nr = t.r + dr[k];\n                int nc = t.c + dc[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d < min_move_dist) {\n                        min_move_dist = d;\n                        best_nr = nr;\n                        best_nc = nc;\n                    }\n                }\n            }\n            \n            while (cur_r != best_nr || cur_c != best_nc) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                commands.push_back(cmd);\n            }\n            \n            // 4. Drop takoyaki\n            target_dir = -1;\n            if (t.r == cur_r && t.c == cur_c + 1) target_dir = 0;\n            else if (t.r == cur_r - 1 && t.c == cur_c) target_dir = 1;\n            else if (t.r == cur_r && t.c == cur_c - 1) target_dir = 2;\n            else if (t.r == cur_r + 1 && t.c == cur_c) target_dir = 3;\n            \n            if (target_dir != -1 && finger != -1) {\n                while (finger_dir[finger] != target_dir) {\n                    string rot_cmd(2 * V_prime, '.');\n                    int d = (target_dir - finger_dir[finger] + 4) % 4;\n                    if (d == 1) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    } else if (d == 3) {\n                        rot_cmd[finger] = 'R';\n                        finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n                    } else if (d == 2) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    }\n                    commands.push_back(rot_cmd);\n                }\n                \n                string drop_cmd(2 * V_prime, '.');\n                drop_cmd[V_prime + finger] = 'P';\n                commands.push_back(drop_cmd);\n                holding[finger] = -1;\n            }\n        }\n        \n        pair_idx = end_idx;\n    }\n\n    // Output commands\n    cout << commands.size() << \"\\n\";\n    for (const string& cmd : commands) {\n        cout << cmd << \"\\n\";\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <numeric>\n#include <map>\n#include <cstdlib>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nstruct Fish {\n    int x, y;\n    int type; // 0: mackerel, 1: sardine\n};\n\nint N;\nvector<Fish> fish;\n\n// Grid parameters\nint G_SIZE;\nint CELL_SIZE;\nvector<vector<int>> grid_m;\nvector<vector<int>> grid_s;\nvector<vector<int>> grid_score;\nvector<vector<bool>> selected;\n\n// Directions for grid traversal\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\n\nvoid read_input() {\n    cin >> N;\n    fish.resize(2 * N);\n    for (int i = 0; i < 2 * N; ++i) {\n        cin >> fish[i].x >> fish[i].y;\n        fish[i].type = (i < N) ? 0 : 1;\n    }\n}\n\nvoid build_grid(int G) {\n    G_SIZE = G;\n    CELL_SIZE = 100000 / G;\n    grid_m.assign(G, vector<int>(G, 0));\n    grid_s.assign(G, vector<int>(G, 0));\n    grid_score.assign(G, vector<int>(G, 0));\n    selected.assign(G, vector<bool>(G, false));\n\n    for (const auto& f : fish) {\n        int gx = min(f.x / CELL_SIZE, G - 1);\n        int gy = min(f.y / CELL_SIZE, G - 1);\n        if (f.type == 0) grid_m[gx][gy]++;\n        else grid_s[gx][gy]++;\n    }\n\n    for (int i = 0; i < G; ++i) {\n        for (int j = 0; j < G; ++j) {\n            grid_score[i][j] = grid_m[i][j] - grid_s[i][j];\n        }\n    }\n}\n\n// Fill holes in the selected region\nvoid fill_holes() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    queue<pair<int, int>> q;\n\n    // Start BFS from boundaries\n    for (int i = 0; i < G_SIZE; ++i) {\n        if (!selected[i][0]) { q.push({i, 0}); visited[i][0] = true; }\n        if (!selected[i][G_SIZE - 1]) { q.push({i, G_SIZE - 1}); visited[i][G_SIZE - 1] = true; }\n        if (!selected[0][i]) { q.push({0, i}); visited[0][i] = true; }\n        if (!selected[G_SIZE - 1][i]) { q.push({G_SIZE - 1, i}); visited[G_SIZE - 1][i] = true; }\n    }\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                if (!visited[nx][ny] && !selected[nx][ny]) {\n                    visited[nx][ny] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    // Any unselected cell not visited is a hole\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (!selected[i][j] && !visited[i][j]) {\n                selected[i][j] = true;\n            }\n        }\n    }\n}\n\n// Identify components of positive score cells\nvector<vector<pair<int, int>>> get_positive_components() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    vector<vector<pair<int, int>>> components;\n    \n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (grid_score[i][j] > 0 && !visited[i][j]) {\n                vector<pair<int, int>> comp;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                comp.push_back({i, j});\n                \n                while(!q.empty()){\n                    auto [cx, cy] = q.front(); q.pop();\n                    for(int d=0; d<4; ++d){\n                        int nx = cx + dx[d];\n                        int ny = cy + dy[d];\n                        if(nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE){\n                            if(!visited[nx][ny] && grid_score[nx][ny] > 0){\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                                comp.push_back({nx, ny});\n                            }\n                        }\n                    }\n                }\n                components.push_back(comp);\n            }\n        }\n    }\n    return components;\n}\n\n// Connect components to the main selected region\nvoid connect_components(const vector<vector<pair<int, int>>>& components) {\n    // Map cell to component index\n    vector<vector<int>> cell_to_comp(G_SIZE, vector<int>(G_SIZE, -1));\n    for (int k = 0; k < components.size(); ++k) {\n        for (auto [x, y] : components[k]) {\n            cell_to_comp[x][y] = k;\n        }\n    }\n\n    vector<bool> comp_selected(components.size(), false);\n    \n    // Find best component to start with\n    int best_comp_idx = -1;\n    long long max_score = -1e18;\n    for (int k = 0; k < components.size(); ++k) {\n        long long s = 0;\n        for (auto [x, y] : components[k]) s += grid_score[x][y];\n        if (s > max_score) {\n            max_score = s;\n            best_comp_idx = k;\n        }\n    }\n\n    if (best_comp_idx == -1) return; // No positive cells\n\n    // Initialize selected with best component\n    for (auto [x, y] : components[best_comp_idx]) {\n        selected[x][y] = true;\n    }\n    comp_selected[best_comp_idx] = true;\n\n    while (true) {\n        // Find unselected component with min connection cost\n        int best_target = -1;\n        long long min_cost = 1e18;\n        pair<int, int> hit_cell = {-1, -1};\n        \n        // Dijkstra from current selected region\n        vector<vector<long long>> dist(G_SIZE, vector<long long>(G_SIZE, 1e18));\n        vector<vector<pair<int, int>>> parent(G_SIZE, vector<pair<int, int>>(G_SIZE, {-1, -1}));\n        priority_queue<pair<long long, pair<int, int>>, vector<pair<long long, pair<int, int>>>, greater<>> pq;\n\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (selected[i][j]) {\n                    dist[i][j] = 0;\n                    pq.push({0, {i, j}});\n                }\n            }\n        }\n\n        vector<long long> comp_min_cost(components.size(), 1e18);\n        vector<pair<int, int>> comp_hit_cell(components.size(), {-1, -1});\n\n        while (!pq.empty()) {\n            auto [d, pos] = pq.top(); pq.pop();\n            int x = pos.first;\n            int y = pos.second;\n\n            if (d > dist[x][y]) continue;\n\n            int c_idx = cell_to_comp[x][y];\n            if (c_idx != -1 && !comp_selected[c_idx]) {\n                if (d < comp_min_cost[c_idx]) {\n                    comp_min_cost[c_idx] = d;\n                    comp_hit_cell[c_idx] = {x, y};\n                }\n            }\n\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                    long long weight = 0;\n                    if (!selected[nx][ny]) {\n                        weight = max(0, -grid_score[nx][ny]);\n                    }\n                    if (dist[x][y] + weight < dist[nx][ny]) {\n                        dist[nx][ny] = dist[x][y] + weight;\n                        parent[nx][ny] = {x, y};\n                        pq.push({dist[nx][ny], {nx, ny}});\n                    }\n                }\n            }\n        }\n\n        // Pick best component to connect\n        for (int k = 0; k < components.size(); ++k) {\n            if (!comp_selected[k] && comp_min_cost[k] < min_cost) {\n                min_cost = comp_min_cost[k];\n                best_target = k;\n                hit_cell = comp_hit_cell[k];\n            }\n        }\n\n        if (best_target == -1) break; // All connected\n\n        // Reconstruct path and mark selected\n        int cx = hit_cell.first;\n        int cy = hit_cell.second;\n        while (cx != -1 && cy != -1) {\n            if (!selected[cx][cy]) {\n                selected[cx][cy] = true;\n            }\n            if (dist[cx][cy] == 0) break; \n            auto p = parent[cx][cy];\n            cx = p.first;\n            cy = p.second;\n        }\n\n        // Mark all cells of the target component as selected\n        for (auto [x, y] : components[best_target]) {\n            selected[x][y] = true;\n        }\n        comp_selected[best_target] = true;\n    }\n}\n\n// Extract boundary polygon\nvector<Point> extract_polygon() {\n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    \n    auto add_edge = [&](int x1, int y1, int x2, int y2) {\n        adj[{x1, y1}].push_back({x2, y2});\n        adj[{x2, y2}].push_back({x1, y1});\n    };\n    \n    // Vertical edges\n    for (int i = 0; i <= G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            bool left = (i > 0 && selected[i-1][j]);\n            bool right = (i < G_SIZE && selected[i][j]);\n            if (left != right) {\n                int x = i * CELL_SIZE;\n                int y1 = j * CELL_SIZE;\n                int y2 = (j + 1) * CELL_SIZE;\n                add_edge({x, y1}, {x, y2});\n            }\n        }\n    }\n    // Horizontal edges\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j <= G_SIZE; ++j) {\n            bool down = (j > 0 && selected[i][j-1]);\n            bool up = (j < G_SIZE && selected[i][j]);\n            if (down != up) {\n                int y = j * CELL_SIZE;\n                int x1 = i * CELL_SIZE;\n                int x2 = (i + 1) * CELL_SIZE;\n                add_edge({x1, y}, {x2, y});\n            }\n        }\n    }\n    \n    if (adj.empty()) return {};\n    \n    // Traverse\n    vector<Point> poly;\n    auto start = adj.begin()->first;\n    pair<int, int> curr = start;\n    pair<int, int> prev = {-1, -1};\n    \n    while (true) {\n        poly.push_back({curr.first, curr.second});\n        auto& neighbors = adj[curr];\n        pair<int, int> next = {-1, -1};\n        for (auto& nb : neighbors) {\n            if (nb != prev) {\n                next = nb;\n                break;\n            }\n        }\n        if (next == make_pair(-1, -1)) break; \n        if (next == start) {\n            break;\n        }\n        prev = curr;\n        curr = next;\n    }\n    \n    return poly;\n}\n\nbool is_inside(const vector<Point>& poly, int px, int py) {\n    // Check on edge first\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x == p2.x) { \n            if (px == p1.x && py >= min(p1.y, p2.y) && py <= max(p1.y, p2.y)) return true;\n        } else { \n            if (py == p1.y && px >= min(p1.x, p2.x) && px <= max(p1.x, p2.x)) return true;\n        }\n    }\n    \n    // Ray casting\n    bool inside = false;\n    for (size_t i = 0, j = poly.size() - 1; i < poly.size(); j = i++) {\n        // Check if ray intersects edge\n        // Edge from p1 to p2. Ray from (px, py) to (-inf, py)\n        // Intersection if p1.y and p2.y are on opposite sides of py\n        // And intersection x < px\n        \n        // Using integer arithmetic to avoid precision issues\n        // x_intersect = p1.x + (py - p1.y) * (p2.x - p1.x) / (p2.y - p1.y)\n        // We want x_intersect > px (ray to left) -> inside toggle\n        // Wait, standard ray casting casts to +inf or -inf.\n        // Let's cast to +inf (right).\n        // If (p1.y > py) != (p2.y > py)\n        // And px < x_intersect\n        \n        if ((poly[i].y > py) != (poly[j].y > py)) {\n             // Calculate intersection x\n             // Avoid division: px * (poly[j].y - poly[i].y) < poly[i].x * (poly[j].y - poly[i].y) + (py - poly[i].y) * (poly[j].x - poly[i].x)\n             // Be careful with sign of (poly[j].y - poly[i].y)\n             long long val = (long long)(poly[j].x - poly[i].x) * (long long)(py - poly[i].y);\n             long long denom = (long long)(poly[j].y - poly[i].y);\n             // We want px < poly[i].x + val / denom\n             // px * denom < poly[i].x * denom + val  (if denom > 0)\n             // px * denom > poly[i].x * denom + val  (if denom < 0)\n             \n             long long rhs = (long long)poly[i].x * denom + val;\n             if (denom > 0) {\n                 if ((long long)px * denom < rhs) inside = !inside;\n             } else {\n                 if ((long long)px * denom > rhs) inside = !inside;\n             }\n        }\n    }\n    return inside;\n}\n\nlong long calculate_score(const vector<Point>& poly) {\n    long long a = 0;\n    long long b = 0;\n    for (const auto& f : fish) {\n        if (is_inside(poly, f.x, f.y)) {\n            if (f.type == 0) a++;\n            else b++;\n        }\n    }\n    return a - b;\n}\n\nvector<Point> solve_grid(int G) {\n    build_grid(G);\n    \n    auto components = get_positive_components();\n    if (components.empty()) {\n        return {{0, 0}, {10, 0}, {10, 10}, {0, 10}};\n    }\n    \n    connect_components(components);\n    fill_holes();\n    \n    vector<Point> poly = extract_polygon();\n    if (poly.size() > 1000) return {}; \n    \n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n    }\n    if (perim > 400000) return {};\n    \n    return poly;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    read_input();\n    \n    vector<Point> best_poly;\n    long long best_score = -1e18;\n    \n    vector<int> grids = {200, 100, 50};\n    \n    for (int G : grids) {\n        vector<Point> poly = solve_grid(G);\n        if (!poly.empty()) {\n            long long score = calculate_score(poly);\n            if (score > best_score) {\n                best_score = score;\n                best_poly = poly;\n            }\n        }\n    }\n    \n    if (best_poly.empty()) {\n        best_poly = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <chrono>\n#include <cmath>\n#include <set>\n\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n};\n\nstruct Placement {\n    int p;      // rectangle index\n    int r;      // rotation (0 or 1)\n    char d;     // direction ('U' or 'L')\n    int b;      // reference rectangle (-1 or previous index)\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    vector<Rectangle> rects(N);\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n    }\n    \n    // Random number generator with fixed seed for reproducibility\n    mt19937 rng(12345);\n    \n    // Track best solution\n    int best_score = 2000000000;\n    vector<Placement> best_placements;\n    \n    // Store rotation choices for each rectangle\n    vector<int> rotations(N, 0);\n    vector<char> directions(N, 'U');\n    vector<int> references(N, -1);\n    \n    for (int turn = 0; turn < T; turn++) {\n        vector<Placement> placements;\n        placements.reserve(N);\n        \n        // Adaptive strategy based on turn number\n        if (turn < T / 4) {\n            // Exploration phase: try diverse strategies\n            int strategy = turn % 6;\n            \n            if (strategy == 0) {\n                // All U, no rotation, b=-1\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, 'U', -1});\n                }\n            } else if (strategy == 1) {\n                // All U, all rotated, b=-1\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 1, 'U', -1});\n                }\n            } else if (strategy == 2) {\n                // All L, no rotation, b=-1\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, 'L', -1});\n                }\n            } else if (strategy == 3) {\n                // All L, all rotated, b=-1\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 1, 'L', -1});\n                }\n            } else if (strategy == 4) {\n                // Alternating U/L\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, (i % 2 == 0) ? 'U' : 'L', -1});\n                }\n            } else {\n                // Random rotations, all U\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, (int)(rng() % 2), 'U', -1});\n                }\n            }\n        } else if (turn < T * 3 / 4) {\n            // Mid phase: refine based on patterns\n            // Try different rotation patterns\n            int pattern = (turn - T / 4) % 8;\n            \n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                if (pattern == 0) rot = 0;\n                else if (pattern == 1) rot = 1;\n                else if (pattern == 2) rot = (i % 2);\n                else if (pattern == 3) rot = ((i / 3) % 2);\n                else if (pattern == 4) rot = (rng() % 2);\n                else if (pattern == 5) rot = (i % 3 == 0) ? 1 : 0;\n                else if (pattern == 6) rot = (i % 5 == 0) ? 1 : 0;\n                else rot = (rng() % 2);\n                \n                char dir = (pattern < 4) ? 'U' : 'L';\n                int ref = -1;\n                if (pattern >= 6 && i > 0) {\n                    ref = i - 1;\n                }\n                \n                placements.push_back({i, rot, dir, ref});\n            }\n        } else {\n            // Exploitation phase: try variations of best found\n            if (!best_placements.empty()) {\n                // Copy best and make small modifications\n                placements = best_placements;\n                \n                // Mutate some placements\n                int num_mutations = max(1, N / 10);\n                for (int m = 0; m < num_mutations; m++) {\n                    int idx = rng() % N;\n                    if (rng() % 2 == 0) {\n                        placements[idx].r = 1 - placements[idx].r;\n                    } else {\n                        placements[idx].d = (placements[idx].d == 'U') ? 'L' : 'U';\n                    }\n                }\n            } else {\n                // Fallback to random\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, (int)(rng() % 2), 'U', -1});\n                }\n            }\n        }\n        \n        // Output placement\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read result\n        int W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        int score = W_prime + H_prime;\n        \n        // Update best solution\n        if (score < best_score) {\n            best_score = score;\n            best_placements = placements;\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <algorithm>\n\nusing namespace std;\n\n// Global variables\nint N, M, H;\nvector<int> A;\nvector<vector<int>> adj;\nvector<int> L;\nvector<int> support_count;\nint violations = 0;\nlong long current_score = 0;\n\n// Check if v is supported based on current global state\nbool is_supported(int v) {\n    if (L[v] == 0) return true;\n    return support_count[v] > 0;\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> M >> H)) return 0;\n\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    // Read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Initialize State\n    L.assign(N, 0);\n    support_count.assign(N, 0);\n    \n    // Initial support_count calculation (all 0, so all 0)\n    // violations = 0\n    current_score = 0;\n    \n    // Best solution tracking\n    long long best_valid_score = -1;\n    vector<int> best_L = L; // Initially all 0, which is valid\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n\n    // SA Parameters\n    const long long PENALTY = 1000000000LL; // 1e9\n    double temp = 100000.0; \n    \n    int iterations = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed >= time_limit) break;\n\n        // Cooling schedule\n        // Geometric cooling\n        temp = 100000.0 * pow(0.99995, iterations);\n        if (temp < 1.0) temp = 1.0;\n\n        // Pick vertex\n        int v = uniform_int_distribution<int>(0, N - 1)(rng);\n        \n        // Pick delta (bias towards +1)\n        int delta = 1;\n        if (uniform_int_distribution<int>(0, 10)(rng) < 3) {\n            delta = -1;\n        }\n\n        int old_L = L[v];\n        int new_L = old_L + delta;\n\n        if (new_L < 0 || new_L > H) {\n            iterations++;\n            continue;\n        }\n        if (new_L == old_L) {\n            iterations++;\n            continue;\n        }\n\n        // Calculate delta_violations and prepare updates\n        int delta_violations = 0;\n        \n        // 1. Update v's own support status\n        bool v_supported_old = is_supported(v);\n        \n        int new_support_count_v = 0;\n        if (new_L > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == new_L - 1) {\n                    new_support_count_v++;\n                }\n            }\n        }\n        bool v_supported_new = (new_L == 0) || (new_support_count_v > 0);\n        \n        if (v_supported_old && !v_supported_new) delta_violations++;\n        if (!v_supported_old && v_supported_new) delta_violations--;\n\n        // 2. Update neighbors' support status\n        // We need to track changes to support_count[u] to update violations\n        // Store changes to apply later if accepted\n        struct NeighborChange {\n            int u;\n            int delta_support;\n            bool violation_change; // true if violation count changes for u\n            int violation_delta; // +1 or -1\n        };\n        vector<NeighborChange> neighbor_changes;\n        neighbor_changes.reserve(adj[v].size());\n\n        for (int u : adj[v]) {\n            int old_contrib = (L[u] == old_L + 1) ? 1 : 0;\n            int new_contrib = (L[u] == new_L + 1) ? 1 : 0;\n            int delta_sc = new_contrib - old_contrib;\n            \n            if (delta_sc != 0) {\n                bool u_supported_old = (L[u] == 0) || (support_count[u] > 0);\n                // Predict new support count\n                int predicted_sc = support_count[u] + delta_sc;\n                bool u_supported_new = (L[u] == 0) || (predicted_sc > 0);\n                \n                int v_delta = 0;\n                if (u_supported_old && !u_supported_new) v_delta = 1;\n                if (!u_supported_old && u_supported_new) v_delta = -1;\n                \n                if (v_delta != 0) {\n                    neighbor_changes.push_back({u, delta_sc, true, v_delta});\n                    delta_violations += v_delta;\n                } else {\n                    neighbor_changes.push_back({u, delta_sc, false, 0});\n                }\n            }\n        }\n\n        long long delta_score = (long long)(new_L - old_L) * A[v];\n        long long delta_cost = (long long)delta_violations * PENALTY - delta_score;\n\n        // Accept / Reject\n        bool accept = false;\n        if (delta_cost < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-(double)delta_cost / temp);\n            if ((double)uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n\n        if (accept) {\n            // Apply changes\n            L[v] = new_L;\n            support_count[v] = new_support_count_v;\n            current_score += delta_score;\n            violations += delta_violations;\n            \n            for (auto& nc : neighbor_changes) {\n                support_count[nc.u] += nc.delta_support;\n            }\n\n            // Update best solution\n            if (violations == 0) {\n                if (current_score > best_valid_score) {\n                    best_valid_score = current_score;\n                    best_L = L;\n                }\n            }\n        }\n        \n        iterations++;\n    }\n\n    // Reconstruct parents from best_L\n    vector<int> P(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (best_L[v] > 0) {\n            // Find a neighbor with level best_L[v] - 1\n            int target = best_L[v] - 1;\n            for (int u : adj[v]) {\n                if (best_L[u] == target) {\n                    P[v] = u;\n                    break;\n                }\n            }\n            // In a valid solution, such u must exist.\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << P[i];\n    }\n    cout << endl;\n\n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\n// Structure to represent an Oni piece\nstruct Oni {\n    int id;\n    int r, c;\n    bool removed;\n};\n\n// Structure to represent a potential operation\nstruct Op {\n    char dir; // 'U', 'D', 'L', 'R'\n    int idx;  // row or col index\n    int k;    // shift amount\n    int cost; // Total moves for this operation (2 * k)\n    vector<int> covered_oni_ids; // IDs of Oni that would be removed by this operation\n};\n\nint main() {\n    // Optimize I/O operations for speed\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return 0;\n    \n    vector<string> grid(N);\n    vector<Oni> onis;\n    // Track Fukunokami positions to check safety\n    vector<vector<bool>> is_fuku(N, vector<bool>(N, false));\n    \n    int oni_count = 0;\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] == 'x') {\n                onis.push_back({oni_count++, i, j, false});\n            } else if (grid[i][j] == 'o') {\n                is_fuku[i][j] = true;\n            }\n        }\n    }\n    \n    vector<Op> ops;\n    // Reserve memory to avoid reallocations. Max ops is roughly 4 * N * N = 1600.\n    ops.reserve(1600);\n    \n    // Generate Column Ops (Up, Down)\n    for (int j = 0; j < N; ++j) {\n        // Up shifts: removes rows 0 to k-1 in column j\n        for (int k = 1; k <= N; ++k) {\n            bool safe = true;\n            // Check if any Fukunokami is in the removal path\n            for (int r = 0; r < k; ++r) {\n                if (is_fuku[r][j]) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (safe) {\n                vector<int> covered;\n                for (const auto& oni : onis) {\n                    // Check if Oni is in this column and within removal range\n                    if (oni.c == j && oni.r < k) {\n                        covered.push_back(oni.id);\n                    }\n                }\n                if (!covered.empty()) {\n                    ops.push_back({'U', j, k, 2 * k, covered});\n                }\n            }\n        }\n        // Down shifts: removes rows N-k to N-1 in column j\n        for (int k = 1; k <= N; ++k) {\n            bool safe = true;\n            for (int r = N - k; r < N; ++r) {\n                if (is_fuku[r][j]) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (safe) {\n                vector<int> covered;\n                for (const auto& oni : onis) {\n                    if (oni.c == j && oni.r >= N - k) {\n                        covered.push_back(oni.id);\n                    }\n                }\n                if (!covered.empty()) {\n                    ops.push_back({'D', j, k, 2 * k, covered});\n                }\n            }\n        }\n    }\n    \n    // Generate Row Ops (Left, Right)\n    for (int i = 0; i < N; ++i) {\n        // Left shifts: removes cols 0 to k-1 in row i\n        for (int k = 1; k <= N; ++k) {\n            bool safe = true;\n            for (int c = 0; c < k; ++c) {\n                if (is_fuku[i][c]) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (safe) {\n                vector<int> covered;\n                for (const auto& oni : onis) {\n                    if (oni.r == i && oni.c < k) {\n                        covered.push_back(oni.id);\n                    }\n                }\n                if (!covered.empty()) {\n                    ops.push_back({'L', i, k, 2 * k, covered});\n                }\n            }\n        }\n        // Right shifts: removes cols N-k to N-1 in row i\n        for (int k = 1; k <= N; ++k) {\n            bool safe = true;\n            for (int c = N - k; c < N; ++c) {\n                if (is_fuku[i][c]) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (safe) {\n                vector<int> covered;\n                for (const auto& oni : onis) {\n                    if (oni.r == i && oni.c >= N - k) {\n                        covered.push_back(oni.id);\n                    }\n                }\n                if (!covered.empty()) {\n                    ops.push_back({'R', i, k, 2 * k, covered});\n                }\n            }\n        }\n    }\n    \n    vector<pair<char, int>> result_moves;\n    result_moves.reserve(1600);\n    \n    int removed_count = 0;\n    int total_onis = onis.size();\n    \n    // Greedy Set Cover: Select operations to cover all Oni with minimum cost\n    while (removed_count < total_onis) {\n        int best_op_idx = -1;\n        int best_cost = 1;\n        int best_new_covered = 0;\n        \n        for (int i = 0; i < ops.size(); ++i) {\n            int new_covered = 0;\n            // Count how many currently unremoved Oni this op would remove\n            for (int id : ops[i].covered_oni_ids) {\n                if (!onis[id].removed) {\n                    new_covered++;\n                }\n            }\n            \n            if (new_covered > 0) {\n                if (best_op_idx == -1) {\n                    best_op_idx = i;\n                    best_cost = ops[i].cost;\n                    best_new_covered = new_covered;\n                } else {\n                    // Compare ratio: cost / new_covered\n                    // We want to minimize this ratio.\n                    // Compare ops[i].cost / new_covered < best_cost / best_new_covered\n                    // Equivalent to: ops[i].cost * best_new_covered < best_cost * new_covered\n                    if ((long long)ops[i].cost * best_new_covered < (long long)best_cost * new_covered) {\n                        best_op_idx = i;\n                        best_cost = ops[i].cost;\n                        best_new_covered = new_covered;\n                    }\n                }\n            }\n        }\n        \n        if (best_op_idx == -1) {\n            // Should not happen given problem guarantees\n            break;\n        }\n        \n        const Op& op = ops[best_op_idx];\n        \n        // Apply moves: Shift k times in direction, then k times in reverse to restore board\n        for (int step = 0; step < op.k; ++step) {\n            result_moves.push_back({op.dir, op.idx});\n        }\n        \n        char reverse_dir;\n        if (op.dir == 'U') reverse_dir = 'D';\n        else if (op.dir == 'D') reverse_dir = 'U';\n        else if (op.dir == 'L') reverse_dir = 'R';\n        else reverse_dir = 'L';\n        \n        for (int step = 0; step < op.k; ++step) {\n            result_moves.push_back({reverse_dir, op.idx});\n        }\n        \n        // Mark covered Oni as removed\n        for (int id : op.covered_oni_ids) {\n            if (!onis[id].removed) {\n                onis[id].removed = true;\n                removed_count++;\n            }\n        }\n    }\n    \n    // Output the sequence of moves\n    for (const auto& mv : result_moves) {\n        cout << mv.first << \" \" << mv.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nint N;\nlong long L;\nvector<int> T;\n\n// Function to simulate the process and calculate error\nlong long simulate(const vector<int>& A, const vector<int>& B, vector<int>& counts) {\n    fill(counts.begin(), counts.end(), 0);\n    int cur = 0;\n    // L weeks\n    for (int k = 0; k < L; ++k) {\n        counts[cur]++;\n        int t = counts[cur];\n        if (t % 2 != 0) {\n            cur = A[cur];\n        } else {\n            cur = B[cur];\n        }\n    }\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(counts[i] - T[i]);\n    }\n    return error;\n}\n\n// Check connectivity from node 0 to all nodes with T[i] > 0\nbool is_connected(const vector<int>& A, const vector<int>& B) {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    q.push(0);\n    visited[0] = true;\n    int count = 0;\n    while(!q.empty()){\n        int u = q.front();\n        q.pop();\n        if (T[u] > 0) count++;\n        \n        // Outgoing edges\n        int v1 = A[u];\n        if (!visited[v1]) {\n            visited[v1] = true;\n            q.push(v1);\n        }\n        int v2 = B[u];\n        if (!visited[v2]) {\n            visited[v2] = true;\n            q.push(v2);\n        }\n    }\n    // Check if all important nodes are visited\n    for(int i=0; i<N; ++i){\n        if(T[i] > 0 && !visited[i]) return false;\n    }\n    return true;\n}\n\nvoid fix_connectivity(vector<int>& A, vector<int>& B, vector<long long>& load) {\n    // Repeatedly ensure all T[i]>0 are reachable from 0\n    // We do this by finding an unreachable important node and adding an edge to it from a reachable node\n    // We try to minimize the disturbance to the load balance\n    \n    while (true) {\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        q.push(0);\n        reachable[0] = true;\n        while(!q.empty()){\n            int u = q.front();\n            q.pop();\n            if(!reachable[A[u]]) { reachable[A[u]] = true; q.push(A[u]); }\n            if(!reachable[B[u]]) { reachable[B[u]] = true; q.push(B[u]); }\n        }\n        \n        int target = -1;\n        for(int i=0; i<N; ++i){\n            if(T[i] > 0 && !reachable[i]){\n                target = i;\n                break;\n            }\n        }\n        \n        if(target == -1) break; // All important nodes reachable\n        \n        // Find best edge to redirect to target\n        // We look for a reachable node u, and change one of its outgoing edges to target\n        // We want to minimize increase in |load[dest] - 2*T[dest]|\n        \n        long long min_cost = -1;\n        int best_u = -1;\n        int best_edge = -1; // 0 for A, 1 for B\n        int old_dest = -1;\n        \n        for(int u=0; u<N; ++u){\n            if(!reachable[u]) continue;\n            // Try changing A[u]\n            {\n                int w = A[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 0;\n                    old_dest = w;\n                }\n            }\n            // Try changing B[u]\n            {\n                int w = B[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 1;\n                    old_dest = w;\n                }\n            }\n        }\n        \n        if(best_u != -1){\n            // Apply change\n            if(best_edge == 0){\n                load[old_dest] -= T[best_u];\n                A[best_u] = target;\n                load[target] += T[best_u];\n            } else {\n                load[old_dest] -= T[best_u];\n                B[best_u] = target;\n                load[target] += T[best_u];\n            }\n        } else {\n            // Should not happen if there is at least one reachable node (0 is reachable)\n            // Fallback: force 0 to point to target\n            int w = A[0];\n            load[w] -= T[0];\n            A[0] = target;\n            load[target] += T[0];\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    T.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution construction using flow balance heuristic\n    // We have 2N items, each (T[i], i). We want to assign them to buckets 0..N-1\n    // such that sum of values in bucket j is close to 2*T[j].\n    \n    vector<pair<int, int>> items;\n    items.reserve(2 * N);\n    for (int i = 0; i < N; ++i) {\n        items.push_back({T[i], i});\n        items.push_back({T[i], i});\n    }\n    \n    // Sort items descending by value\n    sort(items.begin(), items.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n        return a.first > b.first;\n    });\n    \n    vector<long long> load(N, 0);\n    vector<int> A(N), B(N);\n    vector<vector<int>> outgoing(N); // Store assigned destinations for each source\n    \n    for (const auto& item : items) {\n        int val = item.first;\n        int src = item.second;\n        \n        // Find best bucket\n        int best_j = -1;\n        long long min_diff = -1;\n        \n        // To speed up, we can just scan all N. N=100 is small.\n        for (int j = 0; j < N; ++j) {\n            long long diff = abs(load[j] + val - 2LL * T[j]);\n            if (best_j == -1 || diff < min_diff) {\n                min_diff = diff;\n                best_j = j;\n            }\n        }\n        \n        load[best_j] += val;\n        outgoing[src].push_back(best_j);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        A[i] = outgoing[i][0];\n        B[i] = outgoing[i][1];\n    }\n    \n    // Fix connectivity\n    fix_connectivity(A, B, load);\n    \n    // Evaluate initial score\n    vector<int> counts(N);\n    long long current_score = simulate(A, B, counts);\n    long long best_score = current_score;\n    vector<int> best_A = A;\n    vector<int> best_B = B;\n    \n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    \n    double temp = 1000.0;\n    double cooling_rate = 0.9999;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        // Generate neighbor\n        int i = uniform_int_distribution<>(0, N - 1)(rng);\n        int type = uniform_int_distribution<>(0, 1)(rng); // 0 for A, 1 for B\n        int old_val = (type == 0) ? A[i] : B[i];\n        int new_val = uniform_int_distribution<>(0, N - 1)(rng);\n        \n        if (old_val == new_val) continue;\n        \n        // Apply change\n        if (type == 0) A[i] = new_val;\n        else B[i] = new_val;\n        \n        long long new_score = simulate(A, B, counts);\n        \n        double delta = (double)new_score - (double)current_score;\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_A = A;\n                best_B = B;\n            }\n        } else {\n            // Revert\n            if (type == 0) A[i] = old_val;\n            else B[i] = old_val;\n        }\n        \n        temp *= cooling_rate;\n        iter++;\n    }\n    \n    // Output best solution\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n\n// AC Library for DSU\n#include <atcoder/dsu>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct City {\n    int id;\n    long long cx, cy;\n};\n\n// Calculate squared Euclidean distance between estimated centers\nlong long dist2(const City& a, const City& b) {\n    long long dx = a.cx - b.cx;\n    long long dy = a.cy - b.cy;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> G[i];\n    }\n\n    vector<City> cities(N);\n    // Keep a lookup by original ID to retrieve coordinates later\n    vector<City> city_by_id(N);\n\n    for (int i = 0; i < N; ++i) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cities[i].id = i;\n        // Estimate coordinates as the center of the rectangle\n        cities[i].cx = (0LL + lx + rx) / 2;\n        cities[i].cy = (0LL + ly + ry) / 2;\n        city_by_id[i] = cities[i];\n    }\n\n    // Sort cities globally to group spatially close cities together\n    sort(cities.begin(), cities.end(), [](const City& a, const City& b) {\n        if (a.cx != b.cx) return a.cx < b.cx;\n        return a.cy < b.cy;\n    });\n\n    // Partition cities into M groups based on sizes G\n    vector<vector<City>> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].reserve(G[i]);\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].push_back(cities[cur++]);\n        }\n    }\n\n    // Store final edges for each group\n    vector<vector<pair<int, int>>> ans_edges(M);\n    int queries_used = 0;\n\n    for (int k = 0; k < M; ++k) {\n        int S = groups[k].size();\n        if (S <= 1) {\n            continue; // No edges needed for single city group\n        }\n\n        // Sort within group to ensure chunks are spatially local\n        sort(groups[k].begin(), groups[k].end(), [](const City& a, const City& b) {\n            if (a.cx != b.cx) return a.cx < b.cx;\n            return a.cy < b.cy;\n        });\n\n        set<pair<int, int>> queried_edges_set;\n\n        // Chunking strategy:\n        // Divide the group into overlapping chunks of size <= L.\n        // Overlap by 1 node ensures the union of chunk graphs is connected.\n        // Step size is L - 1.\n        int step = L - 1;\n        for (int start = 0; start < S; ) {\n            // Check query budget\n            if (queries_used >= Q) break;\n\n            int end = start + L;\n            if (end > S) end = S;\n            \n            // Prepare chunk city IDs\n            vector<int> chunk_ids;\n            chunk_ids.reserve(end - start);\n            for(int i = start; i < end; ++i) {\n                chunk_ids.push_back(groups[k][i].id);\n            }\n\n            // Perform query\n            cout << \"? \" << chunk_ids.size();\n            for (int id : chunk_ids) {\n                cout << \" \" << id;\n            }\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n\n            // Read response\n            int num_ret = chunk_ids.size() - 1;\n            for (int i = 0; i < num_ret; ++i) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                queried_edges_set.insert({u, v});\n            }\n\n            // If we covered up to the end of the group, stop\n            if (end == S) break;\n            \n            // Next chunk starts with overlap of 1 node\n            start = end - 1;\n        }\n\n        // Build a pool of candidate edges: Queried Edges + Estimated Edges\n        struct Edge {\n            int u, v;\n            long long d2;\n            bool queried;\n        };\n        vector<Edge> pool;\n        \n        // Add queried edges\n        for (auto& p : queried_edges_set) {\n            const City& c1 = city_by_id[p.first];\n            const City& c2 = city_by_id[p.second];\n            pool.push_back({p.first, p.second, dist2(c1, c2), true});\n        }\n\n        // Add all estimated edges (complete graph within group)\n        // To avoid duplicates, check against queried edges\n        // Sort queried edges for binary search\n        vector<pair<int, int>> q_vec(queried_edges_set.begin(), queried_edges_set.end());\n        sort(q_vec.begin(), q_vec.end());\n\n        for (int i = 0; i < S; ++i) {\n            for (int j = i + 1; j < S; ++j) {\n                int u = groups[k][i].id;\n                int v = groups[k][j].id;\n                if (u > v) swap(u, v);\n                \n                // Skip if already in queried set\n                if (binary_search(q_vec.begin(), q_vec.end(), make_pair(u, v))) {\n                    continue;\n                }\n                \n                const City& c1 = groups[k][i];\n                const City& c2 = groups[k][j];\n                pool.push_back({u, v, dist2(c1, c2), false});\n            }\n        }\n\n        // Sort edges: primary key distance (asc), secondary key queried (desc)\n        // This prioritizes queried edges for the same estimated length\n        sort(pool.begin(), pool.end(), [](const Edge& a, const Edge& b) {\n            if (a.d2 != b.d2) return a.d2 < b.d2;\n            return a.queried > b.queried;\n        });\n\n        // Run Kruskal's algorithm to select S-1 edges\n        dsu group_dsu(N); \n        int edges_count = 0;\n        for (const auto& e : pool) {\n            if (group_dsu.same(e.u, e.v)) continue;\n            group_dsu.merge(e.u, e.v);\n            ans_edges[k].push_back({e.u, e.v});\n            edges_count++;\n            if (edges_count == S - 1) break;\n        }\n    }\n\n    // Output final answer\n    cout << \"!\\n\";\n    for (int k = 0; k < M; ++k) {\n        // Output city IDs in the group\n        for (int i = 0; i < (int)groups[k].size(); ++i) {\n            if (i > 0) cout << \" \";\n            cout << groups[k][i].id;\n        }\n        cout << \"\\n\";\n        // Output edges\n        for (auto& edge : ans_edges[k]) {\n            cout << edge.first << \" \" << edge.second << \"\\n\";\n        }\n    }\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n\nusing namespace std;\n\n// Structure to represent an action\nstruct Action {\n    char type;\n    char dir;\n};\n\n// Structure to represent a position on the grid\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\nint N, M;\nbool has_block[20][20];\nint dist_map[20][20];\nPos parent_pos[20][20];\nAction parent_act[20][20];\n\nconst int INF = 1e9;\n// Directions: Up, Down, Left, Right\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// BFS to find shortest path from start to end\n// If store_path is true, populates parent arrays for path reconstruction\n// Returns the distance (number of turns)\nint bfs(Pos start, Pos end, bool store_path) {\n    // Initialize distance map\n    for(int i = 0; i < N; ++i) \n        for(int j = 0; j < N; ++j) \n            dist_map[i][j] = INF;\n    \n    queue<Pos> q;\n    dist_map[start.r][start.c] = 0;\n    q.push(start);\n    \n    while(!q.empty()) {\n        Pos curr = q.front();\n        q.pop();\n        \n        if (curr == end) return dist_map[curr.r][curr.c];\n        \n        int d = dist_map[curr.r][curr.c];\n        \n        // Try Move actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r + dr[i];\n            int nc = curr.c + dc[i];\n            // Can move if valid and no block\n            if(is_valid(nr, nc) && !has_block[nr][nc]) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'M', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n        \n        // Try Slide actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r;\n            int nc = curr.c;\n            // Simulate slide until hitting block or wall\n            while(true) {\n                int nnr = nr + dr[i];\n                int nnc = nc + dc[i];\n                if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                    break;\n                }\n                nr = nnr;\n                nc = nnc;\n            }\n            // Stopped at (nr, nc)\n            if(dist_map[nr][nc] == INF) {\n                dist_map[nr][nc] = d + 1;\n                if(store_path) {\n                    parent_pos[nr][nc] = curr;\n                    parent_act[nr][nc] = {'S', dir_char[i]};\n                }\n                q.push({nr, nc});\n            }\n        }\n    }\n    return INF;\n}\n\n// Reconstruct path from parent arrays\nvector<Action> get_path(Pos end) {\n    vector<Action> path;\n    Pos curr = end;\n    while(dist_map[curr.r][curr.c] != 0) {\n        path.push_back(parent_act[curr.r][curr.c]);\n        curr = parent_pos[curr.r][curr.c];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    vector<Pos> points(M);\n    for(int i = 0; i < M; ++i) {\n        cin >> points[i].r >> points[i].c;\n    }\n    \n    // Initialize blocks (initially no blocks inside N x N)\n    for(int i = 0; i < N; ++i)\n        for(int j = 0; j < N; ++j)\n            has_block[i][j] = false;\n            \n    Pos curr = points[0];\n    vector<Action> all_actions;\n    \n    // Iterate through each target\n    for(int k = 0; k < M - 1; ++k) {\n        Pos target = points[k+1];\n        Pos next_target = (k + 2 < M) ? points[k+2] : Pos{-1, -1};\n        \n        // Calculate base plan (without placing new blocks)\n        int base_dist = bfs(curr, target, true);\n        vector<Action> base_path = get_path(target);\n        \n        int best_dist = base_dist;\n        vector<Action> best_path = base_path;\n        Pos best_S = {-1, -1};\n        Pos best_adj = {-1, -1};\n        \n        // Identify candidate block positions (Stoppers)\n        // A block is useful if it stops a slide at 'target' or 'next_target'\n        vector<Pos> candidates;\n        auto add_candidates = [&](Pos t) {\n            if(t.r == -1) return;\n            for(int i = 0; i < 4; ++i) {\n                int sr = t.r + dr[i];\n                int sc = t.c + dc[i];\n                if(is_valid(sr, sc)) {\n                    candidates.push_back({sr, sc});\n                }\n            }\n        };\n        add_candidates(target);\n        add_candidates(next_target);\n        \n        // Sort and remove duplicates\n        sort(candidates.begin(), candidates.end(), [](const Pos& a, const Pos& b){\n            if(a.r != b.r) return a.r < b.r;\n            return a.c < b.c;\n        });\n        candidates.erase(unique(candidates.begin(), candidates.end(), [](const Pos& a, const Pos& b){\n            return a.r == b.r && a.c == b.c;\n        }), candidates.end());\n        \n        // Evaluate each candidate block position\n        for(const auto& S : candidates) {\n            if(has_block[S.r][S.c]) continue;\n            if(S == target) continue; // Don't block the target itself\n            \n            // Heuristic benefit: if this block helps the next target\n            int benefit = 0;\n            if(next_target.r != -1) {\n                for(int i = 0; i < 4; ++i) {\n                    if(S.r == next_target.r + dr[i] && S.c == next_target.c + dc[i]) {\n                        benefit = 10; // Estimated saving\n                        break;\n                    }\n                }\n            }\n            \n            // Try placing block from each adjacent cell\n            for(int i = 0; i < 4; ++i) {\n                int ar = S.r + dr[i];\n                int ac = S.c + dc[i];\n                if(!is_valid(ar, ac)) continue;\n                \n                // Cost to reach adjacent cell (without block S)\n                int d1 = bfs(curr, {ar, ac}, false);\n                if(d1 == INF) continue;\n                \n                // Temporarily place block\n                has_block[S.r][S.c] = true;\n                \n                // Cost to reach target from adjacent cell (with block S)\n                int d2 = bfs({ar, ac}, target, false);\n                \n                // Remove block\n                has_block[S.r][S.c] = false;\n                \n                if(d2 == INF) continue;\n                \n                // Total cost = path to adj + 1 (Alter) + path to target - benefit\n                int total = d1 + 1 + d2 - benefit;\n                \n                if(total < best_dist) {\n                    best_dist = total;\n                    best_S = S;\n                    best_adj = {ar, ac};\n                }\n            }\n        }\n        \n        // Execute the best plan\n        if(best_S.r != -1) {\n            // 1. Move to best_adj\n            bfs(curr, best_adj, true);\n            vector<Action> p1 = get_path(best_adj);\n            all_actions.insert(all_actions.end(), p1.begin(), p1.end());\n            curr = best_adj;\n            \n            // 2. Alter (Place block)\n            char act_dir = 0;\n            for(int i = 0; i < 4; ++i) {\n                if(curr.r + dr[i] == best_S.r && curr.c + dc[i] == best_S.c) {\n                    act_dir = dir_char[i];\n                    break;\n                }\n            }\n            all_actions.push_back({'A', act_dir});\n            has_block[best_S.r][best_S.c] = true;\n            \n            // 3. Move to target\n            bfs(curr, target, true);\n            vector<Action> p2 = get_path(target);\n            all_actions.insert(all_actions.end(), p2.begin(), p2.end());\n            curr = target;\n        } else {\n            // Execute base plan\n            all_actions.insert(all_actions.end(), base_path.begin(), base_path.end());\n            curr = target;\n        }\n    }\n    \n    // Output all actions\n    for(const auto& act : all_actions) {\n        cout << act.type << \" \" << act.dir << \"\\n\";\n    }\n    \n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    int area() const { return (x2 - x1) * (y2 - y1); }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n};\n\n// Check if a rectangle contains the desired point\nbool canPlace(const Rect& rect, int x, int y) {\n    return rect.contains(x, y);\n}\n\n// Try to create a rectangle with target area containing point (x,y)\nRect makeRect(int x1, int y1, int x2, int y2, int x, int y, long long targetArea) {\n    Rect rect = {x1, y1, x2, y2};\n    long long area = rect.area();\n    \n    if (area <= 0) return rect;\n    \n    // Adjust dimensions to match target area while containing (x,y)\n    int width = x2 - x1;\n    int height = y2 - y1;\n    \n    if (width <= 0 || height <= 0) return rect;\n    \n    // Try to adjust height to match area\n    long long newHeight = (targetArea + width - 1) / width;\n    newHeight = max(1LL, min((long long)height, newHeight));\n    \n    // Ensure point is contained\n    int newY1 = max(x1, min(y1, y - (int)newHeight + 1));\n    int newY2 = min(y2, newY1 + (int)newHeight);\n    \n    if (newY2 - newY1 < 1) {\n        newY1 = max(x1, y - (int)newHeight + 1);\n        newY2 = min(y2, y + 1);\n    }\n    \n    return {x1, newY1, x2, newY2};\n}\n\n// Recursive space partitioning\nvoid partition(vector<Company>& comps, int idx, int end, Rect space) {\n    if (idx >= end) return;\n    if (idx == end - 1) {\n        // Last company gets remaining space\n        comps[idx].a = space.x1;\n        comps[idx].b = space.y1;\n        comps[idx].c = space.x2;\n        comps[idx].d = space.y2;\n        return;\n    }\n    \n    // Calculate total area needed for remaining companies\n    long long totalArea = 0;\n    for (int i = idx; i < end; i++) {\n        totalArea += comps[i].r;\n    }\n    \n    if (totalArea == 0) return;\n    \n    // Find split point\n    long long leftArea = 0;\n    int split = idx;\n    for (int i = idx; i < end - 1; i++) {\n        leftArea += comps[i].r;\n        if (leftArea * 2 >= totalArea) {\n            split = i + 1;\n            break;\n        }\n    }\n    \n    int width = space.x2 - space.x1;\n    int height = space.y2 - space.y1;\n    \n    if (width <= 0 || height <= 0) return;\n    \n    // Decide split direction based on aspect ratio and point positions\n    double aspectRatio = (double)width / height;\n    bool splitVertically = aspectRatio > 1.0;\n    \n    // Check if all points in left group are on one side\n    int leftMidX = 0, leftMidY = 0;\n    int rightMidX = 0, rightMidY = 0;\n    for (int i = idx; i < split; i++) {\n        leftMidX += comps[i].x;\n        leftMidY += comps[i].y;\n    }\n    for (int i = split; i < end; i++) {\n        rightMidX += comps[i].x;\n        rightMidY += comps[i].y;\n    }\n    leftMidX /= (split - idx);\n    leftMidY /= (split - idx);\n    rightMidX /= (end - split);\n    rightMidY /= (end - split);\n    \n    // Choose split direction that separates the groups better\n    int xDiff = abs(leftMidX - rightMidX);\n    int yDiff = abs(leftMidY - rightMidY);\n    splitVertically = (xDiff >= yDiff);\n    \n    Rect leftSpace, rightSpace;\n    \n    if (splitVertically) {\n        // Split horizontally (vertical line)\n        long long leftRatio = leftArea * space.area() / totalArea;\n        int splitX = space.x1 + max(1, min(space.x2 - space.x1 - 1, \n                      (int)((long long)width * leftArea / totalArea)));\n        \n        // Ensure split contains points properly\n        bool leftHasPoint = false, rightHasPoint = false;\n        for (int i = idx; i < split; i++) {\n            if (comps[i].x < splitX) leftHasPoint = true;\n        }\n        for (int i = split; i < end; i++) {\n            if (comps[i].x >= splitX) rightHasPoint = true;\n        }\n        \n        if (!leftHasPoint || !rightHasPoint) {\n            // Adjust split to ensure points are contained\n            int maxXLeft = -1, minXRight = 10001;\n            for (int i = idx; i < split; i++) maxXLeft = max(maxXLeft, comps[i].x);\n            for (int i = split; i < end; i++) minXRight = min(minXRight, comps[i].x);\n            splitX = max(space.x1 + 1, min(space.x2 - 1, (maxXLeft + minXRight + 1) / 2));\n        }\n        \n        leftSpace = {space.x1, space.y1, splitX, space.y2};\n        rightSpace = {splitX, space.y1, space.x2, space.y2};\n    } else {\n        // Split vertically (horizontal line)\n        int splitY = space.y1 + max(1, min(space.y2 - space.y1 - 1,\n                      (int)((long long)height * leftArea / totalArea)));\n        \n        bool leftHasPoint = false, rightHasPoint = false;\n        for (int i = idx; i < split; i++) {\n            if (comps[i].y < splitY) leftHasPoint = true;\n        }\n        for (int i = split; i < end; i++) {\n            if (comps[i].y >= splitY) rightHasPoint = true;\n        }\n        \n        if (!leftHasPoint || !rightHasPoint) {\n            int maxYLeft = -1, minYRight = 10001;\n            for (int i = idx; i < split; i++) maxYLeft = max(maxYLeft, comps[i].y);\n            for (int i = split; i < end; i++) minYRight = min(minYRight, comps[i].y);\n            splitY = max(space.y1 + 1, min(space.y2 - 1, (maxYLeft + minYRight + 1) / 2));\n        }\n        \n        leftSpace = {space.x1, space.y1, space.x2, splitY};\n        rightSpace = {space.x1, splitY, space.x2, space.y2};\n    }\n    \n    partition(comps, idx, split, leftSpace);\n    partition(comps, split, end, rightSpace);\n}\n\n// Local optimization to improve area matching\nvoid optimize(vector<Company>& comps) {\n    int n = comps.size();\n    bool improved = true;\n    int iterations = 0;\n    const int MAX_ITER = 1000;\n    \n    while (improved && iterations < MAX_ITER) {\n        improved = false;\n        iterations++;\n        \n        for (int i = 0; i < n; i++) {\n            for (int j = i + 1; j < n; j++) {\n                // Try to swap area between adjacent rectangles\n                if (comps[i].c <= comps[j].a || comps[j].c <= comps[i].a ||\n                    comps[i].d <= comps[j].b || comps[j].d <= comps[i].b) {\n                    continue; // Not adjacent\n                }\n                \n                // Check if we can improve by adjusting boundaries\n                int currentScoreI = 0, currentScoreJ = 0;\n                int areaI = (comps[i].c - comps[i].a) * (comps[i].d - comps[i].b);\n                int areaJ = (comps[j].c - comps[j].a) * (comps[j].d - comps[j].b);\n                \n                auto calcScore = [](int desired, int actual) -> double {\n                    if (actual <= 0) return 0.0;\n                    double ratio = (double)min(desired, actual) / max(desired, actual);\n                    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n                };\n                \n                currentScoreI = calcScore(comps[i].r, areaI) * 1000000;\n                currentScoreJ = calcScore(comps[j].r, areaJ) * 1000000;\n                \n                // Try small adjustments\n                for (int dx = -10; dx <= 10; dx += 5) {\n                    for (int dy = -10; dy <= 10; dy += 5) {\n                        if (dx == 0 && dy == 0) continue;\n                        \n                        // Try adjusting company i\n                        int newA = comps[i].a, newB = comps[i].b;\n                        int newC = comps[i].c, newD = comps[i].d;\n                        \n                        // Simple boundary adjustment\n                        if (dx > 0 && newC + dx <= 10000) {\n                            newC += dx;\n                        } else if (dx < 0 && newA - dx <= newC - 1) {\n                            newA += dx;\n                        }\n                        if (dy > 0 && newD + dy <= 10000) {\n                            newD += dy;\n                        } else if (dy < 0 && newB - dy <= newD - 1) {\n                            newB += dy;\n                        }\n                        \n                        if (newC - newA < 1 || newD - newB < 1) continue;\n                        if (!canPlace({newA, newB, newC, newD}, comps[i].x, comps[i].y)) continue;\n                        \n                        int newAreaI = (newC - newA) * (newD - newB);\n                        int newScoreI = calcScore(comps[i].r, newAreaI) * 1000000;\n                        \n                        if (newScoreI > currentScoreI) {\n                            comps[i].a = newA;\n                            comps[i].b = newB;\n                            comps[i].c = newC;\n                            comps[i].d = newD;\n                            improved = true;\n                        }\n                    }\n                }\n            }\n        }\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<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n    }\n    \n    // Sort by space-filling curve (Morton order approximation)\n    sort(companies.begin(), companies.end(), [](const Company& a, const Company& b) {\n        // Interleave bits for Morton order\n        auto morton = [](int x, int y) -> long long {\n            long long result = 0;\n            for (int i = 0; i < 14; i++) {\n                result |= ((long long)(x & (1 << i)) << i);\n                result |= ((long long)(y & (1 << i)) << (i + 1));\n            }\n            return result;\n        };\n        return morton(a.x, a.y) < morton(b.x, b.y);\n    });\n    \n    // Partition space\n    Rect fullSpace = {0, 0, 10000, 10000};\n    partition(companies, 0, n, fullSpace);\n    \n    // Local optimization\n    optimize(companies);\n    \n    // Ensure all rectangles are valid and contain their points\n    for (int i = 0; i < n; i++) {\n        // Ensure minimum size\n        if (companies[i].c - companies[i].a < 1) {\n            companies[i].c = companies[i].a + 1;\n        }\n        if (companies[i].d - companies[i].b < 1) {\n            companies[i].d = companies[i].b + 1;\n        }\n        \n        // Ensure point is contained\n        if (!canPlace({companies[i].a, companies[i].b, companies[i].c, companies[i].d}, \n                      companies[i].x, companies[i].y)) {\n            // Adjust to contain point\n            companies[i].a = min(companies[i].a, companies[i].x);\n            companies[i].b = min(companies[i].b, companies[i].y);\n            companies[i].c = max(companies[i].c, companies[i].x + 1);\n            companies[i].d = max(companies[i].d, companies[i].y + 1);\n        }\n        \n        // Ensure bounds\n        companies[i].a = max(0, min(9999, companies[i].a));\n        companies[i].b = max(0, min(9999, companies[i].b));\n        companies[i].c = max(1, min(10000, companies[i].c));\n        companies[i].d = max(1, min(10000, companies[i].d));\n        \n        if (companies[i].a >= companies[i].c) companies[i].c = companies[i].a + 1;\n        if (companies[i].b >= companies[i].d) companies[i].d = companies[i].b + 1;\n    }\n    \n    // Output in original order\n    vector<tuple<int,int,int,int>> result(n);\n    for (const auto& comp : companies) {\n        result[comp.id] = {comp.a, comp.b, comp.c, comp.d};\n    }\n    \n    for (int i = 0; i < n; i++) {\n        auto [a, b, c, d] = result[i];\n        cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    int ci, cj;\n    int score;\n    string path;\n    vector<bool> tile_visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int si, sj;\n    cin >> si >> sj;\n    \n    vector<vector<int>> t(50, vector<int>(50));\n    int max_tile = 0;\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> t[i][j];\n            max_tile = max(max_tile, t[i][j]);\n        }\n    }\n    \n    vector<vector<int>> p(50, vector<int>(50));\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> p[i][j];\n        }\n    }\n    \n    // Directions: U, D, L, R\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    const char dc[] = {'U', 'D', 'L', 'R'};\n    \n    string best_path = \"\";\n    int best_score = 0;\n    \n    auto get_time = []() {\n        return chrono::duration<double>(chrono::steady_clock::now().time_since_epoch()).count();\n    };\n    \n    double start_time = get_time();\n    double time_limit = 1.95;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int strategy_count = 0;\n    \n    while (get_time() - start_time < time_limit) {\n        strategy_count++;\n        \n        // Vary strategy parameters\n        double greediness = 0.5 + 0.5 * sin(strategy_count * 0.1);\n        double exploration = 0.3 + 0.4 * ((double)rng() / rng.max());\n        int beam_width = 1 + (strategy_count % 5);\n        \n        vector<State> beam;\n        vector<bool> initial_visited(max_tile + 1, false);\n        initial_visited[t[si][sj]] = true;\n        beam.push_back({si, sj, p[si][sj], \"\", initial_visited});\n        \n        for (int step = 0; step < 2500 && get_time() - start_time < time_limit; step++) {\n            vector<State> next_beam;\n            \n            for (auto& state : beam) {\n                vector<tuple<int, int, int, int>> candidates; // {value, connectivity, randomness_score, direction}\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = state.ci + di[d];\n                    int nj = state.cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        int tile_id = t[ni][nj];\n                        if (!state.tile_visited[tile_id]) {\n                            // Calculate connectivity score (how many unvisited neighbors this tile has)\n                            int connectivity = 0;\n                            for (int d2 = 0; d2 < 4; d2++) {\n                                int nn_i = ni + di[d2];\n                                int nn_j = nj + dj[d2];\n                                if (nn_i >= 0 && nn_i < 50 && nn_j >= 0 && nn_j < 50) {\n                                    if (!state.tile_visited[t[nn_i][nn_j]]) {\n                                        connectivity++;\n                                    }\n                                }\n                            }\n                            \n                            int rand_score = rng() % 100;\n                            candidates.push_back({p[ni][nj], connectivity, rand_score, d});\n                        }\n                    }\n                }\n                \n                if (candidates.empty()) {\n                    if (state.score > best_score) {\n                        best_score = state.score;\n                        best_path = state.path;\n                    }\n                    continue;\n                }\n                \n                // Sort candidates by combined score\n                sort(candidates.begin(), candidates.end(), [greediness](const tuple<int,int,int,int>& a, const tuple<int,int,int,int>& b) {\n                    int score_a = (int)(get<0>(a) * greediness + get<1>(a) * (1 - greediness) * 0.5);\n                    int score_b = (int)(get<0>(b) * greediness + get<1>(b) * (1 - greediness) * 0.5);\n                    if (score_a != score_b) return score_a > score_b;\n                    return get<0>(a) > get<0>(b);\n                });\n                \n                // Select top candidates for beam\n                int select_count = min(beam_width, (int)candidates.size());\n                for (int i = 0; i < select_count; i++) {\n                    if ((double)rng() / rng.max() > exploration && i > 0) break;\n                    \n                    State new_state = state;\n                    int d = get<3>(candidates[i]);\n                    new_state.path += dc[d];\n                    new_state.ci += di[d];\n                    new_state.cj += dj[d];\n                    new_state.score += p[new_state.ci][new_state.cj];\n                    new_state.tile_visited[t[new_state.ci][new_state.cj]] = true;\n                    next_beam.push_back(new_state);\n                }\n            }\n            \n            if (next_beam.empty()) break;\n            \n            // Keep top states by score\n            sort(next_beam.begin(), next_beam.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(beam_width, (int)next_beam.size()); i++) {\n                beam.push_back(next_beam[i]);\n            }\n        }\n        \n        // Check final beam states\n        for (auto& state : beam) {\n            if (state.score > best_score) {\n                best_score = state.score;\n                best_path = state.path;\n            }\n        }\n        \n        // Occasionally try pure greedy for comparison\n        if (strategy_count % 20 == 0) {\n            vector<bool> tile_visited(max_tile + 1, false);\n            string path = \"\";\n            int ci = si, cj = sj;\n            int score = p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n            \n            while (get_time() - start_time < time_limit) {\n                pair<int, int> best_candidate = {-1, -1};\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = ci + di[d];\n                    int nj = cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        if (!tile_visited[t[ni][nj]]) {\n                            if (best_candidate.first == -1 || p[ni][nj] > best_candidate.first) {\n                                best_candidate = {p[ni][nj], d};\n                            }\n                        }\n                    }\n                }\n                \n                if (best_candidate.first == -1) break;\n                \n                int d = best_candidate.second;\n                path += dc[d];\n                ci += di[d];\n                cj += dj[d];\n                score += p[ci][cj];\n                tile_visited[t[ci][cj]] = true;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best_path = path;\n            }\n        }\n        \n        // Try randomized greedy with different seeds\n        if (strategy_count % 5 == 0) {\n            mt19937 local_rng(strategy_count * 1000 + rng());\n            vector<bool> tile_visited(max_tile + 1, false);\n            string path = \"\";\n            int ci = si, cj = sj;\n            int score = p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n            \n            double local_randomness = 0.1 + 0.6 * ((double)local_rng() / local_rng.max());\n            \n            while (get_time() - start_time < time_limit) {\n                vector<pair<int, int>> candidates;\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = ci + di[d];\n                    int nj = cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        if (!tile_visited[t[ni][nj]]) {\n                            candidates.push_back({p[ni][nj], d});\n                        }\n                    }\n                }\n                \n                if (candidates.empty()) break;\n                \n                sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n                    return a.first > b.first;\n                });\n                \n                int pick_idx = 0;\n                if (candidates.size() > 1 && (double)local_rng() / local_rng.max() < local_randomness) {\n                    pick_idx = local_rng() % min(3, (int)candidates.size());\n                }\n                \n                int d = candidates[pick_idx].second;\n                path += dc[d];\n                ci += di[d];\n                cj += dj[d];\n                score += p[ci][cj];\n                tile_visited[t[ci][cj]] = true;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best_path = path;\n            }\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <functional>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Edge weights\n// h_w[i][j] is weight between (i, j) and (i, j+1)\n// v_w[i][j] is weight between (i, j) and (i+1, j)\ndouble h_w[H][W-1];\ndouble v_w[H-1][W];\nint h_n[H][W-1];\nint v_n[H-1][W];\n\n// Initialize weights\nvoid init() {\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W-1; ++j) {\n            h_w[i][j] = 5000.0;\n            h_n[i][j] = 10; // Pseudo-count to stabilize early updates\n        }\n    }\n    for (int i = 0; i < H-1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_w[i][j] = 5000.0;\n            v_n[i][j] = 10;\n        }\n    }\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nstring dijkstra(int sr, int sc, int tr, int tc) {\n    // Dijkstra with UCB exploration bonus\n    // Static variable to keep track of total queries for UCB calculation\n    static int total_visits = 0;\n    total_visits++;\n    \n    vector<vector<double>> dist(H, vector<double>(W, 1e18));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> dir_from(H, vector<char>(W, 0));\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    \n    dist[sr][sc] = 0;\n    pq.push({0.0, sr, sc});\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char dchar[] = {'U', 'D', 'L', 'R'};\n    \n    double beta = 200.0; // Exploration parameter\n    \n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        \n        int r = top.r;\n        int c = top.c;\n        double d = top.dist;\n        \n        if (d > dist[r][c]) continue;\n        if (r == tr && c == tc) break;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                double weight = 0;\n                int n = 0;\n                \n                if (i == 0) { // U\n                    weight = v_w[r-1][c];\n                    n = v_n[r-1][c];\n                } else if (i == 1) { // D\n                    weight = v_w[r][c];\n                    n = v_n[r][c];\n                } else if (i == 2) { // L\n                    weight = h_w[r][c-1];\n                    n = h_n[r][c-1];\n                } else if (i == 3) { // R\n                    weight = h_w[r][c];\n                    n = h_n[r][c];\n                }\n                \n                // UCB bonus: subtract bonus to encourage exploring uncertain edges\n                double bonus = beta * sqrt(log(total_visits + 1) / (n + 1));\n                double cost = weight - bonus;\n                if (cost < 1.0) cost = 1.0; // Ensure positive cost for Dijkstra\n                \n                if (dist[r][c] + cost < dist[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + cost;\n                    parent[nr][nc] = {r, c};\n                    dir_from[nr][nc] = dchar[i];\n                    pq.push({dist[nr][nc], nr, nc});\n                }\n            }\n        }\n    }\n    \n    // Reconstruct path\n    string path = \"\";\n    int cr = tr, cc = tc;\n    while (cr != sr || cc != sc) {\n        char d = dir_from[cr][cc];\n        path += d;\n        int pr = parent[cr][cc].first;\n        int pc = parent[cr][cc].second;\n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid update_weights(const string& path, int sr, int sc, int observed_len) {\n    int cr = sr, cc = sc;\n    double est_len = 0;\n    \n    struct EdgeRef {\n        bool is_h;\n        int r, c;\n    };\n    vector<EdgeRef> path_edges;\n    \n    for (char d : path) {\n        int nr = cr, nc = cc;\n        if (d == 'U') { nr--; }\n        else if (d == 'D') { nr++; }\n        else if (d == 'L') { nc--; }\n        else if (d == 'R') { nc++; }\n        \n        double w = 0;\n        int n = 0;\n        bool is_h = false;\n        int r = 0, c = 0;\n        \n        if (d == 'U') {\n            w = v_w[cr-1][cc];\n            n = v_n[cr-1][cc];\n            is_h = false; r = cr-1; c = cc;\n        } else if (d == 'D') {\n            w = v_w[cr][cc];\n            n = v_n[cr][cc];\n            is_h = false; r = cr; c = cc;\n        } else if (d == 'L') {\n            w = h_w[cr][cc-1];\n            n = h_n[cr][cc-1];\n            is_h = true; r = cr; c = cc-1;\n        } else if (d == 'R') {\n            w = h_w[cr][cc];\n            n = h_n[cr][cc];\n            is_h = true; r = cr; c = cc;\n        }\n        \n        est_len += w;\n        path_edges.push_back({is_h, r, c});\n        \n        cr = nr;\n        cc = nc;\n    }\n    \n    if (path_edges.empty()) return;\n    \n    // Distribute error evenly among edges in the path\n    double error = observed_len - est_len;\n    double step = error / path_edges.size();\n    \n    for (auto& edge : path_edges) {\n        if (edge.is_h) {\n            int n = h_n[edge.r][edge.c];\n            double eta = 1.0 / (n + 1); // Decaying learning rate\n            h_w[edge.r][edge.c] += eta * step;\n            h_n[edge.r][edge.c]++;\n            // Clamp weights to valid range\n            if (h_w[edge.r][edge.c] < 1000) h_w[edge.r][edge.c] = 1000;\n            if (h_w[edge.r][edge.c] > 9000) h_w[edge.r][edge.c] = 9000;\n        } else {\n            int n = v_n[edge.r][edge.c];\n            double eta = 1.0 / (n + 1);\n            v_w[edge.r][edge.c] += eta * step;\n            v_n[edge.r][edge.c]++;\n            // Clamp weights to valid range\n            if (v_w[edge.r][edge.c] < 1000) v_w[edge.r][edge.c] = 1000;\n            if (v_w[edge.r][edge.c] > 9000) v_w[edge.r][edge.c] = 9000;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    init();\n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        string path = dijkstra(si, sj, ti, tj);\n        cout << path << \"\\n\" << flush;\n        \n        int observed;\n        cin >> observed;\n        \n        update_weights(path, si, sj, observed);\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPHABET = 8;\n\nint countMatches(const vector<string>& grid, const vector<string>& strings) {\n    int matches = 0;\n    for (const string& s : strings) {\n        bool found = false;\n        int len = s.length();\n        \n        // Check horizontal\n        for (int i = 0; i < N && !found; i++) {\n            for (int j = 0; j < N && !found; j++) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[i][(j + k) % N];\n                    if (c != '.' && c != s[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) found = true;\n            }\n        }\n        \n        // Check vertical\n        for (int i = 0; i < N && !found; i++) {\n            for (int j = 0; j < N && !found; j++) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[(i + k) % N][j];\n                    if (c != '.' && c != s[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) found = true;\n            }\n        }\n        \n        if (found) matches++;\n    }\n    return matches;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N_in, M;\n    cin >> N_in >> M;\n    \n    vector<string> strings(M);\n    for (int i = 0; i < M; i++) {\n        cin >> strings[i];\n    }\n    \n    // Initialize grid with '.'\n    vector<string> grid(N, string(N, '.'));\n    \n    // Sort strings by length (longer first - more constrained)\n    vector<pair<int, int>> indexed(M);\n    for (int i = 0; i < M; i++) {\n        indexed[i] = {-(int)strings[i].length(), i};\n    }\n    sort(indexed.begin(), indexed.end());\n    \n    // Greedy placement\n    for (auto& p : indexed) {\n        int idx = p.second;\n        const string& s = strings[idx];\n        int len = s.length();\n        \n        // Try all positions and orientations\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                // Try horizontal\n                bool canPlaceH = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[i][(j + k) % N];\n                    if (c != '.' && c != s[k]) {\n                        canPlaceH = false;\n                        break;\n                    }\n                }\n                if (canPlaceH) {\n                    for (int k = 0; k < len; k++) {\n                        grid[i][(j + k) % N] = s[k];\n                    }\n                    goto next_string;\n                }\n                \n                // Try vertical\n                bool canPlaceV = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[(i + k) % N][j];\n                    if (c != '.' && c != s[k]) {\n                        canPlaceV = false;\n                        break;\n                    }\n                }\n                if (canPlaceV) {\n                    for (int k = 0; k < len; k++) {\n                        grid[(i + k) % N][j] = s[k];\n                    }\n                    goto next_string;\n                }\n            }\n        }\n        next_string:;\n    }\n    \n    // Count initial matches\n    int matches = countMatches(grid, strings);\n    \n    // Simulated annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double temp = 100.0;\n    double cooling = 0.99995;\n    int iterations = 800000;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        char old = grid[i][j];\n        \n        // Choose new character\n        char newChar;\n        if (old == '.') {\n            newChar = 'A' + (rng() % ALPHABET);\n        } else {\n            if (rng() % 3 == 0) {\n                newChar = '.';\n            } else {\n                newChar = 'A' + (rng() % ALPHABET);\n            }\n        }\n        \n        if (newChar == old) continue;\n        \n        grid[i][j] = newChar;\n        int newMatches = countMatches(grid, strings);\n        \n        double delta = newMatches - matches;\n        \n        // Accept if better, or with probability based on temperature\n        if (delta > 0 || (delta == 0 && newChar != '.') || \n            exp(delta / temp) > (double)(rng() % 1000000) / 1000000.0) {\n            matches = newMatches;\n        } else {\n            grid[i][j] = old;\n        }\n        \n        temp *= cooling;\n    }\n    \n    // If all strings match, fill remaining '.' to maximize score\n    if (matches == M) {\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] = 'A' + (rng() % ALPHABET);\n                }\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << grid[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <set>\n\nusing namespace std;\n\n// Constants - Increased for safety\nconst int MAX_N = 70;\nconst int MAX_SEGMENTS = 5000;\nconst long long INF = 1e18;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<Point> road_squares;\nint segment_h[MAX_N][MAX_N];\nint segment_v[MAX_N][MAX_N];\nint num_h_segments = 0;\nint num_v_segments = 0;\nint total_road_squares = 0;\nint total_segments = 0;\n\nvector<Point> key_points;\nmap<Point, int> point_to_idx;\nint num_key_points = 0;\nint start_idx = -1;\n\n// APSP data - reduced size\nconst int MAX_KP = 250;\nlong long dist_mat[MAX_KP][MAX_KP];\nbitset<MAX_SEGMENTS> coverage_mat[MAX_KP][MAX_KP];\nvector<Point> path_mat[MAX_KP][MAX_KP];\n\n// Directions\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\n\nbool is_road(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N && grid[r][c] != '#';\n}\n\nint get_cost(int r, int c) {\n    return grid[r][c] - '0';\n}\n\nvoid identify_segments() {\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            segment_h[i][j] = -1;\n            segment_v[i][j] = -1;\n        }\n    }\n\n    // Horizontal segments\n    for(int i=0; i<N; ++i) {\n        int j = 0;\n        while(j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            int start_j = j;\n            while(j < N && grid[i][j] != '#') {\n                j++;\n            }\n            for(int k=start_j; k<j; ++k) {\n                segment_h[i][k] = num_h_segments;\n            }\n            num_h_segments++;\n        }\n    }\n\n    // Vertical segments\n    for(int j=0; j<N; ++j) {\n        int i = 0;\n        while(i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            int start_i = i;\n            while(i < N && grid[i][j] != '#') {\n                i++;\n            }\n            for(int k=start_i; k<i; ++k) {\n                segment_v[k][j] = num_v_segments;\n            }\n            num_v_segments++;\n        }\n    }\n    \n    total_segments = num_h_segments + num_v_segments;\n}\n\nvoid identify_key_points() {\n    set<Point> kp_set;\n    kp_set.insert({si, sj});\n\n    for(const auto& p : road_squares) {\n        int degree = 0;\n        for(int d=0; d<4; ++d) {\n            int nr = p.r + dr[d];\n            int nc = p.c + dc[d];\n            if(is_road(nr, nc)) degree++;\n        }\n        if(degree != 2) {\n            kp_set.insert(p);\n        }\n    }\n    \n    // Limit key points to avoid memory issues\n    if(kp_set.size() > MAX_KP - 10) {\n        // Keep start and most important points\n        vector<Point> sorted_kp(kp_set.begin(), kp_set.end());\n        // Sort by distance from start, keep closest\n        sort(sorted_kp.begin(), sorted_kp.end(), [&](const Point& a, const Point& b) {\n            return abs(a.r - si) + abs(a.c - sj) < abs(b.r - si) + abs(b.c - sj);\n        });\n        kp_set.clear();\n        for(int i=0; i<MAX_KP - 10 && i<(int)sorted_kp.size(); ++i) {\n            kp_set.insert(sorted_kp[i]);\n        }\n        kp_set.insert({si, sj});\n    }\n\n    for(const auto& p : kp_set) {\n        if(num_key_points >= MAX_KP) break;\n        point_to_idx[p] = num_key_points;\n        key_points.push_back(p);\n        if(p.r == si && p.c == sj) {\n            start_idx = num_key_points;\n        }\n        num_key_points++;\n    }\n}\n\nvoid compute_apsp() {\n    for(int i=0; i<num_key_points; ++i) {\n        for(int j=0; j<num_key_points; ++j) {\n            dist_mat[i][j] = INF;\n        }\n    }\n\n    // Static arrays to avoid reallocation\n    static long long d_grid[MAX_N][MAX_N];\n    static bitset<MAX_SEGMENTS> c_grid[MAX_N][MAX_N];\n    static Point parent_grid[MAX_N][MAX_N];\n    static bool visited[MAX_N][MAX_N];\n\n    for(int src_idx = 0; src_idx < num_key_points; ++src_idx) {\n        Point src = key_points[src_idx];\n        \n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                d_grid[i][j] = INF;\n                visited[i][j] = false;\n            }\n        }\n\n        priority_queue<pair<long long, Point>, vector<pair<long long, Point>>, greater<pair<long long, Point>>> pq;\n        \n        d_grid[src.r][src.c] = 0;\n        c_grid[src.r][src.c].reset();\n        if(segment_h[src.r][src.c] >= 0 && segment_h[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_h[src.r][src.c]);\n        if(segment_v[src.r][src.c] >= 0 && segment_v[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_v[src.r][src.c]);\n        \n        pq.push({0, src});\n        parent_grid[src.r][src.c] = {-1, -1};\n\n        int found_kp = 1; // Found start\n        \n        while(!pq.empty()) {\n            long long cost = pq.top().first;\n            Point u = pq.top().second;\n            pq.pop();\n\n            if(visited[u.r][u.c]) continue;\n            visited[u.r][u.c] = true;\n\n            if(point_to_idx.count(u)) {\n                int v_idx = point_to_idx[u];\n                dist_mat[src_idx][v_idx] = cost;\n                coverage_mat[src_idx][v_idx] = c_grid[u.r][u.c];\n                \n                // Reconstruct path\n                vector<Point> path;\n                Point curr = u;\n                while(curr.r != -1) {\n                    path.push_back(curr);\n                    if(curr.r == src.r && curr.c == src.c) break;\n                    curr = parent_grid[curr.r][curr.c];\n                }\n                reverse(path.begin(), path.end());\n                path_mat[src_idx][v_idx] = path;\n                found_kp++;\n            }\n            \n            if(found_kp >= num_key_points) break;\n\n            for(int d=0; d<4; ++d) {\n                int nr = u.r + dr[d];\n                int nc = u.c + dc[d];\n                if(is_road(nr, nc)) {\n                    long long new_cost = cost + get_cost(nr, nc);\n\n                    if(new_cost < d_grid[nr][nc]) {\n                        d_grid[nr][nc] = new_cost;\n                        c_grid[nr][nc] = c_grid[u.r][u.c];\n                        if(segment_h[nr][nc] >= 0 && segment_h[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_h[nr][nc]);\n                        if(segment_v[nr][nc] >= 0 && segment_v[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_v[nr][nc]);\n                        parent_grid[nr][nc] = u;\n                        pq.push({new_cost, {nr, nc}});\n                    }\n                }\n            }\n        }\n    }\n}\n\n// SA State\nvector<int> current_path;\nlong long current_dist = 0;\nbitset<MAX_SEGMENTS> current_cov;\nlong long best_dist = INF;\nvector<int> best_path;\nint best_coverage = 0;\n\nlong long calc_path_dist(const vector<int>& path) {\n    long long d = 0;\n    for(size_t i=0; i<path.size()-1; ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            d += dist_mat[path[i]][path[i+1]];\n    }\n    return d;\n}\n\nbitset<MAX_SEGMENTS> calc_path_cov(const vector<int>& path) {\n    bitset<MAX_SEGMENTS> c;\n    for(size_t i=0; i<path.size()-1; ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            c |= coverage_mat[path[i]][path[i+1]];\n    }\n    return c;\n}\n\nvoid update_state() {\n    current_dist = calc_path_dist(current_path);\n    current_cov = calc_path_cov(current_path);\n    best_coverage = current_cov.count();\n}\n\nlong long energy() {\n    int covered_segs = current_cov.count();\n    long long penalty = (long long)(total_segments - covered_segs) * 1000000LL;\n    return penalty + current_dist;\n}\n\nvoid solve_sa() {\n    current_path = {start_idx, start_idx};\n    update_state();\n    best_dist = current_dist;\n    best_path = current_path;\n    best_coverage = current_cov.count();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 2.5;\n\n    int iter = 0;\n    double temp = 5000.0;\n    double cooling = 0.999;\n\n    while(true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        // Early termination if we have full coverage and good solution\n        if(best_coverage >= total_segments && iter > 1000) {\n            double remaining = time_limit - elapsed;\n            if(remaining < 0.5) break;\n        }\n        \n        vector<int> next_path = current_path;\n        int type = rng() % 4;\n        \n        if(next_path.size() > 2) {\n            if(type == 0 && next_path.size() > 3) {\n                // 2-opt\n                int i = 1 + rng() % (next_path.size() - 2);\n                int j = i + 1 + rng() % (next_path.size() - 1 - i);\n                if(j >= (int)next_path.size() - 1) j = next_path.size() - 2;\n                reverse(next_path.begin() + i, next_path.begin() + j + 1);\n            } else if(type == 1 && next_path.size() > 3) {\n                // Swap\n                int i = 1 + rng() % (next_path.size() - 2);\n                int j = 1 + rng() % (next_path.size() - 2);\n                swap(next_path[i], next_path[j]);\n            } else if(type == 2) {\n                // Insert\n                int idx = 1 + rng() % (next_path.size());\n                int kp = rng() % num_key_points;\n                next_path.insert(next_path.begin() + idx, kp);\n            } else {\n                // Remove\n                if(next_path.size() > 3) {\n                    int idx = 1 + rng() % (next_path.size() - 2);\n                    next_path.erase(next_path.begin() + idx);\n                }\n            }\n        } else {\n            int kp = rng() % num_key_points;\n            next_path.insert(next_path.begin() + 1, kp);\n        }\n\n        next_path.front() = start_idx;\n        next_path.back() = start_idx;\n\n        // Quick distance check\n        long long next_dist = calc_path_dist(next_path);\n        if(next_dist >= INF) continue;\n        \n        bitset<MAX_SEGMENTS> next_cov = calc_path_cov(next_path);\n        int next_coverage = next_cov.count();\n\n        long long current_energy = energy();\n        long long next_penalty = (long long)(total_segments - next_coverage) * 1000000LL;\n        long long next_energy = next_penalty + next_dist;\n\n        double delta = (double)(next_energy - current_energy);\n        bool accept = false;\n        if(delta < 0) accept = true;\n        else {\n            double prob = exp(-delta / temp);\n            if((double)rng() / rng.max() < prob) accept = true;\n        }\n\n        if(accept) {\n            current_path = next_path;\n            current_dist = next_dist;\n            current_cov = next_cov;\n            \n            if(next_coverage >= total_segments) {\n                if(next_dist < best_dist) {\n                    best_dist = next_dist;\n                    best_path = current_path;\n                    best_coverage = next_coverage;\n                }\n            } else if(next_coverage > best_coverage) {\n                best_coverage = next_coverage;\n                best_path = current_path;\n                best_dist = next_dist;\n            }\n        }\n        \n        if(next_coverage >= total_segments && next_dist < best_dist) {\n            best_dist = next_dist;\n            best_path = next_path;\n            best_coverage = next_coverage;\n        }\n\n        temp *= cooling;\n        iter++;\n        \n        // Adaptive cooling\n        if(iter % 500 == 0) {\n            cooling = 0.9995;\n        }\n    }\n}\n\nvoid greedy_fix() {\n    bitset<MAX_SEGMENTS> cov;\n    for(size_t i=0; i<best_path.size()-1; ++i) {\n        if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n            cov |= coverage_mat[best_path[i]][best_path[i+1]];\n    }\n    \n    if(cov.count() >= total_segments) return;\n\n    // Try to insert points to cover missing segments\n    int fix_iter = 0;\n    while(cov.count() < total_segments && fix_iter < 50) {\n        // Find first missing segment\n        int missing_seg = -1;\n        for(int i=0; i<total_segments && i<MAX_SEGMENTS; ++i) {\n            if(!cov.test(i)) {\n                missing_seg = i;\n                break;\n            }\n        }\n        \n        if(missing_seg == -1) break;\n        \n        int best_kp = -1;\n        long long min_insert_cost = INF;\n        int best_pos = -1;\n\n        for(int kp=0; kp<num_key_points; ++kp) {\n            Point p = key_points[kp];\n            bool covers = false;\n            if(segment_h[p.r][p.c] == missing_seg) covers = true;\n            if(segment_v[p.r][p.c] == missing_seg) covers = true;\n            \n            if(covers) {\n                for(size_t i=0; i<best_path.size()-1; ++i) {\n                    int u = best_path[i];\n                    int v = best_path[i+1];\n                    if(u >= num_key_points || v >= num_key_points) continue;\n                    long long cost = dist_mat[u][kp] + dist_mat[kp][v] - dist_mat[u][v];\n                    if(cost < min_insert_cost) {\n                        min_insert_cost = cost;\n                        best_kp = kp;\n                        best_pos = i + 1;\n                    }\n                }\n            }\n        }\n        \n        if(best_kp != -1 && best_pos != -1) {\n            best_path.insert(best_path.begin() + best_pos, best_kp);\n            cov.reset();\n            for(size_t i=0; i<best_path.size()-1; ++i) {\n                if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n                    cov |= coverage_mat[best_path[i]][best_path[i+1]];\n            }\n        } else {\n            break;\n        }\n        fix_iter++;\n    }\n}\n\nvoid output_solution() {\n    string res = \"\";\n    Point curr = {si, sj};\n    for(size_t i=0; i<best_path.size()-1; ++i) {\n        int u = best_path[i];\n        int v = best_path[i+1];\n        if(u >= num_key_points || v >= num_key_points) continue;\n        const auto& segment = path_mat[u][v];\n        for(size_t k=1; k<segment.size(); ++k) {\n            Point next = segment[k];\n            if(next.r == curr.r + 1) res += 'D';\n            else if(next.r == curr.r - 1) res += 'U';\n            else if(next.c == curr.c + 1) res += 'R';\n            else if(next.c == curr.c - 1) res += 'L';\n            curr = next;\n        }\n    }\n    cout << res << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if(!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for(int i=0; i<N; ++i) {\n        cin >> grid[i];\n    }\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                total_road_squares++;\n            }\n        }\n    }\n\n    identify_segments();\n    identify_key_points();\n    compute_apsp();\n\n    solve_sa();\n    greedy_fix();\n    output_solution();\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <numeric>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    \n    // Read initial input\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    // Read task difficulties\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    // Read dependencies\n    vector<vector<int>> deps(N);\n    vector<vector<int>> rev_deps(N);\n    vector<int> in_degree(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        deps[v].push_back(u);\n        rev_deps[u].push_back(v);\n        in_degree[v]++;\n    }\n    \n    // Skill estimates (start with reasonable guess based on task difficulty distribution)\n    vector<vector<double>> s_est(M, vector<double>(K, 35.0));\n    vector<int> s_obs_count(M, 0);\n    \n    // Task status: -1 = not started, 0 = in progress, 1 = completed\n    vector<int> task_status(N, -1);\n    \n    // Member tracking\n    vector<int> member_task(M, -1);\n    vector<int> member_start_day(M, -1);\n    \n    // Observations for learning: (task_id, observed_days)\n    vector<vector<pair<int, int>>> member_obs(M);\n    \n    // Task priority (estimated remaining tasks in dependency chain)\n    vector<int> task_priority(N, 0);\n    \n    // Calculate task priorities using reverse topological order\n    for (int i = N - 1; i >= 0; i--) {\n        task_priority[i] = 1;\n        for (int next : rev_deps[i]) {\n            task_priority[i] = max(task_priority[i], task_priority[next] + 1);\n        }\n    }\n    \n    int day = 0;\n    int completed_count = 0;\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(42);\n    \n    while (true) {\n        day++;\n        \n        // Read completion information\n        int n_completed;\n        cin >> n_completed;\n        \n        if (n_completed == -1) {\n            break;\n        }\n        \n        vector<int> completed_members(n_completed);\n        for (int i = 0; i < n_completed; i++) {\n            cin >> completed_members[i];\n            completed_members[i]--;\n        }\n        \n        // Process completions and update skill estimates\n        for (int member : completed_members) {\n            if (member_task[member] >= 0) {\n                int task = member_task[member];\n                int days_taken = day - member_start_day[member];\n                \n                task_status[task] = 1;\n                completed_count++;\n                \n                // Record observation\n                member_obs[member].push_back({task, days_taken});\n                s_obs_count[member]++;\n                \n                // Update skill estimate using observed data\n                // w = sum(max(0, d_k - s_k)) \u2248 days_taken (when w > 0)\n                // We try to adjust s_k to reduce the gap\n                if (days_taken > 1 && s_obs_count[member] <= 50) {\n                    // Early learning phase - more aggressive updates\n                    double learning_rate = 0.3 / min(10, s_obs_count[member]);\n                    \n                    for (int k = 0; k < K; k++) {\n                        double deficit = max(0.0, (double)d[task][k] - s_est[member][k]);\n                        // If task took long, increase skill estimate for skills where there was deficit\n                        if (deficit > 0) {\n                            s_est[member][k] += learning_rate * deficit * 0.5;\n                        }\n                        // Cap skill estimates reasonably\n                        s_est[member][k] = min(80.0, max(5.0, s_est[member][k]));\n                    }\n                }\n                \n                member_task[member] = -1;\n                member_start_day[member] = -1;\n            }\n        }\n        \n        // Check if all tasks completed\n        if (completed_count >= N) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Find ready tasks (all dependencies completed, not started)\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == -1) {\n                bool all_deps_done = true;\n                for (int dep : deps[i]) {\n                    if (task_status[dep] != 1) {\n                        all_deps_done = false;\n                        break;\n                    }\n                }\n                if (all_deps_done) {\n                    ready_tasks.push_back(i);\n                }\n            }\n        }\n        \n        // Find idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n        \n        if (idle_members.empty() || ready_tasks.empty()) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Calculate estimated completion time for each (member, task) pair\n        vector<vector<double>> est_time(M, vector<double>(N, 1e9));\n        for (int member : idle_members) {\n            for (int task : ready_tasks) {\n                double w = 0;\n                for (int k = 0; k < K; k++) {\n                    w += max(0.0, (double)d[task][k] - s_est[member][k]);\n                }\n                est_time[member][task] = (w == 0) ? 1.0 : max(1.0, w);\n            }\n        }\n        \n        // Greedy assignment: match tasks to members minimizing estimated time\n        // Prioritize high-priority tasks and good skill matches\n        vector<pair<int, int>> assignments;\n        vector<bool> task_assigned(ready_tasks.size(), false);\n        vector<bool> member_used(idle_members.size(), false);\n        \n        // Create assignment candidates with scores\n        vector<tuple<double, int, int, int>> candidates; // (score, priority, member_idx, task_idx)\n        for (size_t mi = 0; mi < idle_members.size(); mi++) {\n            for (size_t ti = 0; ti < ready_tasks.size(); ti++) {\n                int member = idle_members[mi];\n                int task = ready_tasks[ti];\n                double score = est_time[member][task] - task_priority[task] * 0.1;\n                candidates.push_back({score, task_priority[task], (int)mi, (int)ti});\n            }\n        }\n        \n        // Sort by score (lower is better)\n        sort(candidates.begin(), candidates.end());\n        \n        // Assign greedily\n        for (auto& [score, priority, mi, ti] : candidates) {\n            if (member_used[mi] || task_assigned[ti]) continue;\n            \n            int member = idle_members[mi];\n            int task = ready_tasks[ti];\n            \n            assignments.push_back({member + 1, task + 1});\n            member_used[mi] = true;\n            task_assigned[ti] = true;\n            \n            member_task[member] = task;\n            member_start_day[member] = day;\n            task_status[task] = 0;\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n        \n        // Output skill predictions for visualization (optional)\n        if (day % 50 == 1) {\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 << endl;\n            }\n            cout.flush();\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <random>\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n    int order_id; // -1 for office, order index for pickup/delivery\n    bool is_pickup;\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    const int OFFICE_X = 400, OFFICE_Y = 400;\n    const int NUM_ORDERS = 1000;\n    const int SELECT_COUNT = 50;\n    \n    // Read input\n    vector<Order> orders(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n    }\n    \n    mt19937 rng(42);\n    \n    // Score each order for selection\n    // Lower score = better (closer to office, shorter pickup-delivery)\n    vector<pair<double, int>> order_scores;\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n        int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n        int return_dist = manhattan(orders[i].cx, orders[i].cy, OFFICE_X, OFFICE_Y);\n        // Weight pickup-delivery distance more heavily\n        double score = pickup_dist + 2.0 * delivery_dist + return_dist;\n        // Add some randomness for diversity\n        score += uniform_real_distribution<double>(0, 50)(rng);\n        order_scores.push_back({score, i});\n    }\n    \n    // Select 50 orders with best scores\n    sort(order_scores.begin(), order_scores.end());\n    vector<int> selected;\n    vector<bool> is_selected(NUM_ORDERS, false);\n    for (int i = 0; i < SELECT_COUNT; i++) {\n        selected.push_back(order_scores[i].second);\n        is_selected[order_scores[i].second] = true;\n    }\n    \n    // Build initial route: office -> pickups (sorted by angle) -> deliveries (sorted by angle) -> office\n    auto get_angle = [&](int x, int y) {\n        return atan2(y - OFFICE_Y, x - OFFICE_X);\n    };\n    \n    vector<pair<double, int>> pickups, deliveries;\n    for (int idx : selected) {\n        pickups.push_back({get_angle(orders[idx].ax, orders[idx].ay), idx});\n        deliveries.push_back({get_angle(orders[idx].cx, orders[idx].cy), idx});\n    }\n    sort(pickups.begin(), pickups.end());\n    sort(deliveries.begin(), deliveries.end());\n    \n    vector<Point> route;\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    for (auto& p : pickups) {\n        int idx = p.second;\n        route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n    }\n    for (auto& p : deliveries) {\n        int idx = p.second;\n        route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n    }\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    // Calculate total distance\n    auto calc_distance = [&]() -> long long {\n        long long 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    // Check if route is valid (pickup before delivery for each order)\n    auto is_valid_route = [&]() -> bool {\n        vector<bool> picked(SELECT_COUNT, false);\n        map<int, int> order_to_pos;\n        for (int i = 0; i < SELECT_COUNT; i++) {\n            order_to_pos[selected[i]] = i;\n        }\n        \n        for (size_t i = 0; i < route.size(); i++) {\n            if (route[i].order_id == -1) continue;\n            int order_pos = order_to_pos[route[i].order_id];\n            if (route[i].is_pickup) {\n                picked[order_pos] = true;\n            } else {\n                if (!picked[order_pos]) return false;\n            }\n        }\n        return true;\n    };\n    \n    // Simulated Annealing for route optimization\n    long long best_distance = calc_distance();\n    vector<Point> best_route = route;\n    \n    double temperature = 10000.0;\n    double cooling_rate = 0.9995;\n    int iterations = 0;\n    const int MAX_ITERATIONS = 150000;\n    \n    auto try_swap = [&](int i, int j) -> bool {\n        if (i >= route.size() - 1 || j >= route.size() - 1) return false;\n        if (i == 0 || j == 0 || i == (int)route.size() - 1 || j == (int)route.size() - 1) return false;\n        if (route[i].order_id == -1 || route[j].order_id == -1) return false;\n        \n        // Check if swap violates precedence\n        vector<Point> new_route = route;\n        swap(new_route[i], new_route[j]);\n        \n        // Validate new route\n        vector<bool> picked(NUM_ORDERS, false);\n        for (size_t k = 0; k < new_route.size(); k++) {\n            if (new_route[k].order_id == -1) continue;\n            if (new_route[k].is_pickup) {\n                picked[new_route[k].order_id] = true;\n            } else {\n                if (!picked[new_route[k].order_id]) return false;\n            }\n        }\n        return true;\n    };\n    \n    while (iterations < MAX_ITERATIONS && temperature > 0.1) {\n        iterations++;\n        \n        // Try 2-opt move\n        int i = uniform_int_distribution<int>(1, route.size() - 3)(rng);\n        int j = uniform_int_distribution<int>(i + 1, route.size() - 2)(rng);\n        \n        vector<Point> new_route = route;\n        reverse(new_route.begin() + i, new_route.begin() + j + 1);\n        \n        // Validate new route\n        bool valid = true;\n        vector<bool> picked(NUM_ORDERS, false);\n        for (size_t k = 0; k < new_route.size(); k++) {\n            if (new_route[k].order_id == -1) continue;\n            if (new_route[k].is_pickup) {\n                picked[new_route[k].order_id] = true;\n            } else {\n                if (!picked[new_route[k].order_id]) {\n                    valid = false;\n                    break;\n                }\n            }\n        }\n        \n        if (valid) {\n            long long new_distance = 0;\n            for (size_t k = 0; k + 1 < new_route.size(); k++) {\n                new_distance += manhattan(new_route[k].x, new_route[k].y, new_route[k+1].x, new_route[k+1].y);\n            }\n            \n            double delta = new_distance - best_distance;\n            if (delta < 0 || exp(-delta / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                route = new_route;\n                if (new_distance < best_distance) {\n                    best_distance = new_distance;\n                    best_route = route;\n                }\n            }\n        }\n        \n        // Try relocating a pickup-delivery pair\n        if (uniform_int_distribution<int>(0, 9)(rng) < 3) {\n            int order_idx = uniform_int_distribution<int>(0, SELECT_COUNT - 1)(rng);\n            int order_id = selected[order_idx];\n            \n            // Find positions of pickup and delivery\n            int pickup_pos = -1, delivery_pos = -1;\n            for (size_t k = 0; k < route.size(); k++) {\n                if (route[k].order_id == order_id) {\n                    if (route[k].is_pickup) pickup_pos = k;\n                    else delivery_pos = k;\n                }\n            }\n            \n            if (pickup_pos > 0 && delivery_pos < (int)route.size() - 1) {\n                // Try moving the pair to a new position\n                int new_pos = uniform_int_distribution<int>(1, route.size() - 2)(rng);\n                if (new_pos != pickup_pos && new_pos != delivery_pos) {\n                    vector<Point> new_route2;\n                    vector<Point> pair_points;\n                    pair_points.push_back(route[pickup_pos]);\n                    pair_points.push_back(route[delivery_pos]);\n                    \n                    for (size_t k = 0; k < route.size(); k++) {\n                        if (k == (size_t)pickup_pos || k == (size_t)delivery_pos) continue;\n                        if (k == (size_t)new_pos) {\n                            new_route2.push_back(pair_points[0]);\n                            new_route2.push_back(pair_points[1]);\n                        }\n                        new_route2.push_back(route[k]);\n                    }\n                    if (new_pos >= (int)route.size() - 2) {\n                        new_route2.push_back(pair_points[0]);\n                        new_route2.push_back(pair_points[1]);\n                    }\n                    \n                    // Validate\n                    bool valid2 = true;\n                    vector<bool> picked2(NUM_ORDERS, false);\n                    for (size_t k = 0; k < new_route2.size(); k++) {\n                        if (new_route2[k].order_id == -1) continue;\n                        if (new_route2[k].is_pickup) {\n                            picked2[new_route2[k].order_id] = true;\n                        } else {\n                            if (!picked2[new_route2[k].order_id]) {\n                                valid2 = false;\n                                break;\n                            }\n                        }\n                    }\n                    \n                    if (valid2 && new_route2.size() == route.size()) {\n                        long long new_distance2 = 0;\n                        for (size_t k = 0; k + 1 < new_route2.size(); k++) {\n                            new_distance2 += manhattan(new_route2[k].x, new_route2[k].y, new_route2[k+1].x, new_route2[k+1].y);\n                        }\n                        \n                        if (new_distance2 < best_distance) {\n                            route = new_route2;\n                            best_distance = new_distance2;\n                            best_route = route;\n                        } else if (exp(-(new_distance2 - best_distance) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                            route = new_route2;\n                        }\n                    }\n                }\n            }\n        }\n        \n        temperature *= cooling_rate;\n    }\n    \n    // Try order swapping (replace selected orders with better ones)\n    for (int swap_iter = 0; swap_iter < 100; swap_iter++) {\n        int remove_idx = uniform_int_distribution<int>(0, SELECT_COUNT - 1)(rng);\n        int remove_order = selected[remove_idx];\n        \n        // Find a better unselected order\n        vector<pair<double, int>> candidates;\n        for (int i = 0; i < NUM_ORDERS; i++) {\n            if (!is_selected[i]) {\n                int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n                int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n                double score = pickup_dist + 2.0 * delivery_dist;\n                candidates.push_back({score, i});\n            }\n        }\n        sort(candidates.begin(), candidates.end());\n        \n        for (int try_idx = 0; try_idx < min(10, (int)candidates.size()); try_idx++) {\n            int add_order = candidates[try_idx].second;\n            \n            // Try swapping\n            vector<int> new_selected = selected;\n            new_selected[remove_idx] = add_order;\n            is_selected[remove_order] = false;\n            is_selected[add_order] = true;\n            \n            // Rebuild route\n            vector<pair<double, int>> new_pickups, new_deliveries;\n            for (int idx : new_selected) {\n                new_pickups.push_back({get_angle(orders[idx].ax, orders[idx].ay), idx});\n                new_deliveries.push_back({get_angle(orders[idx].cx, orders[idx].cy), idx});\n            }\n            sort(new_pickups.begin(), new_pickups.end());\n            sort(new_deliveries.begin(), new_deliveries.end());\n            \n            vector<Point> new_route;\n            new_route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n            for (auto& p : new_pickups) {\n                int idx = p.second;\n                new_route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n            }\n            for (auto& p : new_deliveries) {\n                int idx = p.second;\n                new_route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n            }\n            new_route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n            \n            long long new_dist = 0;\n            for (size_t k = 0; k + 1 < new_route.size(); k++) {\n                new_dist += manhattan(new_route[k].x, new_route[k].y, new_route[k+1].x, new_route[k+1].y);\n            }\n            \n            if (new_dist < best_distance) {\n                selected = new_selected;\n                route = new_route;\n                best_distance = new_dist;\n                best_route = route;\n                break;\n            } else {\n                is_selected[remove_order] = true;\n                is_selected[add_order] = false;\n            }\n        }\n    }\n    \n    // Final route optimization with lower temperature\n    route = best_route;\n    temperature = 1000.0;\n    cooling_rate = 0.999;\n    iterations = 0;\n    const int FINAL_ITERATIONS = 50000;\n    \n    while (iterations < FINAL_ITERATIONS && temperature > 0.1) {\n        iterations++;\n        \n        int i = uniform_int_distribution<int>(1, route.size() - 3)(rng);\n        int j = uniform_int_distribution<int>(i + 1, route.size() - 2)(rng);\n        \n        vector<Point> new_route = route;\n        reverse(new_route.begin() + i, new_route.begin() + j + 1);\n        \n        bool valid = true;\n        vector<bool> picked(NUM_ORDERS, false);\n        for (size_t k = 0; k < new_route.size(); k++) {\n            if (new_route[k].order_id == -1) continue;\n            if (new_route[k].is_pickup) {\n                picked[new_route[k].order_id] = true;\n            } else {\n                if (!picked[new_route[k].order_id]) {\n                    valid = false;\n                    break;\n                }\n            }\n        }\n        \n        if (valid) {\n            long long new_distance = 0;\n            for (size_t k = 0; k + 1 < new_route.size(); k++) {\n                new_distance += manhattan(new_route[k].x, new_route[k].y, new_route[k+1].x, new_route[k+1].y);\n            }\n            \n            if (new_distance < best_distance) {\n                route = new_route;\n                best_distance = new_distance;\n                best_route = route;\n            } else if (exp(-(new_distance - best_distance) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                route = new_route;\n            }\n        }\n        \n        temperature *= cooling_rate;\n    }\n    \n    // Output\n    cout << SELECT_COUNT;\n    for (int idx : selected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << endl;\n    \n    cout << best_route.size();\n    for (auto& p : best_route) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\n// Union-Find data structure for tracking connected components\nstruct UnionFind {\n    vector<int> parent;\n    vector<int> rank;\n    int components;\n    \n    UnionFind(int n) : parent(n), rank(n, 0), components(n) {\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]);  // Path compression\n        }\n        return parent[x];\n    }\n    \n    bool unite(int x, int y) {\n        int px = find(x);\n        int py = find(y);\n        if (px == py) return false;\n        \n        // Union by rank\n        if (rank[px] < rank[py]) swap(px, py);\n        parent[py] = px;\n        if (rank[px] == rank[py]) rank[px]++;\n        components--;\n        return true;\n    }\n    \n    bool same(int x, int y) {\n        return find(x) == find(y);\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 edge endpoints\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    \n    UnionFind uf(N);\n    int edges_selected = 0;\n    \n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first;\n        int v = edges[i].second;\n        \n        // Compute expected distance d_i from coordinates\n        double dx = coords[u].first - coords[v].first;\n        double dy = coords[u].second - coords[v].second;\n        double d = round(sqrt(dx * dx + dy * dy));\n        \n        // Check if edge connects different components\n        bool different_components = !uf.same(u, v);\n        \n        bool accept = false;\n        \n        if (different_components) {\n            // Base threshold for inter-component edges\n            // Expected value is 2*d, so 2.4*d is reasonably selective\n            double threshold = 2.4 * d;\n            \n            // Calculate urgency based on remaining edges and components\n            int components_left = uf.components;\n            int edges_left = M - i;\n            int needed = components_left - 1;  // Edges needed to connect all\n            \n            // Urgency ratio: how critical is it to accept edges now?\n            double urgency = (double)needed / max(1, edges_left);\n            \n            // Adjust threshold based on urgency\n            if (urgency > 0.4) {\n                // High urgency: accept almost any inter-component edge\n                threshold = 3.0 * d;\n            } else if (urgency > 0.25) {\n                // Medium-high urgency\n                threshold = 2.7 * d;\n            } else if (urgency > 0.15) {\n                // Medium urgency\n                threshold = 2.5 * d;\n            } else if (urgency > 0.08) {\n                // Low urgency\n                threshold = 2.4 * d;\n            }\n            \n            // If we've selected many edges already, be more selective\n            // Target is N-1 = 399 edges for a tree\n            if (edges_selected > N - 1 + 100) {\n                threshold = 2.2 * d;\n            } else if (edges_selected > N - 1 + 50) {\n                threshold = 2.3 * d;\n            }\n            \n            if (l <= threshold) {\n                accept = true;\n            }\n        } else {\n            // For intra-component edges, only accept if very cheap\n            // These might replace more expensive edges in our spanning tree\n            // Threshold is lower since these are less valuable\n            if (l < d * 1.3) {\n                accept = true;\n            }\n        }\n        \n        // Emergency mode: force connectivity near the end\n        // Last 150 edges: be very aggressive about connecting components\n        if (i >= M - 150 && uf.components > 1 && different_components) {\n            accept = true;\n        }\n        \n        // Final emergency: last 50 edges, must connect if possible\n        if (i >= M - 50 && uf.components > 1 && different_components) {\n            accept = true;\n        }\n        \n        if (accept) {\n            cout << 1 << \"\\n\";\n            uf.unite(u, v);\n            edges_selected++;\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        \n        cout.flush();  // Critical: flush after each output\n    }\n    \n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <cstring>\n\nusing namespace std;\n\n// Structure to represent a position\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\n// Global variables\nint N, M;\nvector<Pos> pets;\nvector<int> pet_types;\nvector<Pos> humans;\nbool walls[32][32]; // Global wall state\nint pet_sum[32][32]; // Prefix sum of pet positions\n\n// Target zone\nint target_r1, target_r2, target_c1, target_c2;\nbool zone_locked = false; // If true, don't search for new zone for a while\nint turns_since_rezone = 0;\n\n// Check bounds\nbool in_grid(int r, int c) {\n    return r >= 0 && r < 30 && c >= 0 && c < 30;\n}\n\n// Update prefix sum of pet positions\nvoid update_pet_sum() {\n    int grid[32][32] = {0};\n    for(const auto& p : pets) {\n        if (in_grid(p.r, p.c)) {\n            grid[p.r][p.c]++;\n        }\n    }\n    // Compute 2D prefix sum\n    memset(pet_sum, 0, sizeof(pet_sum));\n    for(int i=0; i<30; ++i) {\n        for(int j=0; j<30; ++j) {\n            pet_sum[i+1][j+1] = grid[i][j] + pet_sum[i][j+1] + pet_sum[i+1][j] - pet_sum[i][j];\n        }\n    }\n}\n\n// Count pets in rectangle [r1, r2] x [c1, c2] (0-based inclusive)\nint count_pets(int r1, int c1, int r2, int c2) {\n    if (r1 > r2 || c1 > c2) return 0;\n    r1 = max(0, r1); c1 = max(0, c1);\n    r2 = min(29, r2); c2 = min(29, c2);\n    return pet_sum[r2+1][c2+1] - pet_sum[r1][c2+1] - pet_sum[r2+1][c1] + pet_sum[r1][c1];\n}\n\n// Evaluate a zone\nint evaluate_zone(int r1, int r2, int c1, int c2) {\n    if (r1 > r2 || c1 > c2) return -2000000;\n    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n    \n    // Critical: No pets inside\n    if (count_pets(r1, c1, r2, c2) > 0) {\n        return -1000000; \n    }\n    \n    // Penalty for pets adjacent to perimeter\n    int pets_adjacent = 0;\n    for(const auto& p : pets) {\n        int closest_r = max(r1, min(r2, p.r));\n        int closest_c = max(c1, min(c2, p.c));\n        int dist = abs(p.r - closest_r) + abs(p.c - closest_c);\n        if (dist == 1) {\n            pets_adjacent++;\n        }\n    }\n    \n    return area - pets_adjacent * 10;\n}\n\nvoid find_best_zone() {\n    int best_score = -2000000;\n    int best_r1 = 5, best_r2 = 24, best_c1 = 5, best_c2 = 24;\n    \n    for (int r1 = 0; r1 < 30; ++r1) {\n        for (int r2 = r1; r2 < 30; ++r2) {\n            for (int c1 = 0; c1 < 30; ++c1) {\n                for (int c2 = c1; c2 < 30; ++c2) {\n                    int score = evaluate_zone(r1, r2, c1, c2);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1;\n                        best_r2 = r2;\n                        best_c1 = c1;\n                        best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n    \n    target_r1 = best_r1;\n    target_r2 = best_r2;\n    target_c1 = best_c1;\n    target_c2 = best_c2;\n    \n    if (best_score > -500000) {\n        zone_locked = true;\n        turns_since_rezone = 0;\n    } else {\n        zone_locked = false;\n    }\n}\n\n// Get perimeter cells of the target zone\nvector<Pos> get_perimeter() {\n    vector<Pos> cells;\n    for (int c = target_c1; c <= target_c2; ++c) {\n        cells.push_back({target_r1, c});\n        if (target_r2 != target_r1) cells.push_back({target_r2, c});\n    }\n    for (int r = target_r1 + 1; r < target_r2; ++r) {\n        cells.push_back({r, target_c1});\n        if (target_c2 != target_c1) cells.push_back({r, target_c2});\n    }\n    return cells;\n}\n\n// Check if building at (r, c) is safe\nbool can_build(int r, int c, const vector<Pos>& current_humans) {\n    if (!in_grid(r, c)) return false;\n    if (walls[r][c]) return false; // Already a wall\n    \n    // Check if any human is at this position\n    for (const auto& h : current_humans) {\n        if (h.r == r && h.c == c) {\n            return false;\n        }\n    }\n    \n    // Check if any pet is at this position\n    for (const auto& p : pets) {\n        if (p.r == r && p.c == c) {\n            return false;\n        }\n    }\n    \n    // Check adjacency to pets (cannot build adjacent to pets)\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    for (const auto& p : pets) {\n        for (int k = 0; k < 4; ++k) {\n            if (p.r + dr[k] == r && p.c + dc[k] == c) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// BFS for human movement avoiding walls\nPos get_next_move(Pos start, Pos target, const bool grid[32][32]) {\n    if (start == target) return start;\n    \n    queue<Pos> q;\n    q.push(start);\n    int dist[32][32];\n    Pos parent[32][32];\n    for(int i=0; i<32; ++i) for(int j=0; j<32; ++j) {\n        dist[i][j] = -1;\n        parent[i][j] = {-1, -1};\n    }\n    \n    dist[start.r][start.c] = 0;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    \n    while(!q.empty()){\n        Pos cur = q.front(); q.pop();\n        if (cur == target) break;\n        \n        for(int k=0; k<4; ++k){\n            int nr = cur.r + dr[k];\n            int nc = cur.c + dc[k];\n            if(in_grid(nr, nc) && !grid[nr][nc] && dist[nr][nc] == -1){\n                dist[nr][nc] = dist[cur.r][cur.c] + 1;\n                parent[nr][nc] = cur;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if (dist[target.r][target.c] == -1) return start;\n    \n    Pos curr = target;\n    while(parent[curr.r][curr.c] != start){\n        curr = parent[curr.r][curr.c];\n        if (curr.r == -1) return start;\n    }\n    return curr;\n}\n\nchar get_action_char(Pos from, Pos to) {\n    if (from == to) return '.';\n    if (to.r < from.r) return 'U';\n    if (to.r > from.r) return 'D';\n    if (to.c < from.c) return 'L';\n    if (to.c > from.c) return 'R';\n    return '.';\n}\n\nchar get_build_char(Pos from, Pos wall_pos) {\n    if (wall_pos.r < from.r) return 'u';\n    if (wall_pos.r > from.r) return 'd';\n    if (wall_pos.c < from.c) return 'l';\n    if (wall_pos.c > from.c) return 'r';\n    return '.';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N)) return 0;\n    pets.resize(N);\n    pet_types.resize(N);\n    for(int i=0; i<N; ++i){\n        cin >> pets[i].r >> pets[i].c >> pet_types[i];\n        pets[i].r--; pets[i].c--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for(int i=0; i<M; ++i){\n        cin >> humans[i].r >> humans[i].c;\n        humans[i].r--; humans[i].c--;\n    }\n    \n    memset(walls, 0, sizeof(walls));\n    \n    update_pet_sum();\n    find_best_zone();\n    \n    vector<Pos> perimeter = get_perimeter();\n    \n    for(int turn=0; turn<300; ++turn){\n        if (turn > 0) {\n            for(int i=0; i<N; ++i){\n                string s;\n                cin >> s;\n                if (s == \".\") continue;\n                for(char c : s){\n                    if (c == 'U') pets[i].r--;\n                    else if (c == 'D') pets[i].r++;\n                    else if (c == 'L') pets[i].c--;\n                    else if (c == 'R') pets[i].c++;\n                }\n            }\n            update_pet_sum();\n        }\n        \n        bool need_rezone = false;\n        if (!zone_locked) {\n            turns_since_rezone++;\n            if (turns_since_rezone >= 50) need_rezone = true;\n        }\n        \n        if (count_pets(target_r1, target_c1, target_r2, target_c2) > 0) {\n            need_rezone = true;\n            zone_locked = false;\n        }\n        \n        if (need_rezone) {\n            find_best_zone();\n            perimeter = get_perimeter();\n            turns_since_rezone = 0;\n        }\n        \n        bool temp_walls[32][32];\n        memcpy(temp_walls, walls, sizeof(walls));\n        \n        vector<char> human_actions(M, '.');\n        vector<Pos> next_human_pos(M);\n        vector<Pos> old_humans = humans;\n        \n        // Identify buildable segments (check against current human positions)\n        vector<int> buildable_indices;\n        for(size_t i=0; i<perimeter.size(); ++i){\n            if (!walls[perimeter[i].r][perimeter[i].c]) {\n                if (can_build(perimeter[i].r, perimeter[i].c, humans)) {\n                    buildable_indices.push_back(i);\n                }\n            }\n        }\n        \n        vector<bool> segment_taken(perimeter.size(), false);\n        vector<bool> human_assigned_build(M, false);\n        \n        for(int i=0; i<M; ++i){\n            int best_seg = -1;\n            int min_dist = 10000;\n            \n            for(int idx : buildable_indices){\n                if (segment_taken[idx]) continue;\n                int d = abs(humans[i].r - perimeter[idx].r) + abs(humans[i].c - perimeter[idx].c);\n                if (d < min_dist) {\n                    min_dist = d;\n                    best_seg = idx;\n                }\n            }\n            \n            Pos target;\n            if (best_seg != -1) {\n                segment_taken[best_seg] = true;\n                human_assigned_build[i] = true;\n                target = perimeter[best_seg];\n                \n                int dist = abs(humans[i].r - target.r) + abs(humans[i].c - target.c);\n                if (dist == 1) {\n                    // Re-check can_build with temp_walls and updated human positions\n                    // (other humans might move to this position this turn)\n                    bool can_build_now = true;\n                    if (temp_walls[target.r][target.c]) can_build_now = false;\n                    \n                    // Check if any OTHER human will be at this position\n                    for(int j=0; j<M; ++j){\n                        if (i == j) continue;\n                        // Check if human j is already there or will move there\n                        if (humans[j].r == target.r && humans[j].c == target.c) {\n                            can_build_now = false;\n                            break;\n                        }\n                    }\n                    \n                    // Check pet adjacency again\n                    if (can_build_now) {\n                        int dr[] = {-1, 1, 0, 0};\n                        int dc[] = {0, 0, -1, 1};\n                        for (const auto& p : pets) {\n                            for (int k = 0; k < 4; ++k) {\n                                if (p.r + dr[k] == target.r && p.c + dc[k] == target.c) {\n                                    can_build_now = false;\n                                    break;\n                                }\n                            }\n                            if (!can_build_now) break;\n                        }\n                    }\n                    \n                    if (can_build_now) {\n                        human_actions[i] = get_build_char(humans[i], target);\n                        temp_walls[target.r][target.c] = true;\n                        next_human_pos[i] = humans[i]; // Stay\n                    } else {\n                        // Cannot build, move closer or wait\n                        Pos next = get_next_move(humans[i], target, temp_walls);\n                        human_actions[i] = get_action_char(humans[i], next);\n                        next_human_pos[i] = next;\n                    }\n                } else {\n                    Pos next = get_next_move(humans[i], target, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                }\n            } else {\n                // No buildable segments available\n                bool all_built = true;\n                for(const auto& p : perimeter) {\n                    if (!walls[p.r][p.c]) {\n                        all_built = false;\n                        break;\n                    }\n                }\n                \n                if (all_built) {\n                    Pos center = {(target_r1 + target_r2)/2, (target_c1 + target_c2)/2};\n                    Pos next = get_next_move(humans[i], center, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                } else {\n                    // Wait for buildable segments to become available\n                    human_actions[i] = '.';\n                    next_human_pos[i] = humans[i];\n                }\n            }\n        }\n        \n        // Output\n        string out = \"\";\n        for(int i=0; i<M; ++i) out += human_actions[i];\n        cout << out << endl;\n        \n        // Update state\n        for(int i=0; i<M; ++i){\n            humans[i] = next_human_pos[i];\n            char act = human_actions[i];\n            if (act == 'u') walls[old_humans[i].r - 1][old_humans[i].c] = true;\n            else if (act == 'd') walls[old_humans[i].r + 1][old_humans[i].c] = true;\n            else if (act == 'l') walls[old_humans[i].r][old_humans[i].c - 1] = true;\n            else if (act == 'r') walls[old_humans[i].r][old_humans[i].c + 1] = true;\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <cstring>\n#include <iomanip>\n\nusing namespace std;\n\n// Global variables\nint SI, SJ, TI, TJ;\ndouble P;\nvector<string> H; // 20 x 19\nvector<string> V; // 19 x 20\n\n// Directions: U, D, L, R\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIRS[4] = {'U', 'D', 'L', 'R'};\n\n// Grid helpers\ninline int get_idx(int r, int c) { return r * 20 + c; }\ninline int get_r(int idx) { return idx / 20; }\ninline int get_c(int idx) { return idx % 20; }\n\ninline bool is_wall(int r, int c, int dir) {\n    int nr = r + DI[dir];\n    int nc = c + DJ[dir];\n    if (nr < 0 || nr >= 20 || nc < 0 || nc >= 20) return true;\n    if (dir == 0) { // U\n        if (r == 0) return true;\n        return V[r-1][c] == '1';\n    } else if (dir == 1) { // D\n        if (r == 19) return true;\n        return V[r][c] == '1';\n    } else if (dir == 2) { // L\n        if (c == 0) return true;\n        return H[r][c-1] == '1';\n    } else if (dir == 3) { // R\n        if (c == 19) return true;\n        return H[r][c] == '1';\n    }\n    return true;\n}\n\n// DP State\n// dp[t][idx] = probability of being at cell idx at time t (without having reached target before)\n// We treat target as absorbing, but we track probability mass entering target separately for score.\n// Actually, to simplify score calculation with the formula derived:\n// Score = sum_{t=1}^{199} D[t] + 201 * D[200]\n// where D[t] = cumulative prob of reaching target by time t.\n// In DP, we can just let the target cell accumulate probability.\n// dp[t][target_idx] will store D[t].\n// Other cells store prob of being there without having reached target.\n// Wait, if target is absorbing, once mass enters target, it stays there.\n// So dp[t][target_idx] = dp[t-1][target_idx] + (mass entering from neighbors).\n// This matches D[t] definition.\n// So we can use a single DP table where target cell is absorbing.\n\ndouble dp[201][400];\nvector<int> active[201];\ndouble D[201]; // Cumulative prob at target\nstring S;\nint L = 200;\nint TARGET_IDX;\n\n// Pre-allocated buffers for simulation\ndouble next_dp[400];\nvector<int> next_active;\nbool visited[400];\nint visited_token[400];\nint token = 0;\n\nvoid compute_dp_from(int k, const string& current_S, double* out_D_suffix, double* out_final_D) {\n    // We assume dp[k] and active[k] are already set in global cache.\n    // We simulate from k to L.\n    // We use temporary storage for dp values to avoid corrupting cache until accepted.\n    // However, to save memory alloc, we can use a separate buffer for the simulation range.\n    // But since we need to compare score, we just need the D values.\n    // We don't necessarily need to store all dp[t] for t > k, just the current step.\n    // But to commit later, we need them.\n    // For evaluation, we just compute D[t] on the fly.\n    \n    // Copy start state\n    // We will use a local buffer for dp values of current step.\n    // Since active list is small, we can just iterate active[k].\n    \n    // We need to store the resulting D values to calculate score.\n    // And if accepted, we need to update the global dp and active arrays.\n    // To avoid allocating new arrays every time, we can use a static buffer for the 'new' path DP.\n    // But the 'new' path DP depends on the specific mutation.\n    // Let's use a static buffer `sim_dp[201][400]`? Too big to copy often?\n    // Actually, we only need to store the result if we accept.\n    // So during evaluation, we just compute D[t] values and sum them up.\n    // We don't need to store the full distribution unless we accept.\n    // If we accept, THEN we recompute and update the global cache.\n    // This saves memory bandwidth on rejected moves.\n    // Recomputing is cheap compared to memory copy if active list is small.\n    \n    // So:\n    // 1. Load state at k from global cache.\n    // 2. Simulate forward, computing D[t] for t=k+1 to L.\n    // 3. Calculate score.\n    // 4. If accept, re-run simulation and update global cache.\n    \n    // State at k\n    // dp[k][...] is in global. active[k] is in global.\n    \n    double current_D = D[k];\n    double score_suffix = 0.0;\n    \n    // Buffers for simulation\n    // We need two rows of dp: current and next.\n    // But we need to handle active list.\n    // Let's use `sim_dp` map? No, array is faster.\n    // Since we don't store full history, just `curr_dp` and `next_dp`.\n    // But we need to know which cells are active.\n    \n    // Reuse global next_dp and next_active? \n    // Careful with thread safety (not an issue here) and overwriting.\n    // Since this is single threaded, we can use global temp buffers.\n    \n    // Initialize sim state from k\n    // We need to copy dp[k] to a working buffer.\n    // To avoid copying 400 doubles, we only copy active cells.\n    // We can use a map or just a dense array since 400 is small.\n    // Let's use a dense array `work_dp` initialized to 0, and fill active cells.\n    \n    static double work_dp[400];\n    static double next_work_dp[400];\n    static int work_active[400];\n    static int next_work_active[400];\n    static int work_token[400];\n    static int work_token_val = 0;\n    \n    work_token_val++;\n    int w_count = 0;\n    \n    // Load active cells from k\n    for (int idx : active[k]) {\n        double val = dp[k][idx];\n        if (val > 1e-15) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = current_D;\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = current_S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        int nw_count = 0;\n        // Clear next_work_dp for active cells of next step?\n        // We use token system for next_work_dp too?\n        // Or just memset 0? 400 doubles is 3.2KB. Memset is fast.\n        // But we only touch active cells.\n        // Let's use token for next_work_dp as well.\n        // Actually, simpler: just iterate work_active, compute contributions, \n        // and mark next_work_active.\n        // We need to clear next_work_dp values for the new active cells.\n        // We can do this when we add to next_work_active.\n        \n        // To handle clearing efficiently:\n        // We can store the list of indices we modified in next_work_dp and clear them at end of step?\n        // Or use a generation token for next_work_dp.\n        static int next_work_token[400];\n        static int next_work_token_val = 0;\n        next_work_token_val++;\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = get_r(idx);\n            int c = get_c(idx);\n            \n            bool wall = is_wall(r, c, dir_idx);\n            \n            if (wall) {\n                // Stay\n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob;\n            } else {\n                int nr = r + DI[dir_idx];\n                int nc = c + DJ[dir_idx];\n                int nidx = get_idx(nr, nc);\n                \n                // Stay (forget)\n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob * P;\n                \n                // Move\n                if (nidx == TARGET_IDX) {\n                    sim_D += prob * (1.0 - P);\n                } else {\n                    if (next_work_token[nidx] != next_work_token_val) {\n                        next_work_token[nidx] = next_work_token_val;\n                        next_work_dp[nidx] = 0.0;\n                        next_work_active[nw_count++] = nidx;\n                    }\n                    next_work_dp[nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        // Update D for step t+1\n        // D[t+1] = sim_D\n        // Score contribution for t+1:\n        // We need D[t+1] for the formula.\n        // Formula: Score = sum_{j=1}^{199} D[j] + 201 * D[200]\n        // We are computing D[k+1]...D[L].\n        // We need to add to score_suffix.\n        // Note: D[k] is already accounted for in prefix score.\n        // So we add contribution of D[t+1].\n        \n        double D_next = sim_D;\n        if (t + 1 < L) {\n            score_suffix += D_next;\n        } else {\n            score_suffix += 201.0 * D_next;\n        }\n        \n        // Swap buffers\n        w_count = nw_count;\n        for(int i=0; i<w_count; ++i) {\n            int idx = next_work_active[i];\n            work_dp[idx] = next_work_dp[idx];\n            work_active[i] = idx;\n            work_token[idx] = work_token_val; // Mark as valid in work_dp\n        }\n    }\n    \n    *out_D_suffix = score_suffix;\n    *out_final_D = sim_D;\n}\n\nvoid update_cache_from(int k) {\n    // Recompute DP from k and update global cache\n    // Similar to compute_dp_from but writes to global dp and active\n    \n    // Load state at k (already in global)\n    double current_D = D[k];\n    \n    // We need work buffers again\n    static double work_dp[400];\n    static int work_active[400];\n    static int work_token[400];\n    static int work_token_val = 0;\n    work_token_val++;\n    \n    int w_count = 0;\n    for (int idx : active[k]) {\n        double val = dp[k][idx];\n        if (val > 1e-15) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = current_D;\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        // Prepare next step global arrays\n        active[t+1].clear();\n        // We need to clear dp[t+1] for relevant cells. \n        // Since we iterate active[t+1] to clear later or use token?\n        // Let's just fill dp[t+1] as we go. But we need to ensure it's 0 initially.\n        // Since we only access cells in active[t+1], we can just set them.\n        // But we might add to same cell multiple times.\n        // So we need to know if it's the first time we touch it in this step.\n        // Use a token array for global dp? Or just memset 0 for 400 doubles?\n        // Memset 3.2KB is very fast. Let's do that for simplicity.\n        // Wait, 200 steps * memset = 200 * 3KB = 600KB bandwidth. Negligible.\n        // But we do this every accepted move.\n        // If accepted moves are frequent, this adds up.\n        // Let's use token for global dp update too.\n        static int global_next_token[400];\n        static int global_next_token_val = 0;\n        global_next_token_val++;\n        \n        int next_count = 0;\n        double next_D = sim_D;\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = get_r(idx);\n            int c = get_c(idx);\n            \n            bool wall = is_wall(r, c, dir_idx);\n            \n            if (wall) {\n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active[t+1].push_back(idx);\n                }\n                dp[t+1][idx] += prob;\n            } else {\n                int nr = r + DI[dir_idx];\n                int nc = c + DJ[dir_idx];\n                int nidx = get_idx(nr, nc);\n                \n                // Stay\n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active[t+1].push_back(idx);\n                }\n                dp[t+1][idx] += prob * P;\n                \n                // Move\n                if (nidx == TARGET_IDX) {\n                    next_D += prob * (1.0 - P);\n                } else {\n                    if (global_next_token[nidx] != global_next_token_val) {\n                        global_next_token[nidx] = global_next_token_val;\n                        dp[t+1][nidx] = 0.0;\n                        active[t+1].push_back(nidx);\n                    }\n                    dp[t+1][nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        sim_D = next_D;\n        D[t+1] = sim_D;\n        \n        // Prepare for next iteration\n        w_count = 0;\n        for (int idx : active[t+1]) {\n            work_dp[idx] = dp[t+1][idx];\n            work_active[w_count++] = idx;\n            work_token[idx] = work_token_val;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> SI >> SJ >> TI >> TJ >> P)) return 0;\n    \n    H.resize(20);\n    for (int i = 0; i < 20; ++i) cin >> H[i];\n    V.resize(19);\n    for (int i = 0; i < 19; ++i) cin >> V[i];\n    \n    TARGET_IDX = get_idx(TI, TJ);\n    \n    // BFS for shortest path\n    vector<int> dist(400, -1);\n    vector<int> parent(400, -1);\n    vector<int> parent_dir(400, -1);\n    queue<int> q;\n    \n    int start_idx = get_idx(SI, SJ);\n    dist[start_idx] = 0;\n    q.push(start_idx);\n    \n    while(!q.empty()){\n        int idx = q.front(); q.pop();\n        if(idx == TARGET_IDX) break;\n        int r = get_r(idx), c = get_c(idx);\n        for(int d=0; d<4; ++d){\n            if(!is_wall(r, c, d)){\n                int nr = r + DI[d], nc = c + DJ[d];\n                int nidx = get_idx(nr, nc);\n                if(dist[nidx] == -1){\n                    dist[nidx] = dist[idx] + 1;\n                    parent[nidx] = idx;\n                    parent_dir[nidx] = d;\n                    q.push(nidx);\n                }\n            }\n        }\n    }\n    \n    // Construct initial path\n    string path = \"\";\n    if(dist[TARGET_IDX] != -1){\n        int curr = TARGET_IDX;\n        while(curr != start_idx){\n            path += DIRS[parent_dir[curr]];\n            curr = parent[curr];\n        }\n        reverse(path.begin(), path.end());\n    } else {\n        path = \"D\"; // Fallback\n    }\n    \n    S = \"\";\n    while(S.length() < L) S += path;\n    if(S.length() > L) S = S.substr(0, L);\n    \n    // Initial DP Compute\n    // Clear dp\n    for(int t=0; t<=L; ++t) {\n        // We only clear active cells to save time? \n        // But initially we don't know active cells.\n        // Just memset 0 for dp[0] and others will be filled.\n        // Actually, we can just rely on active lists to access dp.\n        // But dp array is global, so it might have garbage from previous runs (not in this case).\n        // Let's assume 0 initialized (global).\n        // But we need to clear for safety if run locally multiple times? \n        // In contest, one run per process. Global is 0.\n    }\n    \n    dp[0][start_idx] = 1.0;\n    active[0].push_back(start_idx);\n    D[0] = 0.0;\n    \n    // Run full DP\n    // Reuse update_cache_from logic but from 0\n    // But update_cache_from uses S.\n    // So just call update_cache_from(0).\n    // Wait, update_cache_from assumes dp[k] and active[k] are set.\n    // They are set for k=0.\n    update_cache_from(0);\n    \n    double current_score = 0.0;\n    for(int t=1; t<L; ++t) current_score += D[t];\n    current_score += 201.0 * D[L];\n    \n    double best_score = current_score;\n    string best_S = S;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9;\n    \n    double temp = 100.0;\n    double cooling = 0.99995;\n    \n    int iter = 0;\n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        // Pick random k\n        int k = uniform_int_distribution<int>(0, L-1)(rng);\n        int old_dir = 0;\n        if(S[k] == 'U') old_dir = 0;\n        else if(S[k] == 'D') old_dir = 1;\n        else if(S[k] == 'L') old_dir = 2;\n        else if(S[k] == 'R') old_dir = 3;\n        \n        int new_dir = uniform_int_distribution<int>(0, 3)(rng);\n        // Ensure change\n        if(new_dir == old_dir) new_dir = (new_dir + 1) % 4;\n        \n        char new_char = DIRS[new_dir];\n        \n        // Evaluate\n        S[k] = new_char;\n        double new_suffix_score, new_final_D;\n        compute_dp_from(k, S, &new_suffix_score, &new_final_D);\n        \n        // Calculate prefix score\n        // Score = sum_{t=1}^{k} D[t] + (adjustment for D[k] if k < L) + suffix\n        // Wait, the formula is sum_{t=1}^{L-1} D[t] + 201 D[L].\n        // The prefix part sum_{t=1}^{k} D[t] is unchanged because D[t] for t<=k depends only on S[0...t-1].\n        // Since we changed S[k], D[k+1] changes. D[k] is unchanged.\n        // So prefix score up to k is constant.\n        // We need to calculate sum_{t=1}^{k} D[t].\n        // We can maintain this sum or recompute. Recomputing k terms is fast (k < 200).\n        double prefix_score = 0.0;\n        for(int t=1; t<=k; ++t) {\n            if(t < L) prefix_score += D[t];\n            else prefix_score += 201.0 * D[t]; // Should not happen as k < L\n        }\n        // Wait, if k = L-1, then D[L] is in suffix.\n        // The formula splits at L-1.\n        // Sum_{t=1}^{L-1} D[t] + 201 D[L].\n        // If k < L-1:\n        // Prefix: sum_{t=1}^{k} D[t].\n        // Suffix should cover t=k+1 to L.\n        // Suffix logic in compute_dp_from:\n        // It adds D[t+1] for t from k to L-1.\n        // i.e. D[k+1] ... D[L].\n        // Coeff for D[t] where t < L is 1. Coeff for D[L] is 201.\n        // My compute_dp_from implements:\n        // if (t+1 < L) score += D_next; else score += 201 * D_next;\n        // This is correct.\n        // So Total Score = Prefix (sum_{t=1}^k D[t]) + Suffix.\n        // Note: D[k] is included in Prefix.\n        \n        double new_total_score = prefix_score + new_suffix_score;\n        \n        double delta = new_total_score - current_score;\n        \n        if(delta > 0 || exp(delta / temp) > uniform_real_distribution<double>(0, 1)(rng)){\n            current_score = new_total_score;\n            // Commit changes to cache\n            // We need to update D[t] for t > k as well.\n            // compute_dp_from didn't store them globally.\n            // So we must call update_cache_from(k).\n            // But update_cache_from uses S. S is already updated.\n            update_cache_from(k);\n            \n            if(current_score > best_score){\n                best_score = current_score;\n                best_S = S;\n            }\n        } else {\n            S[k] = DIRS[old_dir]; // Revert\n        }\n        \n        temp *= cooling;\n        iter++;\n    }\n    \n    cout << best_S << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entry_direction] = exit_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\n// -1 means cannot enter from that direction\nconst int to_table[8][4] = {\n    {1, 0, -1, -1},  // tile 0\n    {3, -1, -1, 0},  // tile 1\n    {-1, -1, 3, 2},  // tile 2\n    {-1, 2, 1, -1},  // tile 3\n    {1, 0, 3, 2},    // tile 4\n    {3, 2, 1, 0},    // tile 5\n    {2, -1, 0, -1},  // tile 6\n    {-1, 3, -1, 1},  // tile 7\n};\n\nconst int di[4] = {0, -1, 0, 1};  // left, up, right, down\nconst int dj[4] = {-1, 0, 1, 0};\n\nint tiles[N][N];\nint rotation[N][N];\nint best_rotation[N][N];\n\n// Get effective tile type after rotation\ninline int get_tile(int i, int j) {\n    return (tiles[i][j] + rotation[i][j]) % 8;\n}\n\n// Trace a loop starting from position (si, sj) with entry direction sd\n// Returns the length of the loop, or 0 if not a valid loop\nint trace_loop(int si, int sj, int sd) {\n    int i = si, j = sj, d = sd;\n    int length = 0;\n    const int max_len = N * N * 4 + 10;\n    \n    do {\n        int tile = get_tile(i, j);\n        int d2 = to_table[tile][d];\n        \n        if (d2 == -1) return 0;\n        \n        i += di[d2];\n        j += dj[d2];\n        \n        if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n        \n        d = (d2 + 2) % 4;\n        length++;\n        \n        if (length > max_len) return 0;\n        \n    } while (!(i == si && j == sj && d == sd));\n    \n    return length;\n}\n\n// Find all loops and return the two longest lengths\npair<int, int> find_two_longest_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    \n    int max1 = 0, max2 = 0;\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                if (!visited[i][j][d]) {\n                    int len = trace_loop(i, j, d);\n                    \n                    if (len > 0) {\n                        // Mark all states in this loop as visited\n                        int ci = i, cj = j, cd = d;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2];\n                            cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == i && cj == j && cd == d));\n                        \n                        if (len > max1) {\n                            max2 = max1;\n                            max1 = len;\n                        } else if (len > max2) {\n                            max2 = len;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    return {max1, max2};\n}\n\n// Calculate score\nlong long calculate_score() {\n    auto [l1, l2] = find_two_longest_loops();\n    return (long long)l1 * l2;\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        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            tiles[i][j] = s[j] - '0';\n            rotation[i][j] = 0;\n        }\n    }\n    \n    // Initialize with random rotations\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            rotation[i][j] = uniform_int_distribution<>(0, 3)(rng);\n        }\n    }\n    \n    long long best_score = calculate_score();\n    memcpy(best_rotation, rotation, sizeof(rotation));\n    \n    long long current_score = best_score;\n    \n    // Simulated annealing\n    double temperature = 10000.0;\n    double cooling_rate = 0.99995;\n    int iterations = 0;\n    int max_iterations = 2000000;\n    int no_improve_count = 0;\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    while (iterations < max_iterations && temperature > 0.001) {\n        // Check time limit (leave some margin)\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.8) break;\n        \n        // Pick random tile\n        int i = uniform_int_distribution<>(0, N-1)(rng);\n        int j = uniform_int_distribution<>(0, N-1)(rng);\n        \n        // Try changing rotation\n        int old_rot = rotation[i][j];\n        int new_rot = (old_rot + uniform_int_distribution<>(1, 3)(rng)) % 4;\n        rotation[i][j] = new_rot;\n        \n        long long new_score = calculate_score();\n        \n        // Accept or reject using Metropolis criterion\n        double delta = (double)(new_score - current_score);\n        bool accept = false;\n        \n        if (delta > 0) {\n            accept = true;\n        } else if (temperature > 0.001) {\n            double prob = exp(delta / temperature);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n                no_improve_count = 0;\n            } else {\n                no_improve_count++;\n            }\n        } else {\n            rotation[i][j] = old_rot;  // revert\n        }\n        \n        // Adaptive cooling: cool faster if no improvement\n        if (no_improve_count > 10000) {\n            cooling_rate = 0.9999;\n        }\n        \n        temperature *= cooling_rate;\n        iterations++;\n        \n        // Periodic restart if stuck\n        if (no_improve_count > 50000 && temperature < 1.0) {\n            temperature = 100.0;\n            no_improve_count = 0;\n            // Randomize some tiles\n            for (int k = 0; k < 100; k++) {\n                int ri = uniform_int_distribution<>(0, N-1)(rng);\n                int rj = uniform_int_distribution<>(0, N-1)(rng);\n                rotation[ri][rj] = uniform_int_distribution<>(0, 3)(rng);\n            }\n            current_score = calculate_score();\n        }\n    }\n    \n    // Output best rotation\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << best_rotation[i][j];\n        }\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nvector<string> board;\nint empty_r, empty_c;\nstring moves = \"\";\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nchar int_to_hex(int v) {\n    if (v < 10) return '0' + v;\n    return 'a' + (v - 10);\n}\n\nint get_tile(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N) return -1;\n    if (board[r][c] == '0') return 0;\n    return hex_to_int(board[r][c]);\n}\n\nbool has_connection(int tile_val, int d) {\n    if (tile_val == 0) return false;\n    const int mask[] = {2, 8, 1, 4};\n    return (tile_val & mask[d]) != 0;\n}\n\nbool tiles_connect(int r1, int c1, int r2, int c2) {\n    int t1 = get_tile(r1, c1);\n    int t2 = get_tile(r2, c2);\n    if (t1 == 0 || t2 == 0) return false;\n    \n    if (r2 == r1 + 1) return has_connection(t1, 1) && has_connection(t2, 0);\n    if (r2 == r1 - 1) return has_connection(t1, 0) && has_connection(t2, 1);\n    if (c2 == c1 + 1) return has_connection(t1, 3) && has_connection(t2, 2);\n    if (c2 == c1 - 1) return has_connection(t1, 2) && has_connection(t2, 3);\n    return false;\n}\n\nvoid make_move(int d) {\n    int nr = empty_r + dr[d];\n    int nc = empty_c + dc[d];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return;\n    if ((int)moves.size() >= T - 5) return;\n    \n    swap(board[empty_r][empty_c], board[nr][nc]);\n    empty_r = nr;\n    empty_c = nc;\n    moves += dir_char[d];\n}\n\n// BFS to find shortest path for empty square\nvector<int> find_path_to(int start_r, int start_c, int target_r, int target_c) {\n    if (start_r == target_r && start_c == target_c) return {};\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parent_dir(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({start_r, start_c});\n    visited[start_r][start_c] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                parent[nr][nc] = {r, c};\n                parent_dir[nr][nc] = d;\n                q.push({nr, nc});\n                \n                if (nr == target_r && nc == target_c) {\n                    vector<int> path;\n                    int cr = target_r, cc = target_c;\n                    while (cr != start_r || cc != start_c) {\n                        path.push_back(parent_dir[cr][cc]);\n                        int pr = parent[cr][cc].first;\n                        int pc = parent[cr][cc].second;\n                        cr = pr;\n                        cc = pc;\n                    }\n                    reverse(path.begin(), path.end());\n                    return path;\n                }\n            }\n        }\n    }\n    return {};\n}\n\nvoid move_empty_to(int target_r, int target_c) {\n    while (empty_r != target_r || empty_c != target_c) {\n        if ((int)moves.size() >= T - 10) break;\n        \n        vector<int> path = find_path_to(empty_r, empty_c, target_r, target_c);\n        if (path.empty()) break;\n        \n        for (int d : path) {\n            if ((int)moves.size() >= T - 5) break;\n            make_move(d);\n        }\n    }\n}\n\n// Move a tile from (tile_r, tile_c) to (target_r, target_c)\nvoid move_tile_to(int tile_r, int tile_c, int target_r, int target_c) {\n    while (tile_r != target_r || tile_c != target_c) {\n        if ((int)moves.size() >= T - 20) break;\n        \n        int desired_empty_r, desired_empty_c, move_d;\n        \n        if (tile_r < target_r) {\n            desired_empty_r = tile_r + 1;\n            desired_empty_c = tile_c;\n            move_d = 0;\n        } else if (tile_r > target_r) {\n            desired_empty_r = tile_r - 1;\n            desired_empty_c = tile_c;\n            move_d = 1;\n        } else if (tile_c < target_c) {\n            desired_empty_r = tile_r;\n            desired_empty_c = tile_c + 1;\n            move_d = 2;\n        } else {\n            desired_empty_r = tile_r;\n            desired_empty_c = tile_c - 1;\n            move_d = 3;\n        }\n        \n        if (desired_empty_r < 0 || desired_empty_r >= N || \n            desired_empty_c < 0 || desired_empty_c >= N) break;\n        \n        move_empty_to(desired_empty_r, desired_empty_c);\n        \n        if (empty_r == desired_empty_r && empty_c == desired_empty_c) {\n            make_move(move_d);\n            if (move_d == 0) tile_r++;\n            else if (move_d == 1) tile_r--;\n            else if (move_d == 2) tile_c++;\n            else if (move_d == 3) tile_c--;\n        } else {\n            break;\n        }\n    }\n}\n\nint calculate_tree_size() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int max_size = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0' || visited[i][j]) continue;\n            \n            int size = 0;\n            queue<pair<int,int>> q;\n            q.push({i, j});\n            visited[i][j] = true;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front();\n                q.pop();\n                size++;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && \n                        !visited[nr][nc] && board[nr][nc] != '0') {\n                        if (tiles_connect(r, c, nr, nc)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n            }\n            max_size = max(max_size, size);\n        }\n    }\n    return max_size;\n}\n\nstruct TileInfo {\n    int value;\n    int r, c;\n    int id;\n};\n\n// Check compatibility between two tiles in specific directions\nint compatibility(int t1_val, int t2_val, int d) {\n    // d: direction from t1 to t2 (0=up, 1=down, 2=left, 3=right)\n    const int opp[] = {1, 0, 3, 2};\n    bool c1 = has_connection(t1_val, d);\n    bool c2 = has_connection(t2_val, opp[d]);\n    if (c1 && c2) return 2;\n    if (c1 || c2) return -1;\n    return 0;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    \n    vector<TileInfo> tiles;\n    int tile_id = 0;\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            } else {\n                tiles.push_back({hex_to_int(board[i][j]), i, j, tile_id++});\n            }\n        }\n    }\n    \n    int total_tiles = N * N - 1;\n    \n    // Create target grid positions (snake pattern, empty at bottom-right)\n    vector<pair<int,int>> targets;\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)) targets.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (!(i == N-1 && j == N-1)) targets.push_back({i, j});\n            }\n        }\n    }\n    \n    // Build adjacency graph based on tile compatibility\n    vector<vector<int>> compat(total_tiles, vector<int>(total_tiles, 0));\n    for (int i = 0; i < total_tiles; i++) {\n        for (int j = 0; j < total_tiles; j++) {\n            if (i == j) continue;\n            int score = 0;\n            score += compatibility(tiles[i].value, tiles[j].value, 1); // i above j\n            score += compatibility(tiles[i].value, tiles[j].value, 3); // i left of j\n            compat[i][j] = score;\n        }\n    }\n    \n    // Greedy assignment: place tiles trying to maximize connections\n    vector<int> assignment(total_tiles, -1); // assignment[target_idx] = tile_idx\n    vector<bool> tile_used(total_tiles, false);\n    \n    for (int ti = 0; ti < total_tiles; ti++) {\n        int best_tile = -1;\n        int best_score = -1e9;\n        \n        for (int tidx = 0; tidx < total_tiles; tidx++) {\n            if (tile_used[tidx]) continue;\n            \n            int score = 0;\n            int tr = targets[ti].first;\n            int tc = targets[ti].second;\n            \n            // Check compatibility with already placed neighbors\n            for (int d = 0; d < 4; d++) {\n                int pr = tr + dr[d];\n                int pc = tc + dc[d];\n                if (pr >= 0 && pr < N && pc >= 0 && pc < N && !(pr == N-1 && pc == N-1)) {\n                    // Find which target index this is\n                    int neighbor_target = -1;\n                    for (int nt = 0; nt < ti; nt++) {\n                        if (targets[nt].first == pr && targets[nt].second == pc) {\n                            neighbor_target = nt;\n                            break;\n                        }\n                    }\n                    if (neighbor_target >= 0 && assignment[neighbor_target] >= 0) {\n                        int neighbor_tile = assignment[neighbor_target];\n                        int opp = (d == 0) ? 1 : (d == 1) ? 0 : (d == 2) ? 3 : 2;\n                        if (has_connection(tiles[tidx].value, d) && \n                            has_connection(tiles[neighbor_tile].value, opp)) {\n                            score += 10;\n                        }\n                    }\n                }\n            }\n            \n            // Prefer tiles closer to target\n            int dist = abs(tiles[tidx].r - tr) + abs(tiles[tidx].c - tc);\n            score -= dist / 2;\n            \n            // Prefer tiles with more connections\n            int connections = __builtin_popcount(tiles[tidx].value);\n            score += connections;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_tile = tidx;\n            }\n        }\n        \n        if (best_tile >= 0) {\n            assignment[ti] = best_tile;\n            tile_used[best_tile] = true;\n        }\n    }\n    \n    // Execute the placement\n    for (int ti = 0; ti < total_tiles; ti++) {\n        if ((int)moves.size() >= T - 50) break;\n        if (assignment[ti] < 0) continue;\n        \n        int tidx = assignment[ti];\n        int tr = targets[ti].first;\n        int tc = targets[ti].second;\n        \n        // Find current position of this tile\n        int tile_val = tiles[tidx].value;\n        int cur_r = -1, cur_c = -1;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (get_tile(i, j) == tile_val) {\n                    cur_r = i;\n                    cur_c = j;\n                    break;\n                }\n            }\n            if (cur_r >= 0) break;\n        }\n        \n        if (cur_r < 0) continue;\n        \n        move_tile_to(cur_r, cur_c, tr, tc);\n    }\n    \n    // Local optimization: try to improve connections with swaps\n    int initial_tree_size = calculate_tree_size();\n    \n    if (initial_tree_size < total_tiles && (int)moves.size() < T - 100) {\n        // Try swapping adjacent tiles to improve connectivity\n        for (int iter = 0; iter < 50 && (int)moves.size() < T - 100; iter++) {\n            int best_improvement = 0;\n            int best_swap_r1 = -1, best_swap_c1 = -1;\n            int best_swap_r2 = -1, best_swap_c2 = -1;\n            \n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (board[i][j] == '0') continue;\n                    for (int d = 0; d < 4; d++) {\n                        int ni = i + dr[d];\n                        int nj = j + dc[d];\n                        if (ni >= 0 && ni < N && nj >= 0 && nj < N && board[ni][nj] != '0') {\n                            // Try swapping these two tiles\n                            // This is complex, skip for now\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Move empty to corner\n    move_empty_to(N-1, N-1);\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\nstruct Strawberry {\n    int id;\n    long long x, y;\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> lines;\n\nconst long long COORD_MIN = -1000000000LL;\nconst long long COORD_MAX = 1000000000LL;\n\n// Clamp coordinate to valid range\nlong long clampCoord(long long v) {\n    if (v < COORD_MIN) return COORD_MIN;\n    if (v > COORD_MAX) return COORD_MAX;\n    return v;\n}\n\n// Check which side of line a point is on\n// Returns: 1 if left, -1 if right, 0 if on line\nint sideOfLine(const Line& l, long long x, long long y) {\n    __int128 dx1 = (__int128)l.qx - l.px;\n    __int128 dy1 = (__int128)l.qy - l.py;\n    __int128 dx2 = (__int128)x - l.px;\n    __int128 dy2 = (__int128)y - l.py;\n    __int128 cross = dx1 * dy2 - dy1 * dx2;\n    if (cross > 0) return 1;\n    if (cross < 0) return -1;\n    return 0;\n}\n\n// Check if strawberry is on any cut line\nbool isCut(int idx) {\n    for (const auto& l : lines) {\n        if (sideOfLine(l, strawberries[idx].x, strawberries[idx].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\n// Get region assignment for each strawberry using string signature\nvector<string> getRegions() {\n    vector<string> region(N);\n    for (int i = 0; i < N; i++) {\n        if (isCut(i)) {\n            region[i] = \"CUT\";\n            continue;\n        }\n        string sig = \"\";\n        for (size_t j = 0; j < lines.size(); j++) {\n            int s = sideOfLine(lines[j], strawberries[i].x, strawberries[i].y);\n            sig += (s == 1 ? \"L\" : (s == -1 ? \"R\" : \"0\"));\n        }\n        region[i] = sig;\n    }\n    return region;\n}\n\n// Calculate score\nint calculateScore() {\n    auto regions = getRegions();\n    map<string, int> pieceCount;\n    for (int i = 0; i < N; i++) {\n        if (regions[i] != \"CUT\") {\n            pieceCount[regions[i]]++;\n        }\n    }\n    \n    int score = 0;\n    for (int d = 1; d <= 10; d++) {\n        int b_d = 0;\n        for (auto& kv : pieceCount) {\n            if (kv.second == d) b_d++;\n        }\n        score += min(a[d], b_d);\n    }\n    return score;\n}\n\n// Distance squared between two points\nlong long distSq(long long x1, long long y1, long long x2, long long y2) {\n    __int128 dx = (__int128)x1 - x2;\n    __int128 dy = (__int128)y1 - y2;\n    __int128 result = dx * dx + dy * dy;\n    if (result > (__int128)4e18) return 4000000000000000000LL;\n    return (long long)result;\n}\n\n// Create a line that separates two groups of strawberries\nLine createSeparatingLine(const vector<int>& group1, const vector<int>& group2) {\n    if (group1.empty() || group2.empty()) {\n        return Line{0, 0, 1, 0};\n    }\n    \n    // Find centroids\n    long long cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0;\n    for (int idx : group1) {\n        cx1 += strawberries[idx].x;\n        cy1 += strawberries[idx].y;\n    }\n    for (int idx : group2) {\n        cx2 += strawberries[idx].x;\n        cy2 += strawberries[idx].y;\n    }\n    cx1 /= (long long)group1.size();\n    cy1 /= (long long)group1.size();\n    cx2 /= (long long)group2.size();\n    cy2 /= (long long)group2.size();\n    \n    // Line perpendicular to line connecting centroids, passing through midpoint\n    long long mx = (cx1 + cx2) / 2;\n    long long my = (cy1 + cy2) / 2;\n    long long dx = cx2 - cx1;\n    long long dy = cy2 - cy1;\n    \n    // Perpendicular direction with reasonable scale\n    long long scale = 10000;\n    if (dx == 0 && dy == 0) {\n        dx = 1;\n        dy = 0;\n    }\n    \n    long long px = clampCoord(mx - dy * scale / 10000);\n    long long py = clampCoord(my + dx * scale / 10000);\n    long long qx = clampCoord(mx + dy * scale / 10000);\n    long long qy = clampCoord(my - dx * scale / 10000);\n    \n    // Ensure points are different\n    if (px == qx && py == qy) {\n        qx = clampCoord(qx + 1);\n    }\n    \n    return Line{px, py, qx, qy};\n}\n\n// Simple clustering by sorting and grouping\nvector<vector<int>> clusterStrawberries() {\n    vector<vector<int>> clusters;\n    vector<bool> used(N, false);\n    \n    // Create demand list\n    vector<int> demands;\n    for (int d = 1; d <= 10; d++) {\n        for (int i = 0; i < a[d]; i++) {\n            demands.push_back(d);\n        }\n    }\n    sort(demands.rbegin(), demands.rend());\n    \n    // Sort strawberries by x coordinate for spatial ordering\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [](int i, int j) {\n        if (strawberries[i].x != strawberries[j].x)\n            return strawberries[i].x < strawberries[j].x;\n        return strawberries[i].y < strawberries[j].y;\n    });\n    \n    int orderIdx = 0;\n    for (int demand : demands) {\n        if ((int)lines.size() >= K) break;\n        \n        vector<int> cluster;\n        while (orderIdx < N && (int)cluster.size() < demand) {\n            if (!used[order[orderIdx]]) {\n                cluster.push_back(order[orderIdx]);\n                used[order[orderIdx]] = true;\n            }\n            orderIdx++;\n        }\n        \n        if (!cluster.empty()) {\n            clusters.push_back(cluster);\n        }\n    }\n    \n    // Assign remaining strawberries\n    for (int i = 0; i < N; i++) {\n        if (!used[i]) {\n            if (!clusters.empty() && (int)clusters.back().size() < 10) {\n                clusters.back().push_back(i);\n            } else {\n                clusters.push_back({i});\n            }\n            used[i] = true;\n        }\n    }\n    \n    return clusters;\n}\n\n// Generate lines to separate clusters\nvoid generateLines(const vector<vector<int>>& clusters) {\n    lines.clear();\n    \n    for (size_t i = 0; i < clusters.size() && (int)lines.size() < K; i++) {\n        for (size_t j = i + 1; j < clusters.size() && (int)lines.size() < K; j++) {\n            // Check if clusters are already separated\n            bool alreadySeparated = true;\n            for (int idx1 : clusters[i]) {\n                for (int idx2 : clusters[j]) {\n                    bool same = true;\n                    for (const auto& l : lines) {\n                        int s1 = sideOfLine(l, strawberries[idx1].x, strawberries[idx1].y);\n                        int s2 = sideOfLine(l, strawberries[idx2].x, strawberries[idx2].y);\n                        if (s1 != 0 && s2 != 0 && s1 != s2) {\n                            same = false;\n                            break;\n                        }\n                    }\n                    if (same) {\n                        alreadySeparated = false;\n                        break;\n                    }\n                }\n                if (!alreadySeparated) break;\n            }\n            \n            if (!alreadySeparated) {\n                Line l = createSeparatingLine(clusters[i], clusters[j]);\n                \n                // Check if line cuts any strawberry\n                bool cutsStrawberry = false;\n                for (int k = 0; k < N; k++) {\n                    if (sideOfLine(l, strawberries[k].x, strawberries[k].y) == 0) {\n                        cutsStrawberry = true;\n                        break;\n                    }\n                }\n                \n                if (!cutsStrawberry && (int)lines.size() < K) {\n                    lines.push_back(l);\n                }\n            }\n        }\n    }\n}\n\n// Try to improve solution\nvoid optimize() {\n    int baseScore = calculateScore();\n    \n    for (int iter = 0; iter < 50 && (int)lines.size() < K; iter++) {\n        int i1 = rand() % N;\n        int i2 = rand() % N;\n        if (i1 == i2) continue;\n        \n        Line newLine = createSeparatingLine({i1}, {i2});\n        \n        bool cutsStrawberry = false;\n        for (int k = 0; k < N; k++) {\n            if (sideOfLine(newLine, strawberries[k].x, strawberries[k].y) == 0) {\n                cutsStrawberry = true;\n                break;\n            }\n        }\n        \n        if (!cutsStrawberry) {\n            lines.push_back(newLine);\n            int newScore = calculateScore();\n            if (newScore < baseScore) {\n                lines.pop_back();\n            } else {\n                baseScore = newScore;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    srand(42);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        strawberries[i].id = i;\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Cluster strawberries\n    auto clusters = clusterStrawberries();\n    \n    // Generate separating lines\n    generateLines(clusters);\n    \n    // Optimize\n    optimize();\n    \n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const auto& l : lines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <random>\n#include <iomanip>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nstruct Rect {\n    Point p[4]; // p[0] is target (new dot), p[1..3] are existing\n    long long weight;\n    int perimeter_len;\n    \n    // For sorting\n    bool operator<(const Rect& other) const {\n        if (weight != other.weight) return weight > other.weight;\n        return perimeter_len < other.perimeter_len;\n    }\n};\n\nint N, M;\nvector<Point> initial_dots;\nvector<vector<bool>> has_dot;\nvector<vector<bool>> used_h;\nvector<vector<bool>> used_v;\nvector<vector<bool>> used_d1;\nvector<vector<bool>> used_d2;\n\nlong long total_weight_S = 0;\nvector<vector<long long>> weights;\n\nvoid init_weights() {\n    double c = (N - 1) / 2.0;\n    weights.assign(N, vector<long long>(N));\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (long long)round(pow(x - c, 2) + pow(y - c, 2) + 1);\n            weights[x][y] = w;\n            total_weight_S += w;\n        }\n    }\n}\n\nbool is_inside(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\nbool check_perimeter_dots(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps == 0) return true;\n    int sx = (dx > 0) - (dx < 0);\n    int sy = (dy > 0) - (dy < 0);\n    \n    for (int i = 1; i < steps; ++i) {\n        int cx = x1 + i * sx;\n        int cy = y1 + i * sy;\n        if (has_dot[cx][cy]) return false;\n    }\n    return true;\n}\n\nbool check_rect_dots(const Rect& r) {\n    for (int i = 0; i < 4; ++i) {\n        Point p1 = r.p[i];\n        Point p2 = r.p[(i + 1) % 4];\n        if (!check_perimeter_dots(p1.x, p1.y, p2.x, p2.y)) return false;\n    }\n    return true;\n}\n\nbool process_edges(const Rect& r, bool mark) {\n    for (int i = 0; i < 4; ++i) {\n        int x1 = r.p[i].x, y1 = r.p[i].y;\n        int x2 = r.p[(i + 1) % 4].x, y2 = r.p[(i + 1) % 4].y;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        int sx = (dx > 0) - (dx < 0);\n        int sy = (dy > 0) - (dy < 0);\n        \n        for (int i = 0; i < steps; ++i) {\n            int cx = x1 + i * sx;\n            int cy = y1 + i * sy;\n            int nx = cx + sx;\n            int ny = cy + sy;\n            \n            bool used = false;\n            if (sx == 1 && sy == 0) { \n                if (used_h[cx][cy]) used = true;\n                else if (mark) used_h[cx][cy] = true;\n            } else if (sx == 0 && sy == 1) { \n                if (used_v[cx][cy]) used = true;\n                else if (mark) used_v[cx][cy] = true;\n            } else if (sx == 1 && sy == 1) { \n                if (used_d1[cx][cy]) used = true;\n                else if (mark) used_d1[cx][cy] = true;\n            } else if (sx == 1 && sy == -1) { \n                if (used_d2[cx][cy]) used = true;\n                else if (mark) used_d2[cx][cy] = true;\n            } else {\n                return false; \n            }\n            if (used) return false;\n        }\n    }\n    return true;\n}\n\nvector<Rect> generate_candidates(const vector<Point>& active_dots, mt19937& rng) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    // Iterate all pairs of existing dots\n    for (int i = 0; i < S; ++i) {\n        for (int j = i + 1; j < S; ++j) {\n            Point A = active_dots[i];\n            Point B = active_dots[j];\n            \n            // Case 1: A, B are diagonal\n            // Axis aligned\n            if (A.x != B.x && A.y != B.y) {\n                Point C1 = {A.x, B.y};\n                Point C2 = {B.x, A.y};\n                // Target C1, Source C2\n                if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && has_dot[C2.x][C2.y]) {\n                    Rect r; r.p[0]=C1; r.p[1]=C2; r.p[2]=B; r.p[3]=A;\n                    cands.push_back(r);\n                }\n                // Target C2, Source C1\n                if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && has_dot[C1.x][C1.y]) {\n                    Rect r; r.p[0]=C2; r.p[1]=C1; r.p[2]=A; r.p[3]=B;\n                    cands.push_back(r);\n                }\n            }\n            // 45-deg diagonal (Diagonals are H or V)\n            if (A.x == B.x) {\n                if ((A.y + B.y) % 2 == 0) {\n                    int my = (A.y + B.y) / 2;\n                    int dist = abs(A.y - B.y) / 2;\n                    Point C = {A.x - dist, my};\n                    Point D = {A.x + dist, my};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; cands.push_back(r);\n                    }\n                }\n            }\n            if (A.y == B.y) {\n                if ((A.x + B.x) % 2 == 0) {\n                    int mx = (A.x + B.x) / 2;\n                    int dist = abs(A.x - B.x) / 2;\n                    Point C = {mx, A.y - dist};\n                    Point D = {mx, A.y + dist};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; cands.push_back(r);\n                    }\n                }\n            }\n            \n            // Case 2: A, B are side. Need 3rd dot C to form corner.\n            // Iterate all C to find valid corners. O(M^3) total.\n            // Optimization: Only check C that forms right angle.\n            // We can iterate all C. M is small (<=300). M^3 = 2.7e7. Acceptable for initialization.\n            // But inside loop we call this every step? No, we only call this for NEW candidates.\n            // To avoid O(M^3) every step, we rely on the fact that we only need to pair the NEW dot with existing.\n            // But this function generates ALL candidates from scratch.\n            // For the main loop, we should use an incremental approach or accept O(M^3) if M is small.\n            // Given 5s, let's try to be efficient.\n            // Actually, for the main loop, we can just call this function.\n            // If it's too slow, we limit restarts.\n            // Let's optimize: Only iterate C if it forms a right angle with A, B.\n            // But checking all C is simplest.\n            // Let's add this loop.\n            for (int k = 0; k < S; ++k) {\n                if (k == i || k == j) continue;\n                Point C = active_dots[k];\n                // Check if A, B, C form a corner of a rect\n                // 3 permutations: Corner at A, B, or C.\n                // Corner at A: AB perp AC.\n                {\n                    long long dx1 = B.x - A.x, dy1 = B.y - A.y;\n                    long long dx2 = C.x - A.x, dy2 = C.y - A.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {B.x + C.x - A.x, B.y + C.y - A.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=A; r.p[2]=B; r.p[3]=C; cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at B: BA perp BC.\n                {\n                    long long dx1 = A.x - B.x, dy1 = A.y - B.y;\n                    long long dx2 = C.x - B.x, dy2 = C.y - B.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + C.x - B.x, A.y + C.y - B.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=B; r.p[2]=A; r.p[3]=C; cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at C: CA perp CB.\n                {\n                    long long dx1 = A.x - C.x, dy1 = A.y - C.y;\n                    long long dx2 = B.x - C.x, dy2 = B.y - C.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + B.x - C.x, A.y + B.y - C.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return cands;\n}\n\nstruct Solution {\n    vector<Rect> ops;\n    long long score;\n};\n\nSolution solve_one(mt19937& rng) {\n    // Reset state\n    has_dot.assign(N, vector<bool>(N, false));\n    used_h.assign(N, vector<bool>(N, false));\n    used_v.assign(N, vector<bool>(N, false));\n    used_d1.assign(N, vector<bool>(N, false));\n    used_d2.assign(N, vector<bool>(N, false));\n    \n    vector<Point> active_dots = initial_dots;\n    for (auto& p : active_dots) has_dot[p.x][p.y] = true;\n    \n    vector<Rect> ops;\n    // Initial candidates\n    vector<Rect> candidates = generate_candidates(active_dots, rng);\n    \n    while (true) {\n        // Filter valid candidates\n        vector<Rect> valid_cands;\n        valid_cands.reserve(candidates.size());\n        for (auto& r : candidates) {\n            if (!has_dot[r.p[0].x][r.p[0].y] && // Target empty\n                has_dot[r.p[1].x][r.p[1].y] && has_dot[r.p[2].x][r.p[2].y] && has_dot[r.p[3].x][r.p[3].y] && // Sources have dots\n                check_rect_dots(r) && // No other dots on perimeter\n                process_edges(r, false) // Edges free\n               ) {\n                r.weight = get_weight(r.p[0].x, r.p[0].y);\n                // Calculate perimeter len\n                int len = 0;\n                for(int i=0; i<4; ++i) {\n                    len += max(abs(r.p[i].x - r.p[(i+1)%4].x), abs(r.p[i].y - r.p[(i+1)%4].y));\n                }\n                r.perimeter_len = len;\n                valid_cands.push_back(r);\n            }\n        }\n        \n        if (valid_cands.empty()) break;\n        \n        // Sort and pick\n        // Add some noise to break ties and explore\n        for(auto& r : valid_cands) {\n            r.weight += (rng() % 100); \n        }\n        sort(valid_cands.begin(), valid_cands.end());\n        \n        Rect best = valid_cands[0];\n        \n        // Apply\n        ops.push_back(best);\n        has_dot[best.p[0].x][best.p[0].y] = true;\n        active_dots.push_back(best.p[0]);\n        process_edges(best, true);\n        \n        // Update candidates:\n        // 1. Remove invalid ones (done by filtering next iter)\n        // 2. Add new ones involving the new dot.\n        // To do this efficiently, we can just regenerate all candidates?\n        // Regenerating all is O(M^3). M grows.\n        // Instead, generate only those involving the new dot.\n        // But generate_candidates iterates all pairs.\n        // Let's just regenerate all candidates if M is small, else incremental.\n        // Given M <= 300, O(M^3) is 2.7e7. Doing this 100 times is 2.7e9. Too slow.\n        // We MUST use incremental.\n        // But implementing incremental generation of \"3 dots including new one\" is complex.\n        // Compromise: Regenerate candidates only every K steps or if list is small?\n        // Or just rely on the fact that valid_cands shrinks.\n        // If we don't add new candidates, we stop early.\n        // We MUST add new candidates.\n        // Let's create a function `generate_candidates_with_new_dot(new_dot, active_dots)`\n        // This is O(M^2).\n        // We will use this.\n        \n        vector<Rect> new_cands;\n        Point new_dot = best.p[0];\n        int S = active_dots.size() - 1; // Exclude new_dot itself for pairing\n        for (int i = 0; i < S; ++i) {\n            Point A = active_dots[i];\n            Point B = new_dot; // One source is the new dot\n            \n            // We need 3 sources. So we need one more source C from active_dots.\n            // So we iterate C. O(M^2).\n            for (int k = 0; k < S; ++k) {\n                if (k == i) continue;\n                Point C = active_dots[k];\n                // Check corners with A, B, C\n                // Corner at A\n                {\n                    long long dx1 = B.x - A.x, dy1 = B.y - A.y;\n                    long long dx2 = C.x - A.x, dy2 = C.y - A.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {B.x + C.x - A.x, B.y + C.y - A.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=A; r.p[2]=B; r.p[3]=C; new_cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at B\n                {\n                    long long dx1 = A.x - B.x, dy1 = A.y - B.y;\n                    long long dx2 = C.x - B.x, dy2 = C.y - B.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + C.x - B.x, A.y + C.y - B.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=B; r.p[2]=A; r.p[3]=C; new_cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n                // Corner at C\n                {\n                    long long dx1 = A.x - C.x, dy1 = A.y - C.y;\n                    long long dx2 = B.x - C.x, dy2 = B.y - C.y;\n                    if (dx1*dx2 + dy1*dy2 == 0) {\n                        bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                        bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                        if (axis || deg45) {\n                            Point D = {A.x + B.x - C.x, A.y + B.y - C.y};\n                            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Also check diagonal cases with new_dot\n            // A, new_dot diagonal\n            if (A.x != B.x && A.y != B.y) {\n                Point C1 = {A.x, B.y};\n                Point C2 = {B.x, A.y};\n                if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && has_dot[C2.x][C2.y]) {\n                    Rect r; r.p[0]=C1; r.p[1]=C2; r.p[2]=B; r.p[3]=A; new_cands.push_back(r);\n                }\n                if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && has_dot[C1.x][C1.y]) {\n                    Rect r; r.p[0]=C2; r.p[1]=C1; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                }\n            }\n             if (A.x == B.x) {\n                if ((A.y + B.y) % 2 == 0) {\n                    int my = (A.y + B.y) / 2;\n                    int dist = abs(A.y - B.y) / 2;\n                    Point C = {A.x - dist, my};\n                    Point D = {A.x + dist, my};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; new_cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                    }\n                }\n            }\n            if (A.y == B.y) {\n                if ((A.x + B.x) % 2 == 0) {\n                    int mx = (A.x + B.x) / 2;\n                    int dist = abs(A.x - B.x) / 2;\n                    Point C = {mx, A.y - dist};\n                    Point D = {mx, A.y + dist};\n                    if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A; new_cands.push_back(r);\n                    }\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B; new_cands.push_back(r);\n                    }\n                }\n            }\n        }\n        \n        // Merge new_cands into candidates\n        candidates.insert(candidates.end(), new_cands.begin(), new_cands.end());\n    }\n    \n    Solution sol;\n    sol.ops = ops;\n    long long current_weight_sum = 0;\n    for(int x=0; x<N; ++x) for(int y=0; y<N; ++y) if(has_dot[x][y]) current_weight_sum += weights[x][y];\n    \n    // Score calculation\n    // round(1e6 * N*N / M * current_weight_sum / S)\n    double score_d = 1e6 * (double)N * N / M * (double)current_weight_sum / total_weight_S;\n    sol.score = (long long)round(score_d);\n    \n    return sol;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> initial_dots[i].x >> initial_dots[i].y;\n    }\n    \n    init_weights();\n    \n    Solution best_sol;\n    best_sol.score = -1;\n    \n    auto start = chrono::steady_clock::now();\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 4.8) break;\n        \n        Solution sol = solve_one(rng);\n        if (sol.score > best_sol.score) {\n            best_sol = sol;\n        }\n        iterations++;\n    }\n    \n    cout << best_sol.ops.size() << \"\\n\";\n    for (const auto& op : best_sol.ops) {\n        cout << op.p[0].x << \" \" << op.p[0].y << \" \"\n             << op.p[1].x << \" \" << op.p[1].y << \" \"\n             << op.p[2].x << \" \" << op.p[2].y << \" \"\n             << op.p[3].x << \" \" << op.p[3].y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <utility>\n\nusing namespace std;\n\n// Grid type: 10x10 integers\nusing Grid = array<array<int, 10>, 10>;\n\n// Function to calculate the sum of squares of connected component sizes\n// This is the numerator of the score function, which we want to maximize.\nlong long calculate_score(const Grid& g) {\n    long long score = 0;\n    bool visited[10][10] = {};\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                // Use a vector as a queue for BFS\n                vector<pair<int, int>> q;\n                q.reserve(100); \n                q.push_back({r, c});\n                visited[r][c] = true;\n                size++;\n                \n                int head = 0;\n                while(head < (int)q.size()){\n                    auto [cr, cc] = q[head++];\n                    for(int i=0; i<4; ++i){\n                        int nr = cr + dr[i];\n                        int nc = cc + dc[i];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                            if(!visited[nr][nc] && g[nr][nc] == flavor){\n                                visited[nr][nc] = true;\n                                size++;\n                                q.push_back({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Function to apply tilt and return the new grid\nGrid apply_tilt(const Grid& g, char dir) {\n    Grid ng;\n    // Initialize new grid with 0\n    for(auto& row : ng) row.fill(0);\n\n    if (dir == 'L' || dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            vector<int> row_vals;\n            row_vals.reserve(10);\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) row_vals.push_back(g[r][c]);\n            }\n            if (dir == 'L') {\n                for (int i = 0; i < (int)row_vals.size(); ++i) ng[r][i] = row_vals[i];\n            } else { // 'R'\n                int idx = 9;\n                for (int i = (int)row_vals.size() - 1; i >= 0; --i) ng[r][idx--] = row_vals[i];\n            }\n        }\n    } else { // 'F' or 'B'\n        for (int c = 0; c < 10; ++c) {\n            vector<int> col_vals;\n            col_vals.reserve(10);\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) col_vals.push_back(g[r][c]);\n            }\n            if (dir == 'F') {\n                for (int i = 0; i < (int)col_vals.size(); ++i) ng[i][c] = col_vals[i];\n            } else { // 'B'\n                int idx = 9;\n                for (int i = (int)col_vals.size() - 1; i >= 0; --i) ng[idx--][c] = col_vals[i];\n            }\n        }\n    }\n    return ng;\n}\n\nint main() {\n    // Optimize I/O operations\n    cin.tie(NULL);\n    ios_base::sync_with_stdio(false);\n\n    // Read flavors\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) {\n        cin >> f[i];\n    }\n\n    // Initialize empty grid\n    Grid grid;\n    for(auto& row : grid) row.fill(0);\n\n    // Process 100 turns\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        // Place the t-th candy (f[t]) into the p-th empty cell\n        int count = 0;\n        bool placed = false;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    count++;\n                    if (count == p) {\n                        grid[r][c] = f[t];\n                        placed = true;\n                        break;\n                    }\n                }\n            }\n            if (placed) break;\n        }\n\n        // For the last turn, the board is full, tilt doesn't change anything.\n        // We output 'F' for consistency, though it could be skipped.\n        if (t == 99) {\n            cout << \"F\" << endl;\n            break;\n        }\n\n        // Evaluate all 4 possible tilts\n        char best_dir = 'F';\n        long long best_score = -1;\n        char dirs[] = {'F', 'B', 'L', 'R'};\n\n        for (char d : dirs) {\n            Grid ng = apply_tilt(grid, d);\n            long long sc = calculate_score(ng);\n            // Greedy choice: maximize sum of squares of component sizes\n            if (sc > best_score) {\n                best_score = sc;\n                best_dir = d;\n            }\n        }\n\n        // Output the best direction and update the grid\n        cout << best_dir << endl;\n        grid = apply_tilt(grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nint M;\ndouble epsilon;\nint N;\nvector<string> graphs;\nvector<vector<int>> graph_degrees;\nvector<int> graph_edge_counts;\n\n// Parse graph string to adjacency matrix\nvector<vector<int>> parseGraph(const string& s, int n) {\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    int idx = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            adj[i][j] = adj[j][i] = s[idx++] - '0';\n        }\n    }\n    return adj;\n}\n\n// Convert adjacency matrix to graph string\nstring toGraphString(const vector<vector<int>>& adj, int n) {\n    string s;\n    s.reserve(n * (n - 1) / 2);\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Count edges\nint countEdges(const string& s) {\n    return count(s.begin(), s.end(), '1');\n}\n\n// Compute degree sequence (sorted)\nvector<int> degreeSequence(const vector<vector<int>>& adj, int n) {\n    vector<int> deg(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            deg[i] += adj[i][j];\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute degree histogram (more robust than full sequence)\nvector<int> degreeHistogram(const vector<int>& deg, int n) {\n    vector<int> hist(n + 1, 0);\n    for (int d : deg) {\n        hist[d]++;\n    }\n    return hist;\n}\n\n// Generate graph with specific edge density and degree pattern\nstring generateStructuredGraph(int n, double density, int pattern_id, mt19937& rng) {\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    int total_edges = n * (n - 1) / 2;\n    int target_edges = (int)(total_edges * density);\n    \n    // Create edge list\n    vector<pair<int, int>> edges;\n    edges.reserve(total_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    }\n    \n    // Different patterns for different graphs\n    if (pattern_id == 0) {\n        // Random graph\n        shuffle(edges.begin(), edges.end(), rng);\n    } else if (pattern_id == 1) {\n        // Prefer edges between low-index vertices\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.first + a.second < b.first + b.second;\n        });\n    } else if (pattern_id == 2) {\n        // Prefer edges that create degree variation\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return abs(a.first - a.second) < abs(b.first - b.second);\n        });\n    } else {\n        // Mixed pattern\n        shuffle(edges.begin(), edges.end(), rng);\n    }\n    \n    int added = 0;\n    for (auto& [u, v] : edges) {\n        if (added >= target_edges) break;\n        adj[u][v] = adj[v][u] = 1;\n        added++;\n    }\n    \n    return toGraphString(adj, n);\n}\n\n// Generate graphs with maximally separated edge densities\nvector<string> generateGraphs(int m, int n, double eps) {\n    vector<string> result;\n    result.reserve(m);\n    \n    mt19937 rng(42);\n    \n    // Calculate optimal density range based on noise\n    // Higher noise needs more separation between densities\n    double min_density = 0.15;\n    double max_density = 0.85;\n    \n    // For high noise, use wider range and more separation\n    if (eps > 0.2) {\n        min_density = 0.1;\n        max_density = 0.9;\n    }\n    \n    double density_step = (max_density - min_density) / max(1, m - 1);\n    \n    for (int k = 0; k < m; k++) {\n        double density = min_density + density_step * k;\n        int pattern = k % 4;  // Rotate through patterns\n        string g = generateStructuredGraph(n, density, pattern, rng);\n        result.push_back(g);\n    }\n    \n    return result;\n}\n\n// Compute optimal N based on M and epsilon\n// Information-theoretic approach: need to distinguish M graphs under noise\nint computeOptimalN(int m, double eps) {\n    // Base N from M (need enough edges to encode log2(M) bits)\n    // Each edge provides ~1 bit, but noise reduces this\n    double noise_factor = 1.0 - eps;\n    if (noise_factor < 0.01) noise_factor = 0.01;\n    \n    // Bits needed\n    double bits_needed = log2(m);\n    \n    // Effective bits per edge under noise\n    double bits_per_edge = noise_factor * noise_factor;  // Both endpoints must survive\n    \n    // Minimum edges needed\n    double min_edges = bits_needed / max(0.01, bits_per_edge);\n    \n    // Convert to N: edges = N*(N-1)/2\n    double min_n = (1 + sqrt(1 + 8 * min_edges)) / 2;\n    \n    int n = (int)ceil(min_n);\n    \n    // Add safety margin based on noise\n    if (eps > 0.3) n += 15;\n    else if (eps > 0.2) n += 10;\n    else if (eps > 0.1) n += 5;\n    \n    // Ensure we have enough separation for M graphs\n    if (m > 50) n += 10;\n    if (m > 80) n += 15;\n    \n    // Clamp to valid range\n    n = max(4, min(100, n));\n    \n    return n;\n}\n\n// Graph signature for matching\nstruct GraphSignature {\n    int edge_count;\n    vector<int> degree_hist;\n    int min_degree;\n    int max_degree;\n    double degree_variance;\n    \n    GraphSignature() {}\n    \n    GraphSignature(const string& s, int n) {\n        edge_count = countEdges(s);\n        auto adj = parseGraph(s, n);\n        auto deg = degreeSequence(adj, n);\n        \n        min_degree = deg[0];\n        max_degree = deg[n-1];\n        \n        // Degree histogram\n        degree_hist = degreeHistogram(deg, n);\n        \n        // Degree variance\n        double mean = 0;\n        for (int d : deg) mean += d;\n        mean /= n;\n        degree_variance = 0;\n        for (int d : deg) {\n            degree_variance += (d - mean) * (d - mean);\n        }\n        degree_variance /= n;\n    }\n};\n\n// Compute distance between signatures with noise-aware weighting\ndouble signatureDistance(const GraphSignature& s1, const GraphSignature& s2, double eps) {\n    double dist = 0;\n    \n    // Edge count distance (most robust under noise)\n    // Expected edge flip: each edge flips with prob eps\n    double edge_dist = abs(s1.edge_count - s2.edge_count);\n    dist += edge_dist * 1.0;\n    \n    // Degree statistics (moderately robust)\n    double deg_range_dist = abs(s1.min_degree - s2.min_degree) + abs(s1.max_degree - s2.max_degree);\n    dist += deg_range_dist * 0.5;\n    \n    double deg_var_dist = abs(s1.degree_variance - s2.degree_variance);\n    dist += deg_var_dist * 0.3;\n    \n    // Degree histogram (less robust but useful for separation)\n    int hist_dist = 0;\n    for (size_t i = 0; i < s1.degree_hist.size(); i++) {\n        hist_dist += abs(s1.degree_hist[i] - s2.degree_hist[i]);\n    }\n    dist += hist_dist * 0.2;\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> M >> epsilon;\n    \n    // Compute optimal N\n    N = computeOptimalN(M, epsilon);\n    \n    // Generate graphs\n    graphs = generateGraphs(M, N, epsilon);\n    \n    // Precompute signatures for all graphs\n    vector<GraphSignature> signatures(M);\n    for (int i = 0; i < M; i++) {\n        signatures[i] = GraphSignature(graphs[i], N);\n    }\n    \n    // Output N and graphs\n    cout << N << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << graphs[i] << \"\\n\";\n    }\n    cout.flush();\n    \n    // Process 100 queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        GraphSignature h_sig(h, N);\n        \n        // Find best match\n        int best_idx = 0;\n        double best_dist = 1e18;\n        \n        for (int i = 0; i < M; i++) {\n            double dist = signatureDistance(h_sig, signatures[i], epsilon);\n            if (dist < best_dist) {\n                best_dist = dist;\n                best_idx = i;\n            }\n        }\n        \n        cout << best_idx << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nconst long long INF = 1e18;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, int>>> adj(N + 1); // to, edge_index\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\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 (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    // Conflict matrix W\n    // Use 1D array for cache efficiency\n    // W[i * M + j] stores co-occurrence count of edge i and edge j\n    vector<long long> W(M * M, 0);\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Sample paths to build W\n    int num_sources = 1000;\n    int num_targets = 5;\n    \n    // To avoid bias, we can shuffle vertices\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 1);\n    shuffle(vertices.begin(), vertices.end(), rng);\n\n    auto start_time = chrono::steady_clock::now();\n\n    for (int s_idx = 0; s_idx < num_sources; ++s_idx) {\n        int s = vertices[s_idx % N];\n        \n        // Dijkstra\n        vector<long long> dist(N + 1, INF);\n        vector<int> par_edge(N + 1, -1);\n        vector<int> par_node(N + 1, -1);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n            for (auto [v, eid] : adj[u]) {\n                if (dist[u] + edges[eid].w < dist[v]) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    par_node[v] = u;\n                    par_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        // Pick random targets\n        for (int t_idx = 0; t_idx < num_targets; ++t_idx) {\n            int t = vertices[(s_idx * num_targets + t_idx) % N];\n            if (t == s) continue;\n            if (dist[t] == INF) continue;\n\n            // Reconstruct path\n            vector<int> path_edges;\n            int curr = t;\n            while (curr != s) {\n                int eid = par_edge[curr];\n                path_edges.push_back(eid);\n                curr = par_node[curr];\n            }\n\n            // Update W\n            int L = path_edges.size();\n            for (int i = 0; i < L; ++i) {\n                for (int j = i + 1; j < L; ++j) { // j starts from i+1 to avoid self and duplicate\n                    int u = path_edges[i];\n                    int v = path_edges[j];\n                    W[u * M + v]++;\n                    W[v * M + u]++;\n                }\n            }\n        }\n        \n        // Time check for W construction (limit to ~3 seconds)\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 3000) {\n            break; \n        }\n    }\n\n    // Initial Assignment\n    // Calculate degree in conflict graph\n    vector<long long> edge_conflict(M, 0);\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            edge_conflict[i] += W[i * M + j];\n        }\n    }\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 edge_conflict[a] > edge_conflict[b];\n    });\n\n    vector<int> assignment(M, -1);\n    vector<int> day_size(D, 0);\n    vector<vector<int>> day_edges(D);\n    \n    // Greedy assignment\n    for (int e : order) {\n        int best_day = -1;\n        long long min_cost = -1;\n        \n        for (int k = 0; k < D; ++k) {\n            if (day_size[k] < K) {\n                long long cost = 0;\n                for (int other : day_edges[k]) {\n                    cost += W[e * M + other];\n                }\n                if (best_day == -1 || cost < min_cost) {\n                    min_cost = cost;\n                    best_day = k;\n                }\n            }\n        }\n        \n        if (best_day != -1) {\n            assignment[e] = best_day;\n            day_edges[best_day].push_back(e);\n            day_size[best_day]++;\n        }\n    }\n\n    // Prepare for Local Search\n    // Maintain C[k][e] = sum_{j in S_k} W[e][j]\n    // Flattened: C[k * M + e]\n    vector<long long> C(D * M, 0);\n    \n    for (int k = 0; k < D; ++k) {\n        for (int e : day_edges[k]) {\n            for (int other = 0; other < M; ++other) {\n                C[k * M + other] += W[e * M + other];\n            }\n        }\n    }\n    \n    // Current total cost\n    long long current_total_cost = 0;\n    for (int k = 0; k < D; ++k) {\n        for (int i : day_edges[k]) {\n            for (int j : day_edges[k]) {\n                if (i < j) current_total_cost += W[i * M + j];\n            }\n        }\n    }\n    \n    long long best_total_cost = current_total_cost;\n    vector<int> best_assignment = assignment;\n\n    // Local Search\n    auto ls_start = chrono::steady_clock::now();\n    int moves = 0;\n    int max_moves = 500000;\n    \n    vector<int> day_size_ls = day_size;\n    \n    while (moves < max_moves) {\n        auto now = chrono::steady_clock::now();\n        // Limit LS to ~2.5 seconds\n        if (chrono::duration_cast<chrono::milliseconds>(now - ls_start).count() > 2500) break;\n        \n        // Pick random edge\n        int e = uniform_int_distribution<>(0, M - 1)(rng);\n        int k_old = assignment[e];\n        \n        // Find best new day\n        int k_new = -1;\n        long long best_delta = 0;\n        \n        for (int k = 0; k < D; ++k) {\n            if (k == k_old) continue;\n            if (day_size_ls[k] >= K) continue;\n            \n            // Delta = Cost(new) - Cost(old)\n            long long delta = C[k * M + e] - C[k_old * M + e];\n            if (k_new == -1 || delta < best_delta) {\n                best_delta = delta;\n                k_new = k;\n            }\n        }\n        \n        if (k_new != -1 && best_delta < 0) {\n            // Move e\n            assignment[e] = k_new;\n            day_size_ls[k_old]--;\n            day_size_ls[k_new]++;\n            \n            // Update C\n            for (int other = 0; other < M; ++other) {\n                long long w_val = W[e * M + other];\n                C[k_old * M + other] -= w_val;\n                C[k_new * M + other] += w_val;\n            }\n            \n            current_total_cost += best_delta;\n            if (current_total_cost < best_total_cost) {\n                best_total_cost = current_total_cost;\n                best_assignment = assignment;\n            }\n            moves++;\n        } else {\n            moves++;\n        }\n    }\n\n    // Output\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;\n\nstruct Block {\n    vector<tuple<int,int,int>> cells; // relative coordinates from first cell\n    int id;\n    bool usedIn1 = false;\n    bool usedIn2 = false;\n    \n    void normalize() {\n        if (cells.empty()) return;\n        auto [minX, minY, minZ] = cells[0];\n        for (auto& [x, y, z] : cells) {\n            minX = min(minX, x);\n            minY = min(minY, y);\n            minZ = min(minZ, z);\n        }\n        for (auto& [x, y, z] : cells) {\n            x -= minX;\n            y -= minY;\n            z -= minZ;\n        }\n        sort(cells.begin(), cells.end());\n    }\n};\n\nint D;\nvector<string> f1, r1, f2, r2;\nvector<vector<vector<bool>>> valid1, valid2;\nvector<vector<vector<int>>> b1, b2;\nvector<Block> blocks;\n\n// Get 6 neighbors\nvector<tuple<int,int,int>> getNeighbors(int x, int y, int z) {\n    vector<tuple<int,int,int>> neighbors;\n    int dx[] = {1, -1, 0, 0, 0, 0};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {0, 0, 0, 0, 1, -1};\n    \n    for (int d = 0; d < 6; d++) {\n        int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n        if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D) {\n            neighbors.emplace_back(nx, ny, nz);\n        }\n    }\n    return neighbors;\n}\n\n// Check if two block shapes match (with rotation)\nbool shapesMatch(const Block& a, const Block& b) {\n    if (a.cells.size() != b.cells.size()) return false;\n    if (a.cells.empty()) return true;\n    \n    // Generate all 24 rotations of block a\n    vector<vector<tuple<int,int,int>>> rotations;\n    auto [x0, y0, z0] = a.cells[0];\n    \n    // 24 rotations: 6 faces \u00d7 4 rotations each\n    int rotations_24[24][3][3] = {\n        {{1,0,0},{0,1,0},{0,0,1}}, {{0,-1,0},{1,0,0},{0,0,1}}, {{-1,0,0},{0,-1,0},{0,0,1}}, {{0,1,0},{-1,0,0},{0,0,1}},\n        {{1,0,0},{0,0,-1},{0,1,0}}, {{0,0,1},{1,0,0},{0,1,0}}, {{-1,0,0},{0,0,1},{0,1,0}}, {{0,0,-1},{-1,0,0},{0,1,0}},\n        {{1,0,0},{0,0,1},{0,-1,0}}, {{0,0,-1},{1,0,0},{0,-1,0}}, {{-1,0,0},{0,0,-1},{0,-1,0}}, {{0,0,1},{-1,0,0},{0,-1,0}},\n        {{0,1,0},{0,0,1},{1,0,0}}, {{0,0,-1},{0,1,0},{1,0,0}}, {{0,-1,0},{0,0,-1},{1,0,0}}, {{0,0,1},{0,-1,0},{1,0,0}},\n        {{0,1,0},{0,0,-1},{-1,0,0}}, {{0,0,1},{0,1,0},{-1,0,0}}, {{0,-1,0},{0,0,1},{-1,0,0}}, {{0,0,-1},{0,-1,0},{-1,0,0}},\n        {{0,-1,0},{1,0,0},{0,0,1}}, {{1,0,0},{0,0,1},{0,1,0}}, {{0,1,0},{-1,0,0},{0,0,1}}, {{-1,0,0},{0,0,-1},{0,1,0}}\n    };\n    \n    vector<tuple<int,int,int>> baseA = a.cells;\n    for (auto& [x, y, z] : baseA) {\n        x -= x0; y -= y0; z -= z0;\n    }\n    \n    for (int r = 0; r < 24; r++) {\n        vector<tuple<int,int,int>> rotated;\n        for (auto [x, y, z] : baseA) {\n            int nx = rotations_24[r][0][0]*x + rotations_24[r][0][1]*y + rotations_24[r][0][2]*z;\n            int ny = rotations_24[r][1][0]*x + rotations_24[r][1][1]*y + rotations_24[r][1][2]*z;\n            int nz = rotations_24[r][2][0]*x + rotations_24[r][2][1]*y + rotations_24[r][2][2]*z;\n            rotated.emplace_back(nx, ny, nz);\n        }\n        sort(rotated.begin(), rotated.end());\n        \n        auto [bx0, by0, bz0] = b.cells[0];\n        vector<tuple<int,int,int>> baseB = b.cells;\n        for (auto& [x, y, z] : baseB) {\n            x -= bx0; y -= by0; z -= bz0;\n        }\n        sort(baseB.begin(), baseB.end());\n        \n        if (rotated == baseB) return true;\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    f1.resize(D); r1.resize(D);\n    f2.resize(D); r2.resize(D);\n    \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    // Initialize arrays\n    valid1.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    valid2.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    b1.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    b2.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Compute valid positions\n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') valid1[x][y][z] = true;\n                if (f2[z][x] == '1' && r2[z][y] == '1') valid2[x][y][z] = true;\n            }\n        }\n    }\n    \n    // Categorize positions\n    vector<tuple<int,int,int>> common, only1, only2;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && valid2[x][y][z]) {\n                    common.emplace_back(x, y, z);\n                } else if (valid1[x][y][z]) {\n                    only1.emplace_back(x, y, z);\n                } else if (valid2[x][y][z]) {\n                    only2.emplace_back(x, y, z);\n                }\n            }\n        }\n    }\n    \n    int blockId = 0;\n    vector<vector<vector<bool>>> placed1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> placed2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    // Phase 1: Create shared blocks from common positions\n    // Use BFS to create connected regions that exist in both solutions\n    for (auto [sx, sy, sz] : common) {\n        if (placed1[sx][sy][sz] || placed2[sx][sy][sz]) continue;\n        \n        // BFS to find connected common region\n        vector<tuple<int,int,int>> region;\n        queue<tuple<int,int,int>> q;\n        set<tuple<int,int,int>> visited;\n        \n        q.emplace(sx, sy, sz);\n        visited.emplace(sx, sy, sz);\n        \n        int maxRegionSize = min(8, (int)common.size() / 5 + 2);\n        \n        while (!q.empty() && (int)region.size() < maxRegionSize) {\n            auto [x, y, z] = q.front();\n            q.pop();\n            region.emplace_back(x, y, z);\n            \n            for (auto [nx, ny, nz] : getNeighbors(x, y, z)) {\n                if (visited.count({nx, ny, nz})) continue;\n                if (!valid1[nx][ny][nz] || !valid2[nx][ny][nz]) continue;\n                if (placed1[nx][ny][nz] || placed2[nx][ny][nz]) continue;\n                \n                visited.emplace(nx, ny, nz);\n                q.emplace(nx, ny, nz);\n            }\n        }\n        \n        if (region.empty()) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells = region;\n        block.normalize();\n        block.usedIn1 = true;\n        block.usedIn2 = true;\n        \n        for (auto [x, y, z] : region) {\n            placed1[x][y][z] = true;\n            placed2[x][y][z] = true;\n            b1[x][y][z] = blockId;\n            b2[x][y][z] = blockId;\n        }\n        \n        blocks.push_back(block);\n    }\n    \n    // Phase 2: Fill remaining positions in solution 1 with small blocks\n    for (auto [x, y, z] : only1) {\n        if (placed1[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = true;\n        block.usedIn2 = false;\n        \n        placed1[x][y][z] = true;\n        b1[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Also check common positions not yet placed in solution 1\n    for (auto [x, y, z] : common) {\n        if (placed1[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = true;\n        block.usedIn2 = false;\n        \n        placed1[x][y][z] = true;\n        b1[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Phase 3: Fill remaining positions in solution 2 with small blocks\n    for (auto [x, y, z] : only2) {\n        if (placed2[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = false;\n        block.usedIn2 = true;\n        \n        placed2[x][y][z] = true;\n        b2[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Also check common positions not yet placed in solution 2\n    for (auto [x, y, z] : common) {\n        if (placed2[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = false;\n        block.usedIn2 = true;\n        \n        placed2[x][y][z] = true;\n        b2[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Output\n    cout << blockId << \"\\n\";\n    \n    bool first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b1[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b2[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <tuple>\n#include <iomanip>\n\nusing namespace std;\n\n// Global data\nint N, M, K;\nvector<pair<int, int>> vertices;\nvector<tuple<int, int, int>> edges;\nvector<pair<int, int>> residents;\nvector<vector<int>> adj;\n\n// Solution\nvector<int> P;\nvector<int> B;\n\n// Precomputed: residents near each vertex (within 5000 distance)\nvector<vector<pair<int, long long>>> vertexResidents;\n\ninline long long dist2(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\ninline bool isCovered(int k, int i, int p) {\n    long long d2 = dist2(vertices[i].first, vertices[i].second, \n                         residents[k].first, residents[k].second);\n    return d2 <= 1LL * p * p;\n}\n\nvector<bool> getReachable() {\n    vector<bool> reachable(N, false);\n    vector<int> q;\n    q.reserve(N);\n    q.push_back(0);\n    reachable[0] = true;\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (int ej : adj[u]) {\n            if (B[ej]) {\n                int v = (get<0>(edges[ej]) == u) ? get<1>(edges[ej]) : get<0>(edges[ej]);\n                if (!reachable[v]) {\n                    reachable[v] = true;\n                    q.push_back(v);\n                }\n            }\n        }\n    }\n    return reachable;\n}\n\npair<int, vector<bool>> getCoverage() {\n    vector<bool> reachable = getReachable();\n    vector<bool> residentCovered(K, false);\n    int count = 0;\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i] || P[i] == 0) continue;\n        for (auto& [k, d2] : vertexResidents[i]) {\n            if (!residentCovered[k] && 1LL * P[i] * P[i] >= d2) {\n                residentCovered[k] = true;\n                count++;\n            }\n        }\n    }\n    \n    return {count, residentCovered};\n}\n\ninline long long calculateCost() {\n    long long cost = 0;\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    for (int j = 0; j < M; j++) {\n        if (B[j]) {\n            cost += get<2>(edges[j]);\n        }\n    }\n    return cost;\n}\n\nvoid precompute() {\n    vertexResidents.assign(N, vector<pair<int, long long>>());\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            long long d2 = dist2(vertices[i].first, vertices[i].second,\n                                residents[k].first, residents[k].second);\n            if (d2 <= 25000000LL) {\n                vertexResidents[i].push_back({k, d2});\n            }\n        }\n    }\n}\n\nvoid buildInitialTree() {\n    fill(B.begin(), B.end(), 0);\n    fill(P.begin(), P.end(), 0);\n    \n    vector<bool> visited(N, false);\n    vector<int> q;\n    q.reserve(N);\n    q.push_back(0);\n    visited[0] = true;\n    \n    vector<int> parentEdge(N, -1);\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (int ej : adj[u]) {\n            int v = (get<0>(edges[ej]) == u) ? get<1>(edges[ej]) : get<0>(edges[ej]);\n            if (!visited[v]) {\n                visited[v] = true;\n                parentEdge[v] = ej;\n                q.push_back(v);\n            }\n        }\n    }\n    \n    for (int i = 1; i < N; i++) {\n        if (parentEdge[i] >= 0) {\n            B[parentEdge[i]] = 1;\n        }\n    }\n}\n\nvoid optimizeP() {\n    vector<bool> reachable = getReachable();\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i]) {\n            P[i] = 0;\n        }\n    }\n    \n    for (int iter = 0; iter < 3; iter++) {\n        auto [covered, residentCovered] = getCoverage();\n        \n        if (covered == K) {\n            for (int i = 0; i < N; i++) {\n                if (!reachable[i] || P[i] == 0) continue;\n                \n                int oldP = P[i];\n                int lo = 0, hi = P[i];\n                while (lo < hi) {\n                    int mid = (lo + hi) / 2;\n                    P[i] = mid;\n                    auto [c, rc] = getCoverage();\n                    if (c == K) {\n                        hi = mid;\n                    } else {\n                        lo = mid + 1;\n                    }\n                }\n                P[i] = lo;\n                \n                auto [c, rc] = getCoverage();\n                if (c < K) {\n                    P[i] = oldP;\n                }\n            }\n        } else {\n            for (int k = 0; k < K; k++) {\n                if (residentCovered[k]) continue;\n                \n                int bestI = -1;\n                int bestNeeded = 5001;\n                long long bestCostIncrease = 1LL << 60;\n                \n                for (int i = 0; i < N; i++) {\n                    if (!reachable[i]) continue;\n                    \n                    long long d2 = dist2(vertices[i].first, vertices[i].second,\n                                        residents[k].first, residents[k].second);\n                    if (d2 > 25000000LL) continue;\n                    \n                    int needed = (int)ceil(sqrt(d2));\n                    if (needed > 5000) continue;\n                    \n                    int newP = max(P[i], needed);\n                    long long costIncrease = 1LL * newP * newP - 1LL * P[i] * P[i];\n                    \n                    if (costIncrease < bestCostIncrease) {\n                        bestCostIncrease = costIncrease;\n                        bestI = i;\n                        bestNeeded = needed;\n                    }\n                }\n                \n                if (bestI >= 0) {\n                    P[bestI] = max(P[bestI], bestNeeded);\n                }\n            }\n        }\n    }\n}\n\nvoid localSearch(double timeLimit) {\n    auto startTime = chrono::high_resolution_clock::now();\n    \n    auto [bestCovered, bestResidentCovered] = getCoverage();\n    long long bestCost = calculateCost();\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int noImprove = 0;\n    while (true) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        \n        if (elapsed > timeLimit) break;\n        if (noImprove > 5000 && bestCovered == K) break;\n        \n        double temp = max(0.01, 1.0 - elapsed / timeLimit);\n        \n        int edgeIdx = uniform_int_distribution<int>(0, M - 1)(rng);\n        int oldB = B[edgeIdx];\n        B[edgeIdx] = 1 - oldB;\n        \n        auto [newCovered, newResidentCovered] = getCoverage();\n        long long newCost = calculateCost();\n        \n        bool accept = false;\n        if (newCovered > bestCovered) {\n            accept = true;\n        } else if (newCovered == bestCovered) {\n            if (newCost < bestCost) {\n                accept = true;\n            } else if (bestCovered == K) {\n                double delta = (double)(newCost - bestCost);\n                double prob = exp(-delta / (50000.0 * temp));\n                if (uniform_real_distribution<double>(0, 1)(rng) < prob) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept) {\n            if (newCovered > bestCovered || (newCovered == bestCovered && newCost < bestCost)) {\n                bestCovered = newCovered;\n                bestResidentCovered = newResidentCovered;\n                bestCost = newCost;\n                noImprove = 0;\n            }\n            if (noImprove % 20 == 0) {\n                optimizeP();\n                auto [c, rc] = getCoverage();\n                long long cost = calculateCost();\n                if (c > bestCovered || (c == bestCovered && cost < bestCost)) {\n                    bestCovered = c;\n                    bestResidentCovered = rc;\n                    bestCost = cost;\n                    noImprove = 0;\n                }\n            }\n        } else {\n            B[edgeIdx] = oldB;\n            noImprove++;\n        }\n        \n        if (elapsed > timeLimit * 0.7 && bestCovered < K) {\n            for (int tryCount = 0; tryCount < 3; tryCount++) {\n                int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n                if (B[e1] == 0) {\n                    B[e1] = 1;\n                    auto [c, rc] = getCoverage();\n                    if (c >= bestCovered) {\n                        bestCovered = c;\n                        bestResidentCovered = rc;\n                        bestCost = calculateCost();\n                        noImprove = 0;\n                    } else {\n                        B[e1] = 0;\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    vertices.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> vertices[i].first >> vertices[i].second;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    for (int j = 0; j < M; j++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back(j);\n        adj[v].push_back(j);\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].first >> residents[k].second;\n    }\n    \n    P.resize(N, 0);\n    B.resize(M, 0);\n    \n    precompute();\n    buildInitialTree();\n    optimizeP();\n    localSearch(1.95);\n    optimizeP();\n    \n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\n\nstruct Coord {\n    int x, y;\n    bool operator==(const Coord& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Coord& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n};\n\nint grid[N][N];\nCoord pos[TOTAL_BALLS];\n\n// 6 adjacent directions\nconst int DX[6] = {-1, -1, 0, 0, 1, 1};\nconst int DY[6] = {-1, 0, -1, 1, 0, 1};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvector<Coord> getAdjacent(int x, int y) {\n    vector<Coord> adj;\n    for (int i = 0; i < 6; i++) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (isValid(nx, ny)) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\nbool areAdjacent(Coord c1, Coord c2) {\n    for (int i = 0; i < 6; i++) {\n        int nx = c1.x + DX[i];\n        int ny = c1.y + DY[i];\n        if (nx == c2.x && ny == c2.y) return true;\n    }\n    return false;\n}\n\n// BFS with heuristic (A* like)\nvector<Coord> findPath(Coord start, Coord end, const vector<vector<bool>>& blocked) {\n    if (start == end) return {start};\n    \n    priority_queue<tuple<int, int, Coord>, vector<tuple<int, int, Coord>>, greater<>> pq;\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<Coord>> parent(N, vector<Coord>(N, {-1, -1}));\n    \n    auto heuristic = [](Coord a, Coord b) {\n        return abs(a.x - b.x) + abs(a.y - b.y);\n    };\n    \n    dist[start.x][start.y] = 0;\n    pq.push({heuristic(start, end), 0, start});\n    \n    while (!pq.empty()) {\n        auto [f, d, curr] = pq.top();\n        pq.pop();\n        \n        if (d > dist[curr.x][curr.y]) continue;\n        if (curr == end) {\n            vector<Coord> path;\n            Coord c = end;\n            while (c != start) {\n                path.push_back(c);\n                c = parent[c.x][c.y];\n            }\n            path.push_back(start);\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto& next : getAdjacent(curr.x, curr.y)) {\n            if (blocked[next.x][next.y]) continue;\n            int nd = d + 1;\n            if (nd < dist[next.x][next.y]) {\n                dist[next.x][next.y] = nd;\n                parent[next.x][next.y] = curr;\n                pq.push({nd + heuristic(next, end), nd, next});\n            }\n        }\n    }\n    \n    return {};\n}\n\nvector<tuple<int,int,int,int>> operations;\n\nvoid swapBalls(Coord c1, Coord c2) {\n    if (c1 == c2 || !areAdjacent(c1, c2)) return;\n    if (operations.size() >= 10000) return;\n    \n    operations.push_back({c1.x, c1.y, c2.x, c2.y});\n    \n    int val1 = grid[c1.x][c1.y];\n    int val2 = grid[c2.x][c2.y];\n    \n    grid[c1.x][c1.y] = val2;\n    grid[c2.x][c2.y] = val1;\n    \n    pos[val1] = c2;\n    pos[val2] = c1;\n}\n\nvoid moveBall(int value, Coord target) {\n    Coord current = pos[value];\n    \n    while (current != target && operations.size() < 9500) {\n        vector<vector<bool>> blocked(N, vector<bool>(N, false));\n        // Block positions of balls that are already in place (smaller values)\n        for (int v = 0; v < value; v++) {\n            blocked[pos[v].x][pos[v].y] = true;\n        }\n        blocked[target.x][target.y] = false; // Allow target\n        \n        auto path = findPath(current, target, blocked);\n        if (path.size() < 2) {\n            // Try without blocking\n            vector<vector<bool>> empty(N, vector<bool>(N, false));\n            path = findPath(current, target, empty);\n        }\n        \n        if (path.size() < 2) break;\n        \n        Coord next = path[1];\n        swapBalls(current, next);\n        current = pos[value];\n    }\n}\n\nint countViolations() {\n    int E = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (grid[x][y] > grid[x + 1][y]) E++;\n            if (grid[x][y] > grid[x + 1][y + 1]) E++;\n        }\n    }\n    return E;\n}\n\nvoid fixViolations() {\n    bool improved = true;\n    while (improved && operations.size() < 10000) {\n        improved = false;\n        for (int x = 0; x < N - 1 && operations.size() < 10000; x++) {\n            for (int y = 0; y <= x && operations.size() < 10000; y++) {\n                // Check violation with left child\n                if (grid[x][y] > grid[x + 1][y]) {\n                    if (areAdjacent({x, y}, {x + 1, y})) {\n                        swapBalls({x, y}, {x + 1, y});\n                        improved = true;\n                    }\n                }\n                // Check violation with right child\n                if (grid[x][y] > grid[x + 1][y + 1]) {\n                    if (areAdjacent({x, y}, {x + 1, y + 1})) {\n                        swapBalls({x, y}, {x + 1, y + 1});\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n            pos[grid[x][y]] = {x, y};\n        }\n    }\n    \n    // Create sorted list of balls with their target positions\n    vector<pair<int, Coord>> balls(TOTAL_BALLS);\n    int idx = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            balls[idx++] = {grid[x][y], {x, y}};\n        }\n    }\n    \n    // Sort by value - smaller values should go to top\n    sort(balls.begin(), balls.end());\n    \n    // Target positions in tier order\n    vector<Coord> targets(TOTAL_BALLS);\n    idx = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            targets[idx++] = {x, y};\n        }\n    }\n    \n    // Move balls to target positions (smallest first)\n    for (int i = 0; i < TOTAL_BALLS && operations.size() < 9000; i++) {\n        int value = balls[i].first;\n        Coord target = targets[i];\n        moveBall(value, target);\n    }\n    \n    // Fix remaining violations\n    fixViolations();\n    \n    // Output\n    cout << operations.size() << \"\\n\";\n    for (auto& op : operations) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = 4;\n\nstruct Container {\n    int id;\n    int r, c;\n};\n\nint grid[D][D];  // -1: empty, -2: obstacle, >=0: container id\nint dist_from_entrance[D][D];\nvector<pair<int, int>> empty_squares;\nvector<Container> containers;\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\nbool isValid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D && grid[r][c] != -2;\n}\n\n// BFS to find all reachable empty squares from entrance\nvector<vector<bool>> computeReachable() {\n    vector<vector<bool>> reachable(D, vector<bool>(D, false));\n    queue<pair<int, int>> q;\n    \n    q.push({ENTRANCE_R, ENTRANCE_C});\n    reachable[ENTRANCE_R][ENTRANCE_C] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && grid[nr][nc] == -1 && !reachable[nr][nc]) {\n                reachable[nr][nc] = true;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return reachable;\n}\n\n// Check if container at (r, c) is reachable (adjacent to reachable empty square)\nbool isContainerReachable(int r, int c) {\n    for (int i = 0; i < 4; i++) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        \n        if (isValid(nr, nc) && grid[nr][nc] == -1) {\n            auto reachable = computeReachable();\n            if (reachable[nr][nc]) return true;\n        }\n    }\n    return false;\n}\n\n// Check if placing container maintains connectivity for all existing containers\nbool canPlace(int r, int c) {\n    if (!isValid(r, c) || grid[r][c] != -1) return false;\n    \n    grid[r][c] = -3;  // Temporarily occupied\n    \n    bool ok = true;\n    for (const auto& cont : containers) {\n        if (!isContainerReachable(cont.r, cont.c)) {\n            ok = false;\n            break;\n        }\n    }\n    \n    grid[r][c] = -1;\n    return ok;\n}\n\nvoid computeDistances() {\n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            dist_from_entrance[i][j] = 1e9;\n        }\n    }\n    \n    queue<pair<int, int>> q;\n    q.push({ENTRANCE_R, ENTRANCE_C});\n    dist_from_entrance[ENTRANCE_R][ENTRANCE_C] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && dist_from_entrance[nr][nc] > dist_from_entrance[r][c] + 1) {\n                dist_from_entrance[nr][nc] = dist_from_entrance[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            grid[i][j] = -1;\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -2;\n    }\n    \n    computeDistances();\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            if (grid[i][j] == -1 && !(i == ENTRANCE_R && j == ENTRANCE_C)) {\n                empty_squares.push_back({i, j});\n            }\n        }\n    }\n    \n    sort(empty_squares.begin(), empty_squares.end(), [](const pair<int, int>& a, const pair<int, int>& b) {\n        return dist_from_entrance[a.first][a.second] < dist_from_entrance[b.first][b.second];\n    });\n    \n    int total_containers = D * D - 1 - N;\n    \n    for (int d = 0; d < total_containers; d++) {\n        int container_id;\n        cin >> container_id;\n        \n        int best_r = -1, best_c = -1;\n        int best_score = 1e9;\n        \n        for (const auto& [r, c] : empty_squares) {\n            if (grid[r][c] == -1 && canPlace(r, c)) {\n                int score = dist_from_entrance[r][c] * 100;\n                if (container_id < total_containers / 2) {\n                    score -= 50;  // Prefer closer for smaller IDs\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        grid[best_r][best_c] = container_id;\n        containers.push_back({container_id, best_r, best_c});\n        \n        cout << best_r << \" \" << best_c << endl;\n    }\n    \n    // Retrieval: output in order 0, 1, 2, ...\n    vector<bool> retrieved(total_containers, false);\n    vector<pair<int, int>> output_order;\n    \n    for (int target_id = 0; target_id < total_containers; target_id++) {\n        for (auto& cont : containers) {\n            if (cont.id == target_id && !retrieved[target_id]) {\n                if (isContainerReachable(cont.r, cont.c)) {\n                    output_order.push_back({cont.r, cont.c});\n                    retrieved[target_id] = true;\n                    grid[cont.r][cont.c] = -1;  // Remove container\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Output any remaining\n    for (auto& cont : containers) {\n        if (!retrieved[cont.id]) {\n            output_order.push_back({cont.r, cont.c});\n        }\n    }\n    \n    for (const auto& [r, c] : output_order) {\n        cout << r << \" \" << c << endl;\n    }\n    \n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <atcoder/all>\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nint grid[N][N];\nint adj[M + 1][M + 1];  // adjacency matrix\nint color_count[M + 1]; // count of each color\n\n// Check if a color region is connected using BFS\nbool check_connectivity(int c) {\n    vector<pair<int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == c) {\n                cells.push_back({i, j});\n            }\n        }\n    }\n    if (cells.empty()) return c == 0; // color 0 can be empty (connects through outside)\n    \n    // BFS from first cell\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    queue<pair<int, int>> q;\n    q.push(cells[0]);\n    visited[cells[0].first][cells[0].second] = true;\n    int count = 1;\n    \n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\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                !visited[ni][nj] && grid[ni][nj] == c) {\n                visited[ni][nj] = true;\n                count++;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return count == (int)cells.size();\n}\n\n// Check if all color regions are connected\nbool check_all_connectivity() {\n    for (int c = 1; c <= m; c++) {\n        if (!check_connectivity(c)) return false;\n    }\n    // Color 0 connectivity through outside is automatic if other colors are connected\n    return true;\n}\n\n// Build adjacency matrix from current grid\nvoid build_adjacency() {\n    memset(adj, 0, sizeof(adj));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    // Boundary touches color 0\n                    adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Get current adjacency from grid\nvoid get_current_adjacency(int cur_adj[M + 1][M + 1]) {\n    memset(cur_adj, 0, sizeof(int) * (M + 1) * (M + 1));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        cur_adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    cur_adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Check if adjacency is preserved\nbool check_adjacency_preserved() {\n    int cur_adj[M + 1][M + 1];\n    get_current_adjacency(cur_adj);\n    \n    for (int c1 = 0; c1 <= m; c1++) {\n        for (int c2 = c1 + 1; c2 <= m; c2++) {\n            if (adj[c1][c2] != cur_adj[c1][c2]) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Count color 0 squares\nint count_zeros() {\n    int cnt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == 0) cnt++;\n        }\n    }\n    return cnt;\n}\n\n// Try to fill a 0 cell with a color\nbool try_fill_zero(int i, int j, int c) {\n    if (grid[i][j] != 0) return false;\n    \n    int old = grid[i][j];\n    grid[i][j] = c;\n    \n    // Check connectivity\n    if (!check_connectivity(c)) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    // Check adjacency preservation\n    if (!check_adjacency_preserved()) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    return true;\n}\n\n// Get colors adjacent to position (i, j)\nvector<int> get_adjacent_colors(int i, int j) {\n    vector<int> colors;\n    vector<bool> seen(M + 1, false);\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\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            int c = grid[ni][nj];\n            if (c != 0 && !seen[c]) {\n                seen[c] = true;\n                colors.push_back(c);\n            }\n        } else {\n            if (!seen[0]) {\n                seen[0] = true;\n                colors.push_back(0);\n            }\n        }\n    }\n    return colors;\n}\n\n// Check if filling (i,j) with color c would create unwanted adjacency\nbool would_create_bad_adjacency(int i, int j, int c) {\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int d = 0; d < 4; d++) {\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        int neighbor_c;\n        if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n            neighbor_c = grid[ni][nj];\n        } else {\n            neighbor_c = 0;\n        }\n        \n        if (neighbor_c != c && neighbor_c != 0) {\n            // Check if c and neighbor_c should be adjacent\n            if (!adj[min(c, neighbor_c)][max(c, neighbor_c)]) {\n                return true; // Would create unwanted adjacency\n            }\n        }\n    }\n    return false;\n}\n\n// Check if filling (i,j) with color c would miss required adjacency\nbool would_miss_adjacency(int i, int j, int c) {\n    // This is harder to check locally, skip for now\n    return false;\n}\n\n// Greedy fill zeros\nvoid greedy_fill() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        vector<tuple<int, int, int>> candidates;\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    vector<int> adj_colors = get_adjacent_colors(i, j);\n                    for (int c : adj_colors) {\n                        if (c == 0) continue;\n                        if (!would_create_bad_adjacency(i, j, c)) {\n                            candidates.push_back({i, j, c});\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try candidates in random order\n        shuffle(candidates.begin(), candidates.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count()));\n        \n        for (auto [i, j, c] : candidates) {\n            if (grid[i][j] == 0 && try_fill_zero(i, j, c)) {\n                changed = true;\n                break; // Restart to be safe\n            }\n        }\n    }\n}\n\n// Simulated annealing style local search\nvoid local_search() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 5000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find a 0 cell\n        vector<pair<int, int>> zeros;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    zeros.push_back({i, j});\n                }\n            }\n        }\n        \n        if (zeros.empty()) break;\n        \n        auto [i, j] = zeros[rng() % zeros.size()];\n        vector<int> adj_colors = get_adjacent_colors(i, j);\n        \n        if (adj_colors.empty()) continue;\n        \n        int c = adj_colors[rng() % adj_colors.size()];\n        if (c == 0) continue;\n        \n        if (try_fill_zero(i, j, c)) {\n            // Success, continue\n        }\n    }\n}\n\n// Compact regions by moving boundary cells\nvoid compact_regions() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 3000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find boundary cells (colored cells adjacent to 0)\n        vector<tuple<int, int, int>> boundaries; // i, j, color\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0) {\n                    int di[] = {0, 0, 1, -1};\n                    int dj[] = {1, -1, 0, 0};\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 && grid[ni][nj] == 0) {\n                            boundaries.push_back({i, j, grid[i][j]});\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (boundaries.empty()) break;\n        \n        auto [i, j, c] = boundaries[rng() % boundaries.size()];\n        \n        // Try to expand into adjacent 0\n        int di[] = {0, 0, 1, -1};\n        int dj[] = {1, -1, 0, 0};\n        \n        vector<pair<int, int>> adjacent_zeros;\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 && grid[ni][nj] == 0) {\n                adjacent_zeros.push_back({ni, nj});\n            }\n        }\n        \n        if (adjacent_zeros.empty()) continue;\n        \n        auto [ni, nj] = adjacent_zeros[rng() % adjacent_zeros.size()];\n        \n        if (!would_create_bad_adjacency(ni, nj, c)) {\n            int old = grid[ni][nj];\n            grid[ni][nj] = c;\n            \n            if (check_connectivity(c) && check_adjacency_preserved()) {\n                // Keep the change\n            } else {\n                grid[ni][nj] = old;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    \n    int zeros = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> grid[i][j];\n            if (grid[i][j] == 0) zeros++;\n            color_count[grid[i][j]]++;\n        }\n    }\n    \n    // Build target adjacency from input\n    build_adjacency();\n    \n    // Phase 1: Greedy fill\n    greedy_fill();\n    \n    // Phase 2: Local search\n    local_search();\n    \n    // Phase 3: Compact regions\n    compact_regions();\n    \n    // Phase 4: Final greedy pass\n    greedy_fill();\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cout << grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Estimate weights through comparisons\n    // Use a reference-based approach: compare each item against a reference set\n    vector<double> estimated_weight(N, 1.0);\n    vector<int> win_count(N, 0);\n    vector<int> lose_count(N, 0);\n    \n    // Phase 1: Pairwise comparisons to build relative ranking\n    // Use tournament-style comparisons\n    int queries_used = 0;\n    \n    // First, do pairwise comparisons between items\n    // Compare item i vs item j by putting them on opposite sides\n    for (int i = 0; i < N && queries_used < Q; i++) {\n        for (int j = i + 1; j < N && queries_used < Q; j++) {\n            // Compare single items\n            cout << \"1 1 \" << i << \" \" << j << endl;\n            queries_used++;\n            \n            string result;\n            cin >> result;\n            \n            if (result == \">\") {\n                win_count[i]++;\n                lose_count[j]++;\n            } else if (result == \"<\") {\n                lose_count[i]++;\n                win_count[j]++;\n            }\n            // \"=\" means equal, no change\n        }\n    }\n    \n    // Calculate estimated weights based on win/loss ratio\n    for (int i = 0; i < N; i++) {\n        int total = win_count[i] + lose_count[i];\n        if (total > 0) {\n            estimated_weight[i] = 1.0 + (double)win_count[i] / total;\n        }\n    }\n    \n    // If we have remaining queries, do more refined comparisons\n    // Compare items against groups to get better estimates\n    while (queries_used < Q) {\n        // Pick two random items to compare\n        static mt19937 rng(42);\n        int i = rng() % N;\n        int j = rng() % N;\n        if (i == j) continue;\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        if (result == \">\") {\n            estimated_weight[i] += 0.1;\n            estimated_weight[j] -= 0.05;\n        } else if (result == \"<\") {\n            estimated_weight[i] -= 0.05;\n            estimated_weight[j] += 0.1;\n        }\n    }\n    \n    // Phase 2: Partition items into D sets\n    // Use greedy approach: sort by estimated weight, assign to lightest bin\n    \n    // Create indices sorted by estimated weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return estimated_weight[a] > estimated_weight[b];\n    });\n    \n    // Initialize D bins\n    vector<vector<int>> bins(D);\n    vector<double> bin_weight(D, 0.0);\n    \n    // Greedy assignment: assign heaviest items first to lightest bin\n    for (int idx : indices) {\n        // Find bin with minimum current weight\n        int min_bin = 0;\n        for (int d = 1; d < D; d++) {\n            if (bin_weight[d] < bin_weight[min_bin]) {\n                min_bin = d;\n            }\n        }\n        bins[min_bin].push_back(idx);\n        bin_weight[min_bin] += estimated_weight[idx];\n    }\n    \n    // Phase 3: Local optimization to reduce variance\n    // Try swapping items between bins to reduce variance\n    auto calc_variance = [&]() -> double {\n        double mean = 0.0;\n        for (double w : bin_weight) mean += w;\n        mean /= D;\n        double var = 0.0;\n        for (double w : bin_weight) {\n            double diff = w - mean;\n            var += diff * diff;\n        }\n        return var / D;\n    };\n    \n    // Local search optimization\n    bool improved = true;\n    int max_iterations = 1000;\n    int iteration = 0;\n    \n    while (improved && iteration < max_iterations) {\n        improved = false;\n        iteration++;\n        \n        double current_var = calc_variance();\n        \n        // Try swapping pairs of items between different bins\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = d1 + 1; d2 < D && !improved; d2++) {\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    for (int j = 0; j < (int)bins[d2].size() && !improved; j++) {\n                        int item1 = bins[d1][i];\n                        int item2 = bins[d2][j];\n                        \n                        // Calculate new weights if we swap\n                        double new_w1 = bin_weight[d1] - estimated_weight[item1] + estimated_weight[item2];\n                        double new_w2 = bin_weight[d2] - estimated_weight[item2] + estimated_weight[item1];\n                        \n                        // Check if this reduces variance\n                        double mean = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            if (d == d1) mean += new_w1;\n                            else if (d == d2) mean += new_w2;\n                            else mean += bin_weight[d];\n                        }\n                        mean /= D;\n                        \n                        double new_var = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                            double diff = w - mean;\n                            new_var += diff * diff;\n                        }\n                        new_var /= D;\n                        \n                        if (new_var < current_var - 1e-9) {\n                            // Perform swap\n                            swap(bins[d1][i], bins[d2][j]);\n                            bin_weight[d1] = new_w1;\n                            bin_weight[d2] = new_w2;\n                            improved = true;\n                            current_var = new_var;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Also try moving single items\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = 0; d2 < D && !improved; d2++) {\n                if (d1 == d2) continue;\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    int item = bins[d1][i];\n                    \n                    double new_w1 = bin_weight[d1] - estimated_weight[item];\n                    double new_w2 = bin_weight[d2] + estimated_weight[item];\n                    \n                    double mean = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        if (d == d1) mean += new_w1;\n                        else if (d == d2) mean += new_w2;\n                        else mean += bin_weight[d];\n                    }\n                    mean /= D;\n                    \n                    double new_var = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                        double diff = w - mean;\n                        new_var += diff * diff;\n                    }\n                    new_var /= D;\n                    \n                    if (new_var < current_var - 1e-9) {\n                        bins[d1].erase(bins[d1].begin() + i);\n                        bins[d2].push_back(item);\n                        bin_weight[d1] = new_w1;\n                        bin_weight[d2] = new_w2;\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Create output assignment\n    vector<int> assignment(N);\n    for (int d = 0; d < D; d++) {\n        for (int item : bins[d]) {\n            assignment[item] = d;\n        }\n    }\n    \n    // Output final assignment\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    int boxes_per_stack = n / m;\n    \n    // stacks[i] contains boxes from bottom to top\n    vector<vector<int>> stacks(m);\n    // pos[v] = {stack_index, height_index} for box v\n    vector<pair<int, int>> pos(n + 1);\n    \n    for (int i = 0; i < m; i++) {\n        stacks[i].resize(boxes_per_stack);\n        for (int j = 0; j < boxes_per_stack; j++) {\n            cin >> stacks[i][j];\n            pos[stacks[i][j]] = {i, j};\n        }\n    }\n    \n    vector<pair<int, int>> operations;\n    int total_energy = 0;\n    \n    // Remove boxes 1 to n in order\n    for (int v = 1; v <= n; v++) {\n        auto [stack_idx, height_idx] = pos[v];\n        \n        // Check if box v is at the top of its stack\n        if (height_idx == (int)stacks[stack_idx].size() - 1) {\n            // Box is at top, can remove directly\n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1}; // Mark as removed\n        } else {\n            // Need to move boxes above v to other stacks\n            int boxes_to_move = stacks[stack_idx].size() - 1 - height_idx;\n            \n            // Move each box above v to another stack\n            for (int h = stacks[stack_idx].size() - 1; h > height_idx; h--) {\n                int box_to_move = stacks[stack_idx][h];\n                \n                // Find best destination stack (prefer fewer boxes, not current stack)\n                int best_stack = -1;\n                int min_size = n + 1;\n                \n                for (int s = 0; s < m; s++) {\n                    if (s != stack_idx && (int)stacks[s].size() < min_size) {\n                        min_size = stacks[s].size();\n                        best_stack = s;\n                    }\n                }\n                \n                if (best_stack == -1) {\n                    // Fallback: any stack except current\n                    for (int s = 0; s < m; s++) {\n                        if (s != stack_idx) {\n                            best_stack = s;\n                            break;\n                        }\n                    }\n                }\n                \n                // Move box_to_move and all above it (just this box since we're at top)\n                operations.push_back({box_to_move, best_stack + 1});\n                total_energy += 2; // 1 box + 1 = 2 energy\n                \n                // Update stacks\n                stacks[best_stack].push_back(box_to_move);\n                stacks[stack_idx].pop_back();\n                pos[box_to_move] = {best_stack, (int)stacks[best_stack].size() - 1};\n            }\n            \n            // Now box v should be at top\n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        }\n    }\n    \n    // Output operations\n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\n\";\n    }\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<string> h, v;\nvector<vector<int>> d;\nvector<vector<bool>> visited;\nstring result;\n\n// Direction vectors: R, D, L, U\nconst int DI[4] = {0, 1, 0, -1};\nconst int DJ[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nbool canMove(int i, int j, int dir) {\n    int ni = i + DI[dir];\n    int nj = j + DJ[dir];\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    if (dir == 0) { // Right\n        return v[i][j] == '0';\n    } else if (dir == 1) { // Down\n        return h[i][j] == '0';\n    } else if (dir == 2) { // Left\n        return v[i][nj] == '0';\n    } else { // Up\n        return h[ni][j] == '0';\n    }\n}\n\n// BFS to find shortest path from (si,sj) to (ti,tj)\nvector<int> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parentDir(N, vector<int>(N, -1));\n    \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();\n        q.pop();\n        \n        if (i == ti && j == tj) break;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    parent[ni][nj] = {i, j};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (dist[ti][tj] == -1) return {};\n    \n    vector<int> path;\n    int ci = ti, cj = tj;\n    while (ci != si || cj != sj) {\n        path.push_back(parentDir[ci][cj]);\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// DFS to build spanning tree and initial tour\nvoid dfsTour(int i, int j, vector<vector<bool>>& treeVisited) {\n    treeVisited[i][j] = true;\n    \n    for (int dir = 0; dir < 4; dir++) {\n        if (canMove(i, j, dir)) {\n            int ni = i + DI[dir];\n            int nj = j + DJ[dir];\n            if (!treeVisited[ni][nj]) {\n                result += DIR_CHAR[dir];\n                dfsTour(ni, nj, treeVisited);\n                result += DIR_CHAR[(dir + 2) % 4]; // Return\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    h.resize(N - 1);\n    for (int i = 0; i < N - 1; i++) {\n        cin >> h[i];\n    }\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> v[i];\n    }\n    \n    d.resize(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    }\n    \n    // Create initial tour using DFS spanning tree\n    vector<vector<bool>> treeVisited(N, vector<bool>(N, false));\n    dfsTour(0, 0, treeVisited);\n    \n    // Calculate total dirt sum for prioritization\n    long long totalDirt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            totalDirt += d[i][j];\n        }\n    }\n    \n    // Identify high-priority cells (top 30% by dirt value)\n    vector<tuple<int, int, int>> cells; // (dirt, i, j)\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cells.push_back({d[i][j], i, j});\n        }\n    }\n    sort(cells.begin(), cells.end(), greater<tuple<int,int,int>>());\n    \n    // Budget for extra visits (keep under 10^5)\n    int maxLen = 100000;\n    int currentLen = result.size();\n    int budget = maxLen - currentLen - 1000; // Leave some margin\n    \n    // Add extra visits to high-priority cells\n    // Strategy: Insert visits to top cells by going from current position and back\n    int posI = 0, posJ = 0;\n    \n    for (auto& [dirt, ti, tj] : cells) {\n        if (budget <= 10) break;\n        \n        // Only add extra visits for high-dirt cells\n        if (dirt < totalDirt / (N * N) * 1.5) break;\n        \n        // Find path from current position to target and back\n        vector<int> pathTo = bfsPath(posI, posJ, ti, tj);\n        if (pathTo.empty()) continue;\n        \n        vector<int> pathBack = bfsPath(ti, tj, posI, posJ);\n        if (pathBack.empty()) continue;\n        \n        int pathLen = pathTo.size() + pathBack.size();\n        if (pathLen > budget) continue;\n        \n        // Insert the round trip\n        for (int dir : pathTo) {\n            result += DIR_CHAR[dir];\n            posI += DI[dir];\n            posJ += DJ[dir];\n        }\n        for (int dir : pathBack) {\n            result += DIR_CHAR[dir];\n            posI += DI[dir];\n            posJ += DJ[dir];\n        }\n        \n        budget -= pathLen;\n    }\n    \n    // Ensure we end at (0,0)\n    if (posI != 0 || posJ != 0) {\n        vector<int> pathHome = bfsPath(posI, posJ, 0, 0);\n        for (int dir : pathHome) {\n            result += DIR_CHAR[dir];\n        }\n    }\n    \n    // Verify all cells are visited\n    vector<vector<bool>> allVisited(N, vector<bool>(N, false));\n    int ci = 0, cj = 0;\n    allVisited[ci][cj] = true;\n    for (char c : result) {\n        int dir;\n        if (c == 'R') dir = 0;\n        else if (c == 'D') dir = 1;\n        else if (c == 'L') dir = 2;\n        else dir = 3;\n        ci += DI[dir];\n        cj += DJ[dir];\n        allVisited[ci][cj] = true;\n    }\n    \n    // If any cell not visited, do a final sweep\n    bool allGood = true;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!allVisited[i][j]) {\n                allGood = false;\n                break;\n            }\n        }\n        if (!allGood) break;\n    }\n    \n    if (!allGood) {\n        // Fallback: rebuild with guaranteed coverage\n        result.clear();\n        vector<vector<bool>> treeVisited2(N, vector<bool>(N, false));\n        dfsTour(0, 0, treeVisited2);\n    }\n    \n    cout << result << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    vector<int> order;\n    string str;\n    double cost;\n};\n\nint N, M, si, sj;\nvector<string> A;\nvector<string> t;\nvector<vector<pair<int,int>>> charPos(26);\nvector<vector<int>> overlap;\nmt19937 rng;\n\n// Calculate overlap between two words\nint calcOverlap(const string& a, const string& b) {\n    int maxOv = 0;\n    for (int ov = 1; ov < min((int)a.size(), (int)b.size()); ov++) {\n        if (a.substr(a.size() - ov) == b.substr(0, ov)) {\n            maxOv = ov;\n        }\n    }\n    return maxOv;\n}\n\n// Build string from word order\nstring buildString(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s = t[order[0]];\n    for (size_t i = 1; i < order.size(); i++) {\n        int ov = overlap[order[i-1]][order[i]];\n        s += t[order[i]].substr(ov);\n    }\n    return s;\n}\n\n// Estimate minimum cost for a string (greedy position selection)\ndouble estimateCost(const string& s) {\n    if (s.empty()) return 0;\n    int curI = si, curJ = sj;\n    double cost = 0;\n    for (char c : s) {\n        int idx = c - 'A';\n        int minDist = INT_MAX;\n        for (auto [ni, nj] : charPos[idx]) {\n            int dist = abs(ni - curI) + abs(nj - curJ) + 1;\n            minDist = min(minDist, dist);\n        }\n        cost += minDist;\n        // Update to best position (approximate)\n        for (auto [ni, nj] : charPos[idx]) {\n            if (abs(ni - curI) + abs(nj - curJ) + 1 == minDist) {\n                curI = ni;\n                curJ = nj;\n                break;\n            }\n        }\n    }\n    return cost;\n}\n\n// Optimized position selection with lookahead\nvector<pair<int,int>> optimizePositions(const string& s) {\n    int L = s.size();\n    if (L == 0) return {};\n    \n    vector<pair<int,int>> path(L);\n    int curI = si, curJ = sj;\n    \n    for (int pos = 0; pos < L; pos++) {\n        int idx = s[pos] - 'A';\n        int bestI = -1, bestJ = -1;\n        int bestScore = INT_MAX;\n        \n        // Lookahead window\n        int lookahead = min(3, L - pos - 1);\n        \n        for (auto [ni, nj] : charPos[idx]) {\n            int score = abs(ni - curI) + abs(nj - curJ) + 1;\n            \n            // Add estimated cost for next few characters\n            int nextI = ni, nextJ = nj;\n            for (int k = 1; k <= lookahead; k++) {\n                int nextIdx = s[pos + k] - 'A';\n                int minNext = INT_MAX;\n                for (auto [ni2, nj2] : charPos[nextIdx]) {\n                    int d = abs(ni2 - nextI) + abs(nj2 - nextJ) + 1;\n                    if (d < minNext) {\n                        minNext = d;\n                        // Don't actually update, just estimate\n                    }\n                }\n                score += minNext * 0.5; // Discount future costs\n            }\n            \n            if (score < bestScore) {\n                bestScore = score;\n                bestI = ni;\n                bestJ = nj;\n            }\n        }\n        \n        path[pos] = {bestI, bestJ};\n        curI = bestI;\n        curJ = bestJ;\n    }\n    \n    return path;\n}\n\n// Simulated annealing for word ordering\nState simulatedAnnealing(State initial, double timeLimit) {\n    auto startTime = chrono::steady_clock::now();\n    \n    State current = initial;\n    State best = initial;\n    \n    double temp = 1000.0;\n    double coolingRate = 0.9995;\n    int iteration = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - startTime).count();\n        if (elapsed > timeLimit * 0.85) break;\n        \n        // Generate neighbor by swapping two words\n        State neighbor = current;\n        int i1 = rng() % M;\n        int i2 = rng() % M;\n        if (i1 != i2) {\n            swap(neighbor.order[i1], neighbor.order[i2]);\n            neighbor.str = buildString(neighbor.order);\n            neighbor.cost = estimateCost(neighbor.str);\n        }\n        \n        // Accept or reject\n        double delta = neighbor.cost - current.cost;\n        if (delta < 0 || exp(-delta / temp) > (double)rng() / rng.max()) {\n            current = neighbor;\n            if (current.cost < best.cost) {\n                best = current;\n            }\n        }\n        \n        temp *= coolingRate;\n        iteration++;\n    }\n    \n    return best;\n}\n\n// Greedy with different heuristics\nState greedyWithHeuristic(int startWord, int heuristic) {\n    vector<bool> used(M, false);\n    vector<int> order;\n    \n    order.push_back(startWord);\n    used[startWord] = true;\n    \n    for (int i = 1; i < M; i++) {\n        int bestNext = -1;\n        double bestScore = -1e18;\n        \n        for (int j = 0; j < M; j++) {\n            if (!used[j]) {\n                int ov = overlap[order.back()][j];\n                int added = 5 - ov;\n                \n                // Different heuristics\n                double score = 0;\n                if (heuristic == 0) {\n                    // Max overlap\n                    score = ov * 100 - added;\n                } else if (heuristic == 1) {\n                    // Consider character positions\n                    char lastChar = t[order.back()].back();\n                    char firstChar = t[j][0];\n                    int lastPos = charPos[lastChar - 'A'].size();\n                    int firstPos = charPos[firstChar - 'A'].size();\n                    score = ov * 100 - added + (26 - lastPos - firstPos);\n                } else {\n                    // Balanced\n                    score = ov * 50 - added * 2;\n                }\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestNext = j;\n                }\n            }\n        }\n        \n        if (bestNext != -1) {\n            used[bestNext] = true;\n            order.push_back(bestNext);\n        }\n    }\n    \n    State s;\n    s.order = order;\n    s.str = buildString(order);\n    s.cost = estimateCost(s.str);\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    A.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> A[i];\n    }\n    \n    t.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> t[i];\n    }\n    \n    // Map characters to positions\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            charPos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    // Precompute overlaps\n    overlap.assign(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                overlap[i][j] = calcOverlap(t[i], t[j]);\n            }\n        }\n    }\n    \n    // Initialize RNG with time-based seed\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Try multiple strategies\n    State bestState;\n    bestState.cost = 1e18;\n    \n    auto startTime = chrono::steady_clock::now();\n    double timeLimit = 1.8; // Leave some margin\n    \n    // Strategy 1: Multiple greedy with different starts and heuristics\n    for (int start = 0; start < min(M, 30); start++) {\n        for (int heuristic = 0; heuristic < 3; heuristic++) {\n            State s = greedyWithHeuristic(start, heuristic);\n            if (s.cost < bestState.cost) {\n                bestState = s;\n            }\n            \n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - startTime).count() > timeLimit * 0.3) break;\n        }\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - startTime).count() > timeLimit * 0.3) break;\n    }\n    \n    // Strategy 2: Simulated annealing on best greedy result\n    if (bestState.cost < 1e17) {\n        double remainingTime = timeLimit - chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (remainingTime > 0.3) {\n            State saResult = simulatedAnnealing(bestState, remainingTime);\n            if (saResult.cost < bestState.cost) {\n                bestState = saResult;\n            }\n        }\n    }\n    \n    // Strategy 3: Random restarts with local search\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - startTime).count();\n    while (elapsed < timeLimit * 0.9) {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        \n        State s;\n        s.order = order;\n        s.str = buildString(order);\n        s.cost = estimateCost(s.str);\n        \n        // Quick local improvement\n        bool improved = true;\n        int localIter = 0;\n        while (improved && localIter < 50) {\n            improved = false;\n            for (int i = 0; i < M && localIter < 50; i++) {\n                for (int j = i + 1; j < M && localIter < 50; j++) {\n                    State neighbor = s;\n                    swap(neighbor.order[i], neighbor.order[j]);\n                    neighbor.str = buildString(neighbor.order);\n                    neighbor.cost = estimateCost(neighbor.str);\n                    \n                    if (neighbor.cost < s.cost) {\n                        s = neighbor;\n                        improved = true;\n                    }\n                    localIter++;\n                }\n            }\n        }\n        \n        if (s.cost < bestState.cost) {\n            bestState = s;\n        }\n        \n        now = chrono::steady_clock::now();\n        elapsed = chrono::duration<double>(now - startTime).count();\n    }\n    \n    // Generate final path with optimized positions\n    string finalStr = bestState.str;\n    vector<pair<int,int>> path = optimizePositions(finalStr);\n    \n    // Ensure we don't exceed 5000 operations\n    if ((int)path.size() > 5000) {\n        path.resize(5000);\n    }\n    \n    // Output\n    for (auto [i, j] : path) {\n        cout << i << \" \" << j << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n#include <iomanip>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\n// Global constants\nconst double EPS = 1e-9;\n\nstruct Field {\n    int id;\n    vector<pair<int, int>> shape;\n    int h, w;\n    vector<pair<int, int>> valid_positions;\n};\n\nint N, M;\ndouble epsilon;\nvector<Field> fields;\nvector<vector<double>> probs; // probs[k * N * N + r * N + c]\nvector<vector<int>> drill_results; // -1 if not drilled\nvector<double> row_obs;\nvector<double> col_obs;\n\n// Helper to get probability index\ninline int idx(int k, int r, int c) {\n    return k * N * N + r * N + c;\n}\n\n// Initialize probabilities uniformly over valid positions\nvoid init_probs() {\n    probs.assign(M * N * N, 0.0);\n    for (int k = 0; k < M; ++k) {\n        double count = fields[k].valid_positions.size();\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] = 1.0 / count;\n        }\n    }\n}\n\n// Calculate marginal probability that field k covers (i, j)\ndouble get_marginal(int k, int i, int j) {\n    double p = 0.0;\n    for (auto [r, c] : fields[k].valid_positions) {\n        // Check if (i, j) is covered by field k at (r, c)\n        // Shape coords are (di, dj). Grid coords (r+di, c+dj).\n        // So (i, j) covered if (i-r, j-c) is in shape.\n        int di = i - r;\n        int dj = j - c;\n        // Since shape is stored as list, we need to check efficiently.\n        // Given small shape size, linear scan is fine.\n        // But we can precompute a grid for each field?\n        // N is small, shape size is small.\n        // Let's iterate shape.\n        for (auto [si, sj] : fields[k].shape) {\n            if (r + si == i && c + sj == j) {\n                p += probs[idx(k, r, c)];\n                break;\n            }\n        }\n    }\n    return p;\n}\n\n// Precompute coverage for faster marginal calculation\n// covered[k][r][c][i][j] is bool. Too much memory?\n// M * N * N * N * N = 20 * 160000 = 3.2M bools. ~3MB. Fine.\n// Actually we can just store for each (k, r, c) the list of covered (i, j).\n// Or for each (k, i, j) the list of (r, c) that cover it.\n// Let's use: covers[k][i][j] -> vector of (r, c) indices.\nvector<vector<vector<vector<pair<int, int>>>>> cover_map;\n\nvoid build_cover_map() {\n    cover_map.assign(M, vector<vector<vector<pair<int, int>>>>(N, vector<vector<pair<int, int>>>(N)));\n    for (int k = 0; k < M; ++k) {\n        for (auto [r, c] : fields[k].valid_positions) {\n            for (auto [si, sj] : fields[k].shape) {\n                int i = r + si;\n                int j = c + sj;\n                if (i >= 0 && i < N && j >= 0 && j < N) {\n                    cover_map[k][i][j].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\ndouble get_marginal_fast(int k, int i, int j) {\n    double p = 0.0;\n    for (auto [r, c] : cover_map[k][i][j]) {\n        p += probs[idx(k, r, c)];\n    }\n    return p;\n}\n\n// Update probabilities based on row/col observations\nvoid update_row_col() {\n    // Row observations\n    for (int i = 0; i < N; ++i) {\n        double Y = row_obs[i];\n        double sigma_sq = N * epsilon * (1.0 - epsilon);\n        double sigma = sqrt(sigma_sq);\n        \n        // For each field, update its distribution\n        for (int k = 0; k < M; ++k) {\n            // Calculate expected contribution from other fields\n            double E_rest = 0.0;\n            for (int j = 0; j < M; ++j) {\n                if (j == k) continue;\n                for (int col = 0; col < N; ++col) {\n                    E_rest += get_marginal_fast(j, i, col);\n                }\n            }\n            \n            // Update probs for field k\n            vector<double> new_probs;\n            new_probs.reserve(fields[k].valid_positions.size());\n            double sum_p = 0.0;\n            \n            for (auto [r, c] : fields[k].valid_positions) {\n                // Count cells of field k in row i\n                int v_k = 0;\n                for (auto [si, sj] : fields[k].shape) {\n                    if (r + si == i) v_k++;\n                }\n                \n                double V_pred = v_k + E_rest;\n                double mu = N * epsilon + V_pred * (1.0 - 2.0 * epsilon);\n                double diff = Y - mu;\n                double likelihood = exp(-0.5 * diff * diff / sigma_sq);\n                \n                double p = probs[idx(k, r, c)] * likelihood;\n                new_probs.push_back(p);\n                sum_p += p;\n            }\n            \n            // Normalize\n            if (sum_p < EPS) sum_p = EPS;\n            int p_idx = 0;\n            for (auto [r, c] : fields[k].valid_positions) {\n                probs[idx(k, r, c)] = new_probs[p_idx++] / sum_p;\n            }\n        }\n    }\n    \n    // Col observations\n    for (int j = 0; j < N; ++j) {\n        double Y = col_obs[j];\n        double sigma_sq = N * epsilon * (1.0 - epsilon);\n        double sigma = sqrt(sigma_sq);\n        \n        for (int k = 0; k < M; ++k) {\n            double E_rest = 0.0;\n            for (int i = 0; i < M; ++i) {\n                if (i == k) continue;\n                for (int row = 0; row < N; ++row) {\n                    E_rest += get_marginal_fast(i, row, j);\n                }\n            }\n            \n            vector<double> new_probs;\n            new_probs.reserve(fields[k].valid_positions.size());\n            double sum_p = 0.0;\n            \n            for (auto [r, c] : fields[k].valid_positions) {\n                int v_k = 0;\n                for (auto [si, sj] : fields[k].shape) {\n                    if (c + sj == j) v_k++;\n                }\n                \n                double V_pred = v_k + E_rest;\n                double mu = N * epsilon + V_pred * (1.0 - 2.0 * epsilon);\n                double diff = Y - mu;\n                double likelihood = exp(-0.5 * diff * diff / sigma_sq);\n                \n                double p = probs[idx(k, r, c)] * likelihood;\n                new_probs.push_back(p);\n                sum_p += p;\n            }\n            \n            if (sum_p < EPS) sum_p = EPS;\n            int p_idx = 0;\n            for (auto [r, c] : fields[k].valid_positions) {\n                probs[idx(k, r, c)] = new_probs[p_idx++] / sum_p;\n            }\n        }\n    }\n}\n\n// Update probabilities based on drill result at (i, j) with value V\nvoid update_drill(int i, int j, int V) {\n    // Get marginals q_k = P(field k covers (i, j))\n    vector<double> q(M);\n    for (int k = 0; k < M; ++k) {\n        q[k] = get_marginal_fast(k, i, j);\n    }\n    \n    // DP to find distribution of sum S = sum X_k\n    // dp[s] = P(sum = s)\n    // We need P(S=V | X_k=1) and P(S=V | X_k=0)\n    // P(X_k=1 | S=V) = P(S=V | X_k=1) * q[k] / P(S=V)\n    // P(S=V | X_k=1) = P(S_{-k} = V-1)\n    // P(S=V | X_k=0) = P(S_{-k} = V)\n    \n    // Compute distribution of S_{-k} for each k?\n    // That's O(M^3). M=20 -> 8000. Fast.\n    // Or compute total S dist, then remove k?\n    // Removing is division, risky with 0.\n    // Recomputing for each k is safer and fast enough.\n    \n    vector<double> new_q(M);\n    \n    for (int k = 0; k < M; ++k) {\n        // DP for sum of other fields\n        vector<double> dp(V + 2, 0.0); // Max sum needed is V\n        dp[0] = 1.0;\n        \n        for (int other = 0; other < M; ++other) {\n            if (other == k) continue;\n            double p = q[other];\n            // Update dp in reverse\n            for (int s = V; s >= 0; --s) {\n                double val = dp[s] * (1.0 - p);\n                if (s > 0) val += dp[s-1] * p;\n                dp[s] = val;\n            }\n        }\n        \n        double prob_S_V_given_1 = (V > 0) ? dp[V-1] : 0.0;\n        double prob_S_V_given_0 = dp[V];\n        \n        double num_1 = prob_S_V_given_1 * q[k];\n        double num_0 = prob_S_V_given_0 * (1.0 - q[k]);\n        double denom = num_1 + num_0;\n        \n        if (denom < EPS) {\n            // Contradiction or very unlikely. Keep old q?\n            // Should not happen if beliefs are not 0/1.\n            new_q[k] = q[k];\n        } else {\n            new_q[k] = num_1 / denom;\n        }\n    }\n    \n    // Update probs for each field to match new_q\n    for (int k = 0; k < M; ++k) {\n        double old_q = q[k];\n        double target_q = new_q[k];\n        \n        if (abs(old_q - target_q) < EPS) continue;\n        \n        double f1 = (old_q > EPS) ? (target_q / old_q) : 1.0;\n        double f0 = (old_q < 1.0 - EPS) ? ((1.0 - target_q) / (1.0 - old_q)) : 1.0;\n        \n        double sum_p = 0.0;\n        // Apply factors\n        for (auto [r, c] : cover_map[k][i][j]) {\n            probs[idx(k, r, c)] *= f1;\n            sum_p += probs[idx(k, r, c)];\n        }\n        for (auto [r, c] : fields[k].valid_positions) {\n            // Check if NOT in cover_map\n            bool covers = false;\n            for (auto [si, sj] : fields[k].shape) {\n                if (r + si == i && c + sj == j) {\n                    covers = true;\n                    break;\n                }\n            }\n            if (!covers) {\n                probs[idx(k, r, c)] *= f0;\n                sum_p += probs[idx(k, r, c)];\n            }\n        }\n        \n        // Renormalize\n        // Wait, sum_p calculated above is sum of ALL probs for field k?\n        // Yes, because we iterated all valid positions (union of covers and not covers).\n        // But I iterated cover_map then valid_positions.\n        // cover_map is subset of valid_positions.\n        // So I double counted if I'm not careful.\n        // Better: iterate valid_positions once.\n        \n        sum_p = 0.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            bool covers = false;\n            for (auto [si, sj] : fields[k].shape) {\n                if (r + si == i && c + sj == j) {\n                    covers = true;\n                    break;\n                }\n            }\n            // probs already multiplied\n            sum_p += probs[idx(k, r, c)];\n        }\n        \n        if (sum_p < EPS) sum_p = EPS;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] /= sum_p;\n        }\n    }\n}\n\nint main() {\n    // Fast IO\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    cin >> N >> M >> epsilon;\n    \n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        fields[k].id = k;\n        int d;\n        cin >> d;\n        fields[k].shape.resize(d);\n        int min_i = N, min_j = N, max_i = -1, max_j = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> fields[k].shape[i].first >> fields[k].shape[i].second;\n            min_i = min(min_i, fields[k].shape[i].first);\n            min_j = min(min_j, fields[k].shape[i].second);\n            max_i = max(max_i, fields[k].shape[i].first);\n            max_j = max(max_j, fields[k].shape[i].second);\n        }\n        // The problem says shape is translated so min coords are 0.\n        // So min_i, min_j should be 0.\n        // Valid positions for top-left (r, c):\n        // r + max_i < N => r <= N - 1 - max_i\n        // c + max_j < N => c <= N - 1 - max_j\n        fields[k].h = max_i + 1;\n        fields[k].w = max_j + 1;\n        for (int r = 0; r <= N - fields[k].h; ++r) {\n            for (int c = 0; c <= N - fields[k].w; ++c) {\n                fields[k].valid_positions.push_back({r, c});\n            }\n        }\n    }\n    \n    build_cover_map();\n    init_probs();\n    \n    drill_results.assign(N, vector<int>(N, -1));\n    row_obs.assign(N, 0.0);\n    col_obs.assign(N, 0.0);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // 1. Query Rows\n    for (int i = 0; i < N; ++i) {\n        cout << \"q \" << N;\n        for (int j = 0; j < N; ++j) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        cin >> row_obs[i];\n    }\n    \n    // 2. Query Cols\n    for (int j = 0; j < N; ++j) {\n        cout << \"q \" << N;\n        for (int i = 0; i < N; ++i) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << endl;\n        cin >> col_obs[j];\n    }\n    \n    // 3. Update beliefs\n    update_row_col();\n    \n    // 4. Iterative Drilling\n    int ops_count = 2 * N;\n    int max_ops = 2 * N * N;\n    \n    while (ops_count < max_ops) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.5) break; // Safety margin\n        \n        // Find square with max entropy\n        int best_i = -1, best_j = -1;\n        double max_entropy = -1.0;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drill_results[i][j] != -1) continue;\n                \n                double p_oil = 0.0;\n                // P(v > 0) = 1 - Prod(1 - q_k)\n                double p_empty = 1.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal_fast(k, i, j);\n                    p_empty *= (1.0 - q);\n                }\n                p_oil = 1.0 - p_empty;\n                \n                if (p_oil < EPS) p_oil = EPS;\n                if (p_oil > 1.0 - EPS) p_oil = 1.0 - EPS;\n                \n                double H = -p_oil * log2(p_oil) - (1.0 - p_oil) * log2(1.0 - p_oil);\n                if (H > max_entropy) {\n                    max_entropy = H;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1 || max_entropy < 0.3) break; // Low uncertainty\n        \n        // Drill\n        cout << \"q 1 \" << best_i << \" \" << best_j << endl;\n        int val;\n        cin >> val;\n        drill_results[best_i][best_j] = val;\n        ops_count++;\n        \n        // Update\n        update_drill(best_i, best_j, val);\n    }\n    \n    // 5. Construct Answer\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool has_oil = false;\n            if (drill_results[i][j] != -1) {\n                if (drill_results[i][j] > 0) has_oil = true;\n            } else {\n                double p_empty = 1.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal_fast(k, i, j);\n                    p_empty *= (1.0 - q);\n                }\n                if (p_empty < 0.5) has_oil = true;\n            }\n            \n            if (has_oil) {\n                ans.push_back({i, j});\n            }\n        }\n    }\n    \n    // 6. Guess\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << endl;\n    \n    int resp;\n    cin >> resp;\n    // If resp == 0, we could continue, but we exit.\n    // In a contest, we should ideally handle resp==0, but with this strategy we aim for 1.\n    // If 0, we get penalty but program ends.\n    // To be robust, we could loop, but time limit.\n    // Given the heuristic nature, we assume 1.\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\n// Constants\nconst int W = 1000;\nconst double TIME_LIMIT = 2.8; // seconds\n\nstruct Rect {\n    int r0, c0, r1, c1;\n};\n\nstruct Node {\n    int id;\n    bool is_leaf;\n    int left = -1, right = -1; // children indices\n    int res_id = -1; // reservation id if leaf\n    long long target_area = 0;\n    \n    // Layout info\n    int r0, c0, r1, c1; // coordinates\n    int cut_pos = 0; // relative cut position (width for V, height for H)\n    int cut_type = 0; // 0: V, 1: H\n    \n    // Previous day info for cost calculation\n    int prev_cut_pos = 0;\n    int prev_cut_type = 0;\n};\n\nstruct Solver {\n    int D, N;\n    vector<vector<int>> A; // A[d][k]\n    vector<Node> tree;\n    vector<Rect> prev_day_rects; // rects for each reservation k\n    mt19937 rng;\n    \n    // Timing\n    chrono::steady_clock::time_point start_time;\n    \n    Solver() {\n        rng.seed(42);\n    }\n    \n    void run() {\n        start_time = chrono::steady_clock::now();\n        \n        int W_in;\n        if (!(cin >> W_in >> D >> N)) return;\n        // W_in is always 1000\n        \n        A.resize(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        prev_day_rects.resize(N);\n        \n        // Initialize Tree\n        // We create a balanced binary tree with N leaves\n        // Nodes 0 to 2N-2. Leaves are N-1 to 2N-2.\n        tree.resize(2 * N - 1);\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].id = i;\n            if (i >= N - 1) {\n                tree[i].is_leaf = true;\n                tree[i].res_id = i - (N - 1); // temporary mapping\n            } else {\n                tree[i].is_leaf = false;\n                tree[i].left = 2 * i + 1;\n                tree[i].right = 2 * i + 2;\n                // Alternate cut types for balance\n                tree[i].cut_type = (i % 2); \n            }\n        }\n        \n        // Initial assignment for Day 0\n        // Sort reservations by area and assign to leaves\n        // But leaves are fixed in tree structure. We assign res_id to leaves.\n        // To make it simple, we just assign res_id 0..N-1 to leaves 0..N-1 (in leaf index order)\n        // But we should sort to match areas?\n        // For Day 0, there is no previous geometry, so any assignment is fine.\n        // We'll sort A[0] and assign largest to largest capacity leaves?\n        // Since tree is balanced, all leaves have similar capacity potential.\n        // Let's just assign in order.\n        vector<int> p(N);\n        iota(p.begin(), p.end(), 0);\n        // Sort p based on A[0][p[i]]\n        sort(p.begin(), p.end(), [&](int i, int j) {\n            return A[0][i] < A[0][j];\n        });\n        \n        // Assign sorted reservations to leaves in order\n        // Leaves are tree[N-1] ... tree[2N-2]\n        for (int i = 0; i < N; ++i) {\n            tree[N - 1 + i].res_id = p[i];\n            tree[N - 1 + i].target_area = A[0][p[i]];\n        }\n        \n        // Layout Day 0\n        layout(0, 0, 0, W, W);\n        \n        // Store prev info\n        update_prev_info();\n        store_rects(0);\n        \n        // Output Day 0\n        output_day(0);\n        \n        // Subsequent days\n        for (int d = 1; d < D; ++d) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            \n            solve_day(d);\n            output_day(d);\n        }\n    }\n    \n    void solve_day(int d) {\n        // 1. Re-assign reservations to leaves based on area rank\n        // Calculate current area of each leaf\n        vector<pair<long long, int>> leaf_areas; // area, leaf_index\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            long long area = (long long)(tree[leaf_idx].r1 - tree[leaf_idx].r0) * (tree[leaf_idx].c1 - tree[leaf_idx].c0);\n            leaf_areas.push_back({area, leaf_idx});\n        }\n        sort(leaf_areas.begin(), leaf_areas.end());\n        \n        // Sort new requests\n        vector<pair<int, int>> requests; // area, original_k\n        for (int k = 0; k < N; ++k) {\n            requests.push_back({A[d][k], k});\n        }\n        sort(requests.begin(), requests.end());\n        \n        // Match\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = leaf_areas[i].second;\n            int k = requests[i].second;\n            tree[leaf_idx].res_id = k;\n            tree[leaf_idx].target_area = A[d][k];\n        }\n        \n        // 2. Local Search\n        vector<Node> best_tree = tree;\n        double best_cost = calc_approx_cost();\n        \n        int iterations = 10000;\n        // Adjust iterations based on remaining time\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = TIME_LIMIT - elapsed;\n        double time_per_day = TIME_LIMIT / D;\n        if (remaining < time_per_day * 0.5) {\n            iterations = 2000;\n        } else if (remaining > time_per_day * 2) {\n            iterations = 20000;\n        }\n        \n        for (int iter = 0; iter < iterations; ++iter) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            \n            // Mutate\n            // Pick a random internal node\n            int node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n            int mutation_type = uniform_int_distribution<>(0, 2)(rng);\n            \n            // Save state\n            Node saved_node = tree[node_idx];\n            vector<Node> saved_children;\n            if (!tree[node_idx].is_leaf) {\n                saved_children.push_back(tree[tree[node_idx].left]);\n                saved_children.push_back(tree[tree[node_idx].right]);\n            }\n            \n            bool valid = true;\n            if (mutation_type == 0) {\n                // Swap children\n                swap(tree[node_idx].left, tree[node_idx].right);\n            } else if (mutation_type == 1) {\n                // Flip cut type\n                tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n            } else {\n                // Swap children and flip cut type\n                swap(tree[node_idx].left, tree[node_idx].right);\n                tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n            }\n            \n            // Layout and Calc Cost\n            layout(0, 0, 0, W, W);\n            double cost = calc_approx_cost();\n            \n            // Acceptance (Hill Climbing with some randomness)\n            // Simple HC: accept if better\n            // SA: accept if worse with prob\n            // Given time, let's use simple HC with restart if stuck?\n            // Or just HC.\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_tree = tree;\n            } else {\n                // Revert\n                tree[node_idx] = saved_node;\n                if (!tree[node_idx].is_leaf) {\n                    tree[tree[node_idx].left] = saved_children[0];\n                    tree[tree[node_idx].right] = saved_children[1];\n                }\n                // Restore layout to consistent state (though we will overwrite next iter or end)\n                // Actually, we should restore layout to match reverted tree for next iter cost calc?\n                // No, next iter will mutate again and re-layout.\n                // But we need `tree` to be consistent for `calc_approx_cost` if we don't revert layout?\n                // `calc_approx_cost` uses `tree` nodes' `prev_cut_pos` which is static.\n                // It uses `tree` nodes' `cut_pos` which is set by `layout`.\n                // So we must layout after revert to have valid `cut_pos`.\n                layout(0, 0, 0, W, W);\n            }\n        }\n        \n        tree = best_tree;\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n        store_rects(d);\n    }\n    \n    void layout(int u, int r0, int c0, int r1, int c1) {\n        tree[u].r0 = r0; tree[u].c0 = c0; tree[u].r1 = r1; tree[u].c1 = c1;\n        if (tree[u].is_leaf) return;\n        \n        int left = tree[u].left;\n        int right = tree[u].right;\n        long long area_l = get_subtree_area(left);\n        long long area_r = get_subtree_area(right);\n        long long total = area_l + area_r;\n        \n        if (total == 0) {\n            // Should not happen given constraints\n            tree[u].cut_pos = (tree[u].cut_type == 0) ? (c1 - c0) / 2 : (r1 - r0) / 2;\n        } else {\n            if (tree[u].cut_type == 0) { // V-cut\n                // Split width\n                // Use integer division with rounding\n                // w_l = round(W * area_l / total)\n                long long w = c1 - c0;\n                long long w_l = (w * area_l + total / 2) / total;\n                if (w_l < 1) w_l = 1;\n                if (w_l > w - 1) w_l = w - 1;\n                tree[u].cut_pos = c0 + w_l;\n                \n                layout(left, r0, c0, r1, tree[u].cut_pos);\n                layout(right, r0, tree[u].cut_pos, r1, c1);\n            } else { // H-cut\n                // Split height\n                long long h = r1 - r0;\n                long long h_l = (h * area_l + total / 2) / total;\n                if (h_l < 1) h_l = 1;\n                if (h_l > h - 1) h_l = h - 1;\n                tree[u].cut_pos = r0 + h_l;\n                \n                layout(left, r0, c0, tree[u].cut_pos, c1);\n                layout(right, tree[u].cut_pos, c0, r1, c1);\n            }\n        }\n    }\n    \n    long long get_subtree_area(int u) {\n        if (tree[u].is_leaf) return tree[u].target_area;\n        return get_subtree_area(tree[u].left) + get_subtree_area(tree[u].right);\n    }\n    \n    double calc_approx_cost() {\n        double cost = 0;\n        for (int i = 0; i < N - 1; ++i) { // Internal nodes\n            if (tree[i].cut_type != tree[i].prev_cut_type) {\n                // Type changed\n                int span_old = (tree[i].prev_cut_type == 0) ? (tree[i].r1 - tree[i].r0) : (tree[i].c1 - tree[i].c0);\n                // Note: r1, c1 etc are from CURRENT layout. \n                // We should use PREVIOUS layout dimensions for old span?\n                // We don't store previous dimensions per node easily.\n                // Approximation: use current span.\n                int span_new = (tree[i].cut_type == 0) ? (tree[i].r1 - tree[i].r0) : (tree[i].c1 - tree[i].c0);\n                cost += span_old + span_new;\n            } else {\n                int pos_diff = abs(tree[i].cut_pos - tree[i].prev_cut_pos);\n                int span = (tree[i].cut_type == 0) ? (tree[i].r1 - tree[i].r0) : (tree[i].c1 - tree[i].c0);\n                cost += 2.0 * pos_diff * span;\n            }\n        }\n        return cost;\n    }\n    \n    void update_prev_info() {\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].prev_cut_pos = tree[i].cut_pos;\n            tree[i].prev_cut_type = tree[i].cut_type;\n        }\n    }\n    \n    void store_rects(int d) {\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            prev_day_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n    }\n    \n    void output_day(int d) {\n        // We need to output in order of k=0..N-1\n        // But we stored rects in prev_day_rects[k]\n        // Wait, for day d, we just computed rects.\n        // We should output the rects we just computed.\n        // store_rects saves them for NEXT day's cost calc.\n        // But we need to output current day's rects.\n        // They are in tree leaves now.\n        vector<Rect> current_rects(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            current_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n        \n        for (int k = 0; k < N; ++k) {\n            cout << current_rects[k].r0 << \" \" << current_rects[k].c0 << \" \" \n                 << current_rects[k].r1 << \" \" << current_rects[k].c1 << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver solver;\n    solver.run();\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long MOD = 998244353;\n\nstruct Operation {\n    int m, p, q;\n};\n\nint N, M, K;\nvector<vector<long long>> a;\nvector<vector<vector<long long>>> s;\n\n// Calculate total score\nlong long calculateScore(const vector<vector<long long>>& board) {\n    long long score = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            score += board[i][j] % MOD;\n        }\n    }\n    return score;\n}\n\n// Apply operations to get final board\nvector<vector<long long>> applyOperations(const vector<Operation>& ops) {\n    vector<vector<long long>> board = a;\n    for (const auto& op : ops) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                board[op.p + i][op.q + j] += s[op.m][i][j];\n            }\n        }\n    }\n    return board;\n}\n\n// Calculate delta score for adding one operation\nlong long calculateDelta(const vector<vector<long long>>& board, int m, int p, int q) {\n    long long delta = 0;\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            long long old_mod = board[p + i][q + j] % MOD;\n            long long new_mod = (board[p + i][q + j] + s[m][i][j]) % MOD;\n            delta += new_mod - old_mod;\n        }\n    }\n    return delta;\n}\n\n// Greedy initialization\nvector<Operation> greedyInit(mt19937& rng) {\n    vector<Operation> ops;\n    ops.reserve(K);\n    vector<vector<long long>> board = a;\n    \n    for (int op = 0; op < K; op++) {\n        long long best_delta = LLONG_MIN;\n        int best_m = 0, best_p = 0, best_q = 0;\n        \n        // Try all operations with some randomization\n        vector<tuple<int, int, int>> candidates;\n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    candidates.emplace_back(m, p, q);\n                }\n            }\n        }\n        \n        // Sample subset for speed\n        if (candidates.size() > 200) {\n            shuffle(candidates.begin(), candidates.end(), rng);\n            candidates.resize(200);\n        }\n        \n        for (const auto& [m, p, q] : candidates) {\n            long long delta = calculateDelta(board, m, p, q);\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_m = m;\n                best_p = p;\n                best_q = q;\n            }\n        }\n        \n        ops.push_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] += s[best_m][i][j];\n            }\n        }\n    }\n    \n    return ops;\n}\n\n// Local search improvement\nvector<Operation> localSearch(vector<Operation> ops, mt19937& rng, int iterations) {\n    vector<vector<long long>> board = applyOperations(ops);\n    long long best_score = calculateScore(board);\n    \n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    \n    int no_improve = 0;\n    for (int iter = 0; iter < iterations && no_improve < iterations / 3; iter++) {\n        bool improved = false;\n        \n        // Try changing one operation\n        for (int trial = 0; trial < 50; trial++) {\n            int idx = dist_op(rng);\n            int new_m = dist_m(rng);\n            int new_p = dist_p(rng);\n            int new_q = dist_q(rng);\n            \n            Operation old_op = ops[idx];\n            ops[idx] = {new_m, new_p, new_q};\n            \n            vector<vector<long long>> new_board = applyOperations(ops);\n            long long new_score = calculateScore(new_board);\n            \n            if (new_score > best_score) {\n                best_score = new_score;\n                board = new_board;\n                improved = true;\n                no_improve = 0;\n            } else {\n                ops[idx] = old_op;\n            }\n        }\n        \n        // Try swapping two operations\n        for (int trial = 0; trial < 30; trial++) {\n            int idx1 = dist_op(rng);\n            int idx2 = dist_op(rng);\n            if (idx1 == idx2) continue;\n            \n            swap(ops[idx1], ops[idx2]);\n            \n            vector<vector<long long>> new_board = applyOperations(ops);\n            long long new_score = calculateScore(new_board);\n            \n            if (new_score > best_score) {\n                best_score = new_score;\n                board = new_board;\n                improved = true;\n                no_improve = 0;\n            } else {\n                swap(ops[idx1], ops[idx2]);\n            }\n        }\n        \n        if (!improved) no_improve++;\n    }\n    \n    return ops;\n}\n\n// Simulated annealing\nvector<Operation> simulatedAnnealing(vector<Operation> ops, mt19937& rng, double time_limit) {\n    auto start_time = chrono::steady_clock::now();\n    \n    vector<vector<long long>> board = applyOperations(ops);\n    long long current_score = calculateScore(board);\n    long long best_score = current_score;\n    vector<Operation> best_ops = ops;\n    \n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double temperature = 10000.0;\n    double cooling_rate = 0.9995;\n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        // Generate neighbor\n        int idx = dist_op(rng);\n        Operation old_op = ops[idx];\n        \n        int change_type = dist_op(rng) % 3;\n        if (change_type == 0) {\n            ops[idx].m = dist_m(rng);\n        } else if (change_type == 1) {\n            ops[idx].p = dist_p(rng);\n        } else {\n            ops[idx].q = dist_q(rng);\n        }\n        \n        vector<vector<long long>> new_board = applyOperations(ops);\n        long long new_score = calculateScore(new_board);\n        \n        double delta = (double)(new_score - current_score);\n        double accept_prob = exp(delta / temperature);\n        \n        if (delta > 0 || dist_real(rng) < accept_prob) {\n            current_score = new_score;\n            board = new_board;\n            \n            if (new_score > best_score) {\n                best_score = new_score;\n                best_ops = ops;\n            }\n        } else {\n            ops[idx] = old_op;\n        }\n        \n        temperature *= cooling_rate;\n        iterations++;\n        \n        if (iterations % 1000 == 0 && temperature < 0.01) break;\n    }\n    \n    return best_ops;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    a.assign(N, vector<long long>(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    s.assign(M, vector<vector<long long>>(3, vector<long long>(3)));\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> s[m][i][j];\n            }\n        }\n    }\n    \n    // Multiple restarts with different seeds\n    vector<Operation> best_ops;\n    long long best_score = -1;\n    \n    // Time budget: ~1.8 seconds to leave margin\n    auto start_time = chrono::steady_clock::now();\n    double time_budget = 1.8;\n    \n    int num_restarts = 3;\n    for (int restart = 0; restart < num_restarts; restart++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_budget * 0.9) break;\n        \n        double remaining = time_budget - elapsed;\n        double time_per_restart = remaining / (num_restarts - restart);\n        \n        mt19937 rng(restart * 12345 + 67890);\n        \n        // Greedy initialization\n        vector<Operation> ops = greedyInit(rng);\n        \n        // Local search\n        ops = localSearch(ops, rng, 500);\n        \n        // Simulated annealing\n        ops = simulatedAnnealing(ops, rng, time_per_restart * 0.6);\n        \n        // Evaluate\n        vector<vector<long long>> board = applyOperations(ops);\n        long long score = calculateScore(board);\n        \n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n    }\n    \n    // Output\n    cout << best_ops.size() << \"\\n\";\n    for (const auto& op : best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct State {\n    int container[N][N]; // -1 if empty, otherwise container number\n    int crane_row[5];    // current row of each crane\n    int crane_col[5];    // current col of each crane\n    int crane_holding[5]; // -1 if not holding, otherwise container number\n    int next_receive[5]; // next container index to receive at each gate\n    vector<int> dispatched[5]; // containers dispatched from each gate\n};\n\nint get_target_row(int container_num) {\n    return container_num / N;\n}\n\nint get_target_col(int container_num) {\n    return N - 1;\n}\n\nbool can_move_small(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return false;\n    return state.container[row][col] == -1;\n}\n\nbool can_move_large(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return true;\n    return true; // Large crane can move over containers\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\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    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            state.container[i][j] = -1;\n        }\n        state.crane_row[i] = i;\n        state.crane_col[i] = 0;\n        state.crane_holding[i] = -1;\n        state.next_receive[i] = 0;\n        state.dispatched[i].clear();\n    }\n    \n    // Output strings for each crane\n    vector<string> actions(N, \"\");\n    \n    // Track which containers need to be dispatched from each gate\n    vector<vector<int>> target_containers(N);\n    for (int c = 0; c < N * N; c++) {\n        target_containers[c / N].push_back(c);\n    }\n    \n    // Simple greedy strategy: move containers from left to right\n    // Large crane (0) handles row 0, small cranes handle their rows\n    // Use columns 1-3 as buffer\n    \n    int turn = 0;\n    int total_dispatched = 0;\n    \n    while (turn < MAX_TURNS && total_dispatched < N * N) {\n        string turn_actions(N, '.');\n        bool any_action = false;\n        \n        // Step 1: Receive containers (simulated - happens automatically)\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && \n                state.container[i][0] == -1 && \n                state.crane_holding[0] == -1) { // Check if crane 0 not blocking\n                // Container arrives at gate\n                // This happens automatically in the simulation\n            }\n        }\n        \n        // Step 2: Plan crane actions\n        for (int c = 0; c < N; c++) {\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            int holding = state.crane_holding[c];\n            \n            char action = '.';\n            \n            if (holding == -1) {\n                // Not holding - try to pick up a container\n                if (state.container[r][col] != -1) {\n                    // Pick up container\n                    action = 'P';\n                    any_action = true;\n                } else {\n                    // Move towards containers or dispatch gates\n                    bool is_large = (c == 0);\n                    \n                    // Priority: go to left side to pick up, then right to dispatch\n                    int target_col = 0;\n                    int target_row = r;\n                    \n                    // Look for containers to pick up\n                    bool found_container = false;\n                    for (int j = 0; j < N && !found_container; j++) {\n                        for (int i = 0; i < N && !found_container; i++) {\n                            if (state.container[i][j] != -1) {\n                                int container = state.container[i][j];\n                                int target_r = get_target_row(container);\n                                if (c == target_r || (c == 0 && target_r == 0)) {\n                                    target_row = i;\n                                    target_col = j;\n                                    found_container = true;\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (!found_container) {\n                        // Go to left side to wait for new containers\n                        target_col = 0;\n                    }\n                    \n                    // Move towards target\n                    if (col < target_col) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_col) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_row) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_row) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            } else {\n                // Holding a container - try to dispatch it\n                int target_r = get_target_row(holding);\n                int target_c = get_target_col(holding);\n                \n                if (r == target_r && col == target_c) {\n                    // At dispatch gate - release\n                    action = 'Q';\n                    any_action = true;\n                } else {\n                    // Move towards dispatch gate\n                    bool is_large = (c == 0);\n                    \n                    if (col < target_c) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_c) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_r) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_r) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            }\n            \n            turn_actions[c] = action;\n        }\n        \n        // If no actions, break to avoid infinite loop\n        if (!any_action && total_dispatched < N * N) {\n            // Try to do something - at least move cranes\n            for (int c = 0; c < N; c++) {\n                if (state.crane_col[c] < N - 1) {\n                    turn_actions[c] = 'R';\n                }\n            }\n        }\n        \n        // Apply actions (simplified simulation)\n        for (int c = 0; c < N; c++) {\n            char action = turn_actions[c];\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            \n            if (action == 'P' && state.crane_holding[c] == -1 && state.container[r][col] != -1) {\n                state.crane_holding[c] = state.container[r][col];\n                state.container[r][col] = -1;\n            } else if (action == 'Q' && state.crane_holding[c] != -1 && state.container[r][col] == -1) {\n                state.container[r][col] = state.crane_holding[c];\n                state.crane_holding[c] = -1;\n            } else if (action == 'R' && col < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col + 1] == -1) {\n                    state.crane_col[c]++;\n                }\n            } else if (action == 'L' && col > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col - 1] == -1) {\n                    state.crane_col[c]--;\n                }\n            } else if (action == 'D' && r < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r + 1][col] == -1) {\n                    state.crane_row[c]++;\n                }\n            } else if (action == 'U' && r > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r - 1][col] == -1) {\n                    state.crane_row[c]--;\n                }\n            }\n        }\n        \n        // Step 3: Dispatch containers at right edge\n        for (int i = 0; i < N; i++) {\n            if (state.container[i][N - 1] != -1) {\n                int container = state.container[i][N - 1];\n                state.dispatched[i].push_back(container);\n                state.container[i][N - 1] = -1;\n                total_dispatched++;\n            }\n        }\n        \n        // Simulate container arrival at left edge\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && state.container[i][0] == -1) {\n                // Check if any crane is holding at this position\n                bool crane_blocking = false;\n                for (int c = 0; c < N; c++) {\n                    if (state.crane_row[c] == i && state.crane_col[c] == 0 && state.crane_holding[c] != -1) {\n                        crane_blocking = true;\n                        break;\n                    }\n                }\n                if (!crane_blocking) {\n                    state.container[i][0] = A[i][state.next_receive[i]];\n                    state.next_receive[i]++;\n                }\n            }\n        }\n        \n        // Record actions\n        for (int c = 0; c < N; c++) {\n            actions[c] += turn_actions[c];\n        }\n        \n        turn++;\n        \n        // Safety break\n        if (turn >= 5000) break;\n    }\n    \n    // Pad all strings to same length\n    size_t max_len = 0;\n    for (int i = 0; i < N; i++) {\n        max_len = max(max_len, actions[i].size());\n    }\n    for (int i = 0; i < N; i++) {\n        while (actions[i].size() < max_len) {\n            actions[i] += '.';\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << actions[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Structure to represent a cell with non-zero height\nstruct Cell {\n    int r, c;\n    int h;\n    int id;\n};\n\nint N;\nvector<vector<int>> H;\nvector<string> ops;\nint curr_r, curr_c;\nlong long current_load;\n\n// Helper to record an operation\nvoid add_op(const string& s) {\n    ops.push_back(s);\n}\n\n// Helper to move the truck to a target coordinate and record moves\nvoid move_to(int tr, int tc) {\n    while (curr_r < tr) {\n        add_op(\"D\");\n        curr_r++;\n    }\n    while (curr_r > tr) {\n        add_op(\"U\");\n        curr_r--;\n    }\n    while (curr_c < tc) {\n        add_op(\"R\");\n        curr_c++;\n    }\n    while (curr_c > tc) {\n        add_op(\"L\");\n        curr_c--;\n    }\n}\n\n// Manhattan distance\nint dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    H.assign(N, vector<int>(N));\n    vector<Cell> sources;\n    vector<Cell> sinks;\n\n    // Read input and classify cells into sources (h > 0) and sinks (h < 0)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n            if (H[i][j] > 0) {\n                sources.push_back({i, j, H[i][j], i * N + j});\n            } else if (H[i][j] < 0) {\n                sinks.push_back({i, j, H[i][j], i * N + j});\n            }\n        }\n    }\n\n    curr_r = 0;\n    curr_c = 0;\n    current_load = 0;\n\n    // Continue until all sources are processed and truck is empty\n    while (!sources.empty() || current_load > 0) {\n        if (current_load == 0) {\n            // Truck is empty, need to pick up soil from a source.\n            // Heuristic: Select source u that minimizes:\n            // 100 * dist(curr, u) + (100 + h[u]) * dist(u, nearest_sink_to_u)\n            // This accounts for the empty travel to the source and the first loaded leg.\n            \n            int best_idx = -1;\n            long long best_score = -1;\n\n            for (int i = 0; i < (int)sources.size(); ++i) {\n                // Find nearest sink for this source\n                int min_d_sink = 1e9;\n                for (const auto& s : sinks) {\n                    int d = dist(sources[i].r, sources[i].c, s.r, s.c);\n                    if (d < min_d_sink) {\n                        min_d_sink = d;\n                    }\n                }\n                \n                int d1 = dist(curr_r, curr_c, sources[i].r, sources[i].c);\n                // Cost estimate: Empty travel + Loaded travel to first sink\n                // We use sources[i].h because we plan to load all soil from this source\n                long long score = 100LL * d1 + (100LL + sources[i].h) * min_d_sink;\n                \n                if (best_idx == -1 || score < best_score) {\n                    best_score = score;\n                    best_idx = i;\n                }\n            }\n\n            // Pick the best source\n            Cell u = sources[best_idx];\n            // Remove from sources list efficiently\n            sources[best_idx] = sources.back();\n            sources.pop_back();\n\n            // Move to source and load all soil\n            move_to(u.r, u.c);\n            long long amount = u.h;\n            add_op(\"+\" + to_string(amount));\n            current_load += amount;\n            H[u.r][u.c] = 0;\n        }\n\n        if (current_load > 0) {\n            // Truck has soil, need to deliver to a sink.\n            // Heuristic: Go to the nearest sink to minimize loaded travel cost.\n            int best_idx = -1;\n            int min_d = 1e9;\n\n            for (int i = 0; i < (int)sinks.size(); ++i) {\n                int d = dist(curr_r, curr_c, sinks[i].r, sinks[i].c);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n\n            // Safety check, though sinks should not be empty if load > 0\n            if (best_idx == -1) break; \n\n            Cell v = sinks[best_idx];\n            \n            // Move to sink and unload as much as possible\n            move_to(v.r, v.c);\n            // Use H to get current demand, as sinks list stores initial h\n            long long amount = min(current_load, (long long)-H[v.r][v.c]);\n            add_op(\"-\" + to_string(amount));\n            current_load -= amount;\n            H[v.r][v.c] += amount;\n            \n            // If sink is satisfied (height becomes 0), remove from list\n            if (H[v.r][v.c] == 0) {\n                sinks[best_idx] = sinks.back();\n                sinks.pop_back();\n            }\n        }\n    }\n\n    // Output all operations\n    for (const auto& op : ops) {\n        cout << op << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::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); // 60 seeds\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    vector<int> values(seed_count, 0);\n    \n    // Read initial seeds\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n            values[i] += X[i][j];\n        }\n    }\n    \n    // Calculate neighbor count for each position\n    vector<vector<int>> neighbor_count(N, vector<int>(N, 0));\n    int di[] = {-1, 1, 0, 0};\n    int dj[] = {0, 0, -1, 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 ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    neighbor_count[i][j]++;\n                }\n            }\n        }\n    }\n    \n    // Create position list sorted by neighbor count (descending)\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    // Track which seeds have been used recently\n    vector<bool> used_recently(seed_count, false);\n    int use_cooldown = 3; // Seeds can't be reused for this many turns\n    vector<int> last_used(seed_count, -use_cooldown);\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (int t = 0; t < T; t++) {\n        // Create indices sorted by value (with diversity consideration)\n        vector<int> indices(seed_count);\n        iota(indices.begin(), indices.end(), 0);\n        \n        // Sort by value, but penalize recently used seeds\n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            int val_a = values[a];\n            int val_b = values[b];\n            // Penalize recently used seeds\n            if (t - last_used[a] < use_cooldown) val_a -= 50;\n            if (t - last_used[b] < use_cooldown) val_b -= 50;\n            if (val_a != val_b) return val_a > val_b;\n            return a < b; // Tie-break by index for determinism\n        });\n        \n        // Sort positions by neighbor count (descending)\n        sort(positions.begin(), positions.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n            if (neighbor_count[a.first][a.second] != neighbor_count[b.first][b.second]) {\n                return neighbor_count[a.first][a.second] > neighbor_count[b.first][b.second];\n            }\n            // Secondary sort: prefer center positions\n            int dist_a = abs(a.first - N/2) + abs(a.second - N/2);\n            int dist_b = abs(b.first - N/2) + abs(b.second - N/2);\n            return dist_a < dist_b;\n        });\n        \n        // Assign seeds to positions\n        vector<vector<int>> A(N, vector<int>(N));\n        vector<bool> seed_used(seed_count, false);\n        \n        for (int p = 0; p < N * N; p++) {\n            int i = positions[p].first;\n            int j = positions[p].second;\n            \n            // Find best unused seed\n            for (int idx : indices) {\n                if (!seed_used[idx]) {\n                    A[i][j] = idx;\n                    seed_used[idx] = true;\n                    last_used[idx] = t;\n                    break;\n                }\n            }\n        }\n        \n        // Output the placement\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            values[i] = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                values[i] += X[i][j];\n            }\n        }\n        \n        // Output debug info as comments\n        int max_val = *max_element(values.begin(), values.end());\n        cerr << \"# Turn \" << t << \" max_value: \" << max_val << endl;\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\n// Structure to represent a point on the grid\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\n// Manhattan distance\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\n// Structure to represent a transport task\nstruct Pair {\n    Point s, t;\n    int id;\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M_in, V;\n    if (!(cin >> N >> M_in >> V)) return 0;\n\n    vector<string> S_grid(N), T_grid(N);\n    vector<Point> starts, targets;\n\n    // Read grid configurations\n    for (int i = 0; i < N; ++i) cin >> S_grid[i];\n    for (int i = 0; i < N; ++i) cin >> T_grid[i];\n\n    // Extract start and target coordinates\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (S_grid[i][j] == '1') starts.push_back({i, j});\n            if (T_grid[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n\n    // Filter out takoyaki that are already at target positions\n    vector<bool> s_used(starts.size(), false);\n    vector<bool> t_used(targets.size(), false);\n    \n    // Match identical positions first (cost 0)\n    for (size_t i = 0; i < starts.size(); ++i) {\n        for (size_t j = 0; j < targets.size(); ++j) {\n            if (!s_used[i] && !t_used[j] && starts[i] == targets[j]) {\n                s_used[i] = true;\n                t_used[j] = true;\n                break;\n            }\n        }\n    }\n\n    vector<Point> S_rem, T_rem;\n    for (size_t i = 0; i < starts.size(); ++i) if (!s_used[i]) S_rem.push_back(starts[i]);\n    for (size_t i = 0; i < targets.size(); ++i) if (!t_used[i]) T_rem.push_back(targets[i]);\n\n    int M = S_rem.size();\n    \n    // Output Arm Design: Star Graph\n    // Root 0, Leaves 1 to V-1, Edge Length 1\n    // This allows up to V-1 simultaneous pickups/dropoffs near the root\n    int V_prime = V;\n    cout << V_prime << \"\\n\";\n    for (int i = 1; i < V_prime; ++i) {\n        cout << 0 << \" \" << 1 << \"\\n\";\n    }\n    // Initial root position (0,0), will move immediately in simulation\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    if (M == 0) {\n        // No moves needed\n        cout << 0 << \"\\n\";\n        return 0;\n    }\n\n    // Greedy Matching between remaining Starts and Targets\n    vector<Pair> pairs;\n    vector<bool> t_matched(T_rem.size(), false);\n    for (int i = 0; i < M; ++i) {\n        int best_j = -1;\n        int min_d = 1e9;\n        for (int j = 0; j < (int)T_rem.size(); ++j) {\n            if (!t_matched[j]) {\n                int d = dist(S_rem[i], T_rem[j]);\n                if (d < min_d) {\n                    min_d = d;\n                    best_j = j;\n                }\n            }\n        }\n        if (best_j != -1) {\n            pairs.push_back({S_rem[i], T_rem[best_j], i});\n            t_matched[best_j] = true;\n        }\n    }\n\n    // Sort pairs to improve spatial locality (reduce travel distance between tasks)\n    // Using a coarse grid hash for clustering\n    sort(pairs.begin(), pairs.end(), [](const Pair& a, const Pair& b) {\n        int ma = (a.s.r / 5) * 10 + (a.s.c / 5);\n        int mb = (b.s.r / 5) * 10 + (b.s.c / 5);\n        if (ma != mb) return ma < mb;\n        return dist(a.s, a.t) < dist(b.s, b.t);\n    });\n\n    // Simulation State\n    int cur_r = 0, cur_c = 0;\n    // Move to a valid neighbor of the first start position\n    {\n        int dr[] = {0, 0, 1, -1};\n        int dc[] = {1, -1, 0, 0};\n        for(int k=0; k<4; ++k) {\n            int nr = pairs[0].s.r + dr[k];\n            int nc = pairs[0].s.c + dc[k];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                cur_r = nr; cur_c = nc;\n                break;\n            }\n        }\n    }\n\n    // Finger state: holding[u] = index in pairs, -1 if none\n    // finger_dir[u]: 0:R, 1:U, 2:L, 3:D\n    vector<int> holding(V_prime, -1);\n    vector<int> finger_dir(V_prime, 0); \n\n    vector<string> commands;\n    // We process tasks in batches to allow potential parallelism, \n    // but here we implement robust 1-by-1 transport ordered by proximity.\n    int batch_size = V_prime - 1; \n    \n    int pair_idx = 0;\n    while (pair_idx < M) {\n        int end_idx = min(pair_idx + batch_size, M);\n        \n        // Collect indices for current batch\n        vector<int> batch_indices;\n        for(int i=pair_idx; i<end_idx; ++i) batch_indices.push_back(i);\n        \n        // Order batch by nearest neighbor from current position to minimize travel\n        vector<bool> visited_batch(batch_indices.size(), false);\n        vector<int> ordered_batch;\n        int curr_r = cur_r, curr_c = cur_c;\n        \n        for(int k=0; k<(int)batch_indices.size(); ++k) {\n            int best_k = -1;\n            int min_d = 1e9;\n            for(int j=0; j<(int)batch_indices.size(); ++j) {\n                if(!visited_batch[j]) {\n                    int d = dist({curr_r, curr_c}, pairs[batch_indices[j]].s);\n                    if(d < min_d) {\n                        min_d = d;\n                        best_k = j;\n                    }\n                }\n            }\n            if(best_k != -1) {\n                visited_batch[best_k] = true;\n                ordered_batch.push_back(batch_indices[best_k]);\n                // Update heuristic current position to target of this task\n                // This encourages chaining pickups and dropoffs efficiently\n                curr_r = pairs[batch_indices[best_k]].t.r;\n                curr_c = pairs[batch_indices[best_k]].t.c;\n            }\n        }\n        \n        // Execute transport for each pair in the ordered batch\n        for (int idx : ordered_batch) {\n            Point s = pairs[idx].s;\n            Point t = pairs[idx].t;\n            \n            // 1. Move root to a neighbor of s\n            int best_nr = -1, best_nc = -1;\n            int min_move_dist = 1e9;\n            int dr[] = {0, 0, 1, -1};\n            int dc[] = {1, -1, 0, 0};\n            \n            for(int k=0; k<4; ++k) {\n                int nr = s.r + dr[k];\n                int nc = s.c + dc[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d < min_move_dist) {\n                        min_move_dist = d;\n                        best_nr = nr;\n                        best_nc = nc;\n                    }\n                }\n            }\n            \n            // Generate move commands\n            while (cur_r != best_nr || cur_c != best_nc) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                commands.push_back(cmd);\n            }\n            \n            // 2. Pick up takoyaki\n            // Find a free finger (since we do 1-by-1, one is always free)\n            int finger = -1;\n            for(int u=1; u<V_prime; ++u) {\n                if(holding[u] == -1) {\n                    finger = u;\n                    break;\n                }\n            }\n            \n            // Determine target direction for finger to point to s\n            int target_dir = -1;\n            if (s.r == cur_r && s.c == cur_c + 1) target_dir = 0; // R\n            else if (s.r == cur_r - 1 && s.c == cur_c) target_dir = 1; // U\n            else if (s.r == cur_r && s.c == cur_c - 1) target_dir = 2; // L\n            else if (s.r == cur_r + 1 && s.c == cur_c) target_dir = 3; // D\n            \n            if (target_dir != -1 && finger != -1) {\n                // Rotate finger to target direction\n                while (finger_dir[finger] != target_dir) {\n                    string rot_cmd(2 * V_prime, '.');\n                    int d = (target_dir - finger_dir[finger] + 4) % 4;\n                    if (d == 1) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    } else if (d == 3) {\n                        rot_cmd[finger] = 'R';\n                        finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n                    } else if (d == 2) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    }\n                    commands.push_back(rot_cmd);\n                }\n                \n                // Grab\n                string grab_cmd(2 * V_prime, '.');\n                grab_cmd[V_prime + finger] = 'P';\n                commands.push_back(grab_cmd);\n                holding[finger] = idx;\n            }\n            \n            // 3. Move root to a neighbor of t\n            best_nr = -1, best_nc = -1;\n            min_move_dist = 1e9;\n            for(int k=0; k<4; ++k) {\n                int nr = t.r + dr[k];\n                int nc = t.c + dc[k];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d < min_move_dist) {\n                        min_move_dist = d;\n                        best_nr = nr;\n                        best_nc = nc;\n                    }\n                }\n            }\n            \n            while (cur_r != best_nr || cur_c != best_nc) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                commands.push_back(cmd);\n            }\n            \n            // 4. Drop takoyaki\n            target_dir = -1;\n            if (t.r == cur_r && t.c == cur_c + 1) target_dir = 0;\n            else if (t.r == cur_r - 1 && t.c == cur_c) target_dir = 1;\n            else if (t.r == cur_r && t.c == cur_c - 1) target_dir = 2;\n            else if (t.r == cur_r + 1 && t.c == cur_c) target_dir = 3;\n            \n            if (target_dir != -1 && finger != -1) {\n                while (finger_dir[finger] != target_dir) {\n                    string rot_cmd(2 * V_prime, '.');\n                    int d = (target_dir - finger_dir[finger] + 4) % 4;\n                    if (d == 1) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    } else if (d == 3) {\n                        rot_cmd[finger] = 'R';\n                        finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n                    } else if (d == 2) {\n                        rot_cmd[finger] = 'L';\n                        finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n                    }\n                    commands.push_back(rot_cmd);\n                }\n                \n                string drop_cmd(2 * V_prime, '.');\n                drop_cmd[V_prime + finger] = 'P';\n                commands.push_back(drop_cmd);\n                holding[finger] = -1;\n            }\n        }\n        \n        pair_idx = end_idx;\n    }\n\n    // Output commands\n    cout << commands.size() << \"\\n\";\n    for (const string& cmd : commands) {\n        cout << cmd << \"\\n\";\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <numeric>\n#include <map>\n#include <cstdlib>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n};\n\nstruct Fish {\n    int x, y;\n    int type; // 0: mackerel, 1: sardine\n};\n\nint N;\nvector<Fish> fish;\n\n// Grid parameters\nint G_SIZE;\nint CELL_SIZE;\nvector<vector<int>> grid_m;\nvector<vector<int>> grid_s;\nvector<vector<int>> grid_score;\nvector<vector<bool>> selected;\n\n// Directions for grid traversal\nconst int dx[4] = {0, 0, 1, -1};\nconst int dy[4] = {1, -1, 0, 0};\n\nvoid read_input() {\n    cin >> N;\n    fish.resize(2 * N);\n    for (int i = 0; i < 2 * N; ++i) {\n        cin >> fish[i].x >> fish[i].y;\n        fish[i].type = (i < N) ? 0 : 1;\n    }\n}\n\nvoid build_grid(int G) {\n    G_SIZE = G;\n    CELL_SIZE = 100000 / G;\n    grid_m.assign(G, vector<int>(G, 0));\n    grid_s.assign(G, vector<int>(G, 0));\n    grid_score.assign(G, vector<int>(G, 0));\n    selected.assign(G, vector<bool>(G, false));\n\n    for (const auto& f : fish) {\n        int gx = min(f.x / CELL_SIZE, G - 1);\n        int gy = min(f.y / CELL_SIZE, G - 1);\n        if (f.type == 0) grid_m[gx][gy]++;\n        else grid_s[gx][gy]++;\n    }\n\n    for (int i = 0; i < G; ++i) {\n        for (int j = 0; j < G; ++j) {\n            grid_score[i][j] = grid_m[i][j] - grid_s[i][j];\n        }\n    }\n}\n\n// Fill holes in the selected region\nvoid fill_holes() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    queue<pair<int, int>> q;\n\n    // Start BFS from boundaries\n    for (int i = 0; i < G_SIZE; ++i) {\n        if (!selected[i][0]) { q.push({i, 0}); visited[i][0] = true; }\n        if (!selected[i][G_SIZE - 1]) { q.push({i, G_SIZE - 1}); visited[i][G_SIZE - 1] = true; }\n        if (!selected[0][i]) { q.push({0, i}); visited[0][i] = true; }\n        if (!selected[G_SIZE - 1][i]) { q.push({G_SIZE - 1, i}); visited[G_SIZE - 1][i] = true; }\n    }\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                if (!visited[nx][ny] && !selected[nx][ny]) {\n                    visited[nx][ny] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    // Any unselected cell not visited is a hole\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (!selected[i][j] && !visited[i][j]) {\n                selected[i][j] = true;\n            }\n        }\n    }\n}\n\n// Identify components of positive score cells\nvector<vector<pair<int, int>>> get_positive_components() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    vector<vector<pair<int, int>>> components;\n    \n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (grid_score[i][j] > 0 && !visited[i][j]) {\n                vector<pair<int, int>> comp;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                comp.push_back({i, j});\n                \n                while(!q.empty()){\n                    auto [cx, cy] = q.front(); q.pop();\n                    for(int d=0; d<4; ++d){\n                        int nx = cx + dx[d];\n                        int ny = cy + dy[d];\n                        if(nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE){\n                            if(!visited[nx][ny] && grid_score[nx][ny] > 0){\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                                comp.push_back({nx, ny});\n                            }\n                        }\n                    }\n                }\n                components.push_back(comp);\n            }\n        }\n    }\n    return components;\n}\n\n// Connect components to the main selected region\nvoid connect_components(const vector<vector<pair<int, int>>>& components) {\n    // Map cell to component index\n    vector<vector<int>> cell_to_comp(G_SIZE, vector<int>(G_SIZE, -1));\n    for (int k = 0; k < components.size(); ++k) {\n        for (auto [x, y] : components[k]) {\n            cell_to_comp[x][y] = k;\n        }\n    }\n\n    vector<bool> comp_selected(components.size(), false);\n    \n    // Find best component to start with\n    int best_comp_idx = -1;\n    long long max_score = -1e18;\n    for (int k = 0; k < components.size(); ++k) {\n        long long s = 0;\n        for (auto [x, y] : components[k]) s += grid_score[x][y];\n        if (s > max_score) {\n            max_score = s;\n            best_comp_idx = k;\n        }\n    }\n\n    if (best_comp_idx == -1) return; // No positive cells\n\n    // Initialize selected with best component\n    for (auto [x, y] : components[best_comp_idx]) {\n        selected[x][y] = true;\n    }\n    comp_selected[best_comp_idx] = true;\n\n    while (true) {\n        // Find unselected component with min connection cost\n        int best_target = -1;\n        long long min_cost = 1e18;\n        pair<int, int> hit_cell = {-1, -1};\n        \n        // Dijkstra from current selected region\n        vector<vector<long long>> dist(G_SIZE, vector<long long>(G_SIZE, 1e18));\n        vector<vector<pair<int, int>>> parent(G_SIZE, vector<pair<int, int>>(G_SIZE, {-1, -1}));\n        priority_queue<pair<long long, pair<int, int>>, vector<pair<long long, pair<int, int>>>, greater<>> pq;\n\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (selected[i][j]) {\n                    dist[i][j] = 0;\n                    pq.push({0, {i, j}});\n                }\n            }\n        }\n\n        vector<long long> comp_min_cost(components.size(), 1e18);\n        vector<pair<int, int>> comp_hit_cell(components.size(), {-1, -1});\n\n        while (!pq.empty()) {\n            auto [d, pos] = pq.top(); pq.pop();\n            int x = pos.first;\n            int y = pos.second;\n\n            if (d > dist[x][y]) continue;\n\n            int c_idx = cell_to_comp[x][y];\n            if (c_idx != -1 && !comp_selected[c_idx]) {\n                if (d < comp_min_cost[c_idx]) {\n                    comp_min_cost[c_idx] = d;\n                    comp_hit_cell[c_idx] = {x, y};\n                }\n            }\n\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                    long long weight = 0;\n                    if (!selected[nx][ny]) {\n                        weight = max(0, -grid_score[nx][ny]);\n                    }\n                    if (dist[x][y] + weight < dist[nx][ny]) {\n                        dist[nx][ny] = dist[x][y] + weight;\n                        parent[nx][ny] = {x, y};\n                        pq.push({dist[nx][ny], {nx, ny}});\n                    }\n                }\n            }\n        }\n\n        // Pick best component to connect\n        for (int k = 0; k < components.size(); ++k) {\n            if (!comp_selected[k] && comp_min_cost[k] < min_cost) {\n                min_cost = comp_min_cost[k];\n                best_target = k;\n                hit_cell = comp_hit_cell[k];\n            }\n        }\n\n        if (best_target == -1) break; // All connected\n\n        // Reconstruct path and mark selected\n        int cx = hit_cell.first;\n        int cy = hit_cell.second;\n        while (cx != -1 && cy != -1) {\n            if (!selected[cx][cy]) {\n                selected[cx][cy] = true;\n            }\n            if (dist[cx][cy] == 0) break; \n            auto p = parent[cx][cy];\n            cx = p.first;\n            cy = p.second;\n        }\n\n        // Mark all cells of the target component as selected\n        for (auto [x, y] : components[best_target]) {\n            selected[x][y] = true;\n        }\n        comp_selected[best_target] = true;\n    }\n}\n\n// Extract boundary polygon\nvector<Point> extract_polygon() {\n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    \n    auto add_edge = [&](int x1, int y1, int x2, int y2) {\n        adj[{x1, y1}].push_back({x2, y2});\n        adj[{x2, y2}].push_back({x1, y1});\n    };\n    \n    // Vertical edges\n    for (int i = 0; i <= G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            bool left = (i > 0 && selected[i-1][j]);\n            bool right = (i < G_SIZE && selected[i][j]);\n            if (left != right) {\n                int x = i * CELL_SIZE;\n                int y1 = j * CELL_SIZE;\n                int y2 = (j + 1) * CELL_SIZE;\n                add_edge({x, y1}, {x, y2});\n            }\n        }\n    }\n    // Horizontal edges\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j <= G_SIZE; ++j) {\n            bool down = (j > 0 && selected[i][j-1]);\n            bool up = (j < G_SIZE && selected[i][j]);\n            if (down != up) {\n                int y = j * CELL_SIZE;\n                int x1 = i * CELL_SIZE;\n                int x2 = (i + 1) * CELL_SIZE;\n                add_edge({x1, y}, {x2, y});\n            }\n        }\n    }\n    \n    if (adj.empty()) return {};\n    \n    // Traverse\n    vector<Point> poly;\n    auto start = adj.begin()->first;\n    pair<int, int> curr = start;\n    pair<int, int> prev = {-1, -1};\n    \n    while (true) {\n        poly.push_back({curr.first, curr.second});\n        auto& neighbors = adj[curr];\n        pair<int, int> next = {-1, -1};\n        for (auto& nb : neighbors) {\n            if (nb != prev) {\n                next = nb;\n                break;\n            }\n        }\n        if (next == make_pair(-1, -1)) break; \n        if (next == start) {\n            break;\n        }\n        prev = curr;\n        curr = next;\n    }\n    \n    return poly;\n}\n\nbool is_inside(const vector<Point>& poly, int px, int py) {\n    // Check on edge first\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x == p2.x) { \n            if (px == p1.x && py >= min(p1.y, p2.y) && py <= max(p1.y, p2.y)) return true;\n        } else { \n            if (py == p1.y && px >= min(p1.x, p2.x) && px <= max(p1.x, p2.x)) return true;\n        }\n    }\n    \n    // Ray casting\n    bool inside = false;\n    for (size_t i = 0, j = poly.size() - 1; i < poly.size(); j = i++) {\n        // Check if ray intersects edge\n        // Edge from p1 to p2. Ray from (px, py) to (-inf, py)\n        // Intersection if p1.y and p2.y are on opposite sides of py\n        // And intersection x < px\n        \n        // Using integer arithmetic to avoid precision issues\n        // x_intersect = p1.x + (py - p1.y) * (p2.x - p1.x) / (p2.y - p1.y)\n        // We want x_intersect > px (ray to left) -> inside toggle\n        // Wait, standard ray casting casts to +inf or -inf.\n        // Let's cast to +inf (right).\n        // If (p1.y > py) != (p2.y > py)\n        // And px < x_intersect\n        \n        if ((poly[i].y > py) != (poly[j].y > py)) {\n             // Calculate intersection x\n             // Avoid division: px * (poly[j].y - poly[i].y) < poly[i].x * (poly[j].y - poly[i].y) + (py - poly[i].y) * (poly[j].x - poly[i].x)\n             // Be careful with sign of (poly[j].y - poly[i].y)\n             long long val = (long long)(poly[j].x - poly[i].x) * (long long)(py - poly[i].y);\n             long long denom = (long long)(poly[j].y - poly[i].y);\n             // We want px < poly[i].x + val / denom\n             // px * denom < poly[i].x * denom + val  (if denom > 0)\n             // px * denom > poly[i].x * denom + val  (if denom < 0)\n             \n             long long rhs = (long long)poly[i].x * denom + val;\n             if (denom > 0) {\n                 if ((long long)px * denom < rhs) inside = !inside;\n             } else {\n                 if ((long long)px * denom > rhs) inside = !inside;\n             }\n        }\n    }\n    return inside;\n}\n\nlong long calculate_score(const vector<Point>& poly) {\n    long long a = 0;\n    long long b = 0;\n    for (const auto& f : fish) {\n        if (is_inside(poly, f.x, f.y)) {\n            if (f.type == 0) a++;\n            else b++;\n        }\n    }\n    return a - b;\n}\n\nvector<Point> solve_grid(int G) {\n    build_grid(G);\n    \n    auto components = get_positive_components();\n    if (components.empty()) {\n        return {{0, 0}, {10, 0}, {10, 10}, {0, 10}};\n    }\n    \n    connect_components(components);\n    fill_holes();\n    \n    vector<Point> poly = extract_polygon();\n    if (poly.size() > 1000) return {}; \n    \n    long long perim = 0;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n    }\n    if (perim > 400000) return {};\n    \n    return poly;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    read_input();\n    \n    vector<Point> best_poly;\n    long long best_score = -1e18;\n    \n    vector<int> grids = {200, 100, 50};\n    \n    for (int G : grids) {\n        vector<Point> poly = solve_grid(G);\n        if (!poly.empty()) {\n            long long score = calculate_score(poly);\n            if (score > best_score) {\n                best_score = score;\n                best_poly = poly;\n            }\n        }\n    }\n    \n    if (best_poly.empty()) {\n        best_poly = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <chrono>\n\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n};\n\nstruct Placement {\n    int p;      // rectangle index\n    int r;      // rotation (0 or 1)\n    char d;     // direction ('U' or 'L')\n    int b;      // reference rectangle (-1 or previous index)\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    vector<Rectangle> rects(N);\n    vector<pair<int, int>> dims(N);  // Store both orientations\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n        dims[i] = {rects[i].w_obs, rects[i].h_obs};\n    }\n    \n    // Use high-quality random with time-based seed for diversity\n    auto seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937 rng(seed);\n    \n    int best_score = 2000000000;\n    vector<Placement> best_placements;\n    \n    // Track successful patterns\n    vector<int> rot_success(N, 0);  // How often rotation 0 worked better\n    vector<int> dir_success(N, 0);  // How often 'U' worked better\n    \n    // Calculate aspect ratios to guide rotation\n    vector<double> aspect(N);\n    for (int i = 0; i < N; i++) {\n        aspect[i] = (double)max(rects[i].w_obs, rects[i].h_obs) / \n                    min(rects[i].w_obs, rects[i].h_obs);\n    }\n    \n    for (int turn = 0; turn < T; turn++) {\n        vector<Placement> placements;\n        placements.reserve(N);\n        \n        // Temperature for simulated annealing (high early, low late)\n        double temp = 1.0 - (double)turn / T;\n        \n        // Choose strategy based on turn\n        int strategy;\n        if (turn < T / 6) {\n            // Early exploration: try diverse base strategies\n            strategy = turn % 8;\n        } else if (turn < T / 2) {\n            // Mid phase: mix of exploration and exploitation\n            if (rng() % 3 == 0 && !best_placements.empty()) {\n                strategy = 100;  // Mutate best\n            } else {\n                strategy = 8 + (turn % 8);\n            }\n        } else {\n            // Late phase: mostly exploit best with small mutations\n            if (rng() % 4 == 0 || best_placements.empty()) {\n                strategy = 16 + (turn % 4);\n            } else {\n                strategy = 100;  // Mutate best\n            }\n        }\n        \n        if (strategy == 0) {\n            // All U, no rotation, b=-1 (vertical stack)\n            for (int i = 0; i < N; i++) {\n                placements.push_back({i, 0, 'U', -1});\n            }\n        } else if (strategy == 1) {\n            // All U, rotate tall rectangles\n            for (int i = 0; i < N; i++) {\n                int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                placements.push_back({i, rot, 'U', -1});\n            }\n        } else if (strategy == 2) {\n            // All U, rotate to make more square\n            for (int i = 0; i < N; i++) {\n                int rot = (aspect[i] > 1.5 && rng() % 2 == 0) ? 1 : 0;\n                placements.push_back({i, rot, 'U', -1});\n            }\n        } else if (strategy == 3) {\n            // All L, no rotation (horizontal stack)\n            for (int i = 0; i < N; i++) {\n                placements.push_back({i, 0, 'L', -1});\n            }\n        } else if (strategy == 4) {\n            // All L, rotate wide rectangles\n            for (int i = 0; i < N; i++) {\n                int rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                placements.push_back({i, rot, 'L', -1});\n            }\n        } else if (strategy == 5) {\n            // Alternating U/L\n            for (int i = 0; i < N; i++) {\n                char dir = (i % 2 == 0) ? 'U' : 'L';\n                placements.push_back({i, 0, dir, -1});\n            }\n        } else if (strategy == 6) {\n            // Shelf packing: groups of 5 with references\n            for (int i = 0; i < N; i++) {\n                int rot = (i % 3 == 0) ? 1 : 0;\n                char dir = 'U';\n                int ref = -1;\n                if (i > 0 && i % 5 == 0) {\n                    dir = 'L';\n                    ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy == 7) {\n            // Row packing with strategic references\n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                char dir = 'U';\n                int ref = -1;\n                if (i > 0) {\n                    if (i % 4 == 0) {\n                        dir = 'L';\n                        ref = i - 1;\n                    } else if (i % 4 == 1) {\n                        ref = i - 1;\n                    }\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy >= 8 && strategy < 16) {\n            // Varied patterns with different rotation schemes\n            int pat = strategy - 8;\n            for (int i = 0; i < N; i++) {\n                int rot;\n                if (pat == 0) rot = 0;\n                else if (pat == 1) rot = 1;\n                else if (pat == 2) rot = i % 2;\n                else if (pat == 3) rot = (i / 2) % 2;\n                else if (pat == 4) rot = (i / 3) % 2;\n                else if (pat == 5) rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                else if (pat == 6) rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                else rot = rng() % 2;\n                \n                char dir = (pat < 4) ? 'U' : 'L';\n                if (pat >= 6 && i % 3 == 0) dir = (dir == 'U') ? 'L' : 'U';\n                \n                int ref = -1;\n                if (i > 0 && pat >= 4 && i % 5 == 0) ref = i - 1;\n                \n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy == 100) {\n            // Mutate best solution (simulated annealing)\n            placements = best_placements;\n            \n            // Number of mutations decreases over time\n            int base_mutations = max(1, N / 5);\n            int mutations = max(1, (int)(base_mutations * temp));\n            \n            for (int m = 0; m < mutations; m++) {\n                int idx = rng() % N;\n                int change = rng() % 4;\n                \n                if (change == 0) {\n                    // Flip rotation\n                    placements[idx].r = 1 - placements[idx].r;\n                } else if (change == 1) {\n                    // Flip direction\n                    placements[idx].d = (placements[idx].d == 'U') ? 'L' : 'U';\n                } else if (change == 2) {\n                    // Change reference\n                    if (placements[idx].b == -1 && idx > 0) {\n                        placements[idx].b = idx - 1;\n                    } else {\n                        placements[idx].b = -1;\n                    }\n                } else {\n                    // Random change\n                    placements[idx].r = rng() % 2;\n                    placements[idx].d = (rng() % 3 < 2) ? 'U' : 'L';\n                }\n            }\n        } else {\n            // Random exploration with bias\n            for (int i = 0; i < N; i++) {\n                int rot = rng() % 2;\n                char dir = (rng() % 5 < 4) ? 'U' : 'L';\n                int ref = -1;\n                if (i > 0 && rng() % 4 == 0) {\n                    ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        }\n        \n        // Output placement\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read result\n        int W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        int score = W_prime + H_prime;\n        \n        // Update best solution\n        if (score < best_score) {\n            best_score = score;\n            best_placements = placements;\n            \n            // Update success tracking\n            for (int i = 0; i < N; i++) {\n                if (placements[i].r == 0) rot_success[i]++;\n                else rot_success[i]--;\n                if (placements[i].d == 'U') dir_success[i]++;\n                else dir_success[i]--;\n            }\n        }\n        \n        // Output debug info (ignored by judge)\n        cout << \"# Turn \" << turn << \" score=\" << score << \" best=\" << best_score << \"\\n\";\n        cout << flush;\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n\nusing namespace std;\n\n// Global variables\nint N, M, H;\nvector<int> A;\nvector<vector<int>> adj;\nvector<int> L;\nvector<int> support_count;\nint violations = 0;\nlong long current_score = 0;\n\n// Check if v is supported based on current global state\nbool is_supported(int v) {\n    if (L[v] == 0) return true;\n    return support_count[v] > 0;\n}\n\n// Calculate total violations\nint count_violations() {\n    int cnt = 0;\n    for (int v = 0; v < N; ++v) {\n        if (!is_supported(v)) cnt++;\n    }\n    return cnt;\n}\n\n// Calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        score += (long long)(L[v] + 1) * A[v];\n    }\n    return score;\n}\n\n// Initialize with BFS from multiple roots\nvoid initialize_bfs(mt19937& rng) {\n    L.assign(N, -1);\n    support_count.assign(N, 0);\n    \n    // Select multiple roots based on A_v and degree\n    vector<pair<int, int>> candidates;\n    for (int v = 0; v < N; ++v) {\n        candidates.push_back({A[v] * (int)adj[v].size(), v});\n    }\n    sort(candidates.rbegin(), candidates.rend());\n    \n    // Pick top ~10% as roots\n    int num_roots = max(1, N / 10);\n    vector<int> roots;\n    for (int i = 0; i < num_roots && i < (int)candidates.size(); ++i) {\n        roots.push_back(candidates[i].second);\n    }\n    \n    // BFS from roots\n    queue<int> q;\n    for (int r : roots) {\n        L[r] = 0;\n        q.push(r);\n    }\n    \n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        \n        for (int u : adj[v]) {\n            if (L[u] == -1 && L[v] < H) {\n                L[u] = L[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n    \n    // Handle any unvisited vertices (shouldn't happen in connected graph)\n    for (int v = 0; v < N; ++v) {\n        if (L[v] == -1) L[v] = 0;\n    }\n    \n    // Calculate support counts\n    for (int v = 0; v < N; ++v) {\n        if (L[v] > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == L[v] - 1) {\n                    support_count[v]++;\n                }\n            }\n        }\n    }\n    \n    violations = count_violations();\n    current_score = calculate_score();\n}\n\n// Try to make solution valid by fixing violations\nvoid fix_violations(mt19937& rng) {\n    int max_iter = N * 10;\n    for (int iter = 0; iter < max_iter && violations > 0; ++iter) {\n        // Find a violated vertex\n        vector<int> violated;\n        for (int v = 0; v < N; ++v) {\n            if (!is_supported(v)) {\n                violated.push_back(v);\n            }\n        }\n        if (violated.empty()) break;\n        \n        int v = violated[uniform_int_distribution<int>(0, violated.size() - 1)(rng)];\n        \n        // Try to find a support or reduce level\n        bool fixed = false;\n        if (L[v] > 0) {\n            // Check if we can find support at L[v]-1\n            for (int u : adj[v]) {\n                if (L[u] == L[v] - 1) {\n                    // Support exists but support_count is wrong, recalculate\n                    fixed = true;\n                    break;\n                }\n            }\n        }\n        \n        if (!fixed && L[v] > 0) {\n            // Reduce level\n            int old_L = L[v];\n            int new_L = L[v] - 1;\n            \n            // Update support counts\n            for (int u : adj[v]) {\n                if (L[u] == old_L + 1) {\n                    support_count[u]--;\n                    if (support_count[u] == 0 && L[u] > 0) violations++;\n                }\n                if (L[u] == new_L + 1) {\n                    support_count[u]++;\n                    if (support_count[u] == 1 && L[u] > 0) violations--;\n                }\n            }\n            \n            // Update v's support\n            support_count[v] = 0;\n            if (new_L > 0) {\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) support_count[v]++;\n                }\n            }\n            \n            if (is_supported(v)) {\n                if (!is_supported(v) && L[v] > 0) violations--;\n            }\n            \n            L[v] = new_L;\n            current_score -= A[v];\n            \n            if (is_supported(v)) {\n                violations = count_violations();\n            }\n        }\n    }\n    \n    violations = count_violations();\n}\n\n// Greedy improvement: try to push vertices higher\nvoid greedy_improve(mt19937& rng) {\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return A[a] > A[b];\n    });\n    \n    bool improved = true;\n    int max_passes = 10;\n    for (int pass = 0; pass < max_passes && improved; ++pass) {\n        improved = false;\n        for (int v : order) {\n            if (L[v] < H) {\n                int new_L = L[v] + 1;\n                \n                // Check if we can support this level\n                int new_support = 0;\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) new_support++;\n                }\n                \n                if (new_support > 0) {\n                    // Check impact on neighbors at level new_L + 1\n                    bool can_move = true;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L + 1 && support_count[u] == 1) {\n                            can_move = false;\n                            break;\n                        }\n                    }\n                    \n                    if (can_move) {\n                        // Apply move\n                        int old_L = L[v];\n                        \n                        // Update neighbor support counts\n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                support_count[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                support_count[u]++;\n                            }\n                        }\n                        \n                        // Update v's support\n                        support_count[v] = new_support;\n                        \n                        L[v] = new_L;\n                        current_score += A[v];\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Simulated Annealing\nvoid simulated_annealing(mt19937& rng, double time_limit) {\n    auto start_time = chrono::steady_clock::now();\n    \n    const long long PENALTY = 1000000000LL;\n    double temp = 50000.0;\n    double initial_temp = 50000.0;\n    \n    long long best_valid_score = (violations == 0) ? current_score : -1;\n    vector<int> best_L = (violations == 0) ? L : vector<int>();\n    \n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = time_limit - elapsed;\n        \n        if (remaining < 0.05) break;\n        \n        // Adaptive cooling based on remaining time\n        double progress = elapsed / time_limit;\n        temp = initial_temp * pow(0.9999, iterations);\n        if (temp < 1.0) temp = 1.0;\n        \n        // Select vertex with bias towards high A_v\n        int v;\n        {\n            vector<double> weights(N);\n            double sum_w = 0;\n            for (int i = 0; i < N; ++i) {\n                weights[i] = A[i] + 1;\n                sum_w += weights[i];\n            }\n            double r = uniform_real_distribution<double>(0, sum_w)(rng);\n            double cum = 0;\n            v = N - 1;\n            for (int i = 0; i < N; ++i) {\n                cum += weights[i];\n                if (r <= cum) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n        \n        // Pick delta (bias towards +1 for higher score)\n        int delta = 1;\n        double up_prob = 0.7;\n        if (L[v] >= H) up_prob = 0.0;\n        if (uniform_real_distribution<double>(0, 1)(rng) > up_prob) {\n            delta = -1;\n        }\n        \n        int old_L = L[v];\n        int new_L = old_L + delta;\n        \n        if (new_L < 0 || new_L > H) {\n            iterations++;\n            continue;\n        }\n        if (new_L == old_L) {\n            iterations++;\n            continue;\n        }\n        \n        // Calculate delta_violations\n        int delta_violations = 0;\n        \n        // 1. Update v's own support status\n        bool v_supported_old = is_supported(v);\n        \n        int new_support_count_v = 0;\n        if (new_L > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == new_L - 1) {\n                    new_support_count_v++;\n                }\n            }\n        }\n        bool v_supported_new = (new_L == 0) || (new_support_count_v > 0);\n        \n        if (v_supported_old && !v_supported_new) delta_violations++;\n        if (!v_supported_old && v_supported_new) delta_violations--;\n        \n        // 2. Update neighbors' support status\n        vector<pair<int, int>> neighbor_changes;\n        \n        for (int u : adj[v]) {\n            int old_contrib = (L[u] == old_L + 1) ? 1 : 0;\n            int new_contrib = (L[u] == new_L + 1) ? 1 : 0;\n            int delta_sc = new_contrib - old_contrib;\n            \n            if (delta_sc != 0) {\n                bool u_supported_old = (L[u] == 0) || (support_count[u] > 0);\n                int predicted_sc = support_count[u] + delta_sc;\n                bool u_supported_new = (L[u] == 0) || (predicted_sc > 0);\n                \n                int v_delta = 0;\n                if (u_supported_old && !u_supported_new) v_delta = 1;\n                if (!u_supported_old && u_supported_new) v_delta = -1;\n                \n                if (v_delta != 0) {\n                    delta_violations += v_delta;\n                }\n                neighbor_changes.push_back({u, delta_sc});\n            }\n        }\n        \n        long long delta_score = (long long)(new_L - old_L) * A[v];\n        long long delta_cost = (long long)delta_violations * PENALTY - delta_score;\n        \n        // Accept / Reject\n        bool accept = false;\n        if (delta_cost < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-(double)delta_cost / temp);\n            if ((double)uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            L[v] = new_L;\n            support_count[v] = new_support_count_v;\n            current_score += delta_score;\n            violations += delta_violations;\n            \n            for (auto& nc : neighbor_changes) {\n                support_count[nc.first] += nc.second;\n            }\n            \n            if (violations == 0) {\n                if (current_score > best_valid_score) {\n                    best_valid_score = current_score;\n                    best_L = L;\n                }\n            }\n        }\n        \n        iterations++;\n        \n        // Periodically check time\n        if (iterations % 10000 == 0) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed >= time_limit) break;\n        }\n    }\n    \n    if (violations == 0 && current_score > best_valid_score) {\n        best_valid_score = current_score;\n        best_L = L;\n    }\n    \n    if (!best_L.empty()) {\n        L = best_L;\n        violations = 0;\n        current_score = best_valid_score;\n        \n        // Recalculate support counts\n        support_count.assign(N, 0);\n        for (int v = 0; v < N; ++v) {\n            if (L[v] > 0) {\n                for (int u : adj[v]) {\n                    if (L[u] == L[v] - 1) {\n                        support_count[v]++;\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> H)) return 0;\n    \n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    \n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    \n    // Read coordinates (unused)\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n    \n    // Multiple restarts with different seeds\n    long long best_score = -1;\n    vector<int> best_L_final(N, 0);\n    \n    auto total_start = chrono::steady_clock::now();\n    double total_time_limit = 1.85;\n    \n    int num_restarts = 3;\n    double time_per_restart = total_time_limit / num_restarts;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + restart * 1000000);\n        \n        // Initialize\n        initialize_bfs(rng);\n        \n        // Fix any violations\n        fix_violations(rng);\n        \n        // Run SA\n        simulated_annealing(rng, time_per_restart);\n        \n        // Greedy improvement\n        if (violations == 0) {\n            greedy_improve(rng);\n        }\n        \n        // Track best\n        if (violations == 0 && current_score > best_score) {\n            best_score = current_score;\n            best_L_final = L;\n        }\n        \n        // Check total time\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - total_start).count();\n        if (elapsed >= total_time_limit) break;\n    }\n    \n    // Reconstruct parents from best_L\n    vector<int> P(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (best_L_final[v] > 0) {\n            int target = best_L_final[v] - 1;\n            for (int u : adj[v]) {\n                if (best_L_final[u] == target) {\n                    P[v] = u;\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << P[i];\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n\nusing namespace std;\n\n// Direction mapping\n// 0: U, 1: D, 2: L, 3: R\nconst char DIR_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char REVERSE_DIR[] = {'D', 'U', 'R', 'L'};\n\nstruct Candidate {\n    int k;\n    unsigned long long oni_mask;\n};\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<string> grid(N);\n    vector<pair<int, int>> onis; \n    vector<vector<bool>> is_fuku(N, vector<bool>(N, false));\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] == 'x') {\n                onis.push_back({i, j});\n            } else if (grid[i][j] == 'o') {\n                is_fuku[i][j] = true;\n            }\n        }\n    }\n\n    int num_onis = onis.size();\n    // Map (r, c) to oni_id\n    vector<vector<int>> oni_id_map(N, vector<int>(N, -1));\n    for (int i = 0; i < num_onis; ++i) {\n        oni_id_map[onis[i].first][onis[i].second] = i;\n    }\n\n    // 4 * N lines. \n    // 0..N-1: Col 0..N-1 Up\n    // N..2N-1: Col 0..N-1 Down\n    // 2N..3N-1: Row 0..N-1 Left\n    // 3N..4N-1: Row 0..N-1 Right\n    int num_lines = 4 * N;\n    vector<vector<Candidate>> line_candidates(num_lines);\n    vector<int> current_k(num_lines, 0);\n    vector<int> cand_ptr(num_lines, 0);\n\n    // Precompute candidates for each line\n    for (int j = 0; j < N; ++j) {\n        // Col j Up (0)\n        // Removes rows 0 to k-1 in column j\n        int limit = N;\n        for (int r = 0; r < N; ++r) {\n            if (is_fuku[r][j]) {\n                limit = r; \n                break;\n            }\n        }\n        // Collect Oni distances\n        vector<int> oni_dists;\n        for (int r = 0; r < limit; ++r) {\n            if (oni_id_map[r][j] != -1) {\n                oni_dists.push_back(r + 1);\n            }\n        }\n        // Build masks for each relevant k\n        unsigned long long mask = 0;\n        int oni_idx = 0;\n        for (int k = 1; k <= limit; ++k) {\n            if (oni_idx < oni_dists.size() && oni_dists[oni_idx] == k) {\n                int id = oni_id_map[k-1][j];\n                mask |= (1ULL << id);\n                oni_idx++;\n                line_candidates[0 * N + j].push_back({k, mask});\n            }\n        }\n\n        // Col j Down (1)\n        // Removes rows N-k to N-1 in column j\n        limit = N;\n        for (int r = N - 1; r >= 0; --r) {\n            if (is_fuku[r][j]) {\n                limit = N - 1 - r;\n                break;\n            }\n        }\n        vector<pair<int, int>> k_ids;\n        for (int r = N - 1; r >= N - limit; --r) {\n            if (oni_id_map[r][j] != -1) {\n                k_ids.push_back({N - r, oni_id_map[r][j]});\n            }\n        }\n        sort(k_ids.begin(), k_ids.end());\n        mask = 0;\n        for (const auto& p : k_ids) {\n            mask |= (1ULL << p.second);\n            line_candidates[1 * N + j].push_back({p.first, mask});\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        // Row i Left (2)\n        // Removes cols 0 to k-1 in row i\n        int limit = N;\n        for (int c = 0; c < N; ++c) {\n            if (is_fuku[i][c]) {\n                limit = c;\n                break;\n            }\n        }\n        vector<pair<int, int>> k_ids;\n        for (int c = 0; c < limit; ++c) {\n            if (oni_id_map[i][c] != -1) {\n                k_ids.push_back({c + 1, oni_id_map[i][c]});\n            }\n        }\n        sort(k_ids.begin(), k_ids.end());\n        unsigned long long mask = 0;\n        for (const auto& p : k_ids) {\n            mask |= (1ULL << p.second);\n            line_candidates[2 * N + i].push_back({p.first, mask});\n        }\n\n        // Row i Right (3)\n        // Removes cols N-k to N-1 in row i\n        limit = N;\n        for (int c = N - 1; c >= 0; --c) {\n            if (is_fuku[i][c]) {\n                limit = N - 1 - c;\n                break;\n            }\n        }\n        k_ids.clear();\n        for (int c = N - 1; c >= N - limit; --c) {\n            if (oni_id_map[i][c] != -1) {\n                k_ids.push_back({N - c, oni_id_map[i][c]});\n            }\n        }\n        sort(k_ids.begin(), k_ids.end());\n        mask = 0;\n        for (const auto& p : k_ids) {\n            mask |= (1ULL << p.second);\n            line_candidates[3 * N + i].push_back({p.first, mask});\n        }\n    }\n\n    unsigned long long removed_mask = 0;\n    int removed_count = 0;\n    \n    // Greedy Set Cover with Marginal Cost\n    while (removed_count < num_onis) {\n        int best_line = -1;\n        int best_cand_idx = -1;\n        long long best_num = -1; \n        long long best_den = 1;\n\n        for (int l = 0; l < num_lines; ++l) {\n            // Advance pointer to first candidate with k > current_k[l]\n            while (cand_ptr[l] < (int)line_candidates[l].size() && \n                   line_candidates[l][cand_ptr[l]].k <= current_k[l]) {\n                cand_ptr[l]++;\n            }\n\n            // Check candidates\n            for (int idx = cand_ptr[l]; idx < (int)line_candidates[l].size(); ++idx) {\n                int k = line_candidates[l][idx].k;\n                unsigned long long mask = line_candidates[l][idx].oni_mask;\n                \n                unsigned long long new_onis = mask & ~removed_mask;\n                int gain = __builtin_popcountll(new_onis);\n\n                if (gain > 0) {\n                    long long cost = 2LL * (k - current_k[l]);\n                    // Compare cost/gain with best_num/best_den\n                    if (best_line == -1 || cost * best_den < best_num * gain) {\n                        best_line = l;\n                        best_cand_idx = idx;\n                        best_num = cost;\n                        best_den = gain;\n                    }\n                }\n            }\n        }\n\n        if (best_line == -1) {\n            break;\n        }\n\n        // Apply best move\n        int k = line_candidates[best_line][best_cand_idx].k;\n        current_k[best_line] = k;\n        \n        unsigned long long covered = line_candidates[best_line][best_cand_idx].oni_mask;\n        unsigned long long newly_removed = covered & ~removed_mask;\n        int count_new = __builtin_popcountll(newly_removed);\n        removed_mask |= covered;\n        removed_count += count_new;\n    }\n\n    // Output moves\n    vector<pair<char, int>> moves;\n    moves.reserve(1600);\n    for (int l = 0; l < num_lines; ++l) {\n        if (current_k[l] > 0) {\n            int dir = l / N;\n            int idx = l % N;\n            char d = DIR_CHARS[dir];\n            char rd = REVERSE_DIR[dir];\n            for (int s = 0; s < current_k[l]; ++s) moves.push_back({d, idx});\n            for (int s = 0; s < current_k[l]; ++s) moves.push_back({rd, idx});\n        }\n    }\n\n    for (const auto& mv : moves) {\n        cout << mv.first << \" \" << mv.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nint N;\nlong long L;\nvector<int> T;\n\n// Function to simulate the process and calculate error\nlong long simulate(const vector<int>& A, const vector<int>& B, vector<int>& counts) {\n    fill(counts.begin(), counts.end(), 0);\n    int cur = 0;\n    // L weeks\n    for (int k = 0; k < L; ++k) {\n        counts[cur]++;\n        int t = counts[cur];\n        if (t % 2 != 0) {\n            cur = A[cur];\n        } else {\n            cur = B[cur];\n        }\n    }\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(counts[i] - T[i]);\n    }\n    return error;\n}\n\n// Check connectivity from node 0 to all nodes with T[i] > 0\nbool is_connected(const vector<int>& A, const vector<int>& B) {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    q.push(0);\n    visited[0] = true;\n    int count = 0;\n    while(!q.empty()){\n        int u = q.front();\n        q.pop();\n        if (T[u] > 0) count++;\n        \n        // Outgoing edges\n        int v1 = A[u];\n        if (!visited[v1]) {\n            visited[v1] = true;\n            q.push(v1);\n        }\n        int v2 = B[u];\n        if (!visited[v2]) {\n            visited[v2] = true;\n            q.push(v2);\n        }\n    }\n    // Check if all important nodes are visited\n    for(int i=0; i<N; ++i){\n        if(T[i] > 0 && !visited[i]) return false;\n    }\n    return true;\n}\n\nvoid fix_connectivity(vector<int>& A, vector<int>& B, vector<long long>& load) {\n    // Repeatedly ensure all T[i]>0 are reachable from 0\n    // We do this by finding an unreachable important node and adding an edge to it from a reachable node\n    // We try to minimize the disturbance to the load balance\n    \n    while (true) {\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        q.push(0);\n        reachable[0] = true;\n        while(!q.empty()){\n            int u = q.front();\n            q.pop();\n            if(!reachable[A[u]]) { reachable[A[u]] = true; q.push(A[u]); }\n            if(!reachable[B[u]]) { reachable[B[u]] = true; q.push(B[u]); }\n        }\n        \n        int target = -1;\n        for(int i=0; i<N; ++i){\n            if(T[i] > 0 && !reachable[i]){\n                target = i;\n                break;\n            }\n        }\n        \n        if(target == -1) break; // All important nodes reachable\n        \n        // Find best edge to redirect to target\n        // We look for a reachable node u, and change one of its outgoing edges to target\n        // We want to minimize increase in |load[dest] - 2*T[dest]|\n        \n        long long min_cost = -1;\n        int best_u = -1;\n        int best_edge = -1; // 0 for A, 1 for B\n        int old_dest = -1;\n        \n        for(int u=0; u<N; ++u){\n            if(!reachable[u]) continue;\n            // Try changing A[u]\n            {\n                int w = A[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 0;\n                    old_dest = w;\n                }\n            }\n            // Try changing B[u]\n            {\n                int w = B[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 1;\n                    old_dest = w;\n                }\n            }\n        }\n        \n        if(best_u != -1){\n            // Apply change\n            if(best_edge == 0){\n                load[old_dest] -= T[best_u];\n                A[best_u] = target;\n                load[target] += T[best_u];\n            } else {\n                load[old_dest] -= T[best_u];\n                B[best_u] = target;\n                load[target] += T[best_u];\n            }\n        } else {\n            // Should not happen if there is at least one reachable node (0 is reachable)\n            // Fallback: force 0 to point to target\n            int w = A[0];\n            load[w] -= T[0];\n            A[0] = target;\n            load[target] += T[0];\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    T.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution construction using flow balance heuristic\n    // We have 2N items, each (T[i], i). We want to assign them to buckets 0..N-1\n    // such that sum of values in bucket j is close to 2*T[j].\n    \n    vector<pair<int, int>> items;\n    items.reserve(2 * N);\n    for (int i = 0; i < N; ++i) {\n        items.push_back({T[i], i});\n        items.push_back({T[i], i});\n    }\n    \n    // Sort items descending by value\n    sort(items.begin(), items.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n        return a.first > b.first;\n    });\n    \n    vector<long long> load(N, 0);\n    vector<int> A(N), B(N);\n    vector<vector<int>> outgoing(N); // Store assigned destinations for each source\n    \n    for (const auto& item : items) {\n        int val = item.first;\n        int src = item.second;\n        \n        // Find best bucket\n        int best_j = -1;\n        long long min_diff = -1;\n        \n        // To speed up, we can just scan all N. N=100 is small.\n        for (int j = 0; j < N; ++j) {\n            long long diff = abs(load[j] + val - 2LL * T[j]);\n            if (best_j == -1 || diff < min_diff) {\n                min_diff = diff;\n                best_j = j;\n            }\n        }\n        \n        load[best_j] += val;\n        outgoing[src].push_back(best_j);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        A[i] = outgoing[i][0];\n        B[i] = outgoing[i][1];\n    }\n    \n    // Fix connectivity\n    fix_connectivity(A, B, load);\n    \n    // Evaluate initial score\n    vector<int> counts(N);\n    long long current_score = simulate(A, B, counts);\n    long long best_score = current_score;\n    vector<int> best_A = A;\n    vector<int> best_B = B;\n    \n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    \n    double temp = 1000.0;\n    double cooling_rate = 0.9999;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        // Generate neighbor\n        int i = uniform_int_distribution<>(0, N - 1)(rng);\n        int type = uniform_int_distribution<>(0, 1)(rng); // 0 for A, 1 for B\n        int old_val = (type == 0) ? A[i] : B[i];\n        int new_val = uniform_int_distribution<>(0, N - 1)(rng);\n        \n        if (old_val == new_val) continue;\n        \n        // Apply change\n        if (type == 0) A[i] = new_val;\n        else B[i] = new_val;\n        \n        long long new_score = simulate(A, B, counts);\n        \n        double delta = (double)new_score - (double)current_score;\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_A = A;\n                best_B = B;\n            }\n        } else {\n            // Revert\n            if (type == 0) A[i] = old_val;\n            else B[i] = old_val;\n        }\n        \n        temp *= cooling_rate;\n        iter++;\n    }\n    \n    // Output best solution\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n#include <atcoder/dsu>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct City {\n    int id;\n    long long cx, cy;\n    int h_index;\n};\n\n// Hilbert curve functions to improve 2D spatial locality sorting\nvoid rot(int n, int *x, int *y, int rx, int ry) {\n    if (ry == 0) {\n        if (rx == 1) {\n            *x = n - 1 - *x;\n            *y = n - 1 - *y;\n        }\n        std::swap(*x, *y);\n    }\n}\n\nint xy2d(int n, int x, int y) {\n    int rx, ry, s, d = 0;\n    for (s = n / 2; s > 0; s /= 2) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        rot(s, &x, &y, rx, ry);\n    }\n    return d;\n}\n\nstruct Edge {\n    int u, v;\n    long long d2;\n    bool queried;\n};\n\nstruct Group {\n    int id; // Original index 0..M-1\n    vector<City> cities;\n    bool fully_queried = false;\n    vector<pair<int, int>> queried_edges;\n};\n\nlong long dist2(const City& a, const City& b) {\n    long long dx = a.cx - b.cx;\n    long long dy = a.cy - b.cy;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> G[i];\n    }\n\n    vector<City> cities(N);\n    vector<City> city_by_id(N);\n\n    // Hilbert curve grid size (next power of 2 > 10000)\n    const int H_N = 16384;\n\n    for (int i = 0; i < N; ++i) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cities[i].id = i;\n        cities[i].cx = (0LL + lx + rx) / 2;\n        cities[i].cy = (0LL + ly + ry) / 2;\n        // Compute Hilbert index for sorting\n        cities[i].h_index = xy2d(H_N, (int)cities[i].cx, (int)cities[i].cy);\n        city_by_id[i] = cities[i];\n    }\n\n    // Sort cities by Hilbert index to preserve 2D locality\n    sort(cities.begin(), cities.end(), [](const City& a, const City& b) {\n        return a.h_index < b.h_index;\n    });\n\n    // Partition into groups based on input sizes G\n    vector<Group> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].id = i;\n        groups[i].cities.reserve(G[i]);\n        for (int j = 0; j < G[i]; ++j) {\n            groups[i].cities.push_back(cities[cur++]);\n        }\n    }\n\n    // Sort groups by size for query allocation (small groups first)\n    // Small groups (size <= L) can be solved exactly with 1 query.\n    vector<int> group_order(M);\n    iota(group_order.begin(), group_order.end(), 0);\n    sort(group_order.begin(), group_order.end(), [&](int a, int b) {\n        return groups[a].cities.size() < groups[b].cities.size();\n    });\n\n    int queries_used = 0;\n\n    // Allocate queries\n    for (int idx : group_order) {\n        if (queries_used >= Q) break;\n        \n        Group& g = groups[idx];\n        int S = g.cities.size();\n        if (S <= 1) continue;\n\n        if (S <= L) {\n            // Can solve exactly with 1 query\n            vector<int> chunk_ids;\n            chunk_ids.reserve(S);\n            for (const auto& c : g.cities) chunk_ids.push_back(c.id);\n\n            cout << \"? \" << S;\n            for (int id : chunk_ids) cout << \" \" << id;\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n\n            for (int i = 0; i < S - 1; ++i) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                g.queried_edges.push_back({u, v});\n            }\n            g.fully_queried = true;\n        } else {\n            // Large group, use sliding window to cover as much as possible\n            // Cities in g.cities are already sorted by Hilbert index (locality)\n            int step = L - 1;\n            for (int start = 0; start < S; ) {\n                if (queries_used >= Q) break;\n\n                int end = start + L;\n                if (end > S) end = S;\n                \n                vector<int> chunk_ids;\n                chunk_ids.reserve(end - start);\n                for(int i = start; i < end; ++i) {\n                    chunk_ids.push_back(g.cities[i].id);\n                }\n\n                cout << \"? \" << chunk_ids.size();\n                for (int id : chunk_ids) cout << \" \" << id;\n                cout << \"\\n\";\n                cout.flush();\n                queries_used++;\n\n                int num_ret = chunk_ids.size() - 1;\n                for (int i = 0; i < num_ret; ++i) {\n                    int u, v;\n                    cin >> u >> v;\n                    if (u > v) swap(u, v);\n                    g.queried_edges.push_back({u, v});\n                }\n\n                if (end == S) break;\n                // Overlap by 1 to ensure connectivity of queried subgraphs\n                start = end - 1;\n            }\n            g.fully_queried = false;\n        }\n    }\n\n    // Output final answer\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        const Group& g = groups[i];\n        int S = g.cities.size();\n        \n        // Output cities in the group\n        for (int j = 0; j < S; ++j) {\n            if (j > 0) cout << \" \";\n            cout << g.cities[j].id;\n        }\n        cout << \"\\n\";\n\n        // Output edges\n        if (S <= 1) {\n            // No edges needed\n        } else if (g.fully_queried) {\n            // Use queried edges directly (they form the exact MST)\n            for (auto& e : g.queried_edges) {\n                cout << e.first << \" \" << e.second << \"\\n\";\n            }\n        } else {\n            // Run Kruskal with queried edges (high priority) + estimated edges\n            vector<Edge> pool;\n            \n            // Add queried edges\n            for (auto& p : g.queried_edges) {\n                const City& c1 = city_by_id[p.first];\n                const City& c2 = city_by_id[p.second];\n                pool.push_back({p.first, p.second, dist2(c1, c2), true});\n            }\n            \n            // Add estimated edges (complete graph within group)\n            // Use a set to avoid duplicates with queried edges\n            set<pair<int,int>> q_set(g.queried_edges.begin(), g.queried_edges.end());\n\n            for (int j = 0; j < S; ++j) {\n                for (int k = j + 1; k < S; ++k) {\n                    int u = g.cities[j].id;\n                    int v = g.cities[k].id;\n                    if (u > v) swap(u, v);\n                    if (q_set.count({u, v})) continue;\n                    \n                    pool.push_back({u, v, dist2(g.cities[j], g.cities[k]), false});\n                }\n            }\n\n            // Sort edges: distance asc, queried flag desc (prioritize queried)\n            sort(pool.begin(), pool.end(), [](const Edge& a, const Edge& b) {\n                if (a.d2 != b.d2) return a.d2 < b.d2;\n                return a.queried > b.queried;\n            });\n\n            dsu group_dsu(N);\n            int count = 0;\n            for (const auto& e : pool) {\n                if (group_dsu.same(e.u, e.v)) continue;\n                group_dsu.merge(e.u, e.v);\n                cout << e.u << \" \" << e.v << \"\\n\";\n                count++;\n                if (count == S - 1) break;\n            }\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nstruct Action {\n    char type;\n    char dir;\n};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\nint N, M;\nbool has_block[20][20];\nint dist_map[20][20];\nPos parent_pos[20][20];\nAction parent_act[20][20];\n\nconst int INF = 1e9;\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// BFS to find shortest path from start to end\nint bfs(Pos start, Pos end, bool store_path) {\n    for(int i = 0; i < N; ++i) \n        for(int j = 0; j < N; ++j) \n            dist_map[i][j] = INF;\n    \n    queue<Pos> q;\n    dist_map[start.r][start.c] = 0;\n    q.push(start);\n    \n    while(!q.empty()) {\n        Pos curr = q.front();\n        q.pop();\n        \n        if (curr == end) return dist_map[curr.r][curr.c];\n        \n        int d = dist_map[curr.r][curr.c];\n        \n        // Try Move actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r + dr[i];\n            int nc = curr.c + dc[i];\n            if(is_valid(nr, nc) && !has_block[nr][nc]) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'M', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n        \n        // Try Slide actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r;\n            int nc = curr.c;\n            while(true) {\n                int nnr = nr + dr[i];\n                int nnc = nc + dc[i];\n                if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                    break;\n                }\n                nr = nnr;\n                nc = nnc;\n            }\n            if(nr != curr.r || nc != curr.c) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'S', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return INF;\n}\n\nvector<Action> get_path(Pos end) {\n    vector<Action> path;\n    Pos curr = end;\n    while(dist_map[curr.r][curr.c] != 0) {\n        path.push_back(parent_act[curr.r][curr.c]);\n        curr = parent_pos[curr.r][curr.c];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Simulate actions and update position and block state\nPos simulate_action(Pos curr, const Action& act, bool update_blocks = false) {\n    if(act.type == 'M') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r + dr[i];\n                int nc = curr.c + dc[i];\n                // Safety check - should never happen if BFS is correct\n                if(!is_valid(nr, nc) || has_block[nr][nc]) {\n                    cerr << \"ERROR: Invalid move at (\" << curr.r << \",\" << curr.c \n                         << \") direction \" << act.dir << endl;\n                    return curr;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'S') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r;\n                int nc = curr.c;\n                while(true) {\n                    int nnr = nr + dr[i];\n                    int nnc = nc + dc[i];\n                    if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                        break;\n                    }\n                    nr = nnr;\n                    nc = nnc;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'A') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int br = curr.r + dr[i];\n                int bc = curr.c + dc[i];\n                if(is_valid(br, bc)) {\n                    if(update_blocks) {\n                        has_block[br][bc] = !has_block[br][bc];\n                    }\n                }\n                return curr;\n            }\n        }\n    }\n    return curr;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    vector<Pos> points(M);\n    for(int i = 0; i < M; ++i) {\n        cin >> points[i].r >> points[i].c;\n    }\n    \n    // Initialize blocks\n    memset(has_block, 0, sizeof(has_block));\n    \n    Pos curr = points[0];\n    vector<Action> all_actions;\n    \n    for(int k = 0; k < M - 1; ++k) {\n        Pos target = points[k+1];\n        \n        // Get base path without adding blocks\n        int base_dist = bfs(curr, target, true);\n        vector<Action> base_path = get_path(target);\n        \n        int best_dist = base_dist;\n        vector<Action> best_path = base_path;\n        Pos best_S = {-1, -1};\n        Pos best_adj = {-1, -1};\n        int best_dir = -1;\n        \n        // Only try adding blocks if base path is long enough to justify it\n        if(base_dist > 3) {\n            // Candidate block positions around target\n            vector<Pos> candidates;\n            for(int i = 0; i < 4; ++i) {\n                int sr = target.r + dr[i];\n                int sc = target.c + dc[i];\n                if(is_valid(sr, sc) && !has_block[sr][sc] && !(sr == curr.r && sc == curr.c)) {\n                    candidates.push_back({sr, sc});\n                }\n            }\n            \n            for(const auto& S : candidates) {\n                // Try placing block from each adjacent cell\n                for(int i = 0; i < 4; ++i) {\n                    int ar = S.r + dr[i];\n                    int ac = S.c + dc[i];\n                    if(!is_valid(ar, ac) || has_block[ar][ac]) continue;\n                    if(ar == S.r && ac == S.c) continue;\n                    \n                    // Cost to reach adjacent cell\n                    int d1 = bfs(curr, {ar, ac}, false);\n                    if(d1 == INF || d1 > best_dist) continue;\n                    \n                    // Temporarily place block\n                    has_block[S.r][S.c] = true;\n                    \n                    // Cost to reach target from adjacent cell\n                    int d2 = bfs({ar, ac}, target, false);\n                    \n                    // Remove block\n                    has_block[S.r][S.c] = false;\n                    \n                    if(d2 == INF) continue;\n                    \n                    int total = d1 + 1 + d2;\n                    \n                    if(total < best_dist) {\n                        best_dist = total;\n                        best_S = S;\n                        best_adj = {ar, ac};\n                        best_dir = i;\n                    }\n                }\n            }\n        }\n        \n        // Execute the best plan\n        if(best_S.r != -1) {\n            // 1. Move to best_adj\n            bfs(curr, best_adj, true);\n            vector<Action> p1 = get_path(best_adj);\n            \n            // Validate path before adding\n            Pos temp = curr;\n            for(const auto& act : p1) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p1.begin(), p1.end());\n            curr = best_adj;\n            \n            // 2. Alter (Place block)\n            all_actions.push_back({'A', dir_char[best_dir]});\n            has_block[best_S.r][best_S.c] = true;\n            \n            // 3. Move to target\n            bfs(curr, target, true);\n            vector<Action> p2 = get_path(target);\n            \n            // Validate path before adding\n            temp = curr;\n            for(const auto& act : p2) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p2.begin(), p2.end());\n            curr = target;\n        } else {\n            // Execute base plan\n            // Validate path\n            Pos temp = curr;\n            for(const auto& act : base_path) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), base_path.begin(), base_path.end());\n            curr = target;\n        }\n    }\n    \n    // Final validation of all actions\n    Pos validate_pos = points[0];\n    for(const auto& act : all_actions) {\n        validate_pos = simulate_action(validate_pos, act, true);\n    }\n    \n    // Output all actions\n    for(const auto& act : all_actions) {\n        cout << act.type << \" \" << act.dir << \"\\n\";\n    }\n    \n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { \n        return (long long)max(0, x2 - x1) * max(0, y2 - y1); \n    }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n    bool overlaps(const Rect& other) const {\n        return !(x2 <= other.x1 || other.x2 <= x1 || y2 <= other.y1 || other.y2 <= y1);\n    }\n};\n\n// Check if all companies in range are contained in rect\nbool allContained(const vector<Company>& comps, int idx, int end, const Rect& space) {\n    for (int i = idx; i < end; i++) {\n        if (!space.contains(comps[i].x, comps[i].y)) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Find bounding box of points in range\nRect boundingBox(const vector<Company>& comps, int idx, int end) {\n    int minX = 10001, minY = 10001, maxX = -1, maxY = -1;\n    for (int i = idx; i < end; i++) {\n        minX = min(minX, comps[i].x);\n        minY = min(minY, comps[i].y);\n        maxX = max(maxX, comps[i].x);\n        maxY = max(maxY, comps[i].y);\n    }\n    return {minX, minY, maxX + 1, maxY + 1};\n}\n\n// Try to partition with given split direction and position\nbool tryPartition(const vector<Company>& comps, int idx, int end,\n                  int x1, int y1, int x2, int y2,\n                  bool vertical, int splitPos,\n                  int& outSplit, bool& outVertical) {\n    Rect left, right;\n    int splitIdx = idx + 1;\n    \n    // Find split index based on area\n    long long leftArea = 0, totalArea = 0;\n    for (int i = idx; i < end; i++) totalArea += comps[i].r;\n    for (int i = idx; i < end - 1; i++) {\n        leftArea += comps[i].r;\n        if (leftArea * 2 >= totalArea) {\n            splitIdx = i + 1;\n            break;\n        }\n    }\n    \n    if (vertical) {\n        left = {x1, y1, splitPos, y2};\n        right = {splitPos, y1, x2, y2};\n    } else {\n        left = {x1, y1, x2, splitPos};\n        right = {x1, splitPos, x2, y2};\n    }\n    \n    // Verify all points are contained\n    bool leftOK = allContained(comps, idx, splitIdx, left);\n    bool rightOK = allContained(comps, splitIdx, end, right);\n    \n    if (leftOK && rightOK && splitPos > x1 && splitPos < x2) {\n        outSplit = splitPos;\n        outVertical = vertical;\n        return true;\n    }\n    \n    return false;\n}\n\n// Recursive space partitioning with guaranteed containment\nbool partition(vector<Company>& comps, int idx, int end, \n               int x1, int y1, int x2, int y2) {\n    int count = end - idx;\n    \n    if (count <= 0) return true;\n    if (x2 <= x1 || y2 <= y1) return false;\n    \n    // Verify all points are in current space\n    for (int i = idx; i < end; i++) {\n        if (comps[i].x < x1 || comps[i].x >= x2 || \n            comps[i].y < y1 || comps[i].y >= y2) {\n            return false;\n        }\n    }\n    \n    if (count == 1) {\n        comps[idx].a = x1;\n        comps[idx].b = y1;\n        comps[idx].c = x2;\n        comps[idx].d = y2;\n        return true;\n    }\n    \n    // Calculate bounding box of points\n    Rect bbox = boundingBox(comps, idx, end);\n    \n    // Try different split strategies\n    long long leftArea = 0, totalArea = 0;\n    for (int i = idx; i < end; i++) totalArea += comps[i].r;\n    \n    int bestSplitIdx = idx + 1;\n    for (int i = idx; i < end - 1; i++) {\n        leftArea += comps[i].r;\n        if (leftArea * 2 >= totalArea) {\n            bestSplitIdx = i + 1;\n            break;\n        }\n    }\n    \n    // Try vertical splits at different positions\n    for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n        Rect left = {x1, y1, splitPos, y2};\n        Rect right = {splitPos, y1, x2, y2};\n        \n        if (allContained(comps, idx, bestSplitIdx, left) &&\n            allContained(comps, bestSplitIdx, end, right)) {\n            \n            if (partition(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                partition(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                return true;\n            }\n        }\n    }\n    \n    // Try horizontal splits at different positions\n    for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n        Rect left = {x1, y1, x2, splitPos};\n        Rect right = {x1, splitPos, x2, y2};\n        \n        if (allContained(comps, idx, bestSplitIdx, left) &&\n            allContained(comps, bestSplitIdx, end, right)) {\n            \n            if (partition(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                partition(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                return true;\n            }\n        }\n    }\n    \n    // If no good split found, try different split indices\n    for (int splitIdx = idx + 1; splitIdx < end; splitIdx++) {\n        // Try vertical\n        for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n            Rect left = {x1, y1, splitPos, y2};\n            Rect right = {splitPos, y1, x2, y2};\n            \n            if (allContained(comps, idx, splitIdx, left) &&\n                allContained(comps, splitIdx, end, right)) {\n                \n                if (partition(comps, idx, splitIdx, x1, y1, splitPos, y2) &&\n                    partition(comps, splitIdx, end, splitPos, y1, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n        \n        // Try horizontal\n        for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n            Rect left = {x1, y1, x2, splitPos};\n            Rect right = {x1, splitPos, x2, y2};\n            \n            if (allContained(comps, idx, splitIdx, left) &&\n                allContained(comps, splitIdx, end, right)) {\n                \n                if (partition(comps, idx, splitIdx, x1, y1, x2, splitPos) &&\n                    partition(comps, splitIdx, end, x1, splitPos, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n    }\n    \n    // Fallback: give each company minimum space at their point\n    for (int i = idx; i < end; i++) {\n        comps[i].a = comps[i].x;\n        comps[i].b = comps[i].y;\n        comps[i].c = comps[i].x + 1;\n        comps[i].d = comps[i].y + 1;\n    }\n    return true;\n}\n\n// Verify no overlaps exist\nbool verifyNoOverlap(const vector<Company>& comps) {\n    int n = comps.size();\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            Rect ri = {comps[i].a, comps[i].b, comps[i].c, comps[i].d};\n            Rect rj = {comps[j].a, comps[j].b, comps[j].c, comps[j].d};\n            if (ri.overlaps(rj)) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Verify all points are contained\nbool verifyPoints(const vector<Company>& comps) {\n    for (const auto& c : comps) {\n        Rect r = {c.a, c.b, c.c, c.d};\n        if (!r.contains(c.x, c.y)) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Simple grid-based fallback that guarantees no overlaps\nvoid gridLayout(vector<Company>& comps) {\n    int n = comps.size();\n    int cols = (int)ceil(sqrt(n));\n    int rows = (n + cols - 1) / cols;\n    int cellW = 10000 / cols;\n    int cellH = 10000 / rows;\n    \n    // Sort by y then x for grid assignment\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (comps[i].y != comps[j].y) return comps[i].y < comps[j].y;\n        return comps[i].x < comps[j].x;\n    });\n    \n    for (int i = 0; i < n; i++) {\n        int idx = order[i];\n        int col = i % cols;\n        int row = i / cols;\n        \n        comps[idx].a = col * cellW;\n        comps[idx].b = row * cellH;\n        comps[idx].c = (col + 1) * cellW;\n        comps[idx].d = (row + 1) * cellH;\n        \n        // Ensure bounds\n        comps[idx].a = max(0, min(9999, comps[idx].a));\n        comps[idx].b = max(0, min(9999, comps[idx].b));\n        comps[idx].c = max(1, min(10000, comps[idx].c));\n        comps[idx].d = max(1, min(10000, comps[idx].d));\n        if (comps[idx].c <= comps[idx].a) comps[idx].c = comps[idx].a + 1;\n        if (comps[idx].d <= comps[idx].b) comps[idx].d = comps[idx].b + 1;\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<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n    }\n    \n    // Sort by x then y for better spatial coherence\n    sort(companies.begin(), companies.end(), [](const Company& a, const Company& b) {\n        if (a.x != b.x) return a.x < b.x;\n        return a.y < b.y;\n    });\n    \n    bool success = partition(companies, 0, n, 0, 0, 10000, 10000);\n    \n    // If partition failed or produced overlaps, use grid fallback\n    if (!success || !verifyNoOverlap(companies) || !verifyPoints(companies)) {\n        gridLayout(companies);\n    }\n    \n    // Final validation and fix\n    for (int i = 0; i < n; i++) {\n        // Ensure positive area\n        if (companies[i].c <= companies[i].a) {\n            companies[i].c = companies[i].a + 1;\n        }\n        if (companies[i].d <= companies[i].b) {\n            companies[i].d = companies[i].b + 1;\n        }\n        \n        // Ensure bounds\n        companies[i].a = max(0, min(9999, companies[i].a));\n        companies[i].b = max(0, min(9999, companies[i].b));\n        companies[i].c = max(1, min(10000, companies[i].c));\n        companies[i].d = max(1, min(10000, companies[i].d));\n        \n        if (companies[i].c <= companies[i].a) companies[i].c = companies[i].a + 1;\n        if (companies[i].d <= companies[i].b) companies[i].d = companies[i].b + 1;\n    }\n    \n    // Final overlap check - if still overlaps, use guaranteed grid\n    if (!verifyNoOverlap(companies)) {\n        gridLayout(companies);\n    }\n    \n    // Output in original order\n    vector<tuple<int,int,int,int>> result(n);\n    for (const auto& comp : companies) {\n        result[comp.id] = {comp.a, comp.b, comp.c, comp.d};\n    }\n    \n    for (int i = 0; i < n; i++) {\n        auto [a, b, c, d] = result[i];\n        cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    int ci, cj;\n    int score;\n    string path;\n    vector<bool> tile_visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int si, sj;\n    cin >> si >> sj;\n    \n    vector<vector<int>> t(50, vector<int>(50));\n    int max_tile = 0;\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> t[i][j];\n            max_tile = max(max_tile, t[i][j]);\n        }\n    }\n    \n    vector<vector<int>> p(50, vector<int>(50));\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> p[i][j];\n        }\n    }\n    \n    // Directions: U, D, L, R\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    const char dc[] = {'U', 'D', 'L', 'R'};\n    \n    string best_path = \"\";\n    int best_score = 0;\n    \n    auto get_time = []() {\n        return chrono::duration<double>(chrono::steady_clock::now().time_since_epoch()).count();\n    };\n    \n    double start_time = get_time();\n    double time_limit = 1.95;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int strategy_count = 0;\n    \n    while (get_time() - start_time < time_limit) {\n        strategy_count++;\n        \n        // Vary strategy parameters\n        double greediness = 0.5 + 0.5 * sin(strategy_count * 0.1);\n        double exploration = 0.3 + 0.4 * ((double)rng() / rng.max());\n        int beam_width = 1 + (strategy_count % 5);\n        \n        vector<State> beam;\n        vector<bool> initial_visited(max_tile + 1, false);\n        initial_visited[t[si][sj]] = true;\n        beam.push_back({si, sj, p[si][sj], \"\", initial_visited});\n        \n        for (int step = 0; step < 2500 && get_time() - start_time < time_limit; step++) {\n            vector<State> next_beam;\n            \n            for (auto& state : beam) {\n                vector<tuple<int, int, int, int>> candidates; // {value, connectivity, randomness_score, direction}\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = state.ci + di[d];\n                    int nj = state.cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        int tile_id = t[ni][nj];\n                        if (!state.tile_visited[tile_id]) {\n                            // Calculate connectivity score (how many unvisited neighbors this tile has)\n                            int connectivity = 0;\n                            for (int d2 = 0; d2 < 4; d2++) {\n                                int nn_i = ni + di[d2];\n                                int nn_j = nj + dj[d2];\n                                if (nn_i >= 0 && nn_i < 50 && nn_j >= 0 && nn_j < 50) {\n                                    if (!state.tile_visited[t[nn_i][nn_j]]) {\n                                        connectivity++;\n                                    }\n                                }\n                            }\n                            \n                            int rand_score = rng() % 100;\n                            candidates.push_back({p[ni][nj], connectivity, rand_score, d});\n                        }\n                    }\n                }\n                \n                if (candidates.empty()) {\n                    if (state.score > best_score) {\n                        best_score = state.score;\n                        best_path = state.path;\n                    }\n                    continue;\n                }\n                \n                // Sort candidates by combined score\n                sort(candidates.begin(), candidates.end(), [greediness](const tuple<int,int,int,int>& a, const tuple<int,int,int,int>& b) {\n                    int score_a = (int)(get<0>(a) * greediness + get<1>(a) * (1 - greediness) * 0.5);\n                    int score_b = (int)(get<0>(b) * greediness + get<1>(b) * (1 - greediness) * 0.5);\n                    if (score_a != score_b) return score_a > score_b;\n                    return get<0>(a) > get<0>(b);\n                });\n                \n                // Select top candidates for beam\n                int select_count = min(beam_width, (int)candidates.size());\n                for (int i = 0; i < select_count; i++) {\n                    if ((double)rng() / rng.max() > exploration && i > 0) break;\n                    \n                    State new_state = state;\n                    int d = get<3>(candidates[i]);\n                    new_state.path += dc[d];\n                    new_state.ci += di[d];\n                    new_state.cj += dj[d];\n                    new_state.score += p[new_state.ci][new_state.cj];\n                    new_state.tile_visited[t[new_state.ci][new_state.cj]] = true;\n                    next_beam.push_back(new_state);\n                }\n            }\n            \n            if (next_beam.empty()) break;\n            \n            // Keep top states by score\n            sort(next_beam.begin(), next_beam.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(beam_width, (int)next_beam.size()); i++) {\n                beam.push_back(next_beam[i]);\n            }\n        }\n        \n        // Check final beam states\n        for (auto& state : beam) {\n            if (state.score > best_score) {\n                best_score = state.score;\n                best_path = state.path;\n            }\n        }\n        \n        // Occasionally try pure greedy for comparison\n        if (strategy_count % 20 == 0) {\n            vector<bool> tile_visited(max_tile + 1, false);\n            string path = \"\";\n            int ci = si, cj = sj;\n            int score = p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n            \n            while (get_time() - start_time < time_limit) {\n                pair<int, int> best_candidate = {-1, -1};\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = ci + di[d];\n                    int nj = cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        if (!tile_visited[t[ni][nj]]) {\n                            if (best_candidate.first == -1 || p[ni][nj] > best_candidate.first) {\n                                best_candidate = {p[ni][nj], d};\n                            }\n                        }\n                    }\n                }\n                \n                if (best_candidate.first == -1) break;\n                \n                int d = best_candidate.second;\n                path += dc[d];\n                ci += di[d];\n                cj += dj[d];\n                score += p[ci][cj];\n                tile_visited[t[ci][cj]] = true;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best_path = path;\n            }\n        }\n        \n        // Try randomized greedy with different seeds\n        if (strategy_count % 5 == 0) {\n            mt19937 local_rng(strategy_count * 1000 + rng());\n            vector<bool> tile_visited(max_tile + 1, false);\n            string path = \"\";\n            int ci = si, cj = sj;\n            int score = p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n            \n            double local_randomness = 0.1 + 0.6 * ((double)local_rng() / local_rng.max());\n            \n            while (get_time() - start_time < time_limit) {\n                vector<pair<int, int>> candidates;\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = ci + di[d];\n                    int nj = cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        if (!tile_visited[t[ni][nj]]) {\n                            candidates.push_back({p[ni][nj], d});\n                        }\n                    }\n                }\n                \n                if (candidates.empty()) break;\n                \n                sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n                    return a.first > b.first;\n                });\n                \n                int pick_idx = 0;\n                if (candidates.size() > 1 && (double)local_rng() / local_rng.max() < local_randomness) {\n                    pick_idx = local_rng() % min(3, (int)candidates.size());\n                }\n                \n                int d = candidates[pick_idx].second;\n                path += dc[d];\n                ci += di[d];\n                cj += dj[d];\n                score += p[ci][cj];\n                tile_visited[t[ci][cj]] = true;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best_path = path;\n            }\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <numeric>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Edge weights and visit counts\ndouble h_w[H][W-1];\ndouble v_w[H-1][W];\nint h_n[H][W-1];\nint v_n[H-1][W];\n\n// Row/column averages for spatial correlation\ndouble h_row_avg[H];\ndouble v_col_avg[W];\nint h_row_n[H];\nint v_col_n[W];\n\n// Confidence in weights (higher = more confident)\ndouble h_conf[H][W-1];\ndouble v_conf[H-1][W];\n\nmt19937 rng(12345);\n\nvoid init() {\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W-1; ++j) {\n            h_w[i][j] = 5000.0;\n            h_n[i][j] = 2;\n            h_conf[i][j] = 0.1;\n        }\n        h_row_avg[i] = 5000.0;\n        h_row_n[i] = 0;\n    }\n    for (int i = 0; i < H-1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_w[i][j] = 5000.0;\n            v_n[i][j] = 2;\n            v_conf[i][j] = 0.1;\n        }\n    }\n    for (int j = 0; j < W; ++j) {\n        v_col_avg[j] = 5000.0;\n        v_col_n[j] = 0;\n    }\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nstring dijkstra(int sr, int sc, int tr, int tc, int query_num) {\n    vector<vector<double>> dist(H, vector<double>(W, 1e18));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> dir_to(H, vector<char>(W, 0));\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    \n    dist[sr][sc] = 0;\n    pq.push({0.0, sr, sc});\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char dchar[] = {'U', 'D', 'L', 'R'};\n    \n    // Exploration bonus: higher early, decays over time\n    double base_bonus = 800.0;\n    double explore_bonus = base_bonus * exp(-query_num / 250.0);\n    \n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        \n        int r = top.r;\n        int c = top.c;\n        double d = top.dist;\n        \n        if (d > dist[r][c] + 1e-9) continue;\n        if (r == tr && c == tc) break;\n        \n        for (int i = 0; i < 4; ++i) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                double weight = 0;\n                int n = 0;\n                double conf = 0;\n                \n                if (i == 0) { // U\n                    weight = v_w[r-1][c];\n                    n = v_n[r-1][c];\n                    conf = v_conf[r-1][c];\n                } else if (i == 1) { // D\n                    weight = v_w[r][c];\n                    n = v_n[r][c];\n                    conf = v_conf[r][c];\n                } else if (i == 2) { // L\n                    weight = h_w[r][c-1];\n                    n = h_n[r][c-1];\n                    conf = h_conf[r][c-1];\n                } else if (i == 3) { // R\n                    weight = h_w[r][c];\n                    n = h_n[r][c];\n                    conf = h_conf[r][c];\n                }\n                \n                // UCB-style exploration bonus based on confidence\n                double bonus = explore_bonus * (1.0 - conf) / sqrt(n + 1);\n                double cost = max(100.0, weight - bonus);\n                \n                if (dist[r][c] + cost < dist[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + cost;\n                    parent[nr][nc] = {r, c};\n                    dir_to[nr][nc] = dchar[i];\n                    pq.push({dist[nr][nc], nr, nc});\n                }\n            }\n        }\n    }\n    \n    // Reconstruct path\n    string path = \"\";\n    int cr = tr, cc = tc;\n    while (cr != sr || cc != sc) {\n        char d = dir_to[cr][cc];\n        path += d;\n        int pr = parent[cr][cc].first;\n        int pc = parent[cr][cc].second;\n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid smooth_weights() {\n    // Smooth horizontal weights toward row averages\n    for (int i = 0; i < H; ++i) {\n        if (h_row_n[i] < 3) continue;\n        double row_avg = 0;\n        int count = 0;\n        for (int j = 0; j < W-1; ++j) {\n            if (h_n[i][j] > 0) {\n                row_avg += h_w[i][j];\n                count++;\n            }\n        }\n        if (count > 0) {\n            row_avg /= count;\n            h_row_avg[i] = row_avg;\n            \n            // Pull individual weights toward row average\n            for (int j = 0; j < W-1; ++j) {\n                double smooth_factor = 0.1 * (1.0 - h_conf[i][j]);\n                h_w[i][j] = (1.0 - smooth_factor) * h_w[i][j] + smooth_factor * row_avg;\n            }\n        }\n    }\n    \n    // Smooth vertical weights toward column averages\n    for (int j = 0; j < W; ++j) {\n        if (v_col_n[j] < 3) continue;\n        double col_avg = 0;\n        int count = 0;\n        for (int i = 0; i < H-1; ++i) {\n            if (v_n[i][j] > 0) {\n                col_avg += v_w[i][j];\n                count++;\n            }\n        }\n        if (count > 0) {\n            col_avg /= count;\n            v_col_avg[j] = col_avg;\n            \n            // Pull individual weights toward column average\n            for (int i = 0; i < H-1; ++i) {\n                double smooth_factor = 0.1 * (1.0 - v_conf[i][j]);\n                v_w[i][j] = (1.0 - smooth_factor) * v_w[i][j] + smooth_factor * col_avg;\n            }\n        }\n    }\n}\n\nvoid update_weights(const string& path, int sr, int sc, int observed_len, int query_num) {\n    if (path.empty()) return;\n    \n    int cr = sr, cc = sc;\n    double est_len = 0;\n    \n    struct EdgeRef {\n        bool is_h;\n        int r, c;\n        double old_weight;\n    };\n    vector<EdgeRef> path_edges;\n    \n    for (char d : path) {\n        int nr = cr, nc = cc;\n        if (d == 'U') { nr--; }\n        else if (d == 'D') { nr++; }\n        else if (d == 'L') { nc--; }\n        else if (d == 'R') { nc++; }\n        \n        double w = 0;\n        bool is_h = false;\n        int r = 0, c = 0;\n        \n        if (d == 'U') {\n            w = v_w[cr-1][cc];\n            is_h = false; r = cr-1; c = cc;\n        } else if (d == 'D') {\n            w = v_w[cr][cc];\n            is_h = false; r = cr; c = cc;\n        } else if (d == 'L') {\n            w = h_w[cr][cc-1];\n            is_h = true; r = cr; c = cc-1;\n        } else if (d == 'R') {\n            w = h_w[cr][cc];\n            is_h = true; r = cr; c = cc;\n        }\n        \n        est_len += w;\n        path_edges.push_back({is_h, r, c, w});\n        \n        cr = nr;\n        cc = nc;\n    }\n    \n    if (est_len < 1.0) return;\n    \n    // Calculate error ratio\n    double ratio = (double)observed_len / est_len;\n    \n    // Adaptive learning rate based on error magnitude and query number\n    double error_magnitude = abs(ratio - 1.0);\n    double base_lr = 0.2 + 0.1 * error_magnitude; // Higher lr for larger errors\n    double decay = exp(-query_num / 400.0);\n    double lr = base_lr * decay;\n    if (lr < 0.02) lr = 0.02;\n    \n    // Update each edge in the path\n    for (auto& edge : path_edges) {\n        double target_weight = edge.old_weight * ratio;\n        \n        if (edge.is_h) {\n            // Exponential moving average\n            h_w[edge.r][edge.c] = (1.0 - lr) * h_w[edge.r][edge.c] + lr * target_weight;\n            h_n[edge.r][edge.c]++;\n            \n            // Update confidence\n            h_conf[edge.r][edge.c] = min(1.0, h_conf[edge.r][edge.c] + 0.05);\n            \n            // Update row statistics\n            h_row_avg[edge.r] = (h_row_avg[edge.r] * h_row_n[edge.r] + h_w[edge.r][edge.c]) / (h_row_n[edge.r] + 1);\n            h_row_n[edge.r]++;\n            \n            // Clamp to valid range\n            if (h_w[edge.r][edge.c] < 1000) h_w[edge.r][edge.c] = 1000;\n            if (h_w[edge.r][edge.c] > 9000) h_w[edge.r][edge.c] = 9000;\n        } else {\n            v_w[edge.r][edge.c] = (1.0 - lr) * v_w[edge.r][edge.c] + lr * target_weight;\n            v_n[edge.r][edge.c]++;\n            \n            // Update confidence\n            v_conf[edge.r][edge.c] = min(1.0, v_conf[edge.r][edge.c] + 0.05);\n            \n            // Update column statistics\n            v_col_avg[edge.c] = (v_col_avg[edge.c] * v_col_n[edge.c] + v_w[edge.r][edge.c]) / (v_col_n[edge.c] + 1);\n            v_col_n[edge.c]++;\n            \n            if (v_w[edge.r][edge.c] < 1000) v_w[edge.r][edge.c] = 1000;\n            if (v_w[edge.r][edge.c] > 9000) v_w[edge.r][edge.c] = 9000;\n        }\n    }\n    \n    // Propagate learning to nearby edges (spatial correlation)\n    double propagate_lr = lr * 0.2;\n    for (auto& edge : path_edges) {\n        if (edge.is_h) {\n            // Propagate to other edges in same row\n            for (int j = 0; j < W-1; ++j) {\n                if (j != edge.c && h_n[edge.r][j] < 3) {\n                    h_w[edge.r][j] = (1.0 - propagate_lr) * h_w[edge.r][j] + propagate_lr * h_w[edge.r][edge.c];\n                    h_conf[edge.r][j] = max(0.0, h_conf[edge.r][j] - 0.02); // Reduce confidence for propagated values\n                }\n            }\n        } else {\n            // Propagate to other edges in same column\n            for (int i = 0; i < H-1; ++i) {\n                if (i != edge.r && v_n[i][edge.c] < 3) {\n                    v_w[i][edge.c] = (1.0 - propagate_lr) * v_w[i][edge.c] + propagate_lr * v_w[edge.r][edge.c];\n                    v_conf[i][edge.c] = max(0.0, v_conf[i][edge.c] - 0.02);\n                }\n            }\n        }\n    }\n    \n    // Periodic smoothing (every 50 queries)\n    if (query_num > 0 && query_num % 50 == 0) {\n        smooth_weights();\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    init();\n    \n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        string path = dijkstra(si, sj, ti, tj, k);\n        cout << path << \"\\n\" << flush;\n        \n        int observed;\n        cin >> observed;\n        \n        update_weights(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int ALPHABET = 8;\n\nint countMatches(const vector<string>& grid, const vector<string>& strings) {\n    int matches = 0;\n    for (const string& s : strings) {\n        bool found = false;\n        int len = s.length();\n        \n        // Check horizontal\n        for (int i = 0; i < N && !found; i++) {\n            for (int j = 0; j < N && !found; j++) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[i][(j + k) % N];\n                    if (c != '.' && c != s[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) found = true;\n            }\n        }\n        \n        // Check vertical\n        for (int i = 0; i < N && !found; i++) {\n            for (int j = 0; j < N && !found; j++) {\n                bool match = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[(i + k) % N][j];\n                    if (c != '.' && c != s[k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) found = true;\n            }\n        }\n        \n        if (found) matches++;\n    }\n    return matches;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N_in, M;\n    cin >> N_in >> M;\n    \n    vector<string> strings(M);\n    for (int i = 0; i < M; i++) {\n        cin >> strings[i];\n    }\n    \n    // Initialize grid with '.'\n    vector<string> grid(N, string(N, '.'));\n    \n    // Sort strings by length (longer first - more constrained)\n    vector<pair<int, int>> indexed(M);\n    for (int i = 0; i < M; i++) {\n        indexed[i] = {-(int)strings[i].length(), i};\n    }\n    sort(indexed.begin(), indexed.end());\n    \n    // Greedy placement\n    for (auto& p : indexed) {\n        int idx = p.second;\n        const string& s = strings[idx];\n        int len = s.length();\n        \n        // Try all positions and orientations\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                // Try horizontal\n                bool canPlaceH = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[i][(j + k) % N];\n                    if (c != '.' && c != s[k]) {\n                        canPlaceH = false;\n                        break;\n                    }\n                }\n                if (canPlaceH) {\n                    for (int k = 0; k < len; k++) {\n                        grid[i][(j + k) % N] = s[k];\n                    }\n                    goto next_string;\n                }\n                \n                // Try vertical\n                bool canPlaceV = true;\n                for (int k = 0; k < len; k++) {\n                    char c = grid[(i + k) % N][j];\n                    if (c != '.' && c != s[k]) {\n                        canPlaceV = false;\n                        break;\n                    }\n                }\n                if (canPlaceV) {\n                    for (int k = 0; k < len; k++) {\n                        grid[(i + k) % N][j] = s[k];\n                    }\n                    goto next_string;\n                }\n            }\n        }\n        next_string:;\n    }\n    \n    // Count initial matches\n    int matches = countMatches(grid, strings);\n    \n    // Simulated annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    double temp = 100.0;\n    double cooling = 0.99995;\n    int iterations = 800000;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        char old = grid[i][j];\n        \n        // Choose new character\n        char newChar;\n        if (old == '.') {\n            newChar = 'A' + (rng() % ALPHABET);\n        } else {\n            if (rng() % 3 == 0) {\n                newChar = '.';\n            } else {\n                newChar = 'A' + (rng() % ALPHABET);\n            }\n        }\n        \n        if (newChar == old) continue;\n        \n        grid[i][j] = newChar;\n        int newMatches = countMatches(grid, strings);\n        \n        double delta = newMatches - matches;\n        \n        // Accept if better, or with probability based on temperature\n        if (delta > 0 || (delta == 0 && newChar != '.') || \n            exp(delta / temp) > (double)(rng() % 1000000) / 1000000.0) {\n            matches = newMatches;\n        } else {\n            grid[i][j] = old;\n        }\n        \n        temp *= cooling;\n    }\n    \n    // If all strings match, fill remaining '.' to maximize score\n    if (matches == M) {\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] = 'A' + (rng() % ALPHABET);\n                }\n            }\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << grid[i] << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nconst int MAX_N = 70;\nconst int MAX_SEGMENTS = 5000;\nconst long long INF = 1e18;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<Point> road_squares;\nint segment_h[MAX_N][MAX_N];\nint segment_v[MAX_N][MAX_N];\nint num_h_segments = 0;\nint num_v_segments = 0;\nint total_road_squares = 0;\nint total_segments = 0;\n\nvector<Point> key_points;\nmap<Point, int> point_to_idx;\nint num_key_points = 0;\nint start_idx = -1;\n\nconst int MAX_KP = 300;\nlong long dist_mat[MAX_KP][MAX_KP];\nbitset<MAX_SEGMENTS> coverage_mat[MAX_KP][MAX_KP];\nvector<Point> path_mat[MAX_KP][MAX_KP];\n\nlong long dist_from_kp[MAX_KP][MAX_N][MAX_N];\nPoint parent_from_kp[MAX_KP][MAX_N][MAX_N];\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\n\nbool is_road(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N && grid[r][c] != '#';\n}\n\nint get_cost(int r, int c) {\n    return grid[r][c] - '0';\n}\n\nvoid identify_segments() {\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            segment_h[i][j] = -1;\n            segment_v[i][j] = -1;\n        }\n    }\n\n    for(int i=0; i<N; ++i) {\n        int j = 0;\n        while(j < N) {\n            if (grid[i][j] == '#') { j++; continue; }\n            int start_j = j;\n            while(j < N && grid[i][j] != '#') j++;\n            for(int k=start_j; k<j; ++k) segment_h[i][k] = num_h_segments;\n            num_h_segments++;\n        }\n    }\n\n    for(int j=0; j<N; ++j) {\n        int i = 0;\n        while(i < N) {\n            if (grid[i][j] == '#') { i++; continue; }\n            int start_i = i;\n            while(i < N && grid[i][j] != '#') i++;\n            for(int k=start_i; k<i; ++k) segment_v[k][j] = num_v_segments;\n            num_v_segments++;\n        }\n    }\n    \n    total_segments = num_h_segments + num_v_segments;\n}\n\nvoid identify_key_points() {\n    set<Point> kp_set;\n    kp_set.insert({si, sj});\n\n    for(const auto& p : road_squares) {\n        int degree = 0;\n        for(int d=0; d<4; ++d) {\n            int nr = p.r + dr[d], nc = p.c + dc[d];\n            if(is_road(nr, nc)) degree++;\n        }\n        if(degree != 2) kp_set.insert(p);\n    }\n    \n    if(kp_set.size() > MAX_KP - 20) {\n        vector<Point> sorted_kp(kp_set.begin(), kp_set.end());\n        sort(sorted_kp.begin(), sorted_kp.end(), [&](const Point& a, const Point& b) {\n            return abs(a.r - si) + abs(a.c - sj) < abs(b.r - si) + abs(b.c - sj);\n        });\n        kp_set.clear();\n        for(int i=0; i<MAX_KP - 20 && i<(int)sorted_kp.size(); ++i) kp_set.insert(sorted_kp[i]);\n        kp_set.insert({si, sj});\n    }\n\n    for(const auto& p : kp_set) {\n        if(num_key_points >= MAX_KP) break;\n        point_to_idx[p] = num_key_points;\n        key_points.push_back(p);\n        if(p.r == si && p.c == sj) start_idx = num_key_points;\n        num_key_points++;\n    }\n}\n\nvoid compute_apsp() {\n    for(int i=0; i<num_key_points; ++i) {\n        for(int j=0; j<num_key_points; ++j) {\n            dist_mat[i][j] = INF;\n        }\n    }\n\n    static long long d_grid[MAX_N][MAX_N];\n    static bitset<MAX_SEGMENTS> c_grid[MAX_N][MAX_N];\n    static Point parent_grid[MAX_N][MAX_N];\n    static bool visited[MAX_N][MAX_N];\n\n    for(int src_idx = 0; src_idx < num_key_points; ++src_idx) {\n        Point src = key_points[src_idx];\n        \n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                d_grid[i][j] = INF;\n                visited[i][j] = false;\n                dist_from_kp[src_idx][i][j] = INF;\n            }\n        }\n\n        priority_queue<pair<long long, Point>, vector<pair<long long, Point>>, greater<pair<long long, Point>>> pq;\n        \n        d_grid[src.r][src.c] = 0;\n        dist_from_kp[src_idx][src.r][src.c] = 0;\n        c_grid[src.r][src.c].reset();\n        if(segment_h[src.r][src.c] >= 0 && segment_h[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_h[src.r][src.c]);\n        if(segment_v[src.r][src.c] >= 0 && segment_v[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_v[src.r][src.c]);\n        \n        pq.push({0, src});\n        parent_grid[src.r][src.c] = {-1, -1};\n        parent_from_kp[src_idx][src.r][src.c] = {-1, -1};\n\n        int found_kp = 1;\n        \n        while(!pq.empty()) {\n            long long cost = pq.top().first;\n            Point u = pq.top().second;\n            pq.pop();\n\n            if(visited[u.r][u.c]) continue;\n            visited[u.r][u.c] = true;\n\n            if(point_to_idx.count(u)) {\n                int v_idx = point_to_idx[u];\n                dist_mat[src_idx][v_idx] = cost;\n                coverage_mat[src_idx][v_idx] = c_grid[u.r][u.c];\n                \n                vector<Point> path;\n                Point curr = u;\n                while(curr.r != -1) {\n                    path.push_back(curr);\n                    if(curr.r == src.r && curr.c == src.c) break;\n                    curr = parent_grid[curr.r][curr.c];\n                }\n                reverse(path.begin(), path.end());\n                path_mat[src_idx][v_idx] = path;\n                found_kp++;\n            }\n\n            for(int d=0; d<4; ++d) {\n                int nr = u.r + dr[d], nc = u.c + dc[d];\n                if(is_road(nr, nc)) {\n                    long long new_cost = cost + get_cost(nr, nc);\n\n                    if(new_cost < d_grid[nr][nc]) {\n                        d_grid[nr][nc] = new_cost;\n                        dist_from_kp[src_idx][nr][nc] = new_cost;\n                        c_grid[nr][nc] = c_grid[u.r][u.c];\n                        if(segment_h[nr][nc] >= 0 && segment_h[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_h[nr][nc]);\n                        if(segment_v[nr][nc] >= 0 && segment_v[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_v[nr][nc]);\n                        parent_grid[nr][nc] = u;\n                        parent_from_kp[src_idx][nr][nc] = u;\n                        pq.push({new_cost, {nr, nc}});\n                    }\n                }\n            }\n        }\n    }\n}\n\nvector<int> current_path;\nlong long current_dist = 0;\nbitset<MAX_SEGMENTS> current_cov;\nlong long best_dist = INF;\nvector<int> best_path;\nint best_coverage = 0;\n\nvoid ensure_start_end(vector<int>& path) {\n    if(path.empty()) {\n        path = {start_idx, start_idx};\n        return;\n    }\n    if(path.front() != start_idx) {\n        path.insert(path.begin(), start_idx);\n    }\n    if(path.back() != start_idx) {\n        path.push_back(start_idx);\n    }\n    // Ensure at least 2 elements\n    if(path.size() == 1) {\n        path.push_back(start_idx);\n    }\n}\n\nlong long calc_path_dist(const vector<int>& path) {\n    long long d = 0;\n    for(size_t i=0; i<path.size()-1; ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            d += dist_mat[path[i]][path[i+1]];\n    }\n    return d;\n}\n\nbitset<MAX_SEGMENTS> calc_path_cov(const vector<int>& path) {\n    bitset<MAX_SEGMENTS> c;\n    for(size_t i=0; i<path.size()-1; ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            c |= coverage_mat[path[i]][path[i+1]];\n    }\n    return c;\n}\n\nvoid update_state() {\n    current_dist = calc_path_dist(current_path);\n    current_cov = calc_path_cov(current_path);\n    best_coverage = current_cov.count();\n}\n\nlong long energy() {\n    int covered_segs = current_cov.count();\n    long long penalty = (long long)(total_segments - covered_segs) * 2000000LL;\n    return penalty + current_dist;\n}\n\nvoid solve_sa() {\n    current_path = {start_idx, start_idx};\n    update_state();\n    best_dist = current_dist;\n    best_path = current_path;\n    best_coverage = current_cov.count();\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 2.3;\n\n    int iter = 0;\n    double temp = 10000.0;\n    double cooling = 0.9995;\n\n    while(true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        if(best_coverage >= total_segments && iter > 2000) {\n            double remaining = time_limit - elapsed;\n            if(remaining < 0.3) break;\n        }\n        \n        vector<int> next_path = current_path;\n        int type = rng() % 5;\n        \n        if(next_path.size() > 2) {\n            if(type == 0 && next_path.size() > 3) {\n                int i = 1 + rng() % (next_path.size() - 2);\n                int j = i + 1 + rng() % (next_path.size() - 1 - i);\n                if(j >= (int)next_path.size() - 1) j = next_path.size() - 2;\n                reverse(next_path.begin() + i, next_path.begin() + j + 1);\n            } else if(type == 1 && next_path.size() > 3) {\n                int i = 1 + rng() % (next_path.size() - 2);\n                int j = 1 + rng() % (next_path.size() - 2);\n                swap(next_path[i], next_path[j]);\n            } else if(type == 2 || type == 4) {\n                int idx = 1 + rng() % (next_path.size());\n                int kp = rng() % num_key_points;\n                next_path.insert(next_path.begin() + idx, kp);\n            } else {\n                if(next_path.size() > 3) {\n                    int idx = 1 + rng() % (next_path.size() - 2);\n                    next_path.erase(next_path.begin() + idx);\n                }\n            }\n        } else {\n            int kp = rng() % num_key_points;\n            next_path.insert(next_path.begin() + 1, kp);\n        }\n\n        ensure_start_end(next_path);\n\n        long long next_dist = calc_path_dist(next_path);\n        if(next_dist >= INF) continue;\n        \n        bitset<MAX_SEGMENTS> next_cov = calc_path_cov(next_path);\n        int next_coverage = next_cov.count();\n\n        long long current_energy = energy();\n        long long next_penalty = (long long)(total_segments - next_coverage) * 2000000LL;\n        long long next_energy = next_penalty + next_dist;\n\n        double delta = (double)(next_energy - current_energy);\n        bool accept = false;\n        if(delta < 0) accept = true;\n        else {\n            double prob = exp(-delta / temp);\n            if((double)rng() / rng.max() < prob) accept = true;\n        }\n\n        if(accept) {\n            current_path = next_path;\n            current_dist = next_dist;\n            current_cov = next_cov;\n            \n            if(next_coverage >= total_segments) {\n                if(next_dist < best_dist) {\n                    best_dist = next_dist;\n                    best_path = current_path;\n                    best_coverage = next_coverage;\n                }\n            } else if(next_coverage > best_coverage) {\n                best_coverage = next_coverage;\n                best_path = current_path;\n                best_dist = next_dist;\n            }\n        }\n        \n        if(next_coverage >= total_segments && next_dist < best_dist) {\n            best_dist = next_dist;\n            best_path = next_path;\n            best_coverage = next_coverage;\n        }\n\n        temp *= cooling;\n        iter++;\n    }\n}\n\nvoid greedy_fix() {\n    ensure_start_end(best_path);\n    \n    bitset<MAX_SEGMENTS> cov;\n    for(size_t i=0; i<best_path.size()-1; ++i) {\n        if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n            cov |= coverage_mat[best_path[i]][best_path[i+1]];\n    }\n    \n    if(cov.count() >= total_segments) return;\n\n    int fix_iter = 0;\n    while(cov.count() < total_segments && fix_iter < 100) {\n        int missing_seg = -1;\n        for(int i=0; i<total_segments && i<MAX_SEGMENTS; ++i) {\n            if(!cov.test(i)) {\n                missing_seg = i;\n                break;\n            }\n        }\n        \n        if(missing_seg == -1) break;\n        \n        int best_kp = -1;\n        long long min_insert_cost = INF;\n        int best_pos = -1;\n\n        for(int kp=0; kp<num_key_points; ++kp) {\n            Point p = key_points[kp];\n            bool covers = false;\n            if(segment_h[p.r][p.c] == missing_seg) covers = true;\n            if(segment_v[p.r][p.c] == missing_seg) covers = true;\n            \n            if(covers) {\n                for(size_t i=0; i<best_path.size()-1; ++i) {\n                    int u = best_path[i], v = best_path[i+1];\n                    if(u >= num_key_points || v >= num_key_points) continue;\n                    long long cost = dist_mat[u][kp] + dist_mat[kp][v] - dist_mat[u][v];\n                    if(cost < min_insert_cost) {\n                        min_insert_cost = cost;\n                        best_kp = kp;\n                        best_pos = i + 1;\n                    }\n                }\n            }\n        }\n        \n        if(best_kp != -1 && best_pos != -1) {\n            best_path.insert(best_path.begin() + best_pos, best_kp);\n            ensure_start_end(best_path);\n            cov.reset();\n            for(size_t i=0; i<best_path.size()-1; ++i) {\n                if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n                    cov |= coverage_mat[best_path[i]][best_path[i+1]];\n            }\n            fix_iter++;\n            continue;\n        }\n        \n        // Try arbitrary road squares\n        Point best_point = {-1, -1};\n        int best_kp_for_point = -1;\n        long long best_point_cost = INF;\n        int best_point_pos = -1;\n        \n        for(const auto& p : road_squares) {\n            bool covers = false;\n            if(segment_h[p.r][p.c] == missing_seg) covers = true;\n            if(segment_v[p.r][p.c] == missing_seg) covers = true;\n            \n            if(!covers) continue;\n            \n            long long min_kp_dist = INF;\n            int nearest_kp = -1;\n            for(int kp=0; kp<num_key_points; ++kp) {\n                if(dist_from_kp[kp][p.r][p.c] < min_kp_dist) {\n                    min_kp_dist = dist_from_kp[kp][p.r][p.c];\n                    nearest_kp = kp;\n                }\n            }\n            \n            if(nearest_kp == -1) continue;\n            \n            for(size_t i=0; i<best_path.size()-1; ++i) {\n                int u = best_path[i], v = best_path[i+1];\n                if(u >= num_key_points || v >= num_key_points) continue;\n                \n                long long cost = dist_mat[u][nearest_kp] + dist_mat[nearest_kp][v] - dist_mat[u][v];\n                if(cost < best_point_cost) {\n                    best_point_cost = cost;\n                    best_kp_for_point = nearest_kp;\n                    best_point_pos = i + 1;\n                    best_point = p;\n                }\n            }\n        }\n        \n        if(best_kp_for_point != -1 && best_point_pos != -1) {\n            best_path.insert(best_path.begin() + best_point_pos, best_kp_for_point);\n            ensure_start_end(best_path);\n            cov.reset();\n            for(size_t i=0; i<best_path.size()-1; ++i) {\n                if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n                    cov |= coverage_mat[best_path[i]][best_path[i+1]];\n            }\n        } else {\n            break;\n        }\n        fix_iter++;\n    }\n}\n\nvoid final_coverage_check() {\n    ensure_start_end(best_path);\n    \n    bitset<MAX_SEGMENTS> final_cov;\n    for(size_t i=0; i<best_path.size()-1; ++i) {\n        if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n            final_cov |= coverage_mat[best_path[i]][best_path[i+1]];\n    }\n    \n    if(final_cov.count() >= total_segments) return;\n    \n    mt19937 rng(42);\n    for(int attempt = 0; attempt < 50 && final_cov.count() < total_segments; ++attempt) {\n        int missing_seg = -1;\n        for(int i=0; i<total_segments && i<MAX_SEGMENTS; ++i) {\n            if(!final_cov.test(i)) {\n                missing_seg = i;\n                break;\n            }\n        }\n        if(missing_seg == -1) break;\n        \n        Point target = {-1, -1};\n        for(const auto& p : road_squares) {\n            if(segment_h[p.r][p.c] == missing_seg || segment_v[p.r][p.c] == missing_seg) {\n                target = p;\n                break;\n            }\n        }\n        \n        if(target.r == -1) continue;\n        \n        long long min_dist = INF;\n        int nearest_kp = -1;\n        for(int kp=0; kp<num_key_points; ++kp) {\n            if(dist_from_kp[kp][target.r][target.c] < min_dist) {\n                min_dist = dist_from_kp[kp][target.r][target.c];\n                nearest_kp = kp;\n            }\n        }\n        \n        if(nearest_kp != -1) {\n            int pos = 1 + rng() % best_path.size();\n            best_path.insert(best_path.begin() + pos, nearest_kp);\n            ensure_start_end(best_path);\n            \n            final_cov.reset();\n            for(size_t i=0; i<best_path.size()-1; ++i) {\n                if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n                    final_cov |= coverage_mat[best_path[i]][best_path[i+1]];\n            }\n        }\n    }\n}\n\nvoid output_solution() {\n    ensure_start_end(best_path);\n    \n    // Validate path\n    if(best_path.empty() || best_path.front() != start_idx || best_path.back() != start_idx) {\n        // Fallback: just output empty path (stay at start)\n        cout << \"\" << endl;\n        return;\n    }\n    \n    string res = \"\";\n    Point curr = {si, sj};\n    for(size_t i=0; i<best_path.size()-1; ++i) {\n        int u = best_path[i], v = best_path[i+1];\n        if(u >= num_key_points || v >= num_key_points) continue;\n        const auto& segment = path_mat[u][v];\n        for(size_t k=1; k<segment.size(); ++k) {\n            Point next = segment[k];\n            if(next.r == curr.r + 1) res += 'D';\n            else if(next.r == curr.r - 1) res += 'U';\n            else if(next.c == curr.c + 1) res += 'R';\n            else if(next.c == curr.c - 1) res += 'L';\n            curr = next;\n        }\n    }\n    cout << res << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if(!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for(int i=0; i<N; ++i) cin >> grid[i];\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                total_road_squares++;\n            }\n        }\n    }\n\n    identify_segments();\n    identify_key_points();\n    compute_apsp();\n\n    solve_sa();\n    greedy_fix();\n    final_coverage_check();\n    output_solution();\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <numeric>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    \n    // Read initial input\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    // Read task difficulties\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    // Read dependencies\n    vector<vector<int>> deps(N);\n    vector<vector<int>> rev_deps(N);\n    vector<int> in_degree(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        deps[v].push_back(u);\n        rev_deps[u].push_back(v);\n        in_degree[v]++;\n    }\n    \n    // Skill estimates (start with reasonable guess based on task difficulty distribution)\n    vector<vector<double>> s_est(M, vector<double>(K, 35.0));\n    vector<int> s_obs_count(M, 0);\n    \n    // Task status: -1 = not started, 0 = in progress, 1 = completed\n    vector<int> task_status(N, -1);\n    \n    // Member tracking\n    vector<int> member_task(M, -1);\n    vector<int> member_start_day(M, -1);\n    \n    // Observations for learning: (task_id, observed_days)\n    vector<vector<pair<int, int>>> member_obs(M);\n    \n    // Task priority (estimated remaining tasks in dependency chain)\n    vector<int> task_priority(N, 0);\n    \n    // Calculate task priorities using reverse topological order\n    for (int i = N - 1; i >= 0; i--) {\n        task_priority[i] = 1;\n        for (int next : rev_deps[i]) {\n            task_priority[i] = max(task_priority[i], task_priority[next] + 1);\n        }\n    }\n    \n    int day = 0;\n    int completed_count = 0;\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(42);\n    \n    while (true) {\n        day++;\n        \n        // Read completion information\n        int n_completed;\n        cin >> n_completed;\n        \n        if (n_completed == -1) {\n            break;\n        }\n        \n        vector<int> completed_members(n_completed);\n        for (int i = 0; i < n_completed; i++) {\n            cin >> completed_members[i];\n            completed_members[i]--;\n        }\n        \n        // Process completions and update skill estimates\n        for (int member : completed_members) {\n            if (member_task[member] >= 0) {\n                int task = member_task[member];\n                int days_taken = day - member_start_day[member];\n                \n                task_status[task] = 1;\n                completed_count++;\n                \n                // Record observation\n                member_obs[member].push_back({task, days_taken});\n                s_obs_count[member]++;\n                \n                // Update skill estimate using observed data\n                // w = sum(max(0, d_k - s_k)) \u2248 days_taken (when w > 0)\n                // We try to adjust s_k to reduce the gap\n                if (days_taken > 1 && s_obs_count[member] <= 50) {\n                    // Early learning phase - more aggressive updates\n                    double learning_rate = 0.3 / min(10, s_obs_count[member]);\n                    \n                    for (int k = 0; k < K; k++) {\n                        double deficit = max(0.0, (double)d[task][k] - s_est[member][k]);\n                        // If task took long, increase skill estimate for skills where there was deficit\n                        if (deficit > 0) {\n                            s_est[member][k] += learning_rate * deficit * 0.5;\n                        }\n                        // Cap skill estimates reasonably\n                        s_est[member][k] = min(80.0, max(5.0, s_est[member][k]));\n                    }\n                }\n                \n                member_task[member] = -1;\n                member_start_day[member] = -1;\n            }\n        }\n        \n        // Check if all tasks completed\n        if (completed_count >= N) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Find ready tasks (all dependencies completed, not started)\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == -1) {\n                bool all_deps_done = true;\n                for (int dep : deps[i]) {\n                    if (task_status[dep] != 1) {\n                        all_deps_done = false;\n                        break;\n                    }\n                }\n                if (all_deps_done) {\n                    ready_tasks.push_back(i);\n                }\n            }\n        }\n        \n        // Find idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n        \n        if (idle_members.empty() || ready_tasks.empty()) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Calculate estimated completion time for each (member, task) pair\n        vector<vector<double>> est_time(M, vector<double>(N, 1e9));\n        for (int member : idle_members) {\n            for (int task : ready_tasks) {\n                double w = 0;\n                for (int k = 0; k < K; k++) {\n                    w += max(0.0, (double)d[task][k] - s_est[member][k]);\n                }\n                est_time[member][task] = (w == 0) ? 1.0 : max(1.0, w);\n            }\n        }\n        \n        // Greedy assignment: match tasks to members minimizing estimated time\n        // Prioritize high-priority tasks and good skill matches\n        vector<pair<int, int>> assignments;\n        vector<bool> task_assigned(ready_tasks.size(), false);\n        vector<bool> member_used(idle_members.size(), false);\n        \n        // Create assignment candidates with scores\n        vector<tuple<double, int, int, int>> candidates; // (score, priority, member_idx, task_idx)\n        for (size_t mi = 0; mi < idle_members.size(); mi++) {\n            for (size_t ti = 0; ti < ready_tasks.size(); ti++) {\n                int member = idle_members[mi];\n                int task = ready_tasks[ti];\n                double score = est_time[member][task] - task_priority[task] * 0.1;\n                candidates.push_back({score, task_priority[task], (int)mi, (int)ti});\n            }\n        }\n        \n        // Sort by score (lower is better)\n        sort(candidates.begin(), candidates.end());\n        \n        // Assign greedily\n        for (auto& [score, priority, mi, ti] : candidates) {\n            if (member_used[mi] || task_assigned[ti]) continue;\n            \n            int member = idle_members[mi];\n            int task = ready_tasks[ti];\n            \n            assignments.push_back({member + 1, task + 1});\n            member_used[mi] = true;\n            task_assigned[ti] = true;\n            \n            member_task[member] = task;\n            member_start_day[member] = day;\n            task_status[task] = 0;\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n        \n        // Output skill predictions for visualization (optional)\n        if (day % 50 == 1) {\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 << endl;\n            }\n            cout.flush();\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n    int order_id;\n    bool is_pickup;\n};\n\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nconst int OFFICE_X = 400, OFFICE_Y = 400;\nconst int NUM_ORDERS = 1000;\nconst int SELECT_COUNT = 50;\n\nlong long calc_distance(const vector<Point>& route) {\n    long long 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\nbool is_valid_route(const vector<Point>& route) {\n    vector<bool> picked(NUM_ORDERS, false);\n    for (size_t i = 0; i < route.size(); i++) {\n        if (route[i].order_id == -1) continue;\n        if (route[i].is_pickup) {\n            picked[route[i].order_id] = true;\n        } else {\n            if (!picked[route[i].order_id]) return false;\n        }\n    }\n    return true;\n}\n\n// Build route using nearest feasible neighbor with lookahead\nvector<Point> build_greedy_route(const vector<int>& selected, const vector<Order>& orders, mt19937& rng) {\n    vector<Point> route;\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    vector<bool> pickup_done(NUM_ORDERS, false);\n    vector<bool> delivery_done(NUM_ORDERS, false);\n    int remaining = SELECT_COUNT * 2;\n    \n    int cur_x = OFFICE_X, cur_y = OFFICE_Y;\n    \n    while (remaining > 0) {\n        // Collect all feasible moves\n        vector<tuple<int, int, bool>> candidates;\n        for (int idx : selected) {\n            if (!pickup_done[idx] && !delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].ax, orders[idx].ay);\n                // Add lookahead: distance from pickup to delivery\n                int lookahead = manhattan(orders[idx].ax, orders[idx].ay, orders[idx].cx, orders[idx].cy);\n                candidates.push_back({dist + lookahead / 3, idx, true});\n            }\n            if (pickup_done[idx] && !delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].cx, orders[idx].cy);\n                // Add lookahead: distance from delivery back toward office\n                int lookahead = manhattan(orders[idx].cx, orders[idx].cy, OFFICE_X, OFFICE_Y);\n                candidates.push_back({dist + lookahead / 4, idx, false});\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        // Sort by score\n        sort(candidates.begin(), candidates.end());\n        \n        // Pick from top k candidates randomly for diversity\n        int k = min((int)candidates.size(), 3);\n        int choice = uniform_int_distribution<int>(0, k - 1)(rng);\n        auto [score, order_idx, is_pickup] = candidates[choice];\n        \n        if (is_pickup) {\n            route.push_back({orders[order_idx].ax, orders[order_idx].ay, order_idx, true});\n            pickup_done[order_idx] = true;\n            cur_x = orders[order_idx].ax;\n            cur_y = orders[order_idx].ay;\n        } else {\n            route.push_back({orders[order_idx].cx, orders[order_idx].cy, order_idx, false});\n            delivery_done[order_idx] = true;\n            cur_x = orders[order_idx].cx;\n            cur_y = orders[order_idx].cy;\n        }\n        remaining--;\n    }\n    \n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    return route;\n}\n\n// Select orders based on simple scoring\nvector<int> select_orders(const vector<Order>& orders, mt19937& rng) {\n    vector<pair<double, int>> scores;\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n        int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n        int return_dist = manhattan(orders[i].cx, orders[i].cy, OFFICE_X, OFFICE_Y);\n        // Favor orders with shorter total distance\n        double score = pickup_dist + delivery_dist * 1.5 + return_dist;\n        // Add small randomness\n        score += uniform_real_distribution<double>(0, 100)(rng);\n        scores.push_back({score, i});\n    }\n    \n    sort(scores.begin(), scores.end());\n    \n    vector<int> selected;\n    for (int i = 0; i < SELECT_COUNT; i++) {\n        selected.push_back(scores[i].second);\n    }\n    \n    return selected;\n}\n\n// Try to swap an order in selection\nbool try_swap_order(vector<int>& selected, vector<bool>& is_selected, const vector<Order>& orders, \n                    long long& best_dist, vector<Point>& best_route, mt19937& rng) {\n    int remove_idx = uniform_int_distribution<int>(0, SELECT_COUNT - 1)(rng);\n    int remove_order = selected[remove_idx];\n    \n    // Find candidate orders to add\n    vector<pair<double, int>> candidates;\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        if (!is_selected[i]) {\n            int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n            int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n            double score = pickup_dist + delivery_dist * 1.5;\n            candidates.push_back({score, i});\n        }\n    }\n    sort(candidates.begin(), candidates.end());\n    \n    for (int try_idx = 0; try_idx < min(15, (int)candidates.size()); try_idx++) {\n        int add_order = candidates[try_idx].second;\n        \n        vector<int> new_selected = selected;\n        new_selected[remove_idx] = add_order;\n        \n        is_selected[remove_order] = false;\n        is_selected[add_order] = true;\n        \n        vector<Point> new_route = build_greedy_route(new_selected, orders, rng);\n        long long new_dist = calc_distance(new_route);\n        \n        if (new_dist < best_dist) {\n            selected = new_selected;\n            best_dist = new_dist;\n            best_route = new_route;\n            return true;\n        } else {\n            is_selected[remove_order] = true;\n            is_selected[add_order] = false;\n        }\n    }\n    \n    return false;\n}\n\n// Local search on route with multiple move types\nvoid optimize_route(vector<Point>& route, long long& best_dist, vector<Point>& best_route, \n                    mt19937& rng, double time_limit) {\n    auto start_time = chrono::steady_clock::now();\n    \n    double temperature = 10000.0;\n    double cooling_rate = 0.9999;\n    int iterations = 0;\n    int no_improve_count = 0;\n    \n    while (temperature > 1.0) {\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        iterations++;\n        int move_type = uniform_int_distribution<int>(0, 3)(rng);\n        \n        bool improved = false;\n        \n        if (move_type == 0 || move_type == 1) {\n            // 2-opt\n            int i = uniform_int_distribution<int>(1, (int)route.size() - 3)(rng);\n            int j = uniform_int_distribution<int>(i + 1, (int)route.size() - 2)(rng);\n            \n            vector<Point> new_route = route;\n            reverse(new_route.begin() + i, new_route.begin() + j + 1);\n            \n            if (is_valid_route(new_route)) {\n                long long new_dist = calc_distance(new_route);\n                double delta = new_dist - best_dist;\n                \n                if (delta < 0 || exp(-delta / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                    route = new_route;\n                    if (new_dist < best_dist) {\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                        no_improve_count = 0;\n                    }\n                }\n            }\n        } else if (move_type == 2) {\n            // Swap two points\n            int i = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            int j = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            \n            if (i != j) {\n                vector<Point> new_route = route;\n                swap(new_route[i], new_route[j]);\n                \n                if (is_valid_route(new_route)) {\n                    long long new_dist = calc_distance(new_route);\n                    if (new_dist < best_dist) {\n                        route = new_route;\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                        no_improve_count = 0;\n                    } else if (exp(-(new_dist - best_dist) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                        route = new_route;\n                    }\n                }\n            }\n        } else {\n            // Relocate single point\n            int pos = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            int new_pos = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            \n            if (pos != new_pos) {\n                vector<Point> new_route = route;\n                Point p = new_route[pos];\n                new_route.erase(new_route.begin() + pos);\n                int insert_pos = new_pos;\n                if (insert_pos > pos) insert_pos--;\n                new_route.insert(new_route.begin() + insert_pos, p);\n                \n                if (is_valid_route(new_route)) {\n                    long long new_dist = calc_distance(new_route);\n                    if (new_dist < best_dist) {\n                        route = new_route;\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                        no_improve_count = 0;\n                    } else if (exp(-(new_dist - best_dist) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                        route = new_route;\n                    }\n                }\n            }\n        }\n        \n        if (!improved) {\n            no_improve_count++;\n            if (no_improve_count > 5000) {\n                cooling_rate = max(0.999, cooling_rate - 0.00005);\n                no_improve_count = 0;\n            }\n        }\n        \n        temperature *= cooling_rate;\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    // Read input\n    vector<Order> orders(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n    }\n    \n    // Use multiple random seeds for diversity\n    vector<long long> seeds = {42, 123, 456, 789, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000};\n    \n    long long global_best_dist = LLONG_MAX;\n    vector<Point> global_best_route;\n    vector<int> global_best_selected;\n    vector<bool> global_is_selected(NUM_ORDERS, false);\n    \n    for (long long seed : seeds) {\n        auto iter_start = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(iter_start - start_time).count();\n        if (elapsed > 1.8) break;\n        \n        mt19937 rng(seed);\n        \n        // Select orders\n        vector<int> selected = select_orders(orders, rng);\n        vector<bool> is_selected(NUM_ORDERS, false);\n        for (int idx : selected) is_selected[idx] = true;\n        \n        // Build initial route\n        vector<Point> route = build_greedy_route(selected, orders, rng);\n        long long cur_dist = calc_distance(route);\n        \n        vector<Point> best_route = route;\n        long long best_dist = cur_dist;\n        \n        // Optimize route - allocate more time here\n        double time_per_seed = 0.12;\n        optimize_route(route, best_dist, best_route, rng, time_per_seed);\n        \n        // Try order swaps with route re-optimization\n        for (int swap_iter = 0; swap_iter < 30; swap_iter++) {\n            auto now = chrono::steady_clock::now();\n            double elapsed2 = chrono::duration<double>(now - start_time).count();\n            if (elapsed2 > 1.8) break;\n            \n            if (try_swap_order(selected, is_selected, orders, best_dist, best_route, rng)) {\n                route = best_route;\n                optimize_route(route, best_dist, best_route, rng, 0.03);\n            }\n        }\n        \n        if (best_dist < global_best_dist) {\n            global_best_dist = best_dist;\n            global_best_route = best_route;\n            global_best_selected = selected;\n            global_is_selected = is_selected;\n        }\n    }\n    \n    // Final intensive optimization on best solution\n    if (!global_best_route.empty()) {\n        mt19937 final_rng(99999);\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = max(0.1, 1.95 - elapsed);\n        \n        vector<Point> route = global_best_route;\n        long long best_dist = global_best_dist;\n        vector<Point> best_route = global_best_route;\n        \n        optimize_route(route, best_dist, best_route, final_rng, remaining);\n        \n        if (best_dist < global_best_dist) {\n            global_best_dist = best_dist;\n            global_best_route = best_route;\n        }\n    }\n    \n    // Output\n    cout << SELECT_COUNT;\n    for (int idx : global_best_selected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << endl;\n    \n    cout << global_best_route.size();\n    for (auto& p : global_best_route) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\nstruct UnionFind {\n    vector<int> parent;\n    vector<int> size;\n    int components;\n    \n    UnionFind(int n) : parent(n), size(n, 1), components(n) {\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        }\n        return parent[x];\n    }\n    \n    bool unite(int x, int y) {\n        int px = find(x);\n        int py = find(y);\n        if (px == py) return false;\n        \n        if (size[px] < size[py]) swap(px, py);\n        parent[py] = px;\n        size[px] += size[py];\n        components--;\n        return true;\n    }\n    \n    bool same(int x, int y) {\n        return find(x) == find(y);\n    }\n    \n    int componentSize(int x) {\n        return size[find(x)];\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    const int TARGET_EDGES = N - 1;  // 399 edges for MST\n    \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    vector<pair<int, int>> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n    }\n    \n    UnionFind uf(N);\n    int edges_selected = 0;\n    int inter_component_selected = 0;\n    \n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first;\n        int v = edges[i].second;\n        \n        double dx = coords[u].first - coords[v].first;\n        double dy = coords[u].second - coords[v].second;\n        double d = round(sqrt(dx * dx + dy * dy));\n        if (d < 1) d = 1;\n        \n        bool different_components = !uf.same(u, v);\n        bool accept = false;\n        \n        int components_left = uf.components;\n        int edges_left = M - i;\n        int needed = components_left - 1;\n        \n        // Progress through the edge stream (0.0 to 1.0)\n        double progress = (double)i / M;\n        \n        // CRITICAL: If we don't have enough edges left to connect, MUST accept\n        if (different_components && needed >= edges_left) {\n            accept = true;\n        }\n        // EMERGENCY: Last 300 edges, accept all inter-component edges\n        else if (i >= M - 300 && different_components && components_left > 1) {\n            accept = true;\n        }\n        // EMERGENCY: Last 500 edges, very lenient on inter-component\n        else if (i >= M - 500 && different_components && components_left > 1) {\n            if (l <= 2.95 * d) {\n                accept = true;\n            }\n        }\n        // Late stage (500-800 from end): moderately lenient\n        else if (i >= M - 800 && different_components && components_left > 1) {\n            double threshold = 2.6 * d;\n            if (components_left > 50) threshold = 2.8 * d;\n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Normal mode: inter-component edges with progressive thresholds\n        else if (different_components) {\n            // Base threshold starts at 2.2d and increases to 2.6d as we progress\n            double base_threshold = 2.2 + 0.4 * progress;\n            double threshold = base_threshold * d;\n            \n            // Adjust based on components remaining\n            if (components_left > 150) {\n                // Many components: can be selective, but ensure we're connecting\n                threshold = min(threshold, 2.5 * d);\n            } else if (components_left > 80) {\n                threshold = min(threshold, 2.4 * d);\n            } else if (components_left > 30) {\n                threshold = min(threshold, 2.3 * d);\n            }\n            \n            // Adjust based on selection rate\n            // Target: select roughly (TARGET_EDGES + 50) by 80% through\n            double expected_progress = progress * 0.8;\n            int target_by_now = (int)(expected_progress * (TARGET_EDGES + 50));\n            \n            if (inter_component_selected < target_by_now - 20) {\n                // Behind on inter-component edges: be more lenient\n                threshold = min(threshold, 2.6 * d);\n            } else if (inter_component_selected > target_by_now + 30) {\n                // Ahead: can be more selective\n                threshold = max(2.1 * d, threshold - 0.1 * d);\n            }\n            \n            // Prioritize edges connecting larger components (more impactful)\n            int size_u = uf.componentSize(u);\n            int size_v = uf.componentSize(v);\n            if (size_u + size_v > N / 2) {\n                // Connecting large components: slightly more lenient\n                threshold = min(threshold, 2.5 * d);\n            }\n            \n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Intra-component edges: accept if they could improve our tree\n        else {\n            // These edges form cycles, only accept if unusually cheap\n            // They might replace more expensive edges in our spanning structure\n            double intra_threshold = 1.25 * d;\n            \n            // More lenient if we haven't selected many edges yet\n            if (edges_selected < TARGET_EDGES) {\n                intra_threshold = 1.35 * d;\n            }\n            \n            // More lenient early in the process\n            if (progress < 0.3) {\n                intra_threshold = 1.4 * d;\n            }\n            \n            if (l <= intra_threshold) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            cout << 1 << \"\\n\";\n            if (uf.unite(u, v)) {\n                inter_component_selected++;\n            }\n            edges_selected++;\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        \n        cout.flush();\n    }\n    \n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <cstring>\n\nusing namespace std;\n\n// Structure to represent a position\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\n// Global variables\nint N, M;\nvector<Pos> pets;\nvector<int> pet_types;\nvector<Pos> humans;\nbool walls[32][32]; // Global wall state\nint pet_sum[32][32]; // Prefix sum of pet positions\n\n// Target zone\nint target_r1, target_r2, target_c1, target_c2;\nbool zone_locked = false; // If true, don't search for new zone for a while\nint turns_since_rezone = 0;\n\n// Check bounds\nbool in_grid(int r, int c) {\n    return r >= 0 && r < 30 && c >= 0 && c < 30;\n}\n\n// Update prefix sum of pet positions\nvoid update_pet_sum() {\n    int grid[32][32] = {0};\n    for(const auto& p : pets) {\n        if (in_grid(p.r, p.c)) {\n            grid[p.r][p.c]++;\n        }\n    }\n    // Compute 2D prefix sum\n    memset(pet_sum, 0, sizeof(pet_sum));\n    for(int i=0; i<30; ++i) {\n        for(int j=0; j<30; ++j) {\n            pet_sum[i+1][j+1] = grid[i][j] + pet_sum[i][j+1] + pet_sum[i+1][j] - pet_sum[i][j];\n        }\n    }\n}\n\n// Count pets in rectangle [r1, r2] x [c1, c2] (0-based inclusive)\nint count_pets(int r1, int c1, int r2, int c2) {\n    if (r1 > r2 || c1 > c2) return 0;\n    r1 = max(0, r1); c1 = max(0, c1);\n    r2 = min(29, r2); c2 = min(29, c2);\n    return pet_sum[r2+1][c2+1] - pet_sum[r1][c2+1] - pet_sum[r2+1][c1] + pet_sum[r1][c1];\n}\n\n// Evaluate a zone\nint evaluate_zone(int r1, int r2, int c1, int c2) {\n    if (r1 > r2 || c1 > c2) return -2000000;\n    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n    \n    // Critical: No pets inside\n    if (count_pets(r1, c1, r2, c2) > 0) {\n        return -1000000; \n    }\n    \n    // Penalty for pets adjacent to perimeter\n    int pets_adjacent = 0;\n    for(const auto& p : pets) {\n        int closest_r = max(r1, min(r2, p.r));\n        int closest_c = max(c1, min(c2, p.c));\n        int dist = abs(p.r - closest_r) + abs(p.c - closest_c);\n        if (dist == 1) {\n            pets_adjacent++;\n        }\n    }\n    \n    return area - pets_adjacent * 10;\n}\n\nvoid find_best_zone() {\n    int best_score = -2000000;\n    int best_r1 = 5, best_r2 = 24, best_c1 = 5, best_c2 = 24;\n    \n    for (int r1 = 0; r1 < 30; ++r1) {\n        for (int r2 = r1; r2 < 30; ++r2) {\n            for (int c1 = 0; c1 < 30; ++c1) {\n                for (int c2 = c1; c2 < 30; ++c2) {\n                    int score = evaluate_zone(r1, r2, c1, c2);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1;\n                        best_r2 = r2;\n                        best_c1 = c1;\n                        best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n    \n    target_r1 = best_r1;\n    target_r2 = best_r2;\n    target_c1 = best_c1;\n    target_c2 = best_c2;\n    \n    if (best_score > -500000) {\n        zone_locked = true;\n        turns_since_rezone = 0;\n    } else {\n        zone_locked = false;\n    }\n}\n\n// Get perimeter cells of the target zone\nvector<Pos> get_perimeter() {\n    vector<Pos> cells;\n    for (int c = target_c1; c <= target_c2; ++c) {\n        cells.push_back({target_r1, c});\n        if (target_r2 != target_r1) cells.push_back({target_r2, c});\n    }\n    for (int r = target_r1 + 1; r < target_r2; ++r) {\n        cells.push_back({r, target_c1});\n        if (target_c2 != target_c1) cells.push_back({r, target_c2});\n    }\n    return cells;\n}\n\n// Check if building at (r, c) is safe\nbool can_build(int r, int c, const vector<Pos>& current_humans) {\n    if (!in_grid(r, c)) return false;\n    if (walls[r][c]) return false; // Already a wall\n    \n    // Check if any human is at this position\n    for (const auto& h : current_humans) {\n        if (h.r == r && h.c == c) {\n            return false;\n        }\n    }\n    \n    // Check if any pet is at this position\n    for (const auto& p : pets) {\n        if (p.r == r && p.c == c) {\n            return false;\n        }\n    }\n    \n    // Check adjacency to pets (cannot build adjacent to pets)\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    for (const auto& p : pets) {\n        for (int k = 0; k < 4; ++k) {\n            if (p.r + dr[k] == r && p.c + dc[k] == c) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// BFS for human movement avoiding walls\nPos get_next_move(Pos start, Pos target, const bool grid[32][32]) {\n    if (start == target) return start;\n    \n    queue<Pos> q;\n    q.push(start);\n    int dist[32][32];\n    Pos parent[32][32];\n    for(int i=0; i<32; ++i) for(int j=0; j<32; ++j) {\n        dist[i][j] = -1;\n        parent[i][j] = {-1, -1};\n    }\n    \n    dist[start.r][start.c] = 0;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    \n    while(!q.empty()){\n        Pos cur = q.front(); q.pop();\n        if (cur == target) break;\n        \n        for(int k=0; k<4; ++k){\n            int nr = cur.r + dr[k];\n            int nc = cur.c + dc[k];\n            if(in_grid(nr, nc) && !grid[nr][nc] && dist[nr][nc] == -1){\n                dist[nr][nc] = dist[cur.r][cur.c] + 1;\n                parent[nr][nc] = cur;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if (dist[target.r][target.c] == -1) return start;\n    \n    Pos curr = target;\n    while(parent[curr.r][curr.c] != start){\n        curr = parent[curr.r][curr.c];\n        if (curr.r == -1) return start;\n    }\n    return curr;\n}\n\nchar get_action_char(Pos from, Pos to) {\n    if (from == to) return '.';\n    if (to.r < from.r) return 'U';\n    if (to.r > from.r) return 'D';\n    if (to.c < from.c) return 'L';\n    if (to.c > from.c) return 'R';\n    return '.';\n}\n\nchar get_build_char(Pos from, Pos wall_pos) {\n    if (wall_pos.r < from.r) return 'u';\n    if (wall_pos.r > from.r) return 'd';\n    if (wall_pos.c < from.c) return 'l';\n    if (wall_pos.c > from.c) return 'r';\n    return '.';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N)) return 0;\n    pets.resize(N);\n    pet_types.resize(N);\n    for(int i=0; i<N; ++i){\n        cin >> pets[i].r >> pets[i].c >> pet_types[i];\n        pets[i].r--; pets[i].c--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for(int i=0; i<M; ++i){\n        cin >> humans[i].r >> humans[i].c;\n        humans[i].r--; humans[i].c--;\n    }\n    \n    memset(walls, 0, sizeof(walls));\n    \n    update_pet_sum();\n    find_best_zone();\n    \n    vector<Pos> perimeter = get_perimeter();\n    \n    for(int turn=0; turn<300; ++turn){\n        if (turn > 0) {\n            for(int i=0; i<N; ++i){\n                string s;\n                cin >> s;\n                if (s == \".\") continue;\n                for(char c : s){\n                    if (c == 'U') pets[i].r--;\n                    else if (c == 'D') pets[i].r++;\n                    else if (c == 'L') pets[i].c--;\n                    else if (c == 'R') pets[i].c++;\n                }\n            }\n            update_pet_sum();\n        }\n        \n        bool need_rezone = false;\n        if (!zone_locked) {\n            turns_since_rezone++;\n            if (turns_since_rezone >= 50) need_rezone = true;\n        }\n        \n        if (count_pets(target_r1, target_c1, target_r2, target_c2) > 0) {\n            need_rezone = true;\n            zone_locked = false;\n        }\n        \n        if (need_rezone) {\n            find_best_zone();\n            perimeter = get_perimeter();\n            turns_since_rezone = 0;\n        }\n        \n        bool temp_walls[32][32];\n        memcpy(temp_walls, walls, sizeof(walls));\n        \n        vector<char> human_actions(M, '.');\n        vector<Pos> next_human_pos(M);\n        vector<Pos> old_humans = humans;\n        \n        // Identify buildable segments (check against current human positions)\n        vector<int> buildable_indices;\n        for(size_t i=0; i<perimeter.size(); ++i){\n            if (!walls[perimeter[i].r][perimeter[i].c]) {\n                if (can_build(perimeter[i].r, perimeter[i].c, humans)) {\n                    buildable_indices.push_back(i);\n                }\n            }\n        }\n        \n        vector<bool> segment_taken(perimeter.size(), false);\n        vector<bool> human_assigned_build(M, false);\n        \n        for(int i=0; i<M; ++i){\n            int best_seg = -1;\n            int min_dist = 10000;\n            \n            for(int idx : buildable_indices){\n                if (segment_taken[idx]) continue;\n                int d = abs(humans[i].r - perimeter[idx].r) + abs(humans[i].c - perimeter[idx].c);\n                if (d < min_dist) {\n                    min_dist = d;\n                    best_seg = idx;\n                }\n            }\n            \n            Pos target;\n            if (best_seg != -1) {\n                segment_taken[best_seg] = true;\n                human_assigned_build[i] = true;\n                target = perimeter[best_seg];\n                \n                int dist = abs(humans[i].r - target.r) + abs(humans[i].c - target.c);\n                if (dist == 1) {\n                    // Re-check can_build with temp_walls and updated human positions\n                    // (other humans might move to this position this turn)\n                    bool can_build_now = true;\n                    if (temp_walls[target.r][target.c]) can_build_now = false;\n                    \n                    // Check if any OTHER human will be at this position\n                    for(int j=0; j<M; ++j){\n                        if (i == j) continue;\n                        // Check if human j is already there or will move there\n                        if (humans[j].r == target.r && humans[j].c == target.c) {\n                            can_build_now = false;\n                            break;\n                        }\n                    }\n                    \n                    // Check pet adjacency again\n                    if (can_build_now) {\n                        int dr[] = {-1, 1, 0, 0};\n                        int dc[] = {0, 0, -1, 1};\n                        for (const auto& p : pets) {\n                            for (int k = 0; k < 4; ++k) {\n                                if (p.r + dr[k] == target.r && p.c + dc[k] == target.c) {\n                                    can_build_now = false;\n                                    break;\n                                }\n                            }\n                            if (!can_build_now) break;\n                        }\n                    }\n                    \n                    if (can_build_now) {\n                        human_actions[i] = get_build_char(humans[i], target);\n                        temp_walls[target.r][target.c] = true;\n                        next_human_pos[i] = humans[i]; // Stay\n                    } else {\n                        // Cannot build, move closer or wait\n                        Pos next = get_next_move(humans[i], target, temp_walls);\n                        human_actions[i] = get_action_char(humans[i], next);\n                        next_human_pos[i] = next;\n                    }\n                } else {\n                    Pos next = get_next_move(humans[i], target, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                }\n            } else {\n                // No buildable segments available\n                bool all_built = true;\n                for(const auto& p : perimeter) {\n                    if (!walls[p.r][p.c]) {\n                        all_built = false;\n                        break;\n                    }\n                }\n                \n                if (all_built) {\n                    Pos center = {(target_r1 + target_r2)/2, (target_c1 + target_c2)/2};\n                    Pos next = get_next_move(humans[i], center, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                } else {\n                    // Wait for buildable segments to become available\n                    human_actions[i] = '.';\n                    next_human_pos[i] = humans[i];\n                }\n            }\n        }\n        \n        // Output\n        string out = \"\";\n        for(int i=0; i<M; ++i) out += human_actions[i];\n        cout << out << endl;\n        \n        // Update state\n        for(int i=0; i<M; ++i){\n            humans[i] = next_human_pos[i];\n            char act = human_actions[i];\n            if (act == 'u') walls[old_humans[i].r - 1][old_humans[i].c] = true;\n            else if (act == 'd') walls[old_humans[i].r + 1][old_humans[i].c] = true;\n            else if (act == 'l') walls[old_humans[i].r][old_humans[i].c - 1] = true;\n            else if (act == 'r') walls[old_humans[i].r][old_humans[i].c + 1] = true;\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\n// Global variables\nint SI, SJ, TI, TJ;\ndouble P;\nchar H[20][20]; // 20 x 19 (last column unused)\nchar V[20][20]; // 19 x 20 (last row unused)\n\n// Directions: U, D, L, R\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIRS[4] = {'U', 'D', 'L', 'R'};\n\n// Grid helpers\ninline int get_idx(int r, int c) { return r * 20 + c; }\ninline int get_r(int idx) { return idx / 20; }\ninline int get_c(int idx) { return idx % 20; }\n\ninline bool is_wall(int r, int c, int dir) {\n    int nr = r + DI[dir];\n    int nc = c + DJ[dir];\n    if (nr < 0 || nr >= 20 || nc < 0 || nc >= 20) return true;\n    if (dir == 0) return (r == 0 || V[r-1][c] == '1');\n    if (dir == 1) return (r == 19 || V[r][c] == '1');\n    if (dir == 2) return (c == 0 || H[r][c-1] == '1');\n    if (dir == 3) return (c == 19 || H[r][c] == '1');\n    return true;\n}\n\nconst int L = 200;\nint TARGET_IDX;\n\n// Global DP cache - use flat arrays for cache efficiency\ndouble dp[201][400];\nint active_count[201];\nint active_list[201][400];\ndouble D[201];\nchar S[201];\n\n// Work buffers (static to avoid allocation)\ndouble work_dp[400];\nint work_active[400];\nint work_token[400];\nint work_token_val = 0;\n\ndouble next_work_dp[400];\nint next_work_active[400];\nint next_work_token[400];\nint next_work_token_val = 0;\n\nconst double PROB_THRESHOLD = 1e-10;\n\ndouble compute_dp_from(int k, const char* current_S, double* out_D_suffix) {\n    work_token_val++;\n    next_work_token_val++;\n    \n    int w_count = 0;\n    for (int i = 0; i < active_count[k]; ++i) {\n        int idx = active_list[k][i];\n        double val = dp[k][idx];\n        if (val > PROB_THRESHOLD) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = D[k];\n    double score_suffix = 0.0;\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = current_S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        int nw_count = 0;\n        double total_mass = 0.0;\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = get_r(idx);\n            int c = get_c(idx);\n            \n            bool wall = is_wall(r, c, dir_idx);\n            \n            if (wall) {\n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob;\n            } else {\n                int nr = r + DI[dir_idx];\n                int nc = c + DJ[dir_idx];\n                int nidx = get_idx(nr, nc);\n                \n                // Stay (forget)\n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob * P;\n                \n                // Move\n                if (nidx == TARGET_IDX) {\n                    sim_D += prob * (1.0 - P);\n                } else {\n                    if (next_work_token[nidx] != next_work_token_val) {\n                        next_work_token[nidx] = next_work_token_val;\n                        next_work_dp[nidx] = 0.0;\n                        next_work_active[nw_count++] = nidx;\n                    }\n                    next_work_dp[nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        double D_next = sim_D;\n        if (t + 1 < L) {\n            score_suffix += D_next;\n        } else {\n            score_suffix += 201.0 * D_next;\n        }\n        \n        // Calculate total mass for early termination\n        total_mass = 0.0;\n        w_count = nw_count;\n        for(int i = 0; i < w_count; ++i) {\n            int idx = next_work_active[i];\n            work_dp[idx] = next_work_dp[idx];\n            work_active[i] = idx;\n            work_token[idx] = work_token_val;\n            total_mass += work_dp[idx];\n        }\n        \n        // Early termination: if most probability reached target\n        if (total_mass < PROB_THRESHOLD && D_next > 0.999) {\n            double remaining_D = D_next;\n            for (int rem = t + 2; rem < L; ++rem) {\n                score_suffix += remaining_D;\n            }\n            break;\n        }\n    }\n    \n    *out_D_suffix = score_suffix;\n    return sim_D;\n}\n\nvoid update_cache_from(int k) {\n    work_token_val++;\n    \n    int w_count = 0;\n    for (int i = 0; i < active_count[k]; ++i) {\n        int idx = active_list[k][i];\n        double val = dp[k][idx];\n        if (val > PROB_THRESHOLD) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = D[k];\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        static int global_next_token[400];\n        static int global_next_token_val = 0;\n        global_next_token_val++;\n        \n        active_count[t+1] = 0;\n        double next_D = sim_D;\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = get_r(idx);\n            int c = get_c(idx);\n            \n            bool wall = is_wall(r, c, dir_idx);\n            \n            if (wall) {\n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active_list[t+1][active_count[t+1]++] = idx;\n                }\n                dp[t+1][idx] += prob;\n            } else {\n                int nr = r + DI[dir_idx];\n                int nc = c + DJ[dir_idx];\n                int nidx = get_idx(nr, nc);\n                \n                // Stay\n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active_list[t+1][active_count[t+1]++] = idx;\n                }\n                dp[t+1][idx] += prob * P;\n                \n                // Move\n                if (nidx == TARGET_IDX) {\n                    next_D += prob * (1.0 - P);\n                } else {\n                    if (global_next_token[nidx] != global_next_token_val) {\n                        global_next_token[nidx] = global_next_token_val;\n                        dp[t+1][nidx] = 0.0;\n                        active_list[t+1][active_count[t+1]++] = nidx;\n                    }\n                    dp[t+1][nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        sim_D = next_D;\n        D[t+1] = sim_D;\n        \n        w_count = 0;\n        for (int i = 0; i < active_count[t+1]; ++i) {\n            int idx = active_list[t+1][i];\n            work_dp[idx] = dp[t+1][idx];\n            work_active[w_count++] = idx;\n            work_token[idx] = work_token_val;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> SI >> SJ >> TI >> TJ >> P)) return 0;\n    \n    for (int i = 0; i < 20; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < 19; ++j) H[i][j] = row[j];\n    }\n    for (int i = 0; i < 19; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < 20; ++j) V[i][j] = row[j];\n    }\n    \n    TARGET_IDX = get_idx(TI, TJ);\n    \n    // BFS for shortest path\n    int dist[400];\n    int parent[400];\n    int parent_dir[400];\n    memset(dist, -1, sizeof(dist));\n    \n    queue<int> q;\n    int start_idx = get_idx(SI, SJ);\n    dist[start_idx] = 0;\n    q.push(start_idx);\n    \n    while(!q.empty()){\n        int idx = q.front(); q.pop();\n        if(idx == TARGET_IDX) break;\n        int r = get_r(idx), c = get_c(idx);\n        for(int d=0; d<4; ++d){\n            if(!is_wall(r, c, d)){\n                int nr = r + DI[d], nc = c + DJ[d];\n                int nidx = get_idx(nr, nc);\n                if(dist[nidx] == -1){\n                    dist[nidx] = dist[idx] + 1;\n                    parent[nidx] = idx;\n                    parent_dir[nidx] = d;\n                    q.push(nidx);\n                }\n            }\n        }\n    }\n    \n    // Construct initial path\n    string path = \"\";\n    if(dist[TARGET_IDX] != -1){\n        int curr = TARGET_IDX;\n        while(curr != start_idx){\n            path += DIRS[parent_dir[curr]];\n            curr = parent[curr];\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    // Fill S with repeated path\n    int path_len = path.length();\n    for(int i = 0; i < L; ++i){\n        S[i] = path[i % path_len];\n    }\n    S[L] = '\\0';\n    \n    // Initial DP Compute\n    memset(dp, 0, sizeof(dp));\n    memset(active_count, 0, sizeof(active_count));\n    \n    dp[0][start_idx] = 1.0;\n    active_list[0][0] = start_idx;\n    active_count[0] = 1;\n    D[0] = 0.0;\n    \n    update_cache_from(0);\n    \n    double current_score = 0.0;\n    for(int t=1; t<L; ++t) current_score += D[t];\n    current_score += 201.0 * D[L];\n    \n    double best_score = current_score;\n    string best_S(S, S + L);\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.8; // Reduced from 1.9\n    \n    double temp = 30.0;\n    int accepted = 0;\n    int total = 0;\n    \n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        // Adaptive temperature\n        if(total > 0 && total % 500 == 0){\n            double rate = (double)accepted / total;\n            if(rate > 0.4) temp *= 0.85;\n            else if(rate < 0.15) temp *= 1.15;\n            accepted = 0;\n            total = 0;\n        }\n        \n        // Single character mutation (fastest)\n        int k = uniform_int_distribution<int>(0, L-1)(rng);\n        char old_char = S[k];\n        \n        int old_dir = 0;\n        if(old_char == 'U') old_dir = 0;\n        else if(old_char == 'D') old_dir = 1;\n        else if(old_char == 'L') old_dir = 2;\n        else if(old_char == 'R') old_dir = 3;\n        \n        int new_dir = uniform_int_distribution<int>(0, 3)(rng);\n        while(new_dir == old_dir) {\n            new_dir = uniform_int_distribution<int>(0, 3)(rng);\n        }\n        \n        char new_char = DIRS[new_dir];\n        S[k] = new_char;\n        \n        double new_suffix_score;\n        compute_dp_from(k, S, &new_suffix_score);\n        \n        // Calculate prefix score\n        double prefix_score = 0.0;\n        for(int t=1; t<=k; ++t) {\n            prefix_score += D[t];\n        }\n        \n        double new_total_score = prefix_score + new_suffix_score;\n        double delta = new_total_score - current_score;\n        \n        if(delta > 0 || exp(delta / temp) > uniform_real_distribution<double>(0, 1)(rng)){\n            current_score = new_total_score;\n            update_cache_from(k);\n            accepted++;\n            \n            if(current_score > best_score){\n                best_score = current_score;\n                best_S = string(S, S + L);\n            }\n        } else {\n            S[k] = old_char;\n        }\n        \n        total++;\n        temp *= 0.99992;\n    }\n    \n    cout << best_S << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\n\n// Connection table: to[tile_type][entry_direction] = exit_direction\n// Directions: 0=left, 1=up, 2=right, 3=down\nconst int to_table[8][4] = {\n    {1, 0, -1, -1},  // tile 0\n    {3, -1, -1, 0},  // tile 1\n    {-1, -1, 3, 2},  // tile 2\n    {-1, 2, 1, -1},  // tile 3\n    {1, 0, 3, 2},    // tile 4\n    {3, 2, 1, 0},    // tile 5\n    {2, -1, 0, -1},  // tile 6\n    {-1, 3, -1, 1},  // tile 7\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nint tiles[N][N];\nint rotation[N][N];\nint best_rotation[N][N];\n\ninline int get_tile(int i, int j) {\n    return (tiles[i][j] + rotation[i][j]) % 8;\n}\n\n// Find all loops and return the two longest lengths\npair<int, int> find_two_longest_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    \n    int max1 = 0, max2 = 0;\n    int loop_count = 0;\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                if (!visited[i][j][d]) {\n                    int si = i, sj = j, sd = d;\n                    int ci = i, cj = j, cd = d;\n                    int length = 0;\n                    bool valid = true;\n                    const int max_len = N * N * 4 + 10;\n                    \n                    do {\n                        int tile = get_tile(ci, cj);\n                        int d2 = to_table[tile][cd];\n                        \n                        if (d2 == -1) {\n                            valid = false;\n                            break;\n                        }\n                        \n                        ci += di[d2];\n                        cj += dj[d2];\n                        \n                        if (ci < 0 || ci >= N || cj < 0 || cj >= N) {\n                            valid = false;\n                            break;\n                        }\n                        \n                        cd = (d2 + 2) % 4;\n                        length++;\n                        \n                        if (length > max_len) {\n                            valid = false;\n                            break;\n                        }\n                        \n                    } while (!(ci == si && cj == sj && cd == sd));\n                    \n                    if (valid && length > 0) {\n                        loop_count++;\n                        // Mark all states in this loop as visited\n                        ci = si; cj = sj; cd = sd;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2];\n                            cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == si && cj == sj && cd == sd));\n                        \n                        if (length > max1) {\n                            max2 = max1;\n                            max1 = length;\n                        } else if (length > max2) {\n                            max2 = length;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    return {max1, max2};\n}\n\nlong long calculate_score() {\n    auto [l1, l2] = find_two_longest_loops();\n    return (long long)l1 * l2;\n}\n\nint count_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    \n    int loop_count = 0;\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                if (!visited[i][j][d]) {\n                    int si = i, sj = j, sd = d;\n                    int ci = i, cj = j, cd = d;\n                    int length = 0;\n                    bool valid = true;\n                    const int max_len = N * N * 4 + 10;\n                    \n                    do {\n                        int tile = get_tile(ci, cj);\n                        int d2 = to_table[tile][cd];\n                        \n                        if (d2 == -1) { valid = false; break; }\n                        ci += di[d2]; cj += dj[d2];\n                        if (ci < 0 || ci >= N || cj < 0 || cj >= N) { valid = false; break; }\n                        cd = (d2 + 2) % 4;\n                        length++;\n                        if (length > max_len) { valid = false; break; }\n                    } while (!(ci == si && cj == sj && cd == sd));\n                    \n                    if (valid && length > 0) {\n                        loop_count++;\n                        ci = si; cj = sj; cd = sd;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2]; cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == si && cj == sj && cd == sd));\n                    }\n                }\n            }\n        }\n    }\n    \n    return loop_count;\n}\n\nvoid initialize_pattern(int pattern, mt19937_64& rng) {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            switch (pattern) {\n                case 0:  // Random\n                    rotation[i][j] = uniform_int_distribution<>(0, 3)(rng);\n                    break;\n                case 1:  // Horizontal pattern\n                    rotation[i][j] = (i % 4);\n                    break;\n                case 2:  // Vertical pattern\n                    rotation[i][j] = (j % 4);\n                    break;\n                case 3:  // Checkerboard\n                    rotation[i][j] = ((i + j) % 4);\n                    break;\n                case 4:  // Diagonal bands\n                    rotation[i][j] = ((i - j + N) % 4);\n                    break;\n                case 5:  // Concentric\n                    {\n                        int dist = min({i, j, N-1-i, N-1-j});\n                        rotation[i][j] = dist % 4;\n                    }\n                    break;\n                default:\n                    rotation[i][j] = uniform_int_distribution<>(0, 3)(rng);\n            }\n        }\n    }\n}\n\nlong long run_sa(mt19937_64& rng, double time_budget, int pattern) {\n    initialize_pattern(pattern, rng);\n    \n    // Ensure at least 2 loops\n    int loops = count_loops();\n    int attempts = 0;\n    while (loops < 2 && attempts < 10) {\n        initialize_pattern(0, rng);  // Try random\n        loops = count_loops();\n        attempts++;\n    }\n    \n    long long current_score = calculate_score();\n    long long best_score = current_score;\n    \n    // Only update best_rotation if we have valid score\n    if (current_score > 0) {\n        memcpy(best_rotation, rotation, sizeof(rotation));\n    }\n    \n    double temperature = 3000.0;\n    int no_improve = 0;\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        if (elapsed > time_budget) break;\n        \n        double remaining = time_budget - elapsed;\n        temperature = max(0.1, 500.0 * (remaining / time_budget));\n        \n        // Pick random tile\n        int i = uniform_int_distribution<>(0, N-1)(rng);\n        int j = uniform_int_distribution<>(0, N-1)(rng);\n        \n        int old_rot = rotation[i][j];\n        int new_rot = (old_rot + uniform_int_distribution<>(1, 3)(rng)) % 4;\n        rotation[i][j] = new_rot;\n        \n        long long new_score = calculate_score();\n        \n        // Reject if no valid loops\n        if (new_score == 0) {\n            rotation[i][j] = old_rot;\n            continue;\n        }\n        \n        double delta = (double)(new_score - current_score);\n        bool accept = false;\n        \n        if (delta > 0) {\n            accept = true;\n        } else if (temperature > 0.1) {\n            double prob = exp(delta / temperature);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n                no_improve = 0;\n            } else {\n                no_improve++;\n            }\n        } else {\n            rotation[i][j] = old_rot;\n        }\n        \n        // Restart if stuck\n        if (no_improve > 15000 && temperature < 5.0) {\n            temperature = 300.0;\n            no_improve = 0;\n            int ri = uniform_int_distribution<>(0, N-8)(rng);\n            int rj = uniform_int_distribution<>(0, N-8)(rng);\n            for (int x = ri; x < ri + 8 && x < N; x++) {\n                for (int y = rj; y < rj + 8 && y < N; y++) {\n                    rotation[x][y] = uniform_int_distribution<>(0, 3)(rng);\n                }\n            }\n            current_score = calculate_score();\n            if (current_score > best_score && current_score > 0) {\n                best_score = current_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n            }\n        }\n    }\n    \n    return best_score;\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        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            tiles[i][j] = s[j] - '0';\n            rotation[i][j] = 0;\n        }\n    }\n    \n    long long global_best = 0;\n    auto start_time = chrono::steady_clock::now();\n    const double total_time = 1.9;\n    \n    // Multiple runs with different patterns and seeds\n    int num_runs = 12;\n    double time_per_run = total_time / num_runs;\n    \n    for (int run = 0; run < num_runs; run++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > total_time - 0.1) break;\n        \n        // Different seed for each run\n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count() + run * 1234567);\n        \n        // Cycle through patterns\n        int pattern = run % 6;\n        long long score = run_sa(rng, time_per_run, pattern);\n        \n        if (score > global_best && score > 0) {\n            global_best = score;\n            // best_rotation already updated in run_sa\n        }\n    }\n    \n    // Ensure we have a valid solution\n    if (global_best == 0) {\n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n        initialize_pattern(0, rng);\n        int attempts = 0;\n        while (count_loops() < 2 && attempts < 20) {\n            initialize_pattern(0, rng);\n            attempts++;\n        }\n        memcpy(best_rotation, rotation, sizeof(rotation));\n    }\n    \n    // Output best rotation\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << best_rotation[i][j];\n        }\n    }\n    cout << '\\n';\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nvector<string> board;\nint empty_r, empty_c;\nstring moves = \"\";\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nchar int_to_hex(int v) {\n    if (v < 10) return '0' + v;\n    return 'a' + (v - 10);\n}\n\nint get_tile(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N) return -1;\n    if (board[r][c] == '0') return 0;\n    return hex_to_int(board[r][c]);\n}\n\nbool has_connection(int tile_val, int d) {\n    if (tile_val == 0) return false;\n    const int mask[] = {2, 8, 1, 4};\n    return (tile_val & mask[d]) != 0;\n}\n\nbool tiles_connect(int r1, int c1, int r2, int c2) {\n    int t1 = get_tile(r1, c1);\n    int t2 = get_tile(r2, c2);\n    if (t1 == 0 || t2 == 0) return false;\n    \n    if (r2 == r1 + 1) return has_connection(t1, 1) && has_connection(t2, 0);\n    if (r2 == r1 - 1) return has_connection(t1, 0) && has_connection(t2, 1);\n    if (c2 == c1 + 1) return has_connection(t1, 3) && has_connection(t2, 2);\n    if (c2 == c1 - 1) return has_connection(t1, 2) && has_connection(t2, 3);\n    return false;\n}\n\nvoid make_move(int d) {\n    int nr = empty_r + dr[d];\n    int nc = empty_c + dc[d];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return;\n    if ((int)moves.size() >= T - 5) return;\n    \n    swap(board[empty_r][empty_c], board[nr][nc]);\n    empty_r = nr;\n    empty_c = nc;\n    moves += dir_char[d];\n}\n\n// BFS to find shortest path for empty square\nvector<int> find_path_to(int start_r, int start_c, int target_r, int target_c) {\n    if (start_r == target_r && start_c == target_c) return {};\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parent_dir(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({start_r, start_c});\n    visited[start_r][start_c] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !visited[nr][nc]) {\n                visited[nr][nc] = true;\n                parent[nr][nc] = {r, c};\n                parent_dir[nr][nc] = d;\n                q.push({nr, nc});\n                \n                if (nr == target_r && nc == target_c) {\n                    vector<int> path;\n                    int cr = target_r, cc = target_c;\n                    while (cr != start_r || cc != start_c) {\n                        path.push_back(parent_dir[cr][cc]);\n                        int pr = parent[cr][cc].first;\n                        int pc = parent[cr][cc].second;\n                        cr = pr;\n                        cc = pc;\n                    }\n                    reverse(path.begin(), path.end());\n                    return path;\n                }\n            }\n        }\n    }\n    return {};\n}\n\nvoid move_empty_to(int target_r, int target_c) {\n    while (empty_r != target_r || empty_c != target_c) {\n        if ((int)moves.size() >= T - 10) break;\n        \n        vector<int> path = find_path_to(empty_r, empty_c, target_r, target_c);\n        if (path.empty()) break;\n        \n        for (int d : path) {\n            if ((int)moves.size() >= T - 5) break;\n            make_move(d);\n        }\n    }\n}\n\n// Move a tile from (tile_r, tile_c) to (target_r, target_c)\nvoid move_tile_to(int tile_r, int tile_c, int target_r, int target_c) {\n    while (tile_r != target_r || tile_c != target_c) {\n        if ((int)moves.size() >= T - 20) break;\n        \n        int desired_empty_r, desired_empty_c, move_d;\n        \n        if (tile_r < target_r) {\n            desired_empty_r = tile_r + 1;\n            desired_empty_c = tile_c;\n            move_d = 0;\n        } else if (tile_r > target_r) {\n            desired_empty_r = tile_r - 1;\n            desired_empty_c = tile_c;\n            move_d = 1;\n        } else if (tile_c < target_c) {\n            desired_empty_r = tile_r;\n            desired_empty_c = tile_c + 1;\n            move_d = 2;\n        } else {\n            desired_empty_r = tile_r;\n            desired_empty_c = tile_c - 1;\n            move_d = 3;\n        }\n        \n        if (desired_empty_r < 0 || desired_empty_r >= N || \n            desired_empty_c < 0 || desired_empty_c >= N) break;\n        \n        move_empty_to(desired_empty_r, desired_empty_c);\n        \n        if (empty_r == desired_empty_r && empty_c == desired_empty_c) {\n            make_move(move_d);\n            if (move_d == 0) tile_r++;\n            else if (move_d == 1) tile_r--;\n            else if (move_d == 2) tile_c++;\n            else if (move_d == 3) tile_c--;\n        } else {\n            break;\n        }\n    }\n}\n\nint calculate_tree_size() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int max_size = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0' || visited[i][j]) continue;\n            \n            int size = 0;\n            queue<pair<int,int>> q;\n            q.push({i, j});\n            visited[i][j] = true;\n            \n            while (!q.empty()) {\n                auto [r, c] = q.front();\n                q.pop();\n                size++;\n                \n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && \n                        !visited[nr][nc] && board[nr][nc] != '0') {\n                        if (tiles_connect(r, c, nr, nc)) {\n                            visited[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n            }\n            max_size = max(max_size, size);\n        }\n    }\n    return max_size;\n}\n\nstruct TileInfo {\n    int value;\n    int r, c;\n    int id;\n};\n\n// Check compatibility between two tiles in specific directions\nint compatibility(int t1_val, int t2_val, int d) {\n    // d: direction from t1 to t2 (0=up, 1=down, 2=left, 3=right)\n    const int opp[] = {1, 0, 3, 2};\n    bool c1 = has_connection(t1_val, d);\n    bool c2 = has_connection(t2_val, opp[d]);\n    if (c1 && c2) return 2;\n    if (c1 || c2) return -1;\n    return 0;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    \n    vector<TileInfo> tiles;\n    int tile_id = 0;\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            } else {\n                tiles.push_back({hex_to_int(board[i][j]), i, j, tile_id++});\n            }\n        }\n    }\n    \n    int total_tiles = N * N - 1;\n    \n    // Create target grid positions (snake pattern, empty at bottom-right)\n    vector<pair<int,int>> targets;\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)) targets.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (!(i == N-1 && j == N-1)) targets.push_back({i, j});\n            }\n        }\n    }\n    \n    // Build adjacency graph based on tile compatibility\n    vector<vector<int>> compat(total_tiles, vector<int>(total_tiles, 0));\n    for (int i = 0; i < total_tiles; i++) {\n        for (int j = 0; j < total_tiles; j++) {\n            if (i == j) continue;\n            int score = 0;\n            score += compatibility(tiles[i].value, tiles[j].value, 1); // i above j\n            score += compatibility(tiles[i].value, tiles[j].value, 3); // i left of j\n            compat[i][j] = score;\n        }\n    }\n    \n    // Greedy assignment: place tiles trying to maximize connections\n    vector<int> assignment(total_tiles, -1); // assignment[target_idx] = tile_idx\n    vector<bool> tile_used(total_tiles, false);\n    \n    for (int ti = 0; ti < total_tiles; ti++) {\n        int best_tile = -1;\n        int best_score = -1e9;\n        \n        for (int tidx = 0; tidx < total_tiles; tidx++) {\n            if (tile_used[tidx]) continue;\n            \n            int score = 0;\n            int tr = targets[ti].first;\n            int tc = targets[ti].second;\n            \n            // Check compatibility with already placed neighbors\n            for (int d = 0; d < 4; d++) {\n                int pr = tr + dr[d];\n                int pc = tc + dc[d];\n                if (pr >= 0 && pr < N && pc >= 0 && pc < N && !(pr == N-1 && pc == N-1)) {\n                    // Find which target index this is\n                    int neighbor_target = -1;\n                    for (int nt = 0; nt < ti; nt++) {\n                        if (targets[nt].first == pr && targets[nt].second == pc) {\n                            neighbor_target = nt;\n                            break;\n                        }\n                    }\n                    if (neighbor_target >= 0 && assignment[neighbor_target] >= 0) {\n                        int neighbor_tile = assignment[neighbor_target];\n                        int opp = (d == 0) ? 1 : (d == 1) ? 0 : (d == 2) ? 3 : 2;\n                        if (has_connection(tiles[tidx].value, d) && \n                            has_connection(tiles[neighbor_tile].value, opp)) {\n                            score += 10;\n                        }\n                    }\n                }\n            }\n            \n            // Prefer tiles closer to target\n            int dist = abs(tiles[tidx].r - tr) + abs(tiles[tidx].c - tc);\n            score -= dist / 2;\n            \n            // Prefer tiles with more connections\n            int connections = __builtin_popcount(tiles[tidx].value);\n            score += connections;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_tile = tidx;\n            }\n        }\n        \n        if (best_tile >= 0) {\n            assignment[ti] = best_tile;\n            tile_used[best_tile] = true;\n        }\n    }\n    \n    // Execute the placement\n    for (int ti = 0; ti < total_tiles; ti++) {\n        if ((int)moves.size() >= T - 50) break;\n        if (assignment[ti] < 0) continue;\n        \n        int tidx = assignment[ti];\n        int tr = targets[ti].first;\n        int tc = targets[ti].second;\n        \n        // Find current position of this tile\n        int tile_val = tiles[tidx].value;\n        int cur_r = -1, cur_c = -1;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (get_tile(i, j) == tile_val) {\n                    cur_r = i;\n                    cur_c = j;\n                    break;\n                }\n            }\n            if (cur_r >= 0) break;\n        }\n        \n        if (cur_r < 0) continue;\n        \n        move_tile_to(cur_r, cur_c, tr, tc);\n    }\n    \n    // Local optimization: try to improve connections with swaps\n    int initial_tree_size = calculate_tree_size();\n    \n    if (initial_tree_size < total_tiles && (int)moves.size() < T - 100) {\n        // Try swapping adjacent tiles to improve connectivity\n        for (int iter = 0; iter < 50 && (int)moves.size() < T - 100; iter++) {\n            int best_improvement = 0;\n            int best_swap_r1 = -1, best_swap_c1 = -1;\n            int best_swap_r2 = -1, best_swap_c2 = -1;\n            \n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (board[i][j] == '0') continue;\n                    for (int d = 0; d < 4; d++) {\n                        int ni = i + dr[d];\n                        int nj = j + dc[d];\n                        if (ni >= 0 && ni < N && nj >= 0 && nj < N && board[ni][nj] != '0') {\n                            // Try swapping these two tiles\n                            // This is complex, skip for now\n                        }\n                    }\n                }\n            }\n        }\n    }\n    \n    // Move empty to corner\n    move_empty_to(N-1, N-1);\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\nstruct Strawberry {\n    int id;\n    long long x, y;\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> lines;\n\nconst long long COORD_MIN = -1000000000LL;\nconst long long COORD_MAX = 1000000000LL;\n\nlong long clampCoord(long long v) {\n    if (v < COORD_MIN) return COORD_MIN;\n    if (v > COORD_MAX) return COORD_MAX;\n    return v;\n}\n\nint sideOfLine(const Line& l, long long x, long long y) {\n    __int128 dx1 = (__int128)l.qx - l.px;\n    __int128 dy1 = (__int128)l.qy - l.py;\n    __int128 dx2 = (__int128)x - l.px;\n    __int128 dy2 = (__int128)y - l.py;\n    __int128 cross = dx1 * dy2 - dy1 * dx2;\n    if (cross > 0) return 1;\n    if (cross < 0) return -1;\n    return 0;\n}\n\nbool isCut(int idx) {\n    for (const auto& l : lines) {\n        if (sideOfLine(l, strawberries[idx].x, strawberries[idx].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\nvector<string> getRegions() {\n    vector<string> region(N);\n    for (int i = 0; i < N; i++) {\n        if (isCut(i)) {\n            region[i] = \"CUT\";\n            continue;\n        }\n        string sig = \"\";\n        for (size_t j = 0; j < lines.size() && j < 60; j++) {\n            int s = sideOfLine(lines[j], strawberries[i].x, strawberries[i].y);\n            sig += (s == 1 ? \"L\" : (s == -1 ? \"R\" : \"0\"));\n        }\n        region[i] = sig;\n    }\n    return region;\n}\n\nint calculateScore() {\n    auto regions = getRegions();\n    map<string, int> pieceCount;\n    for (int i = 0; i < N; i++) {\n        if (regions[i] != \"CUT\") {\n            pieceCount[regions[i]]++;\n        }\n    }\n    \n    int score = 0;\n    for (int d = 1; d <= 10; d++) {\n        int b_d = 0;\n        for (auto& kv : pieceCount) {\n            if (kv.second == d) b_d++;\n        }\n        score += min(a[d], b_d);\n    }\n    return score;\n}\n\nlong long distSq(long long x1, long long y1, long long x2, long long y2) {\n    __int128 dx = (__int128)x1 - x2;\n    __int128 dy = (__int128)y1 - y2;\n    __int128 result = dx * dx + dy * dy;\n    if (result > (__int128)4e18) return 4000000000000000000LL;\n    return (long long)result;\n}\n\nLine createLineFromPoints(long long x1, long long y1, long long x2, long long y2) {\n    long long px = clampCoord(x1);\n    long long py = clampCoord(y1);\n    long long qx = clampCoord(x2);\n    long long qy = clampCoord(y2);\n    \n    if (px == qx && py == qy) {\n        qx = clampCoord(qx + 1);\n    }\n    \n    return Line{px, py, qx, qy};\n}\n\nLine createSeparatingLine(const vector<int>& group1, const vector<int>& group2) {\n    if (group1.empty() || group2.empty()) {\n        return createLineFromPoints(0, 0, 1, 0);\n    }\n    \n    long long cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0;\n    for (int idx : group1) {\n        cx1 += strawberries[idx].x;\n        cy1 += strawberries[idx].y;\n    }\n    for (int idx : group2) {\n        cx2 += strawberries[idx].x;\n        cy2 += strawberries[idx].y;\n    }\n    cx1 /= (long long)group1.size();\n    cy1 /= (long long)group1.size();\n    cx2 /= (long long)group2.size();\n    cy2 /= (long long)group2.size();\n    \n    long long mx = (cx1 + cx2) / 2;\n    long long my = (cy1 + cy2) / 2;\n    long long dx = cx2 - cx1;\n    long long dy = cy2 - cy1;\n    \n    if (dx == 0 && dy == 0) {\n        dx = 1;\n        dy = 0;\n    }\n    \n    long long scale = 500000;\n    long long px = mx - dy;\n    long long py = my + dx;\n    long long qx = mx + dy;\n    long long qy = my - dx;\n    \n    // Extend line to cake boundary\n    long long len = max(abs(qx - px), abs(qy - py));\n    if (len > 0) {\n        px = mx - dy * scale / len;\n        py = my + dx * scale / len;\n        qx = mx + dy * scale / len;\n        qy = my - dx * scale / len;\n    }\n    \n    return createLineFromPoints(px, py, qx, qy);\n}\n\n// Check if line cuts any strawberry\nbool lineCutsStrawberry(const Line& l) {\n    for (int k = 0; k < N; k++) {\n        if (sideOfLine(l, strawberries[k].x, strawberries[k].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\n// Check if two groups are already separated by existing lines\nbool groupsSeparated(const vector<int>& g1, const vector<int>& g2) {\n    if (g1.empty() || g2.empty()) return true;\n    \n    for (int idx1 : g1) {\n        for (int idx2 : g2) {\n            bool same = true;\n            for (const auto& l : lines) {\n                int s1 = sideOfLine(l, strawberries[idx1].x, strawberries[idx1].y);\n                int s2 = sideOfLine(l, strawberries[idx2].x, strawberries[idx2].y);\n                if (s1 != 0 && s2 != 0 && s1 != s2) {\n                    same = false;\n                    break;\n                }\n            }\n            if (same) return false;\n        }\n    }\n    return true;\n}\n\n// Distance-based clustering\nvector<vector<int>> clusterByDistance() {\n    vector<vector<int>> clusters;\n    vector<bool> used(N, false);\n    \n    // Create weighted demand list (prioritize higher demands)\n    vector<pair<int, int>> demands; // (size, priority)\n    for (int d = 1; d <= 10; d++) {\n        for (int i = 0; i < a[d]; i++) {\n            demands.push_back({d, a[d]});\n        }\n    }\n    sort(demands.rbegin(), demands.rend());\n    \n    // Find unassigned strawberry nearest to origin as seed\n    auto findSeed = [&]() -> int {\n        int best = -1;\n        long long bestDist = -1;\n        for (int i = 0; i < N; i++) {\n            if (used[i]) continue;\n            long long d = distSq(strawberries[i].x, strawberries[i].y, 0, 0);\n            if (best == -1 || d < bestDist) {\n                bestDist = d;\n                best = i;\n            }\n        }\n        return best;\n    };\n    \n    for (auto& demand : demands) {\n        if ((int)clusters.size() > K + 10) break;\n        \n        int seed = findSeed();\n        if (seed == -1) break;\n        \n        // Find nearest unassigned strawberries\n        vector<pair<long long, int>> candidates;\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) {\n                long long d = distSq(strawberries[seed].x, strawberries[seed].y,\n                                    strawberries[i].x, strawberries[i].y);\n                candidates.push_back({d, i});\n            }\n        }\n        sort(candidates.begin(), candidates.end());\n        \n        vector<int> cluster;\n        for (auto& cand : candidates) {\n            if ((int)cluster.size() >= demand.first) break;\n            cluster.push_back(cand.second);\n            used[cand.second] = true;\n        }\n        \n        if (!cluster.empty()) {\n            clusters.push_back(cluster);\n        }\n    }\n    \n    // Assign remaining\n    for (int i = 0; i < N; i++) {\n        if (!used[i]) {\n            if (!clusters.empty() && (int)clusters.back().size() < 10) {\n                clusters.back().push_back(i);\n            } else {\n                clusters.push_back({i});\n            }\n            used[i] = true;\n        }\n    }\n    \n    return clusters;\n}\n\nvoid generateLinesFromClusters(const vector<vector<int>>& clusters) {\n    lines.clear();\n    \n    for (size_t i = 0; i < clusters.size() && (int)lines.size() < K; i++) {\n        for (size_t j = i + 1; j < clusters.size() && (int)lines.size() < K; j++) {\n            if (groupsSeparated(clusters[i], clusters[j])) continue;\n            \n            Line l = createSeparatingLine(clusters[i], clusters[j]);\n            \n            if (!lineCutsStrawberry(l)) {\n                lines.push_back(l);\n            }\n        }\n    }\n}\n\n// Try adding a random line\nbool tryAddRandomLine() {\n    if ((int)lines.size() >= K) return false;\n    \n    int i1 = rand() % N;\n    int i2 = rand() % N;\n    while (i1 == i2) i2 = rand() % N;\n    \n    Line newLine = createSeparatingLine({i1}, {i2});\n    \n    if (!lineCutsStrawberry(newLine)) {\n        lines.push_back(newLine);\n        return true;\n    }\n    return false;\n}\n\n// Perturb an existing line\nvoid perturbLine(int idx) {\n    if (idx >= (int)lines.size()) return;\n    \n    Line& l = lines[idx];\n    long long dx = (rand() % 2001) - 1000;\n    long long dy = (rand() % 2001) - 1000;\n    \n    Line newLine = createLineFromPoints(l.px + dx, l.py + dy, l.qx + dx, l.qy + dy);\n    \n    if (!lineCutsStrawberry(newLine)) {\n        lines[idx] = newLine;\n    }\n}\n\n// Optimize using local search\nvoid optimize() {\n    int baseScore = calculateScore();\n    int noImprovement = 0;\n    \n    for (int iter = 0; iter < 500 && noImprovement < 100; iter++) {\n        int choice = rand() % 3;\n        \n        if (choice == 0 && (int)lines.size() < K) {\n            // Try adding a line\n            lines.push_back(createLineFromPoints(0, 0, 1, 0));\n            int newScore = calculateScore();\n            if (newScore >= baseScore) {\n                baseScore = newScore;\n                noImprovement = 0;\n            } else {\n                lines.pop_back();\n                noImprovement++;\n            }\n        } else if (choice == 1 && !lines.empty()) {\n            // Try perturbing a line\n            int idx = rand() % lines.size();\n            Line oldLine = lines[idx];\n            perturbLine(idx);\n            int newScore = calculateScore();\n            if (newScore >= baseScore) {\n                baseScore = newScore;\n                noImprovement = 0;\n            } else {\n                lines[idx] = oldLine;\n                noImprovement++;\n            }\n        } else {\n            // Try adding random line\n            if (tryAddRandomLine()) {\n                int newScore = calculateScore();\n                if (newScore >= baseScore) {\n                    baseScore = newScore;\n                    noImprovement = 0;\n                } else {\n                    lines.pop_back();\n                    noImprovement++;\n                }\n            } else {\n                noImprovement++;\n            }\n        }\n    }\n    \n    // Final cleanup: remove lines that don't help\n    for (int i = (int)lines.size() - 1; i >= 0; i--) {\n        Line removed = lines[i];\n        lines.erase(lines.begin() + i);\n        int newScore = calculateScore();\n        if (newScore < baseScore) {\n            lines.insert(lines.begin() + i, removed);\n        }\n        baseScore = calculateScore();\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    srand(42);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        strawberries[i].id = i;\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Cluster strawberries\n    auto clusters = clusterByDistance();\n    \n    // Generate separating lines\n    generateLinesFromClusters(clusters);\n    \n    // Optimize with local search\n    optimize();\n    \n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const auto& l : lines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nstruct Rect {\n    Point p[4];\n    long long weight;\n    int perimeter_len;\n    \n    bool operator<(const Rect& other) const {\n        if (weight != other.weight) return weight > other.weight;\n        return perimeter_len < other.perimeter_len;\n    }\n};\n\nint N, M;\nvector<Point> initial_dots;\nvector<vector<bool>> has_dot;\nvector<vector<bool>> used_h;  // horizontal edge from (x,y) to (x+1,y)\nvector<vector<bool>> used_v;  // vertical edge from (x,y) to (x,y+1)\nvector<vector<bool>> used_d1; // diagonal from (x,y) to (x+1,y+1)\nvector<vector<bool>> used_d2; // diagonal from (x,y) to (x+1,y-1)\n\nlong long total_weight_S = 0;\nvector<vector<long long>> weights;\ndouble center_c;\n\nvoid init_weights() {\n    center_c = (N - 1) / 2.0;\n    weights.assign(N, vector<long long>(N));\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (long long)round(pow(x - center_c, 2) + pow(y - center_c, 2) + 1);\n            weights[x][y] = w;\n            total_weight_S += w;\n        }\n    }\n}\n\nlong long get_weight(int x, int y) {\n    return weights[x][y];\n}\n\nbool is_inside(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there are dots on the line segment (excluding endpoints)\nbool has_dot_on_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps <= 1) return false;\n    \n    int sx = (dx > 0) - (dx < 0);\n    int sy = (dy > 0) - (dy < 0);\n    \n    for (int i = 1; i < steps; ++i) {\n        int cx = x1 + i * sx;\n        int cy = y1 + i * sy;\n        if (has_dot[cx][cy]) return true;\n    }\n    return false;\n}\n\n// Check if rectangle perimeter has dots (excluding the 4 corners)\nbool check_rect_perimeter_dots(const Rect& r) {\n    for (int i = 0; i < 4; ++i) {\n        if (has_dot_on_segment(r.p[i].x, r.p[i].y, r.p[(i+1)%4].x, r.p[(i+1)%4].y)) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Mark/check edges of rectangle. Returns false if any edge is already used.\nbool process_rect_edges(const Rect& r, bool mark) {\n    for (int i = 0; i < 4; ++i) {\n        int x1 = r.p[i].x, y1 = r.p[i].y;\n        int x2 = r.p[(i+1)%4].x, y2 = r.p[(i+1)%4].y;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        \n        if (steps == 0) return false;\n        \n        int sx = (dx > 0) - (dx < 0);\n        int sy = (dy > 0) - (dy < 0);\n        \n        // Validate edge direction\n        bool valid_dir = false;\n        if (sx == 1 && sy == 0) valid_dir = true;      // right\n        else if (sx == -1 && sy == 0) valid_dir = true; // left\n        else if (sx == 0 && sy == 1) valid_dir = true;  // up\n        else if (sx == 0 && sy == -1) valid_dir = true; // down\n        else if (sx == 1 && sy == 1) valid_dir = true;  // up-right\n        else if (sx == -1 && sy == -1) valid_dir = true;// down-left\n        else if (sx == 1 && sy == -1) valid_dir = true; // down-right\n        else if (sx == -1 && sy == 1) valid_dir = true; // up-left\n        else return false;\n        \n        for (int j = 0; j < steps; ++j) {\n            int cx = x1 + j * sx;\n            int cy = y1 + j * sy;\n            \n            bool used = false;\n            \n            if (sx == 1 && sy == 0) {\n                // Horizontal right: edge from (cx,cy) to (cx+1,cy)\n                if (cx < N-1 && cy >= 0 && cy < N) {\n                    if (used_h[cx][cy]) used = true;\n                    else if (mark) used_h[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == 0) {\n                // Horizontal left: edge from (cx-1,cy) to (cx,cy)\n                if (cx > 0 && cy >= 0 && cy < N) {\n                    if (used_h[cx-1][cy]) used = true;\n                    else if (mark) used_h[cx-1][cy] = true;\n                }\n            } else if (sx == 0 && sy == 1) {\n                // Vertical up: edge from (cx,cy) to (cx,cy+1)\n                if (cx >= 0 && cx < N && cy < N-1) {\n                    if (used_v[cx][cy]) used = true;\n                    else if (mark) used_v[cx][cy] = true;\n                }\n            } else if (sx == 0 && sy == -1) {\n                // Vertical down: edge from (cx,cy-1) to (cx,cy)\n                if (cx >= 0 && cx < N && cy > 0) {\n                    if (used_v[cx][cy-1]) used = true;\n                    else if (mark) used_v[cx][cy-1] = true;\n                }\n            } else if (sx == 1 && sy == 1) {\n                // Diagonal up-right: edge from (cx,cy) to (cx+1,cy+1)\n                if (cx < N-1 && cy < N-1) {\n                    if (used_d1[cx][cy]) used = true;\n                    else if (mark) used_d1[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == -1) {\n                // Diagonal down-left: edge from (cx-1,cy-1) to (cx,cy)\n                if (cx > 0 && cy > 0) {\n                    if (used_d1[cx-1][cy-1]) used = true;\n                    else if (mark) used_d1[cx-1][cy-1] = true;\n                }\n            } else if (sx == 1 && sy == -1) {\n                // Diagonal down-right: edge from (cx,cy) to (cx+1,cy-1)\n                if (cx < N-1 && cy > 0) {\n                    if (used_d2[cx][cy]) used = true;\n                    else if (mark) used_d2[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == 1) {\n                // Diagonal up-left: edge from (cx-1,cy+1) to (cx,cy)\n                if (cx > 0 && cy < N-1) {\n                    if (used_d2[cx-1][cy+1]) used = true;\n                    else if (mark) used_d2[cx-1][cy+1] = true;\n                }\n            }\n            \n            if (used) return false;\n        }\n    }\n    return true;\n}\n\n// Check if 4 points form a valid rectangle (axis-aligned or 45-degree)\nbool is_valid_rectangle(const Point& p1, const Point& p2, const Point& p3, const Point& p4) {\n    // Check all 4 edges have same direction type (all axis or all 45-deg)\n    auto get_edge_type = [](const Point& a, const Point& b) -> int {\n        int dx = b.x - a.x;\n        int dy = b.y - a.y;\n        if (dx == 0 || dy == 0) return 1; // axis-aligned\n        if (abs(dx) == abs(dy)) return 2; // 45-degree\n        return 0; // invalid\n    };\n    \n    int t1 = get_edge_type(p1, p2);\n    int t2 = get_edge_type(p2, p3);\n    int t3 = get_edge_type(p3, p4);\n    int t4 = get_edge_type(p4, p1);\n    \n    if (t1 == 0 || t2 == 0 || t3 == 0 || t4 == 0) return false;\n    if (t1 != t2 || t2 != t3 || t3 != t4) return false;\n    \n    // Check it's actually a rectangle (opposite sides equal, adjacent sides perpendicular)\n    long long dx1 = p2.x - p1.x, dy1 = p2.y - p1.y;\n    long long dx2 = p3.x - p2.x, dy2 = p3.y - p2.y;\n    long long dx3 = p4.x - p3.x, dy3 = p4.y - p3.y;\n    long long dx4 = p1.x - p4.x, dy4 = p1.y - p4.y;\n    \n    // Adjacent edges should be perpendicular\n    if (dx1 * dx2 + dy1 * dy2 != 0) return false;\n    if (dx2 * dx3 + dy2 * dy3 != 0) return false;\n    if (dx3 * dx4 + dy3 * dy4 != 0) return false;\n    if (dx4 * dx1 + dy4 * dy1 != 0) return false;\n    \n    return true;\n}\n\nvector<Rect> generate_candidates(const vector<Point>& active_dots) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    \n    for (int i = 0; i < S; ++i) {\n        for (int j = i + 1; j < S; ++j) {\n            Point A = active_dots[i];\n            Point B = active_dots[j];\n            \n            // Case 1: A, B are diagonal of axis-aligned rectangle\n            if (A.x != B.x && A.y != B.y) {\n                Point C1 = {A.x, B.y};\n                Point C2 = {B.x, A.y};\n                \n                // Target C1, sources: C2, B, A (in order around rectangle)\n                if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && \n                    is_inside(C2.x, C2.y) && has_dot[C2.x][C2.y]) {\n                    Rect r;\n                    r.p[0] = C1; r.p[1] = C2; r.p[2] = B; r.p[3] = A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                \n                // Target C2, sources: C1, A, B\n                if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && \n                    is_inside(C1.x, C1.y) && has_dot[C1.x][C1.y]) {\n                    Rect r;\n                    r.p[0] = C2; r.p[1] = C1; r.p[2] = A; r.p[3] = B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 2: A, B vertical side of 45-degree rectangle\n            if (A.x == B.x && (A.y + B.y) % 2 == 0) {\n                int my = (A.y + B.y) / 2;\n                int dist = abs(A.y - B.y) / 2;\n                Point C = {A.x - dist, my};\n                Point D = {A.x + dist, my};\n                \n                if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                    is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                    is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 3: A, B horizontal side of 45-degree rectangle\n            if (A.y == B.y && (A.x + B.x) % 2 == 0) {\n                int mx = (A.x + B.x) / 2;\n                int dist = abs(A.x - B.x) / 2;\n                Point C = {mx, A.y - dist};\n                Point D = {mx, A.y + dist};\n                \n                if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                    is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                    is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 4: Three corners form right angle, find 4th\n            for (int k = 0; k < S; ++k) {\n                if (k == i || k == j) continue;\n                Point C = active_dots[k];\n                \n                auto try_corner = [&](Point P1, Point P2, Point corner) {\n                    long long dx1 = P1.x - corner.x, dy1 = P1.y - corner.y;\n                    long long dx2 = P2.x - corner.x, dy2 = P2.y - corner.y;\n                    \n                    if (dx1*dx2 + dy1*dy2 != 0) return;\n                    \n                    bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                    bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                    if (!(axis || deg45)) return;\n                    \n                    Point D = {P1.x + P2.x - corner.x, P1.y + P2.y - corner.y};\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=corner; r.p[2]=P1; r.p[3]=P2;\n                        if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                            cands.push_back(r);\n                    }\n                };\n                \n                try_corner(A, B, A);\n                try_corner(A, B, B);\n                try_corner(A, B, C);\n            }\n        }\n    }\n    return cands;\n}\n\nvector<Rect> generate_candidates_with_new(const vector<Point>& active_dots, Point new_dot) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    \n    for (int i = 0; i < S; ++i) {\n        Point A = active_dots[i];\n        Point B = new_dot;\n        \n        // Diagonal cases\n        if (A.x != B.x && A.y != B.y) {\n            Point C1 = {A.x, B.y};\n            Point C2 = {B.x, A.y};\n            \n            if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && \n                is_inside(C2.x, C2.y) && has_dot[C2.x][C2.y]) {\n                Rect r; r.p[0]=C1; r.p[1]=C2; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && \n                is_inside(C1.x, C1.y) && has_dot[C1.x][C1.y]) {\n                Rect r; r.p[0]=C2; r.p[1]=C1; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        if (A.x == B.x && (A.y + B.y) % 2 == 0) {\n            int my = (A.y + B.y) / 2;\n            int dist = abs(A.y - B.y) / 2;\n            Point C = {A.x - dist, my};\n            Point D = {A.x + dist, my};\n            \n            if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        if (A.y == B.y && (A.x + B.x) % 2 == 0) {\n            int mx = (A.x + B.x) / 2;\n            int dist = abs(A.x - B.x) / 2;\n            Point C = {mx, A.y - dist};\n            Point D = {mx, A.y + dist};\n            \n            if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        // Three-corner cases\n        for (int k = 0; k < S; ++k) {\n            if (k == i) continue;\n            Point C = active_dots[k];\n            \n            auto try_corner = [&](Point P1, Point P2, Point corner) {\n                long long dx1 = P1.x - corner.x, dy1 = P1.y - corner.y;\n                long long dx2 = P2.x - corner.x, dy2 = P2.y - corner.y;\n                \n                if (dx1*dx2 + dy1*dy2 != 0) return;\n                \n                bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                if (!(axis || deg45)) return;\n                \n                Point D = {P1.x + P2.x - corner.x, P1.y + P2.y - corner.y};\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=corner; r.p[2]=P1; r.p[3]=P2;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            };\n            \n            try_corner(A, B, A);\n            try_corner(A, B, B);\n            try_corner(A, B, C);\n        }\n    }\n    return cands;\n}\n\nstruct Solution {\n    vector<Rect> ops;\n    long long score;\n};\n\nSolution solve_one(mt19937& rng) {\n    has_dot.assign(N, vector<bool>(N, false));\n    used_h.assign(N, vector<bool>(N, false));\n    used_v.assign(N, vector<bool>(N, false));\n    used_d1.assign(N, vector<bool>(N, false));\n    used_d2.assign(N, vector<bool>(N, false));\n    \n    vector<Point> active_dots = initial_dots;\n    for (auto& p : active_dots) has_dot[p.x][p.y] = true;\n    \n    vector<Rect> ops;\n    vector<Rect> candidates = generate_candidates(active_dots);\n    \n    while (true) {\n        vector<Rect> valid_cands;\n        valid_cands.reserve(candidates.size());\n        \n        for (auto& r : candidates) {\n            // Check target is empty\n            if (has_dot[r.p[0].x][r.p[0].y]) continue;\n            \n            // Check sources have dots\n            if (!has_dot[r.p[1].x][r.p[1].y]) continue;\n            if (!has_dot[r.p[2].x][r.p[2].y]) continue;\n            if (!has_dot[r.p[3].x][r.p[3].y]) continue;\n            \n            // Check no dots on perimeter\n            if (!check_rect_perimeter_dots(r)) continue;\n            \n            // Check edges not used\n            if (!process_rect_edges(r, false)) continue;\n            \n            r.weight = get_weight(r.p[0].x, r.p[0].y);\n            int len = 0;\n            for(int i=0; i<4; ++i) {\n                len += max(abs(r.p[i].x - r.p[(i+1)%4].x), \n                           abs(r.p[i].y - r.p[(i+1)%4].y));\n            }\n            r.perimeter_len = len;\n            valid_cands.push_back(r);\n        }\n        \n        if (valid_cands.empty()) break;\n        \n        // Add randomness\n        for(auto& r : valid_cands) {\n            r.weight += (rng() % 100);\n        }\n        sort(valid_cands.begin(), valid_cands.end());\n        \n        Rect best = valid_cands[0];\n        ops.push_back(best);\n        has_dot[best.p[0].x][best.p[0].y] = true;\n        active_dots.push_back(best.p[0]);\n        process_rect_edges(best, true);\n        \n        vector<Rect> new_cands = generate_candidates_with_new(active_dots, best.p[0]);\n        candidates.insert(candidates.end(), new_cands.begin(), new_cands.end());\n    }\n    \n    Solution sol;\n    sol.ops = ops;\n    long long current_weight_sum = 0;\n    for(int x=0; x<N; ++x) \n        for(int y=0; y<N; ++y) \n            if(has_dot[x][y]) current_weight_sum += weights[x][y];\n    \n    double score_d = 1e6 * (double)N * N / M * (double)current_weight_sum / total_weight_S;\n    sol.score = (long long)round(score_d);\n    \n    return sol;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> initial_dots[i].x >> initial_dots[i].y;\n    }\n    \n    init_weights();\n    \n    Solution best_sol;\n    best_sol.score = -1;\n    \n    auto start = chrono::steady_clock::now();\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 4.8) break;\n        \n        Solution sol = solve_one(rng);\n        if (sol.score > best_sol.score) {\n            best_sol = sol;\n        }\n    }\n    \n    cout << best_sol.ops.size() << \"\\n\";\n    for (const auto& op : best_sol.ops) {\n        cout << op.p[0].x << \" \" << op.p[0].y << \" \"\n             << op.p[1].x << \" \" << op.p[1].y << \" \"\n             << op.p[2].x << \" \" << op.p[2].y << \" \"\n             << op.p[3].x << \" \" << op.p[3].y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <utility>\n#include <algorithm>\n\nusing namespace std;\n\nusing Grid = array<array<int, 10>, 10>;\n\n// Calculate sum of squares of connected component sizes (the actual score numerator)\nlong long calculate_component_score(const Grid& g) {\n    long long score = 0;\n    bool visited[10][10] = {};\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                vector<pair<int, int>> q;\n                q.reserve(100);\n                q.push_back({r, c});\n                visited[r][c] = true;\n                size++;\n                \n                int head = 0;\n                while(head < (int)q.size()){\n                    auto [cr, cc] = q[head++];\n                    for(int i=0; i<4; ++i){\n                        int nr = cr + dr[i];\n                        int nc = cc + dc[i];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                            if(!visited[nr][nc] && g[nr][nc] == flavor){\n                                visited[nr][nc] = true;\n                                size++;\n                                q.push_back({nr, nc});\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Count adjacent same-flavor pairs (proxy for potential merging)\nlong long calculate_adjacency_bonus(const Grid& g) {\n    long long score = 0;\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0) {\n                for(int i=0; i<2; ++i){ // Only check right and down to avoid double counting\n                    int nr = r + dr[i];\n                    int nc = c + dc[i];\n                    if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                        if(g[nr][nc] == g[r][c]){\n                            score += 1;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return score;\n}\n\n// Count how many same-flavor candies are in each quadrant\n// This helps identify if flavors are well-separated\narray<long long, 3> calculate_flavor_distribution(const Grid& g) {\n    array<long long, 3> dist = {0, 0, 0};\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0) {\n                dist[g[r][c] - 1]++;\n            }\n        }\n    }\n    return dist;\n}\n\n// Combined score: component score is primary, adjacency is secondary tiebreaker\nlong long calculate_total_score(const Grid& g) {\n    long long component_score = calculate_component_score(g);\n    long long adjacency_score = calculate_adjacency_bonus(g);\n    return component_score * 1000 + adjacency_score;\n}\n\nGrid apply_tilt(const Grid& g, char dir) {\n    Grid ng;\n    for(auto& row : ng) row.fill(0);\n\n    if (dir == 'L' || dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            vector<int> row_vals;\n            row_vals.reserve(10);\n            for (int c = 0; c < 10; ++c) {\n                if (g[r][c] != 0) row_vals.push_back(g[r][c]);\n            }\n            if (dir == 'L') {\n                for (int i = 0; i < (int)row_vals.size(); ++i) ng[r][i] = row_vals[i];\n            } else {\n                int idx = 9;\n                for (int i = (int)row_vals.size() - 1; i >= 0; --i) ng[r][idx--] = row_vals[i];\n            }\n        }\n    } else {\n        for (int c = 0; c < 10; ++c) {\n            vector<int> col_vals;\n            col_vals.reserve(10);\n            for (int r = 0; r < 10; ++r) {\n                if (g[r][c] != 0) col_vals.push_back(g[r][c]);\n            }\n            if (dir == 'F') {\n                for (int i = 0; i < (int)col_vals.size(); ++i) ng[i][c] = col_vals[i];\n            } else {\n                int idx = 9;\n                for (int i = (int)col_vals.size() - 1; i >= 0; --i) ng[idx--][c] = col_vals[i];\n            }\n        }\n    }\n    return ng;\n}\n\n// Beam search for multi-step lookahead\nstruct MoveSequence {\n    string moves;\n    Grid final_grid;\n    long long score;\n};\n\nvector<MoveSequence> beam_search(const Grid& g, int depth, int beam_width) {\n    vector<MoveSequence> current_beam;\n    char dirs[] = {'F', 'B', 'L', 'R'};\n    \n    // Initialize with single moves\n    for (char d : dirs) {\n        Grid ng = apply_tilt(g, d);\n        long long sc = calculate_total_score(ng);\n        current_beam.push_back({string(1, d), ng, sc});\n    }\n    \n    // Sort by score\n    sort(current_beam.begin(), current_beam.end(), \n         [](const MoveSequence& a, const MoveSequence& b) {\n             return a.score > b.score;\n         });\n    \n    // Keep only top beam_width\n    if ((int)current_beam.size() > beam_width) {\n        current_beam.resize(beam_width);\n    }\n    \n    // Expand for remaining depth\n    for (int d = 1; d < depth; ++d) {\n        vector<MoveSequence> next_beam;\n        \n        for (const auto& seq : current_beam) {\n            for (char dir : dirs) {\n                // Avoid immediately reversing direction\n                if (d > 0 && seq.moves.back() != '\\0') {\n                    char last = seq.moves.back();\n                    if ((last == 'F' && dir == 'B') || (last == 'B' && dir == 'F') ||\n                        (last == 'L' && dir == 'R') || (last == 'R' && dir == 'L')) {\n                        continue;\n                    }\n                }\n                \n                Grid ng = apply_tilt(seq.final_grid, dir);\n                long long sc = calculate_total_score(ng);\n                next_beam.push_back({seq.moves + dir, ng, sc});\n            }\n        }\n        \n        // Sort and keep top beam_width\n        sort(next_beam.begin(), next_beam.end(), \n             [](const MoveSequence& a, const MoveSequence& b) {\n                 return a.score > b.score;\n             });\n        \n        if ((int)next_beam.size() > beam_width) {\n            next_beam.resize(beam_width);\n        }\n        \n        current_beam = next_beam;\n    }\n    \n    return current_beam;\n}\n\nint main() {\n    cin.tie(NULL);\n    ios_base::sync_with_stdio(false);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) {\n        cin >> f[i];\n    }\n\n    Grid grid;\n    for(auto& row : grid) row.fill(0);\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        // Place the t-th candy\n        int count = 0;\n        bool placed = false;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    count++;\n                    if (count == p) {\n                        grid[r][c] = f[t];\n                        placed = true;\n                        break;\n                    }\n                }\n            }\n            if (placed) break;\n        }\n\n        if (t == 99) {\n            cout << \"F\" << endl;\n            break;\n        }\n\n        // Adaptive beam search depth based on remaining turns\n        int depth = (t < 30) ? 3 : (t < 70) ? 2 : 1;\n        int beam_width = (t < 50) ? 8 : 4;\n        \n        vector<MoveSequence> results = beam_search(grid, depth, beam_width);\n        \n        char best_dir = results[0].moves[0];\n        \n        cout << best_dir << endl;\n        grid = apply_tilt(grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nint M;\ndouble epsilon;\nint N;\nvector<string> graphs;\n\n// Parse graph string to adjacency matrix\nvector<vector<int>> parseGraph(const string& s, int n) {\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    int idx = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            adj[i][j] = adj[j][i] = s[idx++] - '0';\n        }\n    }\n    return adj;\n}\n\n// Convert adjacency matrix to graph string\nstring toGraphString(const vector<vector<int>>& adj, int n) {\n    string s;\n    s.reserve(n * (n - 1) / 2);\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Count edges\nint countEdges(const string& s) {\n    return count(s.begin(), s.end(), '1');\n}\n\n// Compute degree sequence (sorted)\nvector<int> degreeSequence(const vector<vector<int>>& adj, int n) {\n    vector<int> deg(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            deg[i] += adj[i][j];\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute degree sum of squares (more stable than full sequence)\nlong long degreeSumSquares(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d;\n    }\n    return sum;\n}\n\n// Count paths of length 2 (related to degree sum of squares)\nint countPaths2(const vector<vector<int>>& adj, int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        int deg = 0;\n        for (int j = 0; j < n; j++) {\n            deg += adj[i][j];\n        }\n        count += deg * (deg - 1) / 2;\n    }\n    return count;\n}\n\n// Compute optimal N - much more aggressive minimization\nint computeOptimalN(int m, double eps) {\n    // For each candidate N, check if we can separate M graphs\n    for (int n = 4; n <= 100; n++) {\n        int total_edges = n * (n - 1) / 2;\n        \n        // Expected noise: each edge flips with probability eps\n        double noise_std = sqrt(total_edges * eps * (1 - eps));\n        \n        // Need separation of at least 2-3 standard deviations between graphs\n        double min_sep = max(1.0, 2.5 * noise_std);\n        \n        // Can we fit M graphs in the edge count range?\n        // Use 80% of range to allow margin\n        double available = total_edges * 0.8;\n        double needed = (m - 1) * min_sep;\n        \n        if (needed <= available) {\n            // Additional constraint: prefer smaller N for easier cases\n            if (m <= 30 && eps <= 0.15 && n > 25) continue;\n            if (m <= 50 && eps <= 0.2 && n > 35) continue;\n            if (m <= 70 && eps <= 0.25 && n > 50) continue;\n            return n;\n        }\n    }\n    \n    return 100;\n}\n\n// Generate graph with specific properties\nstring generateGraph(int n, int target_edges, int seed, int type) {\n    mt19937 rng(seed);\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    \n    vector<pair<int, int>> edges;\n    edges.reserve(n * (n - 1) / 2);\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    }\n    \n    // Different construction strategies for variety\n    if (type == 0) {\n        // Random\n        shuffle(edges.begin(), edges.end(), rng);\n    } else if (type == 1) {\n        // Prefer edges with small index sum (creates dense region)\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.first + a.second < b.first + b.second;\n        });\n    } else if (type == 2) {\n        // Prefer edges that create degree variation\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return max(a.first, a.second) < max(b.first, b.second);\n        });\n    } else if (type == 3) {\n        // Prefer edges with small index difference (creates local clusters)\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return abs(a.first - a.second) < abs(b.first - b.second);\n        });\n    }\n    \n    int added = 0;\n    for (auto& [u, v] : edges) {\n        if (added >= target_edges) break;\n        adj[u][v] = adj[v][u] = 1;\n        added++;\n    }\n    \n    return toGraphString(adj, n);\n}\n\n// Generate M well-separated graphs\nvector<string> generateGraphs(int m, int n, double eps) {\n    vector<string> result;\n    result.reserve(m);\n    \n    int total_edges = n * (n - 1) / 2;\n    double noise_std = sqrt(total_edges * eps * (1 - eps));\n    int min_sep = max(1, (int)(3.0 * noise_std));\n    \n    // Edge count range\n    int min_edges = max(0, (int)(total_edges * 0.1));\n    int max_edges = min(total_edges, (int)(total_edges * 0.9));\n    int range = max_edges - min_edges;\n    \n    // Calculate step size\n    int step = max(min_sep, range / max(1, m - 1));\n    \n    for (int k = 0; k < m; k++) {\n        int edges = min_edges + k * step;\n        edges = max(min_edges, min(max_edges, edges));\n        \n        // Vary structure type\n        int type = k % 4;\n        string g = generateGraph(n, edges, k * 1234 + n, type);\n        result.push_back(g);\n    }\n    \n    return result;\n}\n\n// Graph signature\nstruct GraphSignature {\n    int edge_count;\n    long long degree_sum_sq;\n    int paths2;\n    vector<int> degree_seq;\n    int min_deg, max_deg;\n    \n    GraphSignature() {}\n    \n    GraphSignature(const string& s, int n) {\n        edge_count = countEdges(s);\n        auto adj = parseGraph(s, n);\n        degree_seq = degreeSequence(adj, n);\n        degree_sum_sq = degreeSumSquares(degree_seq);\n        paths2 = countPaths2(adj, n);\n        min_deg = degree_seq[0];\n        max_deg = degree_seq[n-1];\n    }\n};\n\n// Compute distance with noise-adaptive weighting\ndouble signatureDistance(const GraphSignature& s1, const GraphSignature& s2, double eps) {\n    double dist = 0;\n    \n    // Edge count - most important, weight increases with noise\n    double edge_weight = 5.0 + 20.0 * eps;\n    dist += abs(s1.edge_count - s2.edge_count) * edge_weight;\n    \n    // Degree sum of squares - stable under permutation\n    double dss_weight = 0.01 + 0.05 * eps;\n    dist += abs(s1.degree_sum_sq - s2.degree_sum_sq) * dss_weight;\n    \n    // Paths of length 2\n    double p2_weight = 0.02 + 0.03 * eps;\n    dist += abs(s1.paths2 - s2.paths2) * p2_weight;\n    \n    // Degree range\n    dist += abs(s1.min_deg - s2.min_deg) * 2.0;\n    dist += abs(s1.max_deg - s2.max_deg) * 2.0;\n    \n    // Full degree sequence (less weight under high noise)\n    double deg_seq_weight = max(0.1, 1.0 - eps);\n    for (size_t i = 0; i < s1.degree_seq.size(); i++) {\n        dist += abs(s1.degree_seq[i] - s2.degree_seq[i]) * deg_seq_weight;\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> M >> epsilon;\n    \n    // Compute optimal N\n    N = computeOptimalN(M, epsilon);\n    \n    // Generate graphs\n    graphs = generateGraphs(M, N, epsilon);\n    \n    // Precompute signatures\n    vector<GraphSignature> signatures(M);\n    for (int i = 0; i < M; i++) {\n        signatures[i] = GraphSignature(graphs[i], N);\n    }\n    \n    // Output\n    cout << N << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << graphs[i] << \"\\n\";\n    }\n    cout.flush();\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        GraphSignature h_sig(h, N);\n        \n        int best_idx = 0;\n        double best_dist = 1e18;\n        double second_best = 1e18;\n        \n        for (int i = 0; i < M; i++) {\n            double dist = signatureDistance(h_sig, signatures[i], epsilon);\n            if (dist < best_dist) {\n                second_best = best_dist;\n                best_dist = dist;\n                best_idx = i;\n            } else if (dist < second_best) {\n                second_best = dist;\n            }\n        }\n        \n        // Confidence check - if best is much better, trust it\n        // Otherwise, could add more sophisticated logic\n        cout << best_idx << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nconst long long INF = 1e18;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, int>>> adj(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\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    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    auto total_start = chrono::steady_clock::now();\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Conflict matrix W - use int for memory efficiency\n    vector<int> W(M * M, 0);\n\n    // Reduced samples for speed\n    int num_samples = 8000;\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 1);\n\n    auto w_start = chrono::steady_clock::now();\n    \n    for (int iter = 0; iter < num_samples; ++iter) {\n        // Time check every 500 samples\n        if (iter % 500 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - w_start).count() > 1500) break;\n        }\n        \n        int s = vertices[uniform_int_distribution<>(0, N - 1)(rng)];\n        int t = vertices[uniform_int_distribution<>(0, N - 1)(rng)];\n        if (s == t) continue;\n        \n        // Dijkstra from s\n        vector<long long> dist(N + 1, INF);\n        vector<int> par_edge(N + 1, -1);\n        vector<int> par_node(N + 1, -1);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n            for (auto [v, eid] : adj[u]) {\n                if (dist[u] + edges[eid].w < dist[v]) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    par_node[v] = u;\n                    par_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        if (dist[t] == INF) continue;\n\n        // Reconstruct path\n        vector<int> path_edges;\n        int curr = t;\n        while (curr != s && par_edge[curr] != -1) {\n            path_edges.push_back(par_edge[curr]);\n            curr = par_node[curr];\n        }\n\n        // Update W\n        int L = path_edges.size();\n        for (int i = 0; i < L; ++i) {\n            for (int j = i + 1; j < L; ++j) {\n                int u = path_edges[i];\n                int v = path_edges[j];\n                W[u * M + v]++;\n                W[v * M + u]++;\n            }\n        }\n    }\n\n    // Calculate edge importance\n    vector<int> edge_importance(M, 0);\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            edge_importance[i] += W[i * M + j];\n        }\n    }\n\n    // Initial assignment - sort by importance\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return edge_importance[a] > edge_importance[b];\n    });\n\n    vector<int> assignment(M, -1);\n    vector<int> day_size(D, 0);\n    vector<vector<int>> day_edges(D);\n    \n    for (int e : order) {\n        int best_day = -1;\n        long long min_cost = -1;\n        \n        for (int k = 0; k < D; ++k) {\n            if (day_size[k] < K) {\n                long long cost = 0;\n                for (int other : day_edges[k]) {\n                    cost += W[e * M + other];\n                }\n                if (best_day == -1 || cost < min_cost) {\n                    min_cost = cost;\n                    best_day = k;\n                }\n            }\n        }\n        \n        if (best_day != -1) {\n            assignment[e] = best_day;\n            day_edges[best_day].push_back(e);\n            day_size[best_day]++;\n        }\n    }\n\n    // Precompute C[k][e] = sum of W[e][j] for all j in day k\n    vector<long long> C(D * M, 0);\n    for (int k = 0; k < D; ++k) {\n        for (int e : day_edges[k]) {\n            for (int other = 0; other < M; ++other) {\n                C[k * M + other] += W[e * M + other];\n            }\n        }\n    }\n    \n    // Calculate initial cost\n    long long current_cost = 0;\n    for (int k = 0; k < D; ++k) {\n        for (int i : day_edges[k]) {\n            for (int j : day_edges[k]) {\n                if (i < j) current_cost += W[i * M + j];\n            }\n        }\n    }\n    \n    long long best_cost = current_cost;\n    vector<int> best_assignment = assignment;\n\n    // Simulated Annealing - simplified and faster\n    auto ls_start = chrono::steady_clock::now();\n    double temperature = 500.0;\n    double cooling_rate = 0.9998;\n    int moves = 0;\n    int max_moves = 300000;\n    \n    while (moves < max_moves) {\n        // Aggressive time checking\n        if (moves % 10000 == 0) {\n            auto now = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - ls_start).count();\n            if (elapsed > 4000) break;\n            \n            // Also check total time\n            auto total_elapsed = chrono::duration_cast<chrono::milliseconds>(now - total_start).count();\n            if (total_elapsed > 5800) break;\n        }\n        \n        temperature *= cooling_rate;\n        \n        // Single edge move only (faster than swap)\n        int e = uniform_int_distribution<>(0, M - 1)(rng);\n        int k_old = assignment[e];\n        if (k_old < 0) { moves++; continue; }\n        \n        int k_new = uniform_int_distribution<>(0, D - 1)(rng);\n        if (k_new == k_old) { moves++; continue; }\n        if (day_size[k_new] >= K) { moves++; continue; }\n        \n        long long delta = C[k_new * M + e] - C[k_old * M + e];\n        \n        bool accept = (delta < 0) || (temperature > 0.1 && exp(-delta / temperature) > uniform_real_distribution<>(0, 1)(rng));\n        \n        if (accept) {\n            assignment[e] = k_new;\n            day_size[k_old]--;\n            day_size[k_new]++;\n            \n            // Update C - only affected entries\n            for (int other = 0; other < M; ++other) {\n                long long w_val = W[e * M + other];\n                C[k_old * M + other] -= w_val;\n                C[k_new * M + other] += w_val;\n            }\n            \n            current_cost += delta;\n            if (current_cost < best_cost) {\n                best_cost = current_cost;\n                best_assignment = assignment;\n            }\n        }\n        \n        moves++;\n    }\n\n    // Output\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;\n\nstruct Block {\n    vector<tuple<int,int,int>> cells; // relative coordinates from first cell\n    int id;\n    bool usedIn1 = false;\n    bool usedIn2 = false;\n    \n    void normalize() {\n        if (cells.empty()) return;\n        auto [minX, minY, minZ] = cells[0];\n        for (auto& [x, y, z] : cells) {\n            minX = min(minX, x);\n            minY = min(minY, y);\n            minZ = min(minZ, z);\n        }\n        for (auto& [x, y, z] : cells) {\n            x -= minX;\n            y -= minY;\n            z -= minZ;\n        }\n        sort(cells.begin(), cells.end());\n    }\n};\n\nint D;\nvector<string> f1, r1, f2, r2;\nvector<vector<vector<bool>>> valid1, valid2;\nvector<vector<vector<int>>> b1, b2;\nvector<Block> blocks;\n\n// Get 6 neighbors\nvector<tuple<int,int,int>> getNeighbors(int x, int y, int z) {\n    vector<tuple<int,int,int>> neighbors;\n    int dx[] = {1, -1, 0, 0, 0, 0};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {0, 0, 0, 0, 1, -1};\n    \n    for (int d = 0; d < 6; d++) {\n        int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n        if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D) {\n            neighbors.emplace_back(nx, ny, nz);\n        }\n    }\n    return neighbors;\n}\n\n// Check if two block shapes match (with rotation)\nbool shapesMatch(const Block& a, const Block& b) {\n    if (a.cells.size() != b.cells.size()) return false;\n    if (a.cells.empty()) return true;\n    \n    // Generate all 24 rotations of block a\n    vector<vector<tuple<int,int,int>>> rotations;\n    auto [x0, y0, z0] = a.cells[0];\n    \n    // 24 rotations: 6 faces \u00d7 4 rotations each\n    int rotations_24[24][3][3] = {\n        {{1,0,0},{0,1,0},{0,0,1}}, {{0,-1,0},{1,0,0},{0,0,1}}, {{-1,0,0},{0,-1,0},{0,0,1}}, {{0,1,0},{-1,0,0},{0,0,1}},\n        {{1,0,0},{0,0,-1},{0,1,0}}, {{0,0,1},{1,0,0},{0,1,0}}, {{-1,0,0},{0,0,1},{0,1,0}}, {{0,0,-1},{-1,0,0},{0,1,0}},\n        {{1,0,0},{0,0,1},{0,-1,0}}, {{0,0,-1},{1,0,0},{0,-1,0}}, {{-1,0,0},{0,0,-1},{0,-1,0}}, {{0,0,1},{-1,0,0},{0,-1,0}},\n        {{0,1,0},{0,0,1},{1,0,0}}, {{0,0,-1},{0,1,0},{1,0,0}}, {{0,-1,0},{0,0,-1},{1,0,0}}, {{0,0,1},{0,-1,0},{1,0,0}},\n        {{0,1,0},{0,0,-1},{-1,0,0}}, {{0,0,1},{0,1,0},{-1,0,0}}, {{0,-1,0},{0,0,1},{-1,0,0}}, {{0,0,-1},{0,-1,0},{-1,0,0}},\n        {{0,-1,0},{1,0,0},{0,0,1}}, {{1,0,0},{0,0,1},{0,1,0}}, {{0,1,0},{-1,0,0},{0,0,1}}, {{-1,0,0},{0,0,-1},{0,1,0}}\n    };\n    \n    vector<tuple<int,int,int>> baseA = a.cells;\n    for (auto& [x, y, z] : baseA) {\n        x -= x0; y -= y0; z -= z0;\n    }\n    \n    for (int r = 0; r < 24; r++) {\n        vector<tuple<int,int,int>> rotated;\n        for (auto [x, y, z] : baseA) {\n            int nx = rotations_24[r][0][0]*x + rotations_24[r][0][1]*y + rotations_24[r][0][2]*z;\n            int ny = rotations_24[r][1][0]*x + rotations_24[r][1][1]*y + rotations_24[r][1][2]*z;\n            int nz = rotations_24[r][2][0]*x + rotations_24[r][2][1]*y + rotations_24[r][2][2]*z;\n            rotated.emplace_back(nx, ny, nz);\n        }\n        sort(rotated.begin(), rotated.end());\n        \n        auto [bx0, by0, bz0] = b.cells[0];\n        vector<tuple<int,int,int>> baseB = b.cells;\n        for (auto& [x, y, z] : baseB) {\n            x -= bx0; y -= by0; z -= bz0;\n        }\n        sort(baseB.begin(), baseB.end());\n        \n        if (rotated == baseB) return true;\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    f1.resize(D); r1.resize(D);\n    f2.resize(D); r2.resize(D);\n    \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    // Initialize arrays\n    valid1.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    valid2.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    b1.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    b2.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    // Compute valid positions\n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') valid1[x][y][z] = true;\n                if (f2[z][x] == '1' && r2[z][y] == '1') valid2[x][y][z] = true;\n            }\n        }\n    }\n    \n    // Categorize positions\n    vector<tuple<int,int,int>> common, only1, only2;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && valid2[x][y][z]) {\n                    common.emplace_back(x, y, z);\n                } else if (valid1[x][y][z]) {\n                    only1.emplace_back(x, y, z);\n                } else if (valid2[x][y][z]) {\n                    only2.emplace_back(x, y, z);\n                }\n            }\n        }\n    }\n    \n    int blockId = 0;\n    vector<vector<vector<bool>>> placed1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> placed2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    // Phase 1: Create shared blocks from common positions\n    // Use BFS to create connected regions that exist in both solutions\n    for (auto [sx, sy, sz] : common) {\n        if (placed1[sx][sy][sz] || placed2[sx][sy][sz]) continue;\n        \n        // BFS to find connected common region\n        vector<tuple<int,int,int>> region;\n        queue<tuple<int,int,int>> q;\n        set<tuple<int,int,int>> visited;\n        \n        q.emplace(sx, sy, sz);\n        visited.emplace(sx, sy, sz);\n        \n        int maxRegionSize = min(8, (int)common.size() / 5 + 2);\n        \n        while (!q.empty() && (int)region.size() < maxRegionSize) {\n            auto [x, y, z] = q.front();\n            q.pop();\n            region.emplace_back(x, y, z);\n            \n            for (auto [nx, ny, nz] : getNeighbors(x, y, z)) {\n                if (visited.count({nx, ny, nz})) continue;\n                if (!valid1[nx][ny][nz] || !valid2[nx][ny][nz]) continue;\n                if (placed1[nx][ny][nz] || placed2[nx][ny][nz]) continue;\n                \n                visited.emplace(nx, ny, nz);\n                q.emplace(nx, ny, nz);\n            }\n        }\n        \n        if (region.empty()) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells = region;\n        block.normalize();\n        block.usedIn1 = true;\n        block.usedIn2 = true;\n        \n        for (auto [x, y, z] : region) {\n            placed1[x][y][z] = true;\n            placed2[x][y][z] = true;\n            b1[x][y][z] = blockId;\n            b2[x][y][z] = blockId;\n        }\n        \n        blocks.push_back(block);\n    }\n    \n    // Phase 2: Fill remaining positions in solution 1 with small blocks\n    for (auto [x, y, z] : only1) {\n        if (placed1[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = true;\n        block.usedIn2 = false;\n        \n        placed1[x][y][z] = true;\n        b1[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Also check common positions not yet placed in solution 1\n    for (auto [x, y, z] : common) {\n        if (placed1[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = true;\n        block.usedIn2 = false;\n        \n        placed1[x][y][z] = true;\n        b1[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Phase 3: Fill remaining positions in solution 2 with small blocks\n    for (auto [x, y, z] : only2) {\n        if (placed2[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = false;\n        block.usedIn2 = true;\n        \n        placed2[x][y][z] = true;\n        b2[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Also check common positions not yet placed in solution 2\n    for (auto [x, y, z] : common) {\n        if (placed2[x][y][z]) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells.emplace_back(x, y, z);\n        block.usedIn1 = false;\n        block.usedIn2 = true;\n        \n        placed2[x][y][z] = true;\n        b2[x][y][z] = blockId;\n        \n        blocks.push_back(block);\n    }\n    \n    // Output\n    cout << blockId << \"\\n\";\n    \n    bool first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b1[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b2[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <queue>\n#include <tuple>\n#include <iomanip>\n\nusing namespace std;\n\n// Global data\nint N, M, K;\nvector<pair<int, int>> vertices;\nvector<tuple<int, int, int>> edges;\nvector<pair<int, int>> residents;\nvector<vector<int>> adj;\n\n// Solution\nvector<int> P;\nvector<int> B;\n\n// Precomputed: residents near each vertex (within 5000 distance)\nvector<vector<pair<int, long long>>> vertexResidents;\n\ninline long long dist2(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\ninline bool isCovered(int k, int i, int p) {\n    long long d2 = dist2(vertices[i].first, vertices[i].second, \n                         residents[k].first, residents[k].second);\n    return d2 <= 1LL * p * p;\n}\n\nvector<bool> getReachable() {\n    vector<bool> reachable(N, false);\n    vector<int> q;\n    q.reserve(N);\n    q.push_back(0);\n    reachable[0] = true;\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (int ej : adj[u]) {\n            if (B[ej]) {\n                int v = (get<0>(edges[ej]) == u) ? get<1>(edges[ej]) : get<0>(edges[ej]);\n                if (!reachable[v]) {\n                    reachable[v] = true;\n                    q.push_back(v);\n                }\n            }\n        }\n    }\n    return reachable;\n}\n\npair<int, vector<bool>> getCoverage() {\n    vector<bool> reachable = getReachable();\n    vector<bool> residentCovered(K, false);\n    int count = 0;\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i] || P[i] == 0) continue;\n        for (auto& [k, d2] : vertexResidents[i]) {\n            if (!residentCovered[k] && 1LL * P[i] * P[i] >= d2) {\n                residentCovered[k] = true;\n                count++;\n            }\n        }\n    }\n    \n    return {count, residentCovered};\n}\n\ninline long long calculateCost() {\n    long long cost = 0;\n    for (int i = 0; i < N; i++) {\n        cost += 1LL * P[i] * P[i];\n    }\n    for (int j = 0; j < M; j++) {\n        if (B[j]) {\n            cost += get<2>(edges[j]);\n        }\n    }\n    return cost;\n}\n\nvoid precompute() {\n    vertexResidents.assign(N, vector<pair<int, long long>>());\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            long long d2 = dist2(vertices[i].first, vertices[i].second,\n                                residents[k].first, residents[k].second);\n            if (d2 <= 25000000LL) {\n                vertexResidents[i].push_back({k, d2});\n            }\n        }\n    }\n}\n\nvoid buildInitialTree() {\n    fill(B.begin(), B.end(), 0);\n    fill(P.begin(), P.end(), 0);\n    \n    vector<bool> visited(N, false);\n    vector<int> q;\n    q.reserve(N);\n    q.push_back(0);\n    visited[0] = true;\n    \n    vector<int> parentEdge(N, -1);\n    \n    int head = 0;\n    while (head < (int)q.size()) {\n        int u = q[head++];\n        for (int ej : adj[u]) {\n            int v = (get<0>(edges[ej]) == u) ? get<1>(edges[ej]) : get<0>(edges[ej]);\n            if (!visited[v]) {\n                visited[v] = true;\n                parentEdge[v] = ej;\n                q.push_back(v);\n            }\n        }\n    }\n    \n    for (int i = 1; i < N; i++) {\n        if (parentEdge[i] >= 0) {\n            B[parentEdge[i]] = 1;\n        }\n    }\n}\n\nvoid optimizeP() {\n    vector<bool> reachable = getReachable();\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i]) {\n            P[i] = 0;\n        }\n    }\n    \n    for (int iter = 0; iter < 3; iter++) {\n        auto [covered, residentCovered] = getCoverage();\n        \n        if (covered == K) {\n            for (int i = 0; i < N; i++) {\n                if (!reachable[i] || P[i] == 0) continue;\n                \n                int oldP = P[i];\n                int lo = 0, hi = P[i];\n                while (lo < hi) {\n                    int mid = (lo + hi) / 2;\n                    P[i] = mid;\n                    auto [c, rc] = getCoverage();\n                    if (c == K) {\n                        hi = mid;\n                    } else {\n                        lo = mid + 1;\n                    }\n                }\n                P[i] = lo;\n                \n                auto [c, rc] = getCoverage();\n                if (c < K) {\n                    P[i] = oldP;\n                }\n            }\n        } else {\n            for (int k = 0; k < K; k++) {\n                if (residentCovered[k]) continue;\n                \n                int bestI = -1;\n                int bestNeeded = 5001;\n                long long bestCostIncrease = 1LL << 60;\n                \n                for (int i = 0; i < N; i++) {\n                    if (!reachable[i]) continue;\n                    \n                    long long d2 = dist2(vertices[i].first, vertices[i].second,\n                                        residents[k].first, residents[k].second);\n                    if (d2 > 25000000LL) continue;\n                    \n                    int needed = (int)ceil(sqrt(d2));\n                    if (needed > 5000) continue;\n                    \n                    int newP = max(P[i], needed);\n                    long long costIncrease = 1LL * newP * newP - 1LL * P[i] * P[i];\n                    \n                    if (costIncrease < bestCostIncrease) {\n                        bestCostIncrease = costIncrease;\n                        bestI = i;\n                        bestNeeded = needed;\n                    }\n                }\n                \n                if (bestI >= 0) {\n                    P[bestI] = max(P[bestI], bestNeeded);\n                }\n            }\n        }\n    }\n}\n\nvoid localSearch(double timeLimit) {\n    auto startTime = chrono::high_resolution_clock::now();\n    \n    auto [bestCovered, bestResidentCovered] = getCoverage();\n    long long bestCost = calculateCost();\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int noImprove = 0;\n    while (true) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        \n        if (elapsed > timeLimit) break;\n        if (noImprove > 5000 && bestCovered == K) break;\n        \n        double temp = max(0.01, 1.0 - elapsed / timeLimit);\n        \n        int edgeIdx = uniform_int_distribution<int>(0, M - 1)(rng);\n        int oldB = B[edgeIdx];\n        B[edgeIdx] = 1 - oldB;\n        \n        auto [newCovered, newResidentCovered] = getCoverage();\n        long long newCost = calculateCost();\n        \n        bool accept = false;\n        if (newCovered > bestCovered) {\n            accept = true;\n        } else if (newCovered == bestCovered) {\n            if (newCost < bestCost) {\n                accept = true;\n            } else if (bestCovered == K) {\n                double delta = (double)(newCost - bestCost);\n                double prob = exp(-delta / (50000.0 * temp));\n                if (uniform_real_distribution<double>(0, 1)(rng) < prob) {\n                    accept = true;\n                }\n            }\n        }\n        \n        if (accept) {\n            if (newCovered > bestCovered || (newCovered == bestCovered && newCost < bestCost)) {\n                bestCovered = newCovered;\n                bestResidentCovered = newResidentCovered;\n                bestCost = newCost;\n                noImprove = 0;\n            }\n            if (noImprove % 20 == 0) {\n                optimizeP();\n                auto [c, rc] = getCoverage();\n                long long cost = calculateCost();\n                if (c > bestCovered || (c == bestCovered && cost < bestCost)) {\n                    bestCovered = c;\n                    bestResidentCovered = rc;\n                    bestCost = cost;\n                    noImprove = 0;\n                }\n            }\n        } else {\n            B[edgeIdx] = oldB;\n            noImprove++;\n        }\n        \n        if (elapsed > timeLimit * 0.7 && bestCovered < K) {\n            for (int tryCount = 0; tryCount < 3; tryCount++) {\n                int e1 = uniform_int_distribution<int>(0, M - 1)(rng);\n                if (B[e1] == 0) {\n                    B[e1] = 1;\n                    auto [c, rc] = getCoverage();\n                    if (c >= bestCovered) {\n                        bestCovered = c;\n                        bestResidentCovered = rc;\n                        bestCost = calculateCost();\n                        noImprove = 0;\n                    } else {\n                        B[e1] = 0;\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    vertices.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> vertices[i].first >> vertices[i].second;\n    }\n    \n    edges.resize(M);\n    adj.resize(N);\n    for (int j = 0; j < M; j++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[j] = {u, v, w};\n        adj[u].push_back(j);\n        adj[v].push_back(j);\n    }\n    \n    residents.resize(K);\n    for (int k = 0; k < K; k++) {\n        cin >> residents[k].first >> residents[k].second;\n    }\n    \n    P.resize(N, 0);\n    B.resize(M, 0);\n    \n    precompute();\n    buildInitialTree();\n    optimizeP();\n    localSearch(1.95);\n    optimizeP();\n    \n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\n\nstruct Coord {\n    int x, y;\n    bool operator==(const Coord& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Coord& other) const {\n        if (x != other.x) return x < other.x;\n        return y < other.y;\n    }\n};\n\nint grid[N][N];\nCoord pos[TOTAL_BALLS];\n\n// 6 adjacent directions\nconst int DX[6] = {-1, -1, 0, 0, 1, 1};\nconst int DY[6] = {-1, 0, -1, 1, 0, 1};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nvector<Coord> getAdjacent(int x, int y) {\n    vector<Coord> adj;\n    for (int i = 0; i < 6; i++) {\n        int nx = x + DX[i];\n        int ny = y + DY[i];\n        if (isValid(nx, ny)) {\n            adj.push_back({nx, ny});\n        }\n    }\n    return adj;\n}\n\nbool areAdjacent(Coord c1, Coord c2) {\n    for (int i = 0; i < 6; i++) {\n        int nx = c1.x + DX[i];\n        int ny = c1.y + DY[i];\n        if (nx == c2.x && ny == c2.y) return true;\n    }\n    return false;\n}\n\n// BFS with heuristic (A* like)\nvector<Coord> findPath(Coord start, Coord end, const vector<vector<bool>>& blocked) {\n    if (start == end) return {start};\n    \n    priority_queue<tuple<int, int, Coord>, vector<tuple<int, int, Coord>>, greater<>> pq;\n    vector<vector<int>> dist(N, vector<int>(N, 1e9));\n    vector<vector<Coord>> parent(N, vector<Coord>(N, {-1, -1}));\n    \n    auto heuristic = [](Coord a, Coord b) {\n        return abs(a.x - b.x) + abs(a.y - b.y);\n    };\n    \n    dist[start.x][start.y] = 0;\n    pq.push({heuristic(start, end), 0, start});\n    \n    while (!pq.empty()) {\n        auto [f, d, curr] = pq.top();\n        pq.pop();\n        \n        if (d > dist[curr.x][curr.y]) continue;\n        if (curr == end) {\n            vector<Coord> path;\n            Coord c = end;\n            while (c != start) {\n                path.push_back(c);\n                c = parent[c.x][c.y];\n            }\n            path.push_back(start);\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (auto& next : getAdjacent(curr.x, curr.y)) {\n            if (blocked[next.x][next.y]) continue;\n            int nd = d + 1;\n            if (nd < dist[next.x][next.y]) {\n                dist[next.x][next.y] = nd;\n                parent[next.x][next.y] = curr;\n                pq.push({nd + heuristic(next, end), nd, next});\n            }\n        }\n    }\n    \n    return {};\n}\n\nvector<tuple<int,int,int,int>> operations;\n\nvoid swapBalls(Coord c1, Coord c2) {\n    if (c1 == c2 || !areAdjacent(c1, c2)) return;\n    if (operations.size() >= 10000) return;\n    \n    operations.push_back({c1.x, c1.y, c2.x, c2.y});\n    \n    int val1 = grid[c1.x][c1.y];\n    int val2 = grid[c2.x][c2.y];\n    \n    grid[c1.x][c1.y] = val2;\n    grid[c2.x][c2.y] = val1;\n    \n    pos[val1] = c2;\n    pos[val2] = c1;\n}\n\nvoid moveBall(int value, Coord target) {\n    Coord current = pos[value];\n    \n    while (current != target && operations.size() < 9500) {\n        vector<vector<bool>> blocked(N, vector<bool>(N, false));\n        // Block positions of balls that are already in place (smaller values)\n        for (int v = 0; v < value; v++) {\n            blocked[pos[v].x][pos[v].y] = true;\n        }\n        blocked[target.x][target.y] = false; // Allow target\n        \n        auto path = findPath(current, target, blocked);\n        if (path.size() < 2) {\n            // Try without blocking\n            vector<vector<bool>> empty(N, vector<bool>(N, false));\n            path = findPath(current, target, empty);\n        }\n        \n        if (path.size() < 2) break;\n        \n        Coord next = path[1];\n        swapBalls(current, next);\n        current = pos[value];\n    }\n}\n\nint countViolations() {\n    int E = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (grid[x][y] > grid[x + 1][y]) E++;\n            if (grid[x][y] > grid[x + 1][y + 1]) E++;\n        }\n    }\n    return E;\n}\n\nvoid fixViolations() {\n    bool improved = true;\n    while (improved && operations.size() < 10000) {\n        improved = false;\n        for (int x = 0; x < N - 1 && operations.size() < 10000; x++) {\n            for (int y = 0; y <= x && operations.size() < 10000; y++) {\n                // Check violation with left child\n                if (grid[x][y] > grid[x + 1][y]) {\n                    if (areAdjacent({x, y}, {x + 1, y})) {\n                        swapBalls({x, y}, {x + 1, y});\n                        improved = true;\n                    }\n                }\n                // Check violation with right child\n                if (grid[x][y] > grid[x + 1][y + 1]) {\n                    if (areAdjacent({x, y}, {x + 1, y + 1})) {\n                        swapBalls({x, y}, {x + 1, y + 1});\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n            pos[grid[x][y]] = {x, y};\n        }\n    }\n    \n    // Create sorted list of balls with their target positions\n    vector<pair<int, Coord>> balls(TOTAL_BALLS);\n    int idx = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            balls[idx++] = {grid[x][y], {x, y}};\n        }\n    }\n    \n    // Sort by value - smaller values should go to top\n    sort(balls.begin(), balls.end());\n    \n    // Target positions in tier order\n    vector<Coord> targets(TOTAL_BALLS);\n    idx = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            targets[idx++] = {x, y};\n        }\n    }\n    \n    // Move balls to target positions (smallest first)\n    for (int i = 0; i < TOTAL_BALLS && operations.size() < 9000; i++) {\n        int value = balls[i].first;\n        Coord target = targets[i];\n        moveBall(value, target);\n    }\n    \n    // Fix remaining violations\n    fixViolations();\n    \n    // Output\n    cout << operations.size() << \"\\n\";\n    for (auto& op : operations) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = 4;\n\nstruct Container {\n    int id;\n    int r, c;\n};\n\nint grid[D][D];  // -1: empty, -2: obstacle, >=0: container id\nint dist_from_entrance[D][D];\nvector<pair<int, int>> empty_squares;\nvector<Container> containers;\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\nbool isValid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D && grid[r][c] != -2;\n}\n\n// BFS to find all reachable empty squares from entrance\nvector<vector<bool>> computeReachable() {\n    vector<vector<bool>> reachable(D, vector<bool>(D, false));\n    queue<pair<int, int>> q;\n    \n    q.push({ENTRANCE_R, ENTRANCE_C});\n    reachable[ENTRANCE_R][ENTRANCE_C] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && grid[nr][nc] == -1 && !reachable[nr][nc]) {\n                reachable[nr][nc] = true;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return reachable;\n}\n\n// Check if container at (r, c) is reachable (adjacent to reachable empty square)\nbool isContainerReachable(int r, int c) {\n    for (int i = 0; i < 4; i++) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        \n        if (isValid(nr, nc) && grid[nr][nc] == -1) {\n            auto reachable = computeReachable();\n            if (reachable[nr][nc]) return true;\n        }\n    }\n    return false;\n}\n\n// Check if placing container maintains connectivity for all existing containers\nbool canPlace(int r, int c) {\n    if (!isValid(r, c) || grid[r][c] != -1) return false;\n    \n    grid[r][c] = -3;  // Temporarily occupied\n    \n    bool ok = true;\n    for (const auto& cont : containers) {\n        if (!isContainerReachable(cont.r, cont.c)) {\n            ok = false;\n            break;\n        }\n    }\n    \n    grid[r][c] = -1;\n    return ok;\n}\n\nvoid computeDistances() {\n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            dist_from_entrance[i][j] = 1e9;\n        }\n    }\n    \n    queue<pair<int, int>> q;\n    q.push({ENTRANCE_R, ENTRANCE_C});\n    dist_from_entrance[ENTRANCE_R][ENTRANCE_C] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && dist_from_entrance[nr][nc] > dist_from_entrance[r][c] + 1) {\n                dist_from_entrance[nr][nc] = dist_from_entrance[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            grid[i][j] = -1;\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -2;\n    }\n    \n    computeDistances();\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            if (grid[i][j] == -1 && !(i == ENTRANCE_R && j == ENTRANCE_C)) {\n                empty_squares.push_back({i, j});\n            }\n        }\n    }\n    \n    sort(empty_squares.begin(), empty_squares.end(), [](const pair<int, int>& a, const pair<int, int>& b) {\n        return dist_from_entrance[a.first][a.second] < dist_from_entrance[b.first][b.second];\n    });\n    \n    int total_containers = D * D - 1 - N;\n    \n    for (int d = 0; d < total_containers; d++) {\n        int container_id;\n        cin >> container_id;\n        \n        int best_r = -1, best_c = -1;\n        int best_score = 1e9;\n        \n        for (const auto& [r, c] : empty_squares) {\n            if (grid[r][c] == -1 && canPlace(r, c)) {\n                int score = dist_from_entrance[r][c] * 100;\n                if (container_id < total_containers / 2) {\n                    score -= 50;  // Prefer closer for smaller IDs\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        grid[best_r][best_c] = container_id;\n        containers.push_back({container_id, best_r, best_c});\n        \n        cout << best_r << \" \" << best_c << endl;\n    }\n    \n    // Retrieval: output in order 0, 1, 2, ...\n    vector<bool> retrieved(total_containers, false);\n    vector<pair<int, int>> output_order;\n    \n    for (int target_id = 0; target_id < total_containers; target_id++) {\n        for (auto& cont : containers) {\n            if (cont.id == target_id && !retrieved[target_id]) {\n                if (isContainerReachable(cont.r, cont.c)) {\n                    output_order.push_back({cont.r, cont.c});\n                    retrieved[target_id] = true;\n                    grid[cont.r][cont.c] = -1;  // Remove container\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Output any remaining\n    for (auto& cont : containers) {\n        if (!retrieved[cont.id]) {\n            output_order.push_back({cont.r, cont.c});\n        }\n    }\n    \n    for (const auto& [r, c] : output_order) {\n        cout << r << \" \" << c << endl;\n    }\n    \n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <atcoder/all>\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nint grid[N][N];\nint adj[M + 1][M + 1];  // adjacency matrix\nint color_count[M + 1]; // count of each color\n\n// Check if a color region is connected using BFS\nbool check_connectivity(int c) {\n    vector<pair<int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == c) {\n                cells.push_back({i, j});\n            }\n        }\n    }\n    if (cells.empty()) return c == 0; // color 0 can be empty (connects through outside)\n    \n    // BFS from first cell\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    queue<pair<int, int>> q;\n    q.push(cells[0]);\n    visited[cells[0].first][cells[0].second] = true;\n    int count = 1;\n    \n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\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                !visited[ni][nj] && grid[ni][nj] == c) {\n                visited[ni][nj] = true;\n                count++;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return count == (int)cells.size();\n}\n\n// Check if all color regions are connected\nbool check_all_connectivity() {\n    for (int c = 1; c <= m; c++) {\n        if (!check_connectivity(c)) return false;\n    }\n    // Color 0 connectivity through outside is automatic if other colors are connected\n    return true;\n}\n\n// Build adjacency matrix from current grid\nvoid build_adjacency() {\n    memset(adj, 0, sizeof(adj));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    // Boundary touches color 0\n                    adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Get current adjacency from grid\nvoid get_current_adjacency(int cur_adj[M + 1][M + 1]) {\n    memset(cur_adj, 0, sizeof(int) * (M + 1) * (M + 1));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        cur_adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    cur_adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Check if adjacency is preserved\nbool check_adjacency_preserved() {\n    int cur_adj[M + 1][M + 1];\n    get_current_adjacency(cur_adj);\n    \n    for (int c1 = 0; c1 <= m; c1++) {\n        for (int c2 = c1 + 1; c2 <= m; c2++) {\n            if (adj[c1][c2] != cur_adj[c1][c2]) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Count color 0 squares\nint count_zeros() {\n    int cnt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == 0) cnt++;\n        }\n    }\n    return cnt;\n}\n\n// Try to fill a 0 cell with a color\nbool try_fill_zero(int i, int j, int c) {\n    if (grid[i][j] != 0) return false;\n    \n    int old = grid[i][j];\n    grid[i][j] = c;\n    \n    // Check connectivity\n    if (!check_connectivity(c)) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    // Check adjacency preservation\n    if (!check_adjacency_preserved()) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    return true;\n}\n\n// Get colors adjacent to position (i, j)\nvector<int> get_adjacent_colors(int i, int j) {\n    vector<int> colors;\n    vector<bool> seen(M + 1, false);\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\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            int c = grid[ni][nj];\n            if (c != 0 && !seen[c]) {\n                seen[c] = true;\n                colors.push_back(c);\n            }\n        } else {\n            if (!seen[0]) {\n                seen[0] = true;\n                colors.push_back(0);\n            }\n        }\n    }\n    return colors;\n}\n\n// Check if filling (i,j) with color c would create unwanted adjacency\nbool would_create_bad_adjacency(int i, int j, int c) {\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int d = 0; d < 4; d++) {\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        int neighbor_c;\n        if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n            neighbor_c = grid[ni][nj];\n        } else {\n            neighbor_c = 0;\n        }\n        \n        if (neighbor_c != c && neighbor_c != 0) {\n            // Check if c and neighbor_c should be adjacent\n            if (!adj[min(c, neighbor_c)][max(c, neighbor_c)]) {\n                return true; // Would create unwanted adjacency\n            }\n        }\n    }\n    return false;\n}\n\n// Check if filling (i,j) with color c would miss required adjacency\nbool would_miss_adjacency(int i, int j, int c) {\n    // This is harder to check locally, skip for now\n    return false;\n}\n\n// Greedy fill zeros\nvoid greedy_fill() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        vector<tuple<int, int, int>> candidates;\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    vector<int> adj_colors = get_adjacent_colors(i, j);\n                    for (int c : adj_colors) {\n                        if (c == 0) continue;\n                        if (!would_create_bad_adjacency(i, j, c)) {\n                            candidates.push_back({i, j, c});\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try candidates in random order\n        shuffle(candidates.begin(), candidates.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count()));\n        \n        for (auto [i, j, c] : candidates) {\n            if (grid[i][j] == 0 && try_fill_zero(i, j, c)) {\n                changed = true;\n                break; // Restart to be safe\n            }\n        }\n    }\n}\n\n// Simulated annealing style local search\nvoid local_search() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 5000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find a 0 cell\n        vector<pair<int, int>> zeros;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    zeros.push_back({i, j});\n                }\n            }\n        }\n        \n        if (zeros.empty()) break;\n        \n        auto [i, j] = zeros[rng() % zeros.size()];\n        vector<int> adj_colors = get_adjacent_colors(i, j);\n        \n        if (adj_colors.empty()) continue;\n        \n        int c = adj_colors[rng() % adj_colors.size()];\n        if (c == 0) continue;\n        \n        if (try_fill_zero(i, j, c)) {\n            // Success, continue\n        }\n    }\n}\n\n// Compact regions by moving boundary cells\nvoid compact_regions() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 3000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find boundary cells (colored cells adjacent to 0)\n        vector<tuple<int, int, int>> boundaries; // i, j, color\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0) {\n                    int di[] = {0, 0, 1, -1};\n                    int dj[] = {1, -1, 0, 0};\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 && grid[ni][nj] == 0) {\n                            boundaries.push_back({i, j, grid[i][j]});\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (boundaries.empty()) break;\n        \n        auto [i, j, c] = boundaries[rng() % boundaries.size()];\n        \n        // Try to expand into adjacent 0\n        int di[] = {0, 0, 1, -1};\n        int dj[] = {1, -1, 0, 0};\n        \n        vector<pair<int, int>> adjacent_zeros;\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 && grid[ni][nj] == 0) {\n                adjacent_zeros.push_back({ni, nj});\n            }\n        }\n        \n        if (adjacent_zeros.empty()) continue;\n        \n        auto [ni, nj] = adjacent_zeros[rng() % adjacent_zeros.size()];\n        \n        if (!would_create_bad_adjacency(ni, nj, c)) {\n            int old = grid[ni][nj];\n            grid[ni][nj] = c;\n            \n            if (check_connectivity(c) && check_adjacency_preserved()) {\n                // Keep the change\n            } else {\n                grid[ni][nj] = old;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    \n    int zeros = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> grid[i][j];\n            if (grid[i][j] == 0) zeros++;\n            color_count[grid[i][j]]++;\n        }\n    }\n    \n    // Build target adjacency from input\n    build_adjacency();\n    \n    // Phase 1: Greedy fill\n    greedy_fill();\n    \n    // Phase 2: Local search\n    local_search();\n    \n    // Phase 3: Compact regions\n    compact_regions();\n    \n    // Phase 4: Final greedy pass\n    greedy_fill();\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cout << grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Estimate weights through comparisons\n    // Use a reference-based approach: compare each item against a reference set\n    vector<double> estimated_weight(N, 1.0);\n    vector<int> win_count(N, 0);\n    vector<int> lose_count(N, 0);\n    \n    // Phase 1: Pairwise comparisons to build relative ranking\n    // Use tournament-style comparisons\n    int queries_used = 0;\n    \n    // First, do pairwise comparisons between items\n    // Compare item i vs item j by putting them on opposite sides\n    for (int i = 0; i < N && queries_used < Q; i++) {\n        for (int j = i + 1; j < N && queries_used < Q; j++) {\n            // Compare single items\n            cout << \"1 1 \" << i << \" \" << j << endl;\n            queries_used++;\n            \n            string result;\n            cin >> result;\n            \n            if (result == \">\") {\n                win_count[i]++;\n                lose_count[j]++;\n            } else if (result == \"<\") {\n                lose_count[i]++;\n                win_count[j]++;\n            }\n            // \"=\" means equal, no change\n        }\n    }\n    \n    // Calculate estimated weights based on win/loss ratio\n    for (int i = 0; i < N; i++) {\n        int total = win_count[i] + lose_count[i];\n        if (total > 0) {\n            estimated_weight[i] = 1.0 + (double)win_count[i] / total;\n        }\n    }\n    \n    // If we have remaining queries, do more refined comparisons\n    // Compare items against groups to get better estimates\n    while (queries_used < Q) {\n        // Pick two random items to compare\n        static mt19937 rng(42);\n        int i = rng() % N;\n        int j = rng() % N;\n        if (i == j) continue;\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        if (result == \">\") {\n            estimated_weight[i] += 0.1;\n            estimated_weight[j] -= 0.05;\n        } else if (result == \"<\") {\n            estimated_weight[i] -= 0.05;\n            estimated_weight[j] += 0.1;\n        }\n    }\n    \n    // Phase 2: Partition items into D sets\n    // Use greedy approach: sort by estimated weight, assign to lightest bin\n    \n    // Create indices sorted by estimated weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return estimated_weight[a] > estimated_weight[b];\n    });\n    \n    // Initialize D bins\n    vector<vector<int>> bins(D);\n    vector<double> bin_weight(D, 0.0);\n    \n    // Greedy assignment: assign heaviest items first to lightest bin\n    for (int idx : indices) {\n        // Find bin with minimum current weight\n        int min_bin = 0;\n        for (int d = 1; d < D; d++) {\n            if (bin_weight[d] < bin_weight[min_bin]) {\n                min_bin = d;\n            }\n        }\n        bins[min_bin].push_back(idx);\n        bin_weight[min_bin] += estimated_weight[idx];\n    }\n    \n    // Phase 3: Local optimization to reduce variance\n    // Try swapping items between bins to reduce variance\n    auto calc_variance = [&]() -> double {\n        double mean = 0.0;\n        for (double w : bin_weight) mean += w;\n        mean /= D;\n        double var = 0.0;\n        for (double w : bin_weight) {\n            double diff = w - mean;\n            var += diff * diff;\n        }\n        return var / D;\n    };\n    \n    // Local search optimization\n    bool improved = true;\n    int max_iterations = 1000;\n    int iteration = 0;\n    \n    while (improved && iteration < max_iterations) {\n        improved = false;\n        iteration++;\n        \n        double current_var = calc_variance();\n        \n        // Try swapping pairs of items between different bins\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = d1 + 1; d2 < D && !improved; d2++) {\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    for (int j = 0; j < (int)bins[d2].size() && !improved; j++) {\n                        int item1 = bins[d1][i];\n                        int item2 = bins[d2][j];\n                        \n                        // Calculate new weights if we swap\n                        double new_w1 = bin_weight[d1] - estimated_weight[item1] + estimated_weight[item2];\n                        double new_w2 = bin_weight[d2] - estimated_weight[item2] + estimated_weight[item1];\n                        \n                        // Check if this reduces variance\n                        double mean = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            if (d == d1) mean += new_w1;\n                            else if (d == d2) mean += new_w2;\n                            else mean += bin_weight[d];\n                        }\n                        mean /= D;\n                        \n                        double new_var = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                            double diff = w - mean;\n                            new_var += diff * diff;\n                        }\n                        new_var /= D;\n                        \n                        if (new_var < current_var - 1e-9) {\n                            // Perform swap\n                            swap(bins[d1][i], bins[d2][j]);\n                            bin_weight[d1] = new_w1;\n                            bin_weight[d2] = new_w2;\n                            improved = true;\n                            current_var = new_var;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Also try moving single items\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = 0; d2 < D && !improved; d2++) {\n                if (d1 == d2) continue;\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    int item = bins[d1][i];\n                    \n                    double new_w1 = bin_weight[d1] - estimated_weight[item];\n                    double new_w2 = bin_weight[d2] + estimated_weight[item];\n                    \n                    double mean = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        if (d == d1) mean += new_w1;\n                        else if (d == d2) mean += new_w2;\n                        else mean += bin_weight[d];\n                    }\n                    mean /= D;\n                    \n                    double new_var = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                        double diff = w - mean;\n                        new_var += diff * diff;\n                    }\n                    new_var /= D;\n                    \n                    if (new_var < current_var - 1e-9) {\n                        bins[d1].erase(bins[d1].begin() + i);\n                        bins[d2].push_back(item);\n                        bin_weight[d1] = new_w1;\n                        bin_weight[d2] = new_w2;\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Create output assignment\n    vector<int> assignment(N);\n    for (int d = 0; d < D; d++) {\n        for (int item : bins[d]) {\n            assignment[item] = d;\n        }\n    }\n    \n    // Output final assignment\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 <iostream>\n#include <vector>\n#include <algorithm>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    int boxes_per_stack = n / m;\n    \n    vector<vector<int>> stacks(m);\n    vector<pair<int, int>> pos(n + 1);\n    \n    for (int i = 0; i < m; i++) {\n        stacks[i].resize(boxes_per_stack);\n        for (int j = 0; j < boxes_per_stack; j++) {\n            cin >> stacks[i][j];\n            pos[stacks[i][j]] = {i, j};\n        }\n    }\n    \n    vector<pair<int, int>> operations;\n    \n    auto update_positions = [&](int stack_idx) {\n        for (int h = 0; h < (int)stacks[stack_idx].size(); h++) {\n            pos[stacks[stack_idx][h]] = {stack_idx, h};\n        }\n    };\n    \n    // Calculate how soon a box will be needed (0 if already removed or current)\n    auto get_urgency = [&](int box, int current_v) -> int {\n        if (box < current_v) return 1000; // Already removed\n        return box - current_v;\n    };\n    \n    auto find_best_stack = [&](int source_idx, int box_to_move, int current_v) -> int {\n        int best_stack = -1;\n        double best_score = 1e18;\n        \n        int urgency = get_urgency(box_to_move, current_v);\n        \n        for (int s = 0; s < m; s++) {\n            if (s == source_idx) continue;\n            \n            double score = 0;\n            \n            // Base cost: stack size (prefer emptier stacks)\n            score += stacks[s].size() * 1.0;\n            \n            // If this box is needed soon, penalize deep stacks heavily\n            if (urgency < 15) {\n                score += stacks[s].size() * (15 - urgency) * 0.8;\n            }\n            \n            // Check what's already in the destination stack\n            int soon_needed_in_dest = 0;\n            for (int h = 0; h < (int)stacks[s].size(); h++) {\n                int box_in_dest = stacks[s][h];\n                int dest_urgency = get_urgency(box_in_dest, current_v);\n                if (dest_urgency < 10 && dest_urgency > 0) {\n                    soon_needed_in_dest++;\n                    // Penalize if we'd be burying important boxes\n                    if (urgency < 10) {\n                        score += 2.0;\n                    }\n                }\n            }\n            \n            // Prefer stacks with fewer soon-needed boxes (less competition for access)\n            score += soon_needed_in_dest * 1.5;\n            \n            // Small randomization to avoid always picking same stack\n            score += (s * 0.01);\n            \n            if (score < best_score) {\n                best_score = score;\n                best_stack = s;\n            }\n        }\n        \n        if (best_stack == -1) {\n            for (int s = 0; s < m; s++) {\n                if (s != source_idx) {\n                    best_stack = s;\n                    break;\n                }\n            }\n        }\n        \n        return best_stack;\n    };\n    \n    for (int v = 1; v <= n; v++) {\n        auto [stack_idx, height_idx] = pos[v];\n        \n        if (height_idx == (int)stacks[stack_idx].size() - 1) {\n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        } else {\n            // Move boxes above v one at a time from top down\n            while ((int)stacks[stack_idx].size() - 1 > height_idx) {\n                int top_box = stacks[stack_idx].back();\n                int dest_stack = find_best_stack(stack_idx, top_box, v);\n                \n                operations.push_back({top_box, dest_stack + 1});\n                stacks[stack_idx].pop_back();\n                stacks[dest_stack].push_back(top_box);\n                \n                update_positions(stack_idx);\n                update_positions(dest_stack);\n            }\n            \n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        }\n    }\n    \n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\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 DI[4] = {0, 1, 0, -1};\nconst int DJ[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nbool canMove(int i, int j, int dir) {\n    int ni = i + DI[dir];\n    int nj = j + DJ[dir];\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    if (dir == 0) return v[i][j] == '0';\n    else if (dir == 1) return h[i][j] == '0';\n    else if (dir == 2) return v[i][nj] == '0';\n    else return h[ni][j] == '0';\n}\n\nvector<int> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parentDir(N, vector<int>(N, -1));\n    \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();\n        q.pop();\n        \n        if (i == ti && j == tj) break;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    parent[ni][nj] = {i, j};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (dist[ti][tj] == -1) return {};\n    \n    vector<int> path;\n    int ci = ti, cj = tj;\n    while (ci != si || cj != sj) {\n        path.push_back(parentDir[ci][cj]);\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Build BFS tree and create tour by traversing each edge twice\nstring buildBFSTour() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parentDir(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({0, 0});\n    visited[0][0] = true;\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    visited[ni][nj] = true;\n                    parent[ni][nj] = {i, j};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    // Build adjacency list for BFS tree - use 3D vector\n    vector<vector<vector<pair<int,int>>>> children(N, vector<vector<pair<int,int>>>(N));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (parent[i][j].first != -1) {\n                int pi = parent[i][j].first;\n                int pj = parent[i][j].second;\n                children[pi][pj].push_back({i, j});\n            }\n        }\n    }\n    \n    // DFS on BFS tree to create tour\n    string tour;\n    function<void(int, int)> dfsTour = [&](int i, int j) {\n        for (auto& child : children[i][j]) {\n            int ni = child.first;\n            int nj = child.second;\n            int dir = -1;\n            for (int d = 0; d < 4; d++) {\n                if (i + DI[d] == ni && j + DJ[d] == nj) {\n                    dir = d;\n                    break;\n                }\n            }\n            if (dir != -1) {\n                tour += DIR_CHAR[dir];\n                dfsTour(ni, nj);\n                tour += DIR_CHAR[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfsTour(0, 0);\n    return tour;\n}\n\n// Check if all cells are visited\nbool checkCoverage(const string& route) {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int ci = 0, cj = 0;\n    visited[0][0] = true;\n    \n    for (char c : route) {\n        int dir;\n        if (c == 'R') dir = 0;\n        else if (c == 'D') dir = 1;\n        else if (c == 'L') dir = 2;\n        else dir = 3;\n        ci += DI[dir];\n        cj += DJ[dir];\n        visited[ci][cj] = true;\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!visited[i][j]) return false;\n        }\n    }\n    return true;\n}\n\n// Get final position after following route\npair<int,int> getFinalPos(const string& route) {\n    int ci = 0, cj = 0;\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n    }\n    return {ci, cj};\n}\n\n// Get all positions visited in route\nvector<pair<int,int>> getRoutePositions(const string& route) {\n    vector<pair<int,int>> positions;\n    int ci = 0, cj = 0;\n    positions.push_back({ci, cj});\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n        positions.push_back({ci, cj});\n    }\n    return positions;\n}\n\n// Calculate visit count for each cell\nvector<vector<int>> getVisitCount(const string& route) {\n    vector<vector<int>> count(N, vector<int>(N, 0));\n    int ci = 0, cj = 0;\n    count[0][0] = 1;\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n        count[ci][cj]++;\n    }\n    return count;\n}\n\n// Optimize route by inserting extra visits to high-dirt cells\nstring optimizeRoute(string baseRoute, int maxLen) {\n    if ((int)baseRoute.size() >= maxLen - 1000) return baseRoute;\n    \n    vector<vector<int>> visitCount = getVisitCount(baseRoute);\n    vector<pair<int,int>> routePositions = getRoutePositions(baseRoute);\n    \n    // Calculate priority: high dirt + low visit count\n    vector<tuple<double, int, int>> priorities;\n    long long totalDirt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            totalDirt += d[i][j];\n        }\n    }\n    \n    double avgDirt = (double)totalDirt / (N * N);\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            double priority = (double)d[i][j] / (visitCount[i][j] + 1);\n            if (d[i][j] > avgDirt * 1.2) {\n                priorities.push_back({priority, i, j});\n            }\n        }\n    }\n    \n    sort(priorities.begin(), priorities.end(), greater<tuple<double,int,int>>());\n    \n    string result = baseRoute;\n    int budget = maxLen - (int)result.size() - 500;\n    \n    for (auto& [pri, ti, tj] : priorities) {\n        if (budget <= 20) break;\n        \n        // Find position in route closest to target cell\n        int bestPos = -1;\n        int bestDist = 1e9;\n        \n        for (int pos = 0; pos < (int)routePositions.size(); pos++) {\n            int dist = abs(routePositions[pos].first - ti) + abs(routePositions[pos].second - tj);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestPos = pos;\n            }\n        }\n        \n        if (bestPos == -1) continue;\n        \n        int pi = routePositions[bestPos].first;\n        int pj = routePositions[bestPos].second;\n        \n        vector<int> pathTo = bfsPath(pi, pj, ti, tj);\n        if (pathTo.empty()) continue;\n        \n        vector<int> pathBack = bfsPath(ti, tj, pi, pj);\n        if (pathBack.empty()) continue;\n        \n        int pathLen = pathTo.size() + pathBack.size();\n        if (pathLen > budget) continue;\n        \n        string insert;\n        for (int dir : pathTo) insert += DIR_CHAR[dir];\n        for (int dir : pathBack) insert += DIR_CHAR[dir];\n        \n        result.insert(bestPos, insert);\n        budget -= pathLen;\n        \n        // Update route positions\n        routePositions = getRoutePositions(result);\n    }\n    \n    return result;\n}\n\n// Create frequency-based route with multiple passes\nstring buildFrequencyRoute(int maxLen) {\n    vector<tuple<int, int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cells.push_back({d[i][j], i, j});\n        }\n    }\n    sort(cells.begin(), cells.end(), greater<tuple<int,int,int>>());\n    \n    long long totalDirt = 0;\n    for (auto& [dirt, i, j] : cells) {\n        totalDirt += dirt;\n    }\n    \n    string baseTour = buildBFSTour();\n    \n    if ((int)baseTour.size() > maxLen - 1000) {\n        return baseTour;\n    }\n    \n    string result = baseTour;\n    int budget = maxLen - (int)result.size() - 500;\n    \n    pair<int,int> pos = getFinalPos(result);\n    int ci = pos.first, cj = pos.second;\n    \n    int pass = 0;\n    while (budget > 50 && pass < 10) {\n        for (auto& [dirt, ti, tj] : cells) {\n            if (budget <= 50) break;\n            if (dirt < totalDirt / (N * N)) break;\n            \n            vector<int> pathTo = bfsPath(ci, cj, ti, tj);\n            if (pathTo.empty()) continue;\n            \n            vector<int> pathBack = bfsPath(ti, tj, ci, cj);\n            if (pathBack.empty()) continue;\n            \n            int pathLen = pathTo.size() + pathBack.size();\n            if (pathLen > budget) continue;\n            \n            for (int dir : pathTo) {\n                result += DIR_CHAR[dir];\n                ci += DI[dir];\n                cj += DJ[dir];\n            }\n            for (int dir : pathBack) {\n                result += DIR_CHAR[dir];\n                ci += DI[dir];\n                cj += DJ[dir];\n            }\n            \n            budget -= pathLen;\n        }\n        pass++;\n    }\n    \n    // Return to start\n    if (ci != 0 || cj != 0) {\n        vector<int> pathHome = bfsPath(ci, cj, 0, 0);\n        for (int dir : pathHome) {\n            result += DIR_CHAR[dir];\n        }\n    }\n    \n    return result;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    h.resize(N - 1);\n    for (int i = 0; i < N - 1; i++) {\n        cin >> h[i];\n    }\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> v[i];\n    }\n    \n    d.resize(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    }\n    \n    int maxLen = 100000;\n    \n    // Strategy 1: BFS tree tour + optimization\n    string route1 = buildBFSTour();\n    route1 = optimizeRoute(route1, maxLen);\n    \n    // Strategy 2: Frequency-based route\n    string route2 = buildFrequencyRoute(maxLen);\n    \n    // Pick best valid route\n    vector<pair<string, int>> candidates;\n    \n    if (checkCoverage(route1) && (int)route1.size() <= maxLen) {\n        candidates.push_back({route1, (int)route1.size()});\n    }\n    if (checkCoverage(route2) && (int)route2.size() <= maxLen) {\n        candidates.push_back({route2, (int)route2.size()});\n    }\n    \n    string bestRoute;\n    if (candidates.empty()) {\n        bestRoute = buildBFSTour();\n    } else {\n        sort(candidates.begin(), candidates.end(), \n             [](const auto& a, const auto& b) { return a.second < b.second; });\n        bestRoute = candidates[0].first;\n    }\n    \n    // Final validation\n    if (!checkCoverage(bestRoute)) {\n        bestRoute = buildBFSTour();\n    }\n    \n    // Ensure ends at (0,0)\n    pair<int,int> finalPos = getFinalPos(bestRoute);\n    if (finalPos.first != 0 || finalPos.second != 0) {\n        vector<int> pathHome = bfsPath(finalPos.first, finalPos.second, 0, 0);\n        for (int dir : pathHome) {\n            bestRoute += DIR_CHAR[dir];\n        }\n    }\n    \n    // Final length check\n    if ((int)bestRoute.size() > maxLen) {\n        bestRoute = buildBFSTour();\n    }\n    \n    cout << bestRoute << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, si, sj;\nvector<string> A;\nvector<string> t;\nvector<vector<pair<int,int>>> charPos(26);\nvector<vector<int>> overlap;\nvector<int> minCharCost(26); // Minimum cost to type each character\nmt19937 rng;\n\n// Calculate overlap between two words\ninline int calcOverlap(const string& a, const string& b) {\n    int maxOv = 0;\n    for (int ov = 1; ov < 5; ov++) {\n        if (a.substr(5 - ov) == b.substr(0, ov)) {\n            maxOv = ov;\n        }\n    }\n    return maxOv;\n}\n\n// Build string from word order\nstring buildString(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s;\n    s.reserve(M * 5);\n    s = t[order[0]];\n    for (size_t i = 1; i < order.size(); i++) {\n        int ov = overlap[order[i-1]][order[i]];\n        s.append(t[order[i]].substr(ov));\n    }\n    return s;\n}\n\n// Fast cost estimation using precomputed character costs\ninline long long fastEstimateCost(const string& s) {\n    if (s.empty()) return 0;\n    long long cost = 0;\n    int curI = si, curJ = sj;\n    \n    for (char c : s) {\n        int idx = c - 'A';\n        // Use minimum cost for this character (approximation)\n        cost += minCharCost[idx];\n    }\n    \n    // Add base movement cost estimate\n    cost += s.size();\n    \n    return cost;\n}\n\n// More accurate but still fast cost estimation\nlong long estimateCost(const string& s) {\n    if (s.empty()) return 0;\n    int curI = si, curJ = sj;\n    long long cost = 0;\n    \n    for (char c : s) {\n        int idx = c - 'A';\n        int minDist = 1000;\n        int bestI = curI, bestJ = curJ;\n        \n        for (auto [ni, nj] : charPos[idx]) {\n            int dist = abs(ni - curI) + abs(nj - curJ) + 1;\n            if (dist < minDist) {\n                minDist = dist;\n                bestI = ni;\n                bestJ = nj;\n            }\n        }\n        \n        cost += minDist;\n        curI = bestI;\n        curJ = bestJ;\n    }\n    \n    return cost;\n}\n\n// Simulated annealing - simplified and faster\nvector<int> simulatedAnnealing(vector<int> initial, double timeLimit, auto& startTime) {\n    vector<int> current = initial;\n    vector<int> best = initial;\n    long long currentCost = estimateCost(buildString(current));\n    long long bestCost = currentCost;\n    \n    double temp = 2000.0;\n    double coolingRate = 0.9995;\n    int iteration = 0;\n    \n    while (iteration < 50000) {\n        if (iteration % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > timeLimit) break;\n        }\n        \n        vector<int> neighbor = current;\n        int moveType = rng() % 3;\n        \n        if (moveType == 0) {\n            // Swap two elements\n            int i1 = rng() % M;\n            int i2 = rng() % M;\n            swap(neighbor[i1], neighbor[i2]);\n        } else if (moveType == 1) {\n            // Insert: move element from i1 to position i2\n            int i1 = rng() % M;\n            int i2 = rng() % M;\n            if (i1 != i2) {\n                int val = neighbor[i1];\n                neighbor.erase(neighbor.begin() + i1);\n                neighbor.insert(neighbor.begin() + i2, val);\n            }\n        } else {\n            // Reverse segment\n            int i1 = rng() % M;\n            int i2 = rng() % M;\n            if (i1 > i2) swap(i1, i2);\n            if (i2 - i1 > 1) {\n                reverse(neighbor.begin() + i1, neighbor.begin() + i2 + 1);\n            }\n        }\n        \n        long long neighborCost = estimateCost(buildString(neighbor));\n        double delta = (double)(neighborCost - currentCost);\n        \n        if (delta < 0 || (temp > 0.1 && exp(-delta / temp) > (double)rng() / rng.max())) {\n            current = neighbor;\n            currentCost = neighborCost;\n            if (currentCost < bestCost) {\n                best = current;\n                bestCost = currentCost;\n            }\n        }\n        \n        temp *= coolingRate;\n        iteration++;\n    }\n    \n    return best;\n}\n\n// Simple greedy with overlap only (fast)\nvector<int> greedyOverlap(int startWord) {\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    \n    order.push_back(startWord);\n    used[startWord] = true;\n    \n    for (int i = 1; i < M; i++) {\n        int bestNext = -1;\n        int bestOverlap = -1;\n        \n        for (int j = 0; j < M; j++) {\n            if (!used[j]) {\n                int ov = overlap[order.back()][j];\n                if (ov > bestOverlap) {\n                    bestOverlap = ov;\n                    bestNext = j;\n                }\n            }\n        }\n        \n        if (bestNext != -1) {\n            used[bestNext] = true;\n            order.push_back(bestNext);\n        }\n    }\n    \n    return order;\n}\n\n// Greedy with simple position awareness\nvector<int> greedyWithPosition(int startWord) {\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    \n    order.push_back(startWord);\n    used[startWord] = true;\n    \n    for (int i = 1; i < M; i++) {\n        int bestNext = -1;\n        int bestScore = -1000000;\n        \n        for (int j = 0; j < M; j++) {\n            if (!used[j]) {\n                int ov = overlap[order.back()][j];\n                int added = 5 - ov;\n                \n                // Simple score: overlap bonus minus added characters\n                int score = ov * 100 - added * 10;\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestNext = j;\n                }\n            }\n        }\n        \n        if (bestNext != -1) {\n            used[bestNext] = true;\n            order.push_back(bestNext);\n        }\n    }\n    \n    return order;\n}\n\n// Optimize positions for final string\nvector<pair<int,int>> optimizePositions(const string& s) {\n    int L = s.size();\n    if (L == 0) return {};\n    \n    vector<pair<int,int>> path(L);\n    int curI = si, curJ = sj;\n    \n    for (int pos = 0; pos < L; pos++) {\n        int idx = s[pos] - 'A';\n        int bestI = -1, bestJ = -1;\n        int minDist = 1000;\n        \n        for (auto [ni, nj] : charPos[idx]) {\n            int dist = abs(ni - curI) + abs(nj - curJ) + 1;\n            if (dist < minDist) {\n                minDist = dist;\n                bestI = ni;\n                bestJ = nj;\n            }\n        }\n        \n        path[pos] = {bestI, bestJ};\n        curI = bestI;\n        curJ = bestJ;\n    }\n    \n    return path;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    // Read input\n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    A.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> A[i];\n    }\n    \n    t.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> t[i];\n    }\n    \n    // Map characters to positions\n    charPos.resize(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            charPos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    // Precompute minimum character costs\n    for (int c = 0; c < 26; c++) {\n        int minCost = 1000;\n        for (auto [ni, nj] : charPos[c]) {\n            int cost = abs(ni - si) + abs(nj - sj) + 1;\n            minCost = min(minCost, cost);\n        }\n        minCharCost[c] = minCost;\n    }\n    \n    // Precompute overlaps\n    overlap.assign(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                overlap[i][j] = calcOverlap(t[i], t[j]);\n            }\n        }\n    }\n    \n    // Initialize RNG\n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> bestOrder;\n    long long bestCost = LLONG_MAX;\n    \n    double timeLimit = 1.7; // Leave margin for output\n    \n    // Phase 1: Quick greedy starts\n    int numGreedy = min(M, 25);\n    for (int start = 0; start < numGreedy; start++) {\n        vector<int> order = greedyWithPosition(start);\n        long long cost = estimateCost(buildString(order));\n        \n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOrder = order;\n        }\n        \n        // Check time periodically\n        if (start % 5 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > timeLimit * 0.3) break;\n        }\n    }\n    \n    // Phase 2: Simulated annealing on best result\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - startTime).count();\n    \n    if (elapsed < timeLimit * 0.9 && !bestOrder.empty()) {\n        double remainingTime = timeLimit * 0.9 - elapsed;\n        vector<int> saResult = simulatedAnnealing(bestOrder, remainingTime, startTime);\n        long long cost = estimateCost(buildString(saResult));\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOrder = saResult;\n        }\n    }\n    \n    // Build final string and optimize positions\n    string finalStr = buildString(bestOrder);\n    vector<pair<int,int>> path = optimizePositions(finalStr);\n    \n    // Ensure we don't exceed 5000 operations\n    if ((int)path.size() > 5000) {\n        path.resize(5000);\n    }\n    \n    // Output\n    for (auto [i, j] : path) {\n        cout << i << \" \" << j << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst double EPS = 1e-10;\nconst double INF = 1e100;\n\nstruct Field {\n    int id;\n    vector<pair<int, int>> shape;\n    int h, w;\n    vector<pair<int, int>> valid_positions;\n};\n\nint N, M;\ndouble epsilon;\nvector<Field> fields;\nvector<double> probs;\nvector<vector<int>> drill_results;\nvector<double> row_obs;\nvector<double> col_obs;\n\ninline int idx(int k, int r, int c) {\n    return k * N * N + r * N + c;\n}\n\n// Precompute which positions cover which cells\nvector<vector<vector<vector<pair<int, int>>>>> cover_map;\n\nvoid build_cover_map() {\n    cover_map.assign(M, vector<vector<vector<pair<int, int>>>>(N, vector<vector<pair<int, int>>>(N)));\n    for (int k = 0; k < M; ++k) {\n        for (auto [r, c] : fields[k].valid_positions) {\n            for (auto [si, sj] : fields[k].shape) {\n                int i = r + si;\n                int j = c + sj;\n                if (i >= 0 && i < N && j >= 0 && j < N) {\n                    cover_map[k][i][j].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\nvoid init_probs() {\n    probs.assign(M * N * N, 0.0);\n    for (int k = 0; k < M; ++k) {\n        double count = (double)fields[k].valid_positions.size();\n        if (count < EPS) count = 1.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] = 1.0 / count;\n        }\n    }\n}\n\ndouble get_marginal(int k, int i, int j) {\n    double p = 0.0;\n    for (auto [r, c] : cover_map[k][i][j]) {\n        p += probs[idx(k, r, c)];\n    }\n    return min(1.0, max(0.0, p));\n}\n\n// Update based on drill result at (i, j) with value V\nvoid update_drill(int i, int j, int V) {\n    vector<double> q(M);\n    for (int k = 0; k < M; ++k) {\n        q[k] = get_marginal(k, i, j);\n    }\n    \n    // Compute P(S=V) and P(S=V | X_k=1), P(S=V | X_k=0) using DP\n    // First compute full distribution\n    vector<double> dp(M + 1, 0.0);\n    dp[0] = 1.0;\n    \n    for (int k = 0; k < M; ++k) {\n        for (int s = k + 1; s >= 1; --s) {\n            dp[s] = dp[s] * (1.0 - q[k]) + dp[s-1] * q[k];\n        }\n        dp[0] = dp[0] * (1.0 - q[k]);\n    }\n    \n    double prob_S_V = (V <= M) ? dp[V] : 0.0;\n    if (prob_S_V < EPS) prob_S_V = EPS;\n    \n    // Update each field\n    for (int k = 0; k < M; ++k) {\n        // Compute distribution without field k\n        vector<double> dp_without(M, 0.0);\n        dp_without[0] = 1.0;\n        \n        for (int other = 0; other < M; ++other) {\n            if (other == k) continue;\n            double p = q[other];\n            for (int s = other; s >= 1; --s) {\n                dp_without[s] = dp_without[s] * (1.0 - p) + dp_without[s-1] * p;\n            }\n            dp_without[0] = dp_without[0] * (1.0 - p);\n        }\n        \n        double prob_S_V_given_1 = (V > 0 && V - 1 < M) ? dp_without[V - 1] : 0.0;\n        double prob_S_V_given_0 = (V < M) ? dp_without[V] : 0.0;\n        \n        double num_1 = prob_S_V_given_1 * q[k];\n        double num_0 = prob_S_V_given_0 * (1.0 - q[k]);\n        double denom = num_1 + num_0;\n        \n        double new_q;\n        if (denom < EPS) {\n            new_q = q[k];\n        } else {\n            new_q = num_1 / denom;\n        }\n        new_q = min(1.0, max(0.0, new_q));\n        \n        // Update probs for field k\n        double old_q = q[k];\n        if (abs(old_q - new_q) < EPS) continue;\n        \n        double f1 = (old_q > EPS) ? (new_q / old_q) : 1.0;\n        double f0 = (old_q < 1.0 - EPS) ? ((1.0 - new_q) / (1.0 - old_q)) : 1.0;\n        \n        f1 = min(INF, max(1.0/INF, f1));\n        f0 = min(INF, max(1.0/INF, f0));\n        \n        double sum_p = 0.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            bool covers = false;\n            for (auto [si, sj] : fields[k].shape) {\n                if (r + si == i && c + sj == j) {\n                    covers = true;\n                    break;\n                }\n            }\n            \n            if (covers) {\n                probs[idx(k, r, c)] *= f1;\n            } else {\n                probs[idx(k, r, c)] *= f0;\n            }\n            probs[idx(k, r, c)] = min(INF, max(EPS, probs[idx(k, r, c)]));\n            sum_p += probs[idx(k, r, c)];\n        }\n        \n        if (sum_p < EPS) sum_p = EPS;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] /= sum_p;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> epsilon)) return 1;\n    \n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        fields[k].id = k;\n        int d;\n        cin >> d;\n        fields[k].shape.resize(d);\n        int max_i = -1, max_j = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> fields[k].shape[i].first >> fields[k].shape[i].second;\n            max_i = max(max_i, fields[k].shape[i].first);\n            max_j = max(max_j, fields[k].shape[i].second);\n        }\n        fields[k].h = max_i + 1;\n        fields[k].w = max_j + 1;\n        for (int r = 0; r <= N - fields[k].h; ++r) {\n            for (int c = 0; c <= N - fields[k].w; ++c) {\n                fields[k].valid_positions.push_back({r, c});\n            }\n        }\n    }\n    \n    build_cover_map();\n    init_probs();\n    \n    drill_results.assign(N, vector<int>(N, -1));\n    row_obs.assign(N, 0.0);\n    col_obs.assign(N, 0.0);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // 1. Query all rows\n    for (int i = 0; i < N; ++i) {\n        cout << \"q \" << N;\n        for (int j = 0; j < N; ++j) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << \"\\n\" << flush;\n        cin >> row_obs[i];\n    }\n    \n    // 2. Query all columns\n    for (int j = 0; j < N; ++j) {\n        cout << \"q \" << N;\n        for (int i = 0; i < N; ++i) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << \"\\n\" << flush;\n        cin >> col_obs[j];\n    }\n    \n    // 3. Simple belief update from row/col observations\n    // For each cell, estimate probability based on row/col sums\n    vector<vector<double>> cell_prob(N, vector<double>(N, 0.5));\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // Simple heuristic: average contribution from row and col\n            double row_avg = row_obs[i] / N;\n            double col_avg = col_obs[j] / N;\n            cell_prob[i][j] = min(1.0, max(0.0, (row_avg + col_avg) / 2.0));\n        }\n    }\n    \n    // 4. Iterative drilling with entropy-based selection\n    int ops_count = 2 * N;\n    int max_ops = 2 * N * N;\n    \n    while (ops_count < max_ops) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break;\n        \n        int best_i = -1, best_j = -1;\n        double max_entropy = -1.0;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drill_results[i][j] != -1) continue;\n                \n                // Use cell_prob as estimate\n                double p = cell_prob[i][j];\n                // Refine with marginal probabilities\n                double p_marginal = 0.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal(k, i, j);\n                    p_marginal = 1.0 - (1.0 - p_marginal) * (1.0 - q);\n                }\n                p = (p + p_marginal) / 2.0;\n                \n                if (p < EPS) p = EPS;\n                if (p > 1.0 - EPS) p = 1.0 - EPS;\n                \n                double H = -p * log2(p) - (1.0 - p) * log2(1.0 - p);\n                if (H > max_entropy) {\n                    max_entropy = H;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1 || max_entropy < 0.1) break;\n        \n        cout << \"q 1 \" << best_i << \" \" << best_j << \"\\n\" << flush;\n        int val;\n        cin >> val;\n        drill_results[best_i][best_j] = val;\n        ops_count++;\n        \n        // Update cell probabilities based on drill\n        if (val > 0) {\n            cell_prob[best_i][best_j] = 1.0;\n            // Boost nearby cells\n            for (int di = -2; di <= 2; ++di) {\n                for (int dj = -2; dj <= 2; ++dj) {\n                    int ni = best_i + di;\n                    int nj = best_j + dj;\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (drill_results[ni][nj] == -1) {\n                            cell_prob[ni][nj] = min(1.0, cell_prob[ni][nj] + 0.1);\n                        }\n                    }\n                }\n            }\n        } else {\n            cell_prob[best_i][best_j] = 0.0;\n        }\n        \n        // Update belief state\n        update_drill(best_i, best_j, val);\n    }\n    \n    // 5. Construct answer\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool has_oil = false;\n            if (drill_results[i][j] != -1) {\n                has_oil = (drill_results[i][j] > 0);\n            } else {\n                double p_empty = 1.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal(k, i, j);\n                    p_empty *= (1.0 - q);\n                }\n                double p_marginal = 1.0 - p_empty;\n                double p_combined = (p_marginal + cell_prob[i][j]) / 2.0;\n                has_oil = (p_combined > 0.5);\n            }\n            \n            if (has_oil) {\n                ans.push_back({i, j});\n            }\n        }\n    }\n    \n    // 6. Submit answer\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << \"\\n\" << flush;\n    \n    int resp;\n    cin >> resp;\n    \n    // If wrong, we could try again but for now just exit\n    (void)resp;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int W = 1000;\nconst double TIME_LIMIT = 2.8;\n\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const { return (long long)(r1 - r0) * (c1 - c0); }\n};\n\nstruct Node {\n    int id;\n    bool is_leaf;\n    int left = -1, right = -1;\n    int res_id = -1;\n    long long target_area = 0;\n    \n    int r0, c0, r1, c1;\n    int cut_pos = 0;\n    int cut_type = 0;\n    \n    int prev_cut_pos = 0;\n    int prev_cut_type = 0;\n};\n\nstruct Solver {\n    int D, N;\n    vector<vector<int>> A;\n    vector<Node> tree;\n    vector<Rect> prev_day_rects;\n    mt19937 rng;\n    chrono::steady_clock::time_point start_time;\n    \n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    }\n    \n    void run() {\n        start_time = chrono::steady_clock::now();\n        \n        int W_in;\n        if (!(cin >> W_in >> D >> N)) return;\n        \n        A.resize(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        prev_day_rects.resize(N);\n        \n        // Build tree\n        tree.resize(2 * N - 1);\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].id = i;\n            if (i >= N - 1) {\n                tree[i].is_leaf = true;\n                tree[i].res_id = i - (N - 1);\n            } else {\n                tree[i].is_leaf = false;\n                tree[i].left = 2 * i + 1;\n                tree[i].right = 2 * i + 2;\n                tree[i].cut_type = (i % 2);\n            }\n        }\n        \n        // Day 0\n        assign_reservations(0);\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n        output_day(0);\n        \n        // Subsequent days\n        for (int d = 1; d < D; ++d) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            solve_day(d);\n            output_day(d);\n        }\n    }\n    \n    void assign_reservations(int d) {\n        // Sort reservations by area\n        vector<pair<int, int>> requests;\n        for (int k = 0; k < N; ++k) {\n            requests.push_back({A[d][k], k});\n        }\n        sort(requests.begin(), requests.end());\n        \n        // Get current leaf areas\n        vector<pair<long long, int>> leaf_areas;\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            long long area = (long long)(tree[leaf_idx].r1 - tree[leaf_idx].r0) * \n                            (tree[leaf_idx].c1 - tree[leaf_idx].c0);\n            leaf_areas.push_back({area, leaf_idx});\n        }\n        sort(leaf_areas.begin(), leaf_areas.end());\n        \n        // Match smallest request to smallest leaf, etc.\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = leaf_areas[i].second;\n            int k = requests[i].second;\n            tree[leaf_idx].res_id = k;\n            tree[leaf_idx].target_area = A[d][k];\n        }\n    }\n    \n    void solve_day(int d) {\n        assign_reservations(d);\n        \n        // Initial layout\n        layout(0, 0, 0, W, W);\n        \n        // Calculate initial cost\n        double best_cost = calc_total_cost(d);\n        vector<Node> best_tree = tree;\n        \n        // Simulated annealing\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = TIME_LIMIT - elapsed;\n        double time_per_day = TIME_LIMIT / D;\n        \n        int max_iterations = 20000;\n        if (remaining < time_per_day * 0.5) max_iterations = 3000;\n        else if (remaining > time_per_day * 2) max_iterations = 50000;\n        \n        double temperature = 1000.0;\n        double cooling_rate = 0.9995;\n        \n        for (int iter = 0; iter < max_iterations; ++iter) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            \n            // Mutate\n            int node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n            int mutation_type = uniform_int_distribution<>(0, 3)(rng);\n            \n            // Save state\n            Node saved_node = tree[node_idx];\n            int saved_left = tree[node_idx].left;\n            int saved_right = tree[node_idx].right;\n            \n            if (mutation_type == 0) {\n                swap(tree[node_idx].left, tree[node_idx].right);\n            } else if (mutation_type == 1) {\n                tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n            } else if (mutation_type == 2) {\n                swap(tree[node_idx].left, tree[node_idx].right);\n                tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n            } else {\n                // Random cut type\n                tree[node_idx].cut_type = uniform_int_distribution<>(0, 1)(rng);\n            }\n            \n            layout(0, 0, 0, W, W);\n            double new_cost = calc_total_cost(d);\n            \n            // Simulated annealing acceptance\n            double delta = new_cost - best_cost;\n            bool accept = false;\n            if (delta < 0) {\n                accept = true;\n            } else {\n                double prob = exp(-delta / temperature);\n                if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                    accept = true;\n                }\n            }\n            \n            if (accept) {\n                if (new_cost < best_cost) {\n                    best_cost = new_cost;\n                    best_tree = tree;\n                }\n            } else {\n                // Revert\n                tree[node_idx] = saved_node;\n                tree[node_idx].left = saved_left;\n                tree[node_idx].right = saved_right;\n            }\n            \n            temperature *= cooling_rate;\n        }\n        \n        tree = best_tree;\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n    }\n    \n    void layout(int u, int r0, int c0, int r1, int c1) {\n        tree[u].r0 = r0;\n        tree[u].c0 = c0;\n        tree[u].r1 = r1;\n        tree[u].c1 = c1;\n        \n        if (tree[u].is_leaf) return;\n        \n        int left = tree[u].left;\n        int right = tree[u].right;\n        long long area_l = get_subtree_area(left);\n        long long area_r = get_subtree_area(right);\n        long long total = area_l + area_r;\n        \n        int width = c1 - c0;\n        int height = r1 - r0;\n        \n        // Force cut type based on available space\n        int actual_cut_type = tree[u].cut_type;\n        if (width <= 1) {\n            actual_cut_type = 1;\n        } else if (height <= 1) {\n            actual_cut_type = 0;\n        }\n        \n        if (actual_cut_type == 0) {\n            int min_cut = c0 + 1;\n            int max_cut = c1 - 1;\n            \n            if (min_cut > max_cut) {\n                tree[u].cut_pos = c0 + 1;\n            } else {\n                if (total == 0) {\n                    tree[u].cut_pos = (min_cut + max_cut) / 2;\n                } else {\n                    long long w_l = (width * area_l + total / 2) / total;\n                    if (w_l < 1) w_l = 1;\n                    if (w_l > width - 1) w_l = width - 1;\n                    tree[u].cut_pos = c0 + w_l;\n                    if (tree[u].cut_pos < min_cut) tree[u].cut_pos = min_cut;\n                    if (tree[u].cut_pos > max_cut) tree[u].cut_pos = max_cut;\n                }\n            }\n            \n            layout(left, r0, c0, r1, tree[u].cut_pos);\n            layout(right, r0, tree[u].cut_pos, r1, c1);\n        } else {\n            int min_cut = r0 + 1;\n            int max_cut = r1 - 1;\n            \n            if (min_cut > max_cut) {\n                tree[u].cut_pos = r0 + 1;\n            } else {\n                if (total == 0) {\n                    tree[u].cut_pos = (min_cut + max_cut) / 2;\n                } else {\n                    long long h_l = (height * area_l + total / 2) / total;\n                    if (h_l < 1) h_l = 1;\n                    if (h_l > height - 1) h_l = height - 1;\n                    tree[u].cut_pos = r0 + h_l;\n                    if (tree[u].cut_pos < min_cut) tree[u].cut_pos = min_cut;\n                    if (tree[u].cut_pos > max_cut) tree[u].cut_pos = max_cut;\n                }\n            }\n            \n            layout(left, r0, c0, tree[u].cut_pos, c1);\n            layout(right, tree[u].cut_pos, c0, r1, c1);\n        }\n    }\n    \n    long long get_subtree_area(int u) {\n        if (tree[u].is_leaf) return tree[u].target_area;\n        return get_subtree_area(tree[u].left) + get_subtree_area(tree[u].right);\n    }\n    \n    double calc_total_cost(int d) {\n        double cost = 0;\n        \n        // Area penalty (100x shortfall)\n        for (int i = N - 1; i < 2 * N - 1; ++i) {\n            long long actual_area = (long long)(tree[i].r1 - tree[i].r0) * (tree[i].c1 - tree[i].c0);\n            if (actual_area < tree[i].target_area) {\n                cost += 100.0 * (tree[i].target_area - actual_area);\n            }\n        }\n        \n        // Partition movement cost\n        for (int i = 0; i < N - 1; ++i) {\n            if (tree[i].cut_type != tree[i].prev_cut_type) {\n                int span_old = (tree[i].prev_cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                int span_new = (tree[i].cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                cost += span_old + span_new;\n            } else {\n                int pos_diff = abs(tree[i].cut_pos - tree[i].prev_cut_pos);\n                int span = (tree[i].cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                cost += 2.0 * pos_diff * span;\n            }\n        }\n        \n        return cost;\n    }\n    \n    void update_prev_info() {\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].prev_cut_pos = tree[i].cut_pos;\n            tree[i].prev_cut_type = tree[i].cut_type;\n        }\n        \n        // Store rects for next day\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            prev_day_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, \n                                tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n    }\n    \n    void output_day(int d) {\n        vector<Rect> current_rects(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            current_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, \n                               tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n        \n        for (int k = 0; k < N; ++k) {\n            cout << current_rects[k].r0 << \" \" << current_rects[k].c0 << \" \" \n                 << current_rects[k].r1 << \" \" << current_rects[k].c1 << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver solver;\n    solver.run();\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long MOD = 998244353;\n\nstruct Operation {\n    int m, p, q;\n};\n\nint N, M, K;\nvector<vector<long long>> a;\nvector<vector<vector<long long>>> s;\n\n// Safe modulo that handles negative numbers\ninline long long safeMod(long long x) {\n    return ((x % MOD) + MOD) % MOD;\n}\n\n// Calculate score from board\nlong long calculateScore(const vector<vector<long long>>& board) {\n    long long score = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            score += safeMod(board[i][j]);\n        }\n    }\n    return score;\n}\n\n// Apply all operations to get final board\nvector<vector<long long>> applyAllOperations(const vector<Operation>& ops) {\n    vector<vector<long long>> board = a;\n    for (const auto& op : ops) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                board[op.p + i][op.q + j] += s[op.m][i][j];\n            }\n        }\n    }\n    return board;\n}\n\n// Greedy initialization\nvector<Operation> greedyInit(mt19937& rng) {\n    vector<Operation> ops;\n    ops.reserve(K);\n    vector<vector<long long>> board = a;\n    \n    for (int op = 0; op < K; op++) {\n        long long best_delta = LLONG_MIN;\n        int best_m = 0, best_p = 0, best_q = 0;\n        \n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    long long delta = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            long long old_mod = safeMod(board[p + i][q + j]);\n                            long long new_mod = safeMod(board[p + i][q + j] + s[m][i][j]);\n                            delta += new_mod - old_mod;\n                        }\n                    }\n                    \n                    if (delta > best_delta) {\n                        best_delta = delta;\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n        \n        ops.push_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] += s[best_m][i][j];\n            }\n        }\n    }\n    \n    return ops;\n}\n\n// Try to improve by changing one operation\nbool tryImproveOne(vector<Operation>& ops, mt19937& rng, int trials) {\n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    \n    vector<vector<long long>> board = applyAllOperations(ops);\n    long long current_score = calculateScore(board);\n    \n    for (int trial = 0; trial < trials; trial++) {\n        int idx = dist_op(rng);\n        Operation old_op = ops[idx];\n        Operation new_op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n        \n        ops[idx] = new_op;\n        vector<vector<long long>> new_board = applyAllOperations(ops);\n        long long new_score = calculateScore(new_board);\n        \n        if (new_score > current_score) {\n            current_score = new_score;\n            board = new_board;\n        } else {\n            ops[idx] = old_op;\n        }\n    }\n    \n    return true;\n}\n\n// Try to improve by swapping two operations\nbool tryImproveSwap(vector<Operation>& ops, mt19937& rng, int trials) {\n    uniform_int_distribution<int> dist_op(0, K - 1);\n    \n    vector<vector<long long>> board = applyAllOperations(ops);\n    long long current_score = calculateScore(board);\n    \n    for (int trial = 0; trial < trials; trial++) {\n        int idx1 = dist_op(rng);\n        int idx2 = dist_op(rng);\n        if (idx1 == idx2) continue;\n        \n        swap(ops[idx1], ops[idx2]);\n        vector<vector<long long>> new_board = applyAllOperations(ops);\n        long long new_score = calculateScore(new_board);\n        \n        if (new_score > current_score) {\n            current_score = new_score;\n            board = new_board;\n        } else {\n            swap(ops[idx1], ops[idx2]);\n        }\n    }\n    \n    return true;\n}\n\n// Simulated annealing\nvoid simulatedAnnealing(vector<Operation>& ops, mt19937& rng, double time_limit) {\n    auto start_time = chrono::steady_clock::now();\n    \n    vector<vector<long long>> board = applyAllOperations(ops);\n    long long current_score = calculateScore(board);\n    long long best_score = current_score;\n    vector<Operation> best_ops = ops;\n    \n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double temperature = 100000.0;\n    double cooling_rate = 0.9998;\n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        int idx = dist_op(rng);\n        Operation old_op = ops[idx];\n        Operation new_op = old_op;\n        \n        int change_type = dist_op(rng) % 3;\n        if (change_type == 0) {\n            new_op.m = dist_m(rng);\n        } else if (change_type == 1) {\n            new_op.p = dist_p(rng);\n        } else {\n            new_op.q = dist_q(rng);\n        }\n        \n        ops[idx] = new_op;\n        vector<vector<long long>> new_board = applyAllOperations(ops);\n        long long new_score = calculateScore(new_board);\n        \n        double delta = (double)(new_score - current_score);\n        double accept_prob = exp(delta / temperature);\n        \n        if (delta > 0 || dist_real(rng) < accept_prob) {\n            current_score = new_score;\n            board = new_board;\n            \n            if (new_score > best_score) {\n                best_score = new_score;\n                best_ops = ops;\n            }\n        } else {\n            ops[idx] = old_op;\n        }\n        \n        temperature *= cooling_rate;\n        iterations++;\n        \n        if (iterations % 10000 == 0 && temperature < 1.0) break;\n    }\n    \n    ops = best_ops;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    a.assign(N, vector<long long>(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    s.assign(M, vector<vector<long long>>(3, vector<long long>(3)));\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> s[m][i][j];\n            }\n        }\n    }\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_budget = 1.9;\n    \n    vector<Operation> global_best_ops;\n    long long global_best_score = -1;\n    \n    // Multiple restarts with different seeds\n    int num_restarts = 8;\n    for (int restart = 0; restart < num_restarts; restart++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_budget * 0.95) break;\n        \n        double remaining = time_budget - elapsed;\n        double time_per_restart = remaining / max(1, num_restarts - restart);\n        \n        mt19937 rng(restart * 12345 + 67890);\n        \n        // Greedy initialization\n        vector<Operation> ops = greedyInit(rng);\n        \n        // Local improvement\n        tryImproveOne(ops, rng, 200);\n        tryImproveSwap(ops, rng, 100);\n        tryImproveOne(ops, rng, 200);\n        \n        // Simulated annealing with remaining time\n        double sa_time = min(0.15, time_per_restart * 0.5);\n        simulatedAnnealing(ops, rng, sa_time);\n        \n        // Evaluate\n        vector<vector<long long>> board = applyAllOperations(ops);\n        long long score = calculateScore(board);\n        \n        if (score > global_best_score) {\n            global_best_score = score;\n            global_best_ops = ops;\n        }\n    }\n    \n    // Output\n    cout << global_best_ops.size() << \"\\n\";\n    for (const auto& op : global_best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct State {\n    int container[N][N]; // -1 if empty, otherwise container number\n    int crane_row[5];    // current row of each crane\n    int crane_col[5];    // current col of each crane\n    int crane_holding[5]; // -1 if not holding, otherwise container number\n    int next_receive[5]; // next container index to receive at each gate\n    vector<int> dispatched[5]; // containers dispatched from each gate\n};\n\nint get_target_row(int container_num) {\n    return container_num / N;\n}\n\nint get_target_col(int container_num) {\n    return N - 1;\n}\n\nbool can_move_small(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return false;\n    return state.container[row][col] == -1;\n}\n\nbool can_move_large(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return true;\n    return true; // Large crane can move over containers\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\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    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            state.container[i][j] = -1;\n        }\n        state.crane_row[i] = i;\n        state.crane_col[i] = 0;\n        state.crane_holding[i] = -1;\n        state.next_receive[i] = 0;\n        state.dispatched[i].clear();\n    }\n    \n    // Output strings for each crane\n    vector<string> actions(N, \"\");\n    \n    // Track which containers need to be dispatched from each gate\n    vector<vector<int>> target_containers(N);\n    for (int c = 0; c < N * N; c++) {\n        target_containers[c / N].push_back(c);\n    }\n    \n    // Simple greedy strategy: move containers from left to right\n    // Large crane (0) handles row 0, small cranes handle their rows\n    // Use columns 1-3 as buffer\n    \n    int turn = 0;\n    int total_dispatched = 0;\n    \n    while (turn < MAX_TURNS && total_dispatched < N * N) {\n        string turn_actions(N, '.');\n        bool any_action = false;\n        \n        // Step 1: Receive containers (simulated - happens automatically)\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && \n                state.container[i][0] == -1 && \n                state.crane_holding[0] == -1) { // Check if crane 0 not blocking\n                // Container arrives at gate\n                // This happens automatically in the simulation\n            }\n        }\n        \n        // Step 2: Plan crane actions\n        for (int c = 0; c < N; c++) {\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            int holding = state.crane_holding[c];\n            \n            char action = '.';\n            \n            if (holding == -1) {\n                // Not holding - try to pick up a container\n                if (state.container[r][col] != -1) {\n                    // Pick up container\n                    action = 'P';\n                    any_action = true;\n                } else {\n                    // Move towards containers or dispatch gates\n                    bool is_large = (c == 0);\n                    \n                    // Priority: go to left side to pick up, then right to dispatch\n                    int target_col = 0;\n                    int target_row = r;\n                    \n                    // Look for containers to pick up\n                    bool found_container = false;\n                    for (int j = 0; j < N && !found_container; j++) {\n                        for (int i = 0; i < N && !found_container; i++) {\n                            if (state.container[i][j] != -1) {\n                                int container = state.container[i][j];\n                                int target_r = get_target_row(container);\n                                if (c == target_r || (c == 0 && target_r == 0)) {\n                                    target_row = i;\n                                    target_col = j;\n                                    found_container = true;\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (!found_container) {\n                        // Go to left side to wait for new containers\n                        target_col = 0;\n                    }\n                    \n                    // Move towards target\n                    if (col < target_col) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_col) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_row) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_row) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            } else {\n                // Holding a container - try to dispatch it\n                int target_r = get_target_row(holding);\n                int target_c = get_target_col(holding);\n                \n                if (r == target_r && col == target_c) {\n                    // At dispatch gate - release\n                    action = 'Q';\n                    any_action = true;\n                } else {\n                    // Move towards dispatch gate\n                    bool is_large = (c == 0);\n                    \n                    if (col < target_c) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_c) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_r) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_r) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            }\n            \n            turn_actions[c] = action;\n        }\n        \n        // If no actions, break to avoid infinite loop\n        if (!any_action && total_dispatched < N * N) {\n            // Try to do something - at least move cranes\n            for (int c = 0; c < N; c++) {\n                if (state.crane_col[c] < N - 1) {\n                    turn_actions[c] = 'R';\n                }\n            }\n        }\n        \n        // Apply actions (simplified simulation)\n        for (int c = 0; c < N; c++) {\n            char action = turn_actions[c];\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            \n            if (action == 'P' && state.crane_holding[c] == -1 && state.container[r][col] != -1) {\n                state.crane_holding[c] = state.container[r][col];\n                state.container[r][col] = -1;\n            } else if (action == 'Q' && state.crane_holding[c] != -1 && state.container[r][col] == -1) {\n                state.container[r][col] = state.crane_holding[c];\n                state.crane_holding[c] = -1;\n            } else if (action == 'R' && col < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col + 1] == -1) {\n                    state.crane_col[c]++;\n                }\n            } else if (action == 'L' && col > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col - 1] == -1) {\n                    state.crane_col[c]--;\n                }\n            } else if (action == 'D' && r < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r + 1][col] == -1) {\n                    state.crane_row[c]++;\n                }\n            } else if (action == 'U' && r > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r - 1][col] == -1) {\n                    state.crane_row[c]--;\n                }\n            }\n        }\n        \n        // Step 3: Dispatch containers at right edge\n        for (int i = 0; i < N; i++) {\n            if (state.container[i][N - 1] != -1) {\n                int container = state.container[i][N - 1];\n                state.dispatched[i].push_back(container);\n                state.container[i][N - 1] = -1;\n                total_dispatched++;\n            }\n        }\n        \n        // Simulate container arrival at left edge\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && state.container[i][0] == -1) {\n                // Check if any crane is holding at this position\n                bool crane_blocking = false;\n                for (int c = 0; c < N; c++) {\n                    if (state.crane_row[c] == i && state.crane_col[c] == 0 && state.crane_holding[c] != -1) {\n                        crane_blocking = true;\n                        break;\n                    }\n                }\n                if (!crane_blocking) {\n                    state.container[i][0] = A[i][state.next_receive[i]];\n                    state.next_receive[i]++;\n                }\n            }\n        }\n        \n        // Record actions\n        for (int c = 0; c < N; c++) {\n            actions[c] += turn_actions[c];\n        }\n        \n        turn++;\n        \n        // Safety break\n        if (turn >= 5000) break;\n    }\n    \n    // Pad all strings to same length\n    size_t max_len = 0;\n    for (int i = 0; i < N; i++) {\n        max_len = max(max_len, actions[i].size());\n    }\n    for (int i = 0; i < N; i++) {\n        while (actions[i].size() < max_len) {\n            actions[i] += '.';\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << actions[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Structure to represent a cell with non-zero height\nstruct Cell {\n    int r, c;\n    int h;\n    int id;\n};\n\nint N;\nvector<vector<int>> H;\nvector<string> ops;\nint curr_r, curr_c;\nlong long current_load;\n\n// Helper to record an operation\nvoid add_op(const string& s) {\n    ops.push_back(s);\n}\n\n// Helper to move the truck to a target coordinate and record moves\nvoid move_to(int tr, int tc) {\n    while (curr_r < tr) {\n        add_op(\"D\");\n        curr_r++;\n    }\n    while (curr_r > tr) {\n        add_op(\"U\");\n        curr_r--;\n    }\n    while (curr_c < tc) {\n        add_op(\"R\");\n        curr_c++;\n    }\n    while (curr_c > tc) {\n        add_op(\"L\");\n        curr_c--;\n    }\n}\n\n// Manhattan distance\nint dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    H.assign(N, vector<int>(N));\n    vector<Cell> sources;\n    vector<Cell> sinks;\n\n    // Read input and classify cells into sources (h > 0) and sinks (h < 0)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n            if (H[i][j] > 0) {\n                sources.push_back({i, j, H[i][j], i * N + j});\n            } else if (H[i][j] < 0) {\n                sinks.push_back({i, j, H[i][j], i * N + j});\n            }\n        }\n    }\n\n    curr_r = 0;\n    curr_c = 0;\n    current_load = 0;\n\n    // Continue until all sources are processed and truck is empty\n    while (!sources.empty() || current_load > 0) {\n        if (current_load == 0) {\n            // Truck is empty, need to pick up soil from a source.\n            // Heuristic: Select source u that minimizes:\n            // 100 * dist(curr, u) + (100 + h[u]) * dist(u, nearest_sink_to_u)\n            // This accounts for the empty travel to the source and the first loaded leg.\n            \n            int best_idx = -1;\n            long long best_score = -1;\n\n            for (int i = 0; i < (int)sources.size(); ++i) {\n                // Find nearest sink for this source\n                int min_d_sink = 1e9;\n                for (const auto& s : sinks) {\n                    int d = dist(sources[i].r, sources[i].c, s.r, s.c);\n                    if (d < min_d_sink) {\n                        min_d_sink = d;\n                    }\n                }\n                \n                int d1 = dist(curr_r, curr_c, sources[i].r, sources[i].c);\n                // Cost estimate: Empty travel + Loaded travel to first sink\n                // We use sources[i].h because we plan to load all soil from this source\n                long long score = 100LL * d1 + (100LL + sources[i].h) * min_d_sink;\n                \n                if (best_idx == -1 || score < best_score) {\n                    best_score = score;\n                    best_idx = i;\n                }\n            }\n\n            // Pick the best source\n            Cell u = sources[best_idx];\n            // Remove from sources list efficiently\n            sources[best_idx] = sources.back();\n            sources.pop_back();\n\n            // Move to source and load all soil\n            move_to(u.r, u.c);\n            long long amount = u.h;\n            add_op(\"+\" + to_string(amount));\n            current_load += amount;\n            H[u.r][u.c] = 0;\n        }\n\n        if (current_load > 0) {\n            // Truck has soil, need to deliver to a sink.\n            // Heuristic: Go to the nearest sink to minimize loaded travel cost.\n            int best_idx = -1;\n            int min_d = 1e9;\n\n            for (int i = 0; i < (int)sinks.size(); ++i) {\n                int d = dist(curr_r, curr_c, sinks[i].r, sinks[i].c);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n\n            // Safety check, though sinks should not be empty if load > 0\n            if (best_idx == -1) break; \n\n            Cell v = sinks[best_idx];\n            \n            // Move to sink and unload as much as possible\n            move_to(v.r, v.c);\n            // Use H to get current demand, as sinks list stores initial h\n            long long amount = min(current_load, (long long)-H[v.r][v.c]);\n            add_op(\"-\" + to_string(amount));\n            current_load -= amount;\n            H[v.r][v.c] += amount;\n            \n            // If sink is satisfied (height becomes 0), remove from list\n            if (H[v.r][v.c] == 0) {\n                sinks[best_idx] = sinks.back();\n                sinks.pop_back();\n            }\n        }\n    }\n\n    // Output all operations\n    for (const auto& op : ops) {\n        cout << op << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    ios_base::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));\n    vector<int> values(seed_count, 0);\n    \n    // Read initial seeds\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n            values[i] += X[i][j];\n        }\n    }\n    \n    // Track maximum value for each criterion across all seeds\n    vector<int> max_per_criterion(M, 0);\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            max_per_criterion[j] = max(max_per_criterion[j], X[i][j]);\n        }\n    }\n    \n    // Calculate sum of maximums for scoring\n    int sum_max = 0;\n    for (int j = 0; j < M; j++) {\n        sum_max += max_per_criterion[j];\n    }\n    \n    // Calculate neighbor count for each position\n    vector<vector<int>> neighbor_count(N, vector<int>(N, 0));\n    int di[] = {-1, 1, 0, 0};\n    int dj[] = {0, 0, -1, 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 ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    neighbor_count[i][j]++;\n                }\n            }\n        }\n    }\n    \n    // Create position list sorted by neighbor count (descending)\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    // Sort positions by neighbor count, then by distance from center\n    sort(positions.begin(), positions.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        if (neighbor_count[a.first][a.second] != neighbor_count[b.first][b.second]) {\n            return neighbor_count[a.first][a.second] > neighbor_count[b.first][b.second];\n        }\n        int dist_a = abs(a.first - (N-1)/2) + abs(a.second - (N-1)/2);\n        int dist_b = abs(b.first - (N-1)/2) + abs(b.second - (N-1)/2);\n        return dist_a < dist_b;\n    });\n    \n    for (int t = 0; t < T; t++) {\n        // Calculate enhanced score for each seed\n        // Score = total_value + bonus for criterion coverage\n        vector<long long> seed_score(seed_count, 0);\n        for (int i = 0; i < seed_count; i++) {\n            // Base score is total value (weighted heavily)\n            seed_score[i] = (long long)values[i] * 1000;\n            \n            // Bonus for having high values relative to criterion maximums\n            for (int j = 0; j < M; j++) {\n                if (max_per_criterion[j] > 0) {\n                    // Quadratic bonus for high criterion values\n                    long long ratio = (long long)X[i][j] * 1000 / max_per_criterion[j];\n                    seed_score[i] += ratio * ratio / 100;\n                }\n            }\n            \n            // Bonus for having many criteria above threshold\n            int high_criteria = 0;\n            for (int j = 0; j < M; j++) {\n                if (max_per_criterion[j] > 0 && X[i][j] >= max_per_criterion[j] * 0.7) {\n                    high_criteria++;\n                }\n            }\n            seed_score[i] += high_criteria * 5000;\n        }\n        \n        // Create indices sorted by enhanced score\n        vector<int> indices(seed_count);\n        iota(indices.begin(), indices.end(), 0);\n        \n        // Sort by enhanced score descending (deterministic)\n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            if (seed_score[a] != seed_score[b]) {\n                return seed_score[a] > seed_score[b];\n            }\n            if (values[a] != values[b]) {\n                return values[a] > values[b];\n            }\n            return a < b; // Tie-break by index for determinism\n        });\n        \n        // Assign seeds to positions\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        vector<bool> seed_used(seed_count, false);\n        \n        // Place top seeds in order of position priority\n        int seed_idx = 0;\n        for (const auto& pos : positions) {\n            int i = pos.first;\n            int j = pos.second;\n            \n            // Find best unused seed\n            while (seed_idx < seed_count && seed_used[indices[seed_idx]]) {\n                seed_idx++;\n            }\n            \n            if (seed_idx < seed_count) {\n                A[i][j] = indices[seed_idx];\n                seed_used[indices[seed_idx]] = true;\n                seed_idx++;\n            }\n        }\n        \n        // Output the placement\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 and update max per criterion\n        for (int i = 0; i < seed_count; i++) {\n            values[i] = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                values[i] += X[i][j];\n                max_per_criterion[j] = max(max_per_criterion[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 <cmath>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\n// Get finger position given root position and direction\n// dir: 0=R, 1=U, 2=L, 3=D\nPoint getFingerPos(int root_r, int root_c, int dir, int length = 1) {\n    int dr[] = {0, -1, 0, 1};\n    int dc[] = {1, 0, -1, 0};\n    return {root_r + dr[dir] * length, root_c + dc[dir] * length};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M_in, V;\n    if (!(cin >> N >> M_in >> V)) return 0;\n\n    vector<string> S_grid(N), T_grid(N);\n    vector<Point> starts, targets;\n\n    for (int i = 0; i < N; ++i) cin >> S_grid[i];\n    for (int i = 0; i < N; ++i) cin >> T_grid[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (S_grid[i][j] == '1') starts.push_back({i, j});\n            if (T_grid[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n\n    // Output Arm Design: Star Graph with V vertices, edge length 1\n    int V_prime = V;\n    cout << V_prime << \"\\n\";\n    for (int i = 1; i < V_prime; ++i) {\n        cout << 0 << \" \" << 1 << \"\\n\";\n    }\n    // Root starts at (0, 0), all fingers initially point right (direction 0)\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // Track grid state internally - this MUST match judge's state\n    vector<vector<int>> has_takoyaki(N, vector<int>(N, 0));\n    vector<vector<int>> is_target(N, vector<int>(N, 0));\n    \n    for (auto& p : starts) has_takoyaki[p.r][p.c] = 1;\n    for (auto& p : targets) is_target[p.r][p.c] = 1;\n\n    // Count takoyaki already at targets (don't need to move these)\n    int already_done = 0;\n    for (auto& p : starts) {\n        if (is_target[p.r][p.c]) already_done++;\n    }\n\n    int M = starts.size() - already_done;\n    \n    if (M == 0) {\n        return 0;\n    }\n\n    // Simulation State\n    int cur_r = 0, cur_c = 0;\n    vector<int> holding(V_prime, 0); // 0 = not holding, 1 = holding\n    vector<int> finger_dir(V_prime, 0); // 0:R, 1:U, 2:L, 3:D (all start pointing right)\n\n    int total_turns = 0;\n    const int MAX_TURNS = 100000;\n    int takoyaki_moved = 0;\n\n    // Direction vectors: 0=R, 1=U, 2=L, 3=D\n    int dr[] = {0, -1, 0, 1};\n    int dc[] = {1, 0, -1, 0};\n    char moveChar[] = {'R', 'U', 'L', 'D'};\n\n    while (takoyaki_moved < M && total_turns < MAX_TURNS - 500) {\n        // Find a takoyaki that needs to be moved (has takoyaki but not at target)\n        Point pickup_pos = {-1, -1};\n        \n        for (int r = 0; r < N && pickup_pos.r == -1; ++r) {\n            for (int c = 0; c < N && pickup_pos.r == -1; ++c) {\n                if (has_takoyaki[r][c] == 1 && is_target[r][c] == 0) {\n                    pickup_pos = {r, c};\n                }\n            }\n        }\n        \n        if (pickup_pos.r == -1) break;\n        \n        // Find nearest empty target\n        Point drop_pos = {-1, -1};\n        int best_dist = 1e9;\n        for (int tr = 0; tr < N; ++tr) {\n            for (int tc = 0; tc < N; ++tc) {\n                if (is_target[tr][tc] == 1 && has_takoyaki[tr][tc] == 0) {\n                    int d = dist(pickup_pos, {tr, tc});\n                    if (d < best_dist) {\n                        best_dist = d;\n                        drop_pos = {tr, tc};\n                    }\n                }\n            }\n        }\n        \n        if (drop_pos.r == -1) break;\n        \n        // Find a free finger\n        int finger = -1;\n        for(int u = 1; u < V_prime; ++u) {\n            if(holding[u] == 0) {\n                finger = u;\n                break;\n            }\n        }\n        \n        if (finger == -1) break;\n        \n        // Calculate which direction the finger needs to point to reach pickup_pos from root\n        // We need: root + direction_vector = pickup_pos\n        // So: direction_vector = pickup_pos - root\n        int target_dir = -1;\n        for (int d = 0; d < 4; ++d) {\n            Point fp = getFingerPos(cur_r, cur_c, d, 1);\n            if (fp.r == pickup_pos.r && fp.c == pickup_pos.c) {\n                target_dir = d;\n                break;\n            }\n        }\n        \n        // If we can't reach pickup_pos from current root position, move root\n        if (target_dir == -1) {\n            // Find best root position adjacent to pickup_pos\n            int best_nr = -1, best_nc = -1;\n            int min_move_dist = 1e9;\n            \n            for(int d = 0; d < 4; ++d) {\n                int nr = pickup_pos.r - dr[d];\n                int nc = pickup_pos.c - dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d_move = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d_move < min_move_dist) {\n                        min_move_dist = d_move;\n                        best_nr = nr;\n                        best_nc = nc;\n                        target_dir = d;\n                    }\n                }\n            }\n            \n            if (best_nr == -1) break;\n            \n            // Move root to best position\n            while ((cur_r != best_nr || cur_c != best_nc) && total_turns < MAX_TURNS - 100) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                cout << cmd << \"\\n\";\n                total_turns++;\n            }\n        }\n        \n        // Rotate finger to target direction\n        while (finger_dir[finger] != target_dir && total_turns < MAX_TURNS - 100) {\n            string rot_cmd(2 * V_prime, '.');\n            int diff = (target_dir - finger_dir[finger] + 4) % 4;\n            if (diff == 1) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            } else if (diff == 3) {\n                rot_cmd[finger] = 'R';\n                finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n            } else if (diff == 2) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            }\n            cout << rot_cmd << \"\\n\";\n            total_turns++;\n        }\n        \n        // CRITICAL: Verify takoyaki exists at finger position BEFORE pickup\n        Point finger_pos = getFingerPos(cur_r, cur_c, finger_dir[finger], 1);\n        if (finger_pos.r >= 0 && finger_pos.r < N && finger_pos.c >= 0 && finger_pos.c < N &&\n            has_takoyaki[finger_pos.r][finger_pos.c] == 1) {\n            \n            // Grab\n            if (total_turns < MAX_TURNS - 100) {\n                string grab_cmd(2 * V_prime, '.');\n                grab_cmd[V_prime + finger] = 'P';\n                cout << grab_cmd << \"\\n\";\n                total_turns++;\n                holding[finger] = 1;\n                has_takoyaki[finger_pos.r][finger_pos.c] = 0;\n            }\n        }\n        \n        if (holding[finger] == 0) continue; // Failed to pick up\n        \n        // Now move to drop position\n        target_dir = -1;\n        for (int d = 0; d < 4; ++d) {\n            Point fp = getFingerPos(cur_r, cur_c, d, 1);\n            if (fp.r == drop_pos.r && fp.c == drop_pos.c) {\n                target_dir = d;\n                break;\n            }\n        }\n        \n        if (target_dir == -1) {\n            int best_nr = -1, best_nc = -1;\n            int min_move_dist = 1e9;\n            \n            for(int d = 0; d < 4; ++d) {\n                int nr = drop_pos.r - dr[d];\n                int nc = drop_pos.c - dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d_move = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d_move < min_move_dist) {\n                        min_move_dist = d_move;\n                        best_nr = nr;\n                        best_nc = nc;\n                        target_dir = d;\n                    }\n                }\n            }\n            \n            if (best_nr == -1) {\n                holding[finger] = 0;\n                continue;\n            }\n            \n            while ((cur_r != best_nr || cur_c != best_nc) && total_turns < MAX_TURNS - 100) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                cout << cmd << \"\\n\";\n                total_turns++;\n            }\n        }\n        \n        // Rotate finger to drop direction\n        while (finger_dir[finger] != target_dir && total_turns < MAX_TURNS - 100) {\n            string rot_cmd(2 * V_prime, '.');\n            int diff = (target_dir - finger_dir[finger] + 4) % 4;\n            if (diff == 1) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            } else if (diff == 3) {\n                rot_cmd[finger] = 'R';\n                finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n            } else if (diff == 2) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            }\n            cout << rot_cmd << \"\\n\";\n            total_turns++;\n        }\n        \n        // Drop\n        if (holding[finger] == 1 && total_turns < MAX_TURNS - 100) {\n            string drop_cmd(2 * V_prime, '.');\n            drop_cmd[V_prime + finger] = 'P';\n            cout << drop_cmd << \"\\n\";\n            total_turns++;\n            holding[finger] = 0;\n            has_takoyaki[drop_pos.r][drop_pos.c] = 1;\n            takoyaki_moved++;\n        }\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n};\n\nstruct Fish {\n    int x, y;\n    int type;\n};\n\nint N;\nvector<Fish> fish;\n\nint G_SIZE;\nint CELL_SIZE;\nvector<vector<int>> grid_score;\nvector<vector<bool>> selected;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\n\nvoid read_input() {\n    cin >> N;\n    fish.resize(2 * N);\n    for (int i = 0; i < 2 * N; ++i) {\n        cin >> fish[i].x >> fish[i].y;\n        fish[i].type = (i < N) ? 0 : 1;\n    }\n}\n\nvoid build_grid(int G) {\n    G_SIZE = G;\n    CELL_SIZE = 100000 / G;\n    grid_score.assign(G, vector<int>(G, 0));\n    selected.assign(G, vector<bool>(G, false));\n\n    for (const auto& f : fish) {\n        int gx = min(f.x / CELL_SIZE, G - 1);\n        int gy = min(f.y / CELL_SIZE, G - 1);\n        if (f.type == 0) grid_score[gx][gy]++;\n        else grid_score[gx][gy]--;\n    }\n}\n\nvoid flood_fill_selected(int start_x, int start_y) {\n    queue<pair<int, int>> q;\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    q.push({start_x, start_y});\n    visited[start_x][start_y] = true;\n    \n    vector<vector<bool>> new_selected(G_SIZE, vector<bool>(G_SIZE, false));\n    new_selected[start_x][start_y] = true;\n    \n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                if (!visited[nx][ny] && selected[nx][ny]) {\n                    visited[nx][ny] = true;\n                    new_selected[nx][ny] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n    \n    selected = new_selected;\n}\n\nvoid ensure_connected() {\n    // Find all selected cells\n    vector<pair<int, int>> selected_cells;\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (selected[i][j]) {\n                selected_cells.push_back({i, j});\n            }\n        }\n    }\n    \n    if (selected_cells.empty()) return;\n    \n    // Find the largest connected component\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    vector<vector<pair<int, int>>> components;\n    \n    for (auto [sx, sy] : selected_cells) {\n        if (visited[sx][sy]) continue;\n        \n        vector<pair<int, int>> comp;\n        queue<pair<int, int>> q;\n        q.push({sx, sy});\n        visited[sx][sy] = true;\n        comp.push_back({sx, sy});\n        \n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                    if (!visited[nx][ny] && selected[nx][ny]) {\n                        visited[nx][ny] = true;\n                        comp.push_back({nx, ny});\n                        q.push({nx, ny});\n                    }\n                }\n            }\n        }\n        components.push_back(comp);\n    }\n    \n    // Keep only the largest component\n    size_t best_idx = 0;\n    for (size_t i = 1; i < components.size(); ++i) {\n        if (components[i].size() > components[best_idx].size()) {\n            best_idx = i;\n        }\n    }\n    \n    selected.assign(G_SIZE, vector<bool>(G_SIZE, false));\n    for (auto [x, y] : components[best_idx]) {\n        selected[x][y] = true;\n    }\n}\n\nvoid fill_holes() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    queue<pair<int, int>> q;\n\n    // Start BFS from all boundary cells\n    for (int i = 0; i < G_SIZE; ++i) {\n        if (!selected[i][0]) { q.push({i, 0}); visited[i][0] = true; }\n        if (!selected[i][G_SIZE - 1]) { q.push({i, G_SIZE - 1}); visited[i][G_SIZE - 1] = true; }\n        if (!selected[0][i]) { q.push({0, i}); visited[0][i] = true; }\n        if (!selected[G_SIZE - 1][i]) { q.push({G_SIZE - 1, i}); visited[G_SIZE - 1][i] = true; }\n    }\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                if (!visited[nx][ny] && !selected[nx][ny]) {\n                    visited[nx][ny] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    // Any unselected cell not visited is a hole - fill it\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (!selected[i][j] && !visited[i][j]) {\n                selected[i][j] = true;\n            }\n        }\n    }\n}\n\nvoid select_positive_cells() {\n    // Select all positive cells\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (grid_score[i][j] > 0) {\n                selected[i][j] = true;\n            }\n        }\n    }\n    \n    // Simple expansion to connect nearby regions\n    for (int iter = 0; iter < 2; ++iter) {\n        vector<vector<bool>> to_add(G_SIZE, vector<bool>(G_SIZE, false));\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (selected[i][j]) {\n                    for (int d = 0; d < 4; ++d) {\n                        int ni = i + dx[d];\n                        int nj = j + dy[d];\n                        if (ni >= 0 && ni < G_SIZE && nj >= 0 && nj < G_SIZE) {\n                            if (!selected[ni][nj] && grid_score[ni][nj] >= -1) {\n                                to_add[ni][nj] = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (to_add[i][j]) selected[i][j] = true;\n            }\n        }\n    }\n    \n    fill_holes();\n    ensure_connected();\n}\n\nvector<Point> extract_polygon() {\n    // Build edge map for boundary\n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    \n    auto add_edge = [&](pair<int, int> p1, pair<int, int> p2) {\n        adj[p1].push_back(p2);\n        adj[p2].push_back(p1);\n    };\n    \n    // Vertical edges (between columns)\n    for (int i = 0; i <= G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            bool left = (i > 0 && selected[i-1][j]);\n            bool right = (i < G_SIZE && selected[i][j]);\n            if (left != right) {\n                int x = i * CELL_SIZE;\n                int y1 = j * CELL_SIZE;\n                int y2 = (j + 1) * CELL_SIZE;\n                add_edge({x, y1}, {x, y2});\n            }\n        }\n    }\n    \n    // Horizontal edges (between rows)\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j <= G_SIZE; ++j) {\n            bool down = (j > 0 && selected[i][j-1]);\n            bool up = (j < G_SIZE && selected[i][j]);\n            if (down != up) {\n                int y = j * CELL_SIZE;\n                int x1 = i * CELL_SIZE;\n                int x2 = (i + 1) * CELL_SIZE;\n                add_edge({x1, y}, {x2, y});\n            }\n        }\n    }\n    \n    if (adj.empty()) return {};\n    \n    // Find the vertex with minimum y (then minimum x) to start\n    pair<int, int> start = {200000, 200000};\n    for (auto& [p, _] : adj) {\n        if (p.second < start.second || (p.second == start.second && p.first < start.first)) {\n            start = p;\n        }\n    }\n    \n    // Trace boundary keeping selected cells on the left\n    vector<Point> poly;\n    pair<int, int> curr = start;\n    pair<int, int> prev = {-1000000, start.second}; // Coming from left\n    \n    while (true) {\n        poly.push_back({curr.first, curr.second});\n        \n        auto& neighbors = adj[curr];\n        if (neighbors.size() != 2) {\n            // Invalid polygon structure\n            return {};\n        }\n        \n        // Choose next vertex (not the one we came from)\n        pair<int, int> next = (neighbors[0] == prev) ? neighbors[1] : neighbors[0];\n        \n        if (next == start) {\n            break;\n        }\n        \n        prev = curr;\n        curr = next;\n        \n        if (poly.size() > 2000) {\n            // Safety check for infinite loop\n            return {};\n        }\n    }\n    \n    // Remove collinear points\n    if (poly.size() <= 4) return poly;\n    \n    vector<Point> simplified;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        Point p3 = poly[(i + 2) % poly.size()];\n        \n        // Check if p1, p2, p3 are collinear\n        bool collinear = false;\n        if (p1.x == p2.x && p2.x == p3.x) collinear = true;\n        if (p1.y == p2.y && p2.y == p3.y) collinear = true;\n        \n        if (!collinear || i == 0) {\n            simplified.push_back(p2);\n        }\n    }\n    \n    if (simplified.size() < 4) return poly;\n    return simplified;\n}\n\nbool is_inside(const vector<Point>& poly, int px, int py) {\n    // Check on edge first\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x == p2.x) {\n            if (px == p1.x && py >= min(p1.y, p2.y) && py <= max(p1.y, p2.y)) return true;\n        } else {\n            if (py == p1.y && px >= min(p1.x, p2.x) && px <= max(p1.x, p2.x)) return true;\n        }\n    }\n    \n    // Ray casting\n    bool inside = false;\n    for (size_t i = 0, j = poly.size() - 1; i < poly.size(); j = i++) {\n        if ((poly[i].y > py) != (poly[j].y > py)) {\n            long long val = (long long)(poly[j].x - poly[i].x) * (long long)(py - poly[i].y);\n            long long denom = (long long)(poly[j].y - poly[i].y);\n            long long rhs = (long long)poly[i].x * denom + val;\n            if (denom > 0) {\n                if ((long long)px * denom < rhs) inside = !inside;\n            } else {\n                if ((long long)px * denom > rhs) inside = !inside;\n            }\n        }\n    }\n    return inside;\n}\n\nlong long calculate_score(const vector<Point>& poly) {\n    long long a = 0, b = 0;\n    for (const auto& f : fish) {\n        if (is_inside(poly, f.x, f.y)) {\n            if (f.type == 0) a++;\n            else b++;\n        }\n    }\n    return a - b;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    read_input();\n    \n    vector<Point> best_poly;\n    long long best_score = -1e18;\n    \n    vector<int> grids = {100, 150, 80};\n    \n    for (int G : grids) {\n        build_grid(G);\n        select_positive_cells();\n        \n        vector<Point> poly = extract_polygon();\n        if (poly.empty() || poly.size() < 4 || poly.size() > 1000) continue;\n        \n        long long perim = 0;\n        for (size_t i = 0; i < poly.size(); ++i) {\n            Point p1 = poly[i];\n            Point p2 = poly[(i + 1) % poly.size()];\n            perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n        }\n        if (perim > 400000) continue;\n        \n        long long score = calculate_score(poly);\n        if (score > best_score) {\n            best_score = score;\n            best_poly = poly;\n        }\n    }\n    \n    if (best_poly.empty()) {\n        best_poly = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <chrono>\n#include <set>\n\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n};\n\nstruct Placement {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    vector<Rectangle> rects(N);\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n    }\n    \n    auto seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937 rng(seed);\n    \n    int best_score = 2000000000;\n    vector<Placement> best_placements;\n    int best_W = 0, best_H = 0;\n    \n    // Track layout characteristics\n    vector<int> W_history, H_history;\n    int prefer_vertical = 0;  // Positive = prefer vertical shelves, Negative = horizontal\n    \n    for (int turn = 0; turn < T; turn++) {\n        vector<Placement> placements;\n        placements.reserve(N);\n        \n        double progress = (double)turn / T;\n        double temp = 1.0 - progress;\n        \n        // Adaptive strategy selection\n        int strategy;\n        if (turn < T / 10) {\n            // Very early: maximum diversity\n            strategy = turn % 15;\n        } else if (turn < T / 4) {\n            // Early: explore with some bias\n            if (rng() % 4 == 0 && !best_placements.empty()) {\n                strategy = 100;\n            } else {\n                strategy = 15 + (turn % 10);\n            }\n        } else if (turn < T * 2 / 3) {\n            // Mid: balance exploration/exploitation\n            if (rng() % 3 == 0 && !best_placements.empty()) {\n                strategy = 100;\n            } else {\n                strategy = 25 + (turn % 8);\n            }\n        } else {\n            // Late: heavy exploitation\n            if (rng() % 6 != 0 || best_placements.empty()) {\n                strategy = 100;\n            } else {\n                strategy = 33 + (turn % 5);\n            }\n        }\n        \n        // Calculate optimal shelf size based on rectangle sizes\n        int avg_w = 0, avg_h = 0;\n        for (int i = 0; i < N; i++) {\n            avg_w += min(rects[i].w_obs, rects[i].h_obs);\n            avg_h += max(rects[i].w_obs, rects[i].h_obs);\n        }\n        avg_w /= N;\n        avg_h /= N;\n        int optimal_shelf = max(3, min(8, (int)(sqrt((double)N * avg_w / avg_h))));\n        \n        if (strategy < 15) {\n            // Basic diverse strategies\n            if (strategy == 0) {\n                for (int i = 0; i < N; i++) placements.push_back({i, 0, 'U', -1});\n            } else if (strategy == 1) {\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    placements.push_back({i, rot, 'U', -1});\n                }\n            } else if (strategy == 2) {\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                    placements.push_back({i, rot, 'U', -1});\n                }\n            } else if (strategy == 3) {\n                for (int i = 0; i < N; i++) placements.push_back({i, 0, 'L', -1});\n            } else if (strategy == 4) {\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    placements.push_back({i, rot, 'L', -1});\n                }\n            } else if (strategy == 5) {\n                for (int i = 0; i < N; i++) {\n                    char dir = (i % 2 == 0) ? 'U' : 'L';\n                    placements.push_back({i, 0, dir, -1});\n                }\n            } else if (strategy >= 6 && strategy <= 9) {\n                // Shelf packing with different sizes\n                int shelf = 3 + (strategy - 6);\n                for (int i = 0; i < N; i++) {\n                    int rot = 0;\n                    char dir = 'U';\n                    int ref = -1;\n                    if (i > 0 && i % shelf == 0) {\n                        dir = 'L';\n                        ref = i - 1;\n                    } else if (i > 0) {\n                        ref = i - 1;\n                    }\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy == 10) {\n                // Rotate to minimize height variance\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    char dir = 'U';\n                    int ref = (i > 0) ? i - 1 : -1;\n                    if (i > 0 && i % optimal_shelf == 0) dir = 'L';\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy == 11) {\n                // Rotate to minimize width variance\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                    char dir = 'U';\n                    int ref = (i > 0) ? i - 1 : -1;\n                    if (i > 0 && i % optimal_shelf == 0) dir = 'L';\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy == 12) {\n                // Alternating rotation pattern\n                for (int i = 0; i < N; i++) {\n                    int rot = i % 2;\n                    char dir = 'U';\n                    int ref = (i > 0) ? i - 1 : -1;\n                    if (i > 0 && i % 5 == 0) dir = 'L';\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy == 13) {\n                // Group by size (simulate)\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].w_obs + rects[i].h_obs > (avg_w + avg_h)) ? 1 : 0;\n                    char dir = 'U';\n                    int ref = (i > 0) ? i - 1 : -1;\n                    if (i > 0 && i % 6 == 0) dir = 'L';\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else {\n                // Random with U bias\n                for (int i = 0; i < N; i++) {\n                    int rot = rng() % 2;\n                    char dir = (rng() % 5 < 4) ? 'U' : 'L';\n                    int ref = -1;\n                    if (i > 0 && rng() % 3 == 0) ref = i - 1;\n                    placements.push_back({i, rot, dir, ref});\n                }\n            }\n        } else if (strategy >= 15 && strategy < 25) {\n            // Intermediate strategies with varied parameters\n            int shelf = 3 + (strategy - 15) % 6;\n            int rot_mode = (strategy - 15) / 6;\n            \n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                if (rot_mode == 0) rot = 0;\n                else if (rot_mode == 1) rot = 1;\n                else if (rot_mode == 2) rot = i % 2;\n                else if (rot_mode == 3) rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                else rot = rng() % 2;\n                \n                char dir = 'U';\n                int ref = -1;\n                if (i > 0 && i % shelf == 0) {\n                    dir = 'L';\n                    ref = i - 1;\n                } else if (i > 0) {\n                    ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy >= 25 && strategy < 33) {\n            // Advanced patterns\n            int pat = strategy - 25;\n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                char dir = 'U';\n                int ref = -1;\n                \n                if (pat == 0) {\n                    // Uniform height shelves\n                    rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    if (i > 0 && i % 4 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 1) {\n                    // Uniform width shelves\n                    rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                    if (i > 0 && i % 4 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 2) {\n                    // Variable shelf sizes\n                    int shelf = 3 + (i / 10) % 4;\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 3) {\n                    // Zigzag pattern\n                    int row = i / 5;\n                    if (i > 0 && i % 5 == 0) {\n                        dir = (row % 2 == 0) ? 'L' : 'U';\n                        ref = i - 1;\n                    } else if (i > 0) ref = i - 1;\n                } else if (pat == 4) {\n                    // Dense packing\n                    if (i > 0 && i % 3 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 5) {\n                    // Sparse packing\n                    if (i > 0 && i % 8 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 6) {\n                    // Mixed directions\n                    dir = (i % 3 == 0) ? 'L' : 'U';\n                    if (i > 0 && dir == 'U') ref = i - 1;\n                    else if (i > 0 && dir == 'L') ref = i - 1;\n                } else {\n                    // Random advanced\n                    int shelf = 4 + rng() % 4;\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy == 100) {\n            // Mutate best solution with adaptive strategy\n            if (best_placements.empty()) {\n                for (int i = 0; i < N; i++) placements.push_back({i, 0, 'U', -1});\n            } else {\n                placements = best_placements;\n                \n                // Adaptive mutation based on history\n                int base_mut = max(1, N / 3);\n                int mutations = max(1, (int)(base_mut * temp));\n                \n                // Analyze history for bias\n                if (W_history.size() >= 3) {\n                    int recent_W = 0, recent_H = 0;\n                    for (int i = max(0, (int)W_history.size() - 3); i < (int)W_history.size(); i++) {\n                        recent_W += W_history[i];\n                        recent_H += H_history[i];\n                    }\n                    if (recent_W > recent_H * 1.2) {\n                        // Layout too wide, try more vertical packing\n                        prefer_vertical = 1;\n                    } else if (recent_H > recent_W * 1.2) {\n                        // Layout too tall, try more horizontal packing\n                        prefer_vertical = -1;\n                    }\n                }\n                \n                set<int> mutated;\n                for (int m = 0; m < mutations; m++) {\n                    int idx = rng() % N;\n                    if (mutated.count(idx)) continue;\n                    mutated.insert(idx);\n                    \n                    int change = rng() % 6;\n                    if (change == 0) {\n                        placements[idx].r = 1 - placements[idx].r;\n                    } else if (change == 1) {\n                        placements[idx].d = (placements[idx].d == 'U') ? 'L' : 'U';\n                    } else if (change == 2) {\n                        placements[idx].b = (placements[idx].b == -1 && idx > 0) ? idx - 1 : -1;\n                    } else if (change == 3) {\n                        // Bias rotation based on layout preference\n                        if (prefer_vertical > 0) {\n                            placements[idx].r = (rects[idx].h_obs > rects[idx].w_obs) ? 1 : 0;\n                        } else if (prefer_vertical < 0) {\n                            placements[idx].r = (rects[idx].w_obs > rects[idx].h_obs) ? 1 : 0;\n                        } else {\n                            placements[idx].r = rng() % 2;\n                        }\n                    } else if (change == 4) {\n                        // Swap rotation with neighbor\n                        if (idx > 0) swap(placements[idx].r, placements[idx-1].r);\n                    } else {\n                        placements[idx].r = rng() % 2;\n                        placements[idx].d = (rng() % 3 < 2) ? 'U' : 'L';\n                    }\n                }\n            }\n        } else {\n            // Fallback\n            for (int i = 0; i < N; i++) {\n                int rot = rng() % 2;\n                char dir = (rng() % 5 < 4) ? 'U' : 'L';\n                int ref = -1;\n                if (i > 0 && rng() % 4 == 0) ref = i - 1;\n                placements.push_back({i, rot, dir, ref});\n            }\n        }\n        \n        // Output\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read result\n        int W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        int score = W_prime + H_prime;\n        \n        W_history.push_back(W_prime);\n        H_history.push_back(H_prime);\n        \n        if (score < best_score) {\n            best_score = score;\n            best_placements = placements;\n            best_W = W_prime;\n            best_H = H_prime;\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n\nusing namespace std;\n\n// Global variables\nint N, M, H;\nvector<int> A;\nvector<vector<int>> adj;\nvector<int> L;\nvector<int> support_count;\nint violations = 0;\nlong long current_score = 0;\n\n// Check if v is supported\nbool is_supported(int v) {\n    if (L[v] == 0) return true;\n    return support_count[v] > 0;\n}\n\n// Count violations\nint count_violations() {\n    int cnt = 0;\n    for (int v = 0; v < N; ++v) {\n        if (!is_supported(v)) cnt++;\n    }\n    return cnt;\n}\n\n// Calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        score += (long long)(L[v] + 1) * A[v];\n    }\n    return score;\n}\n\n// Initialize with BFS from selected roots\nvoid initialize_bfs(mt19937& rng, double root_fraction = 0.1) {\n    L.assign(N, -1);\n    support_count.assign(N, 0);\n    \n    // Select roots based on A_v and degree with some randomness\n    vector<pair<double, int>> candidates;\n    for (int v = 0; v < N; ++v) {\n        double score = (double)A[v] * adj[v].size();\n        score *= (0.5 + uniform_real_distribution<double>(0, 1)(rng));\n        candidates.push_back({score, v});\n    }\n    sort(candidates.rbegin(), candidates.rend());\n    \n    int num_roots = max(1, (int)(N * root_fraction));\n    vector<int> roots;\n    for (int i = 0; i < num_roots && i < (int)candidates.size(); ++i) {\n        roots.push_back(candidates[i].second);\n    }\n    \n    // BFS from roots\n    queue<int> q;\n    for (int r : roots) {\n        L[r] = 0;\n        q.push(r);\n    }\n    \n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        \n        // Shuffle neighbors for diversity\n        vector<int> neighbors = adj[v];\n        shuffle(neighbors.begin(), neighbors.end(), rng);\n        \n        for (int u : neighbors) {\n            if (L[u] == -1 && L[v] < H) {\n                L[u] = L[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n    \n    // Handle unvisited vertices\n    for (int v = 0; v < N; ++v) {\n        if (L[v] == -1) L[v] = 0;\n    }\n    \n    // Calculate support counts\n    for (int v = 0; v < N; ++v) {\n        if (L[v] > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == L[v] - 1) {\n                    support_count[v]++;\n                }\n            }\n        }\n    }\n    \n    violations = count_violations();\n    current_score = calculate_score();\n}\n\n// Fix violations by reducing levels\nvoid fix_violations(mt19937& rng) {\n    int max_iter = N * 20;\n    for (int iter = 0; iter < max_iter && violations > 0; ++iter) {\n        vector<int> violated;\n        for (int v = 0; v < N; ++v) {\n            if (!is_supported(v)) {\n                violated.push_back(v);\n            }\n        }\n        if (violated.empty()) break;\n        \n        int v = violated[uniform_int_distribution<int>(0, violated.size() - 1)(rng)];\n        \n        if (L[v] > 0) {\n            int old_L = L[v];\n            int new_L = L[v] - 1;\n            \n            // Update neighbor support counts\n            for (int u : adj[v]) {\n                if (L[u] == old_L + 1) {\n                    support_count[u]--;\n                }\n                if (L[u] == new_L + 1) {\n                    support_count[u]++;\n                }\n            }\n            \n            // Update v's support\n            support_count[v] = 0;\n            if (new_L > 0) {\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) support_count[v]++;\n                }\n            }\n            \n            L[v] = new_L;\n            current_score -= A[v];\n        }\n    }\n    \n    violations = count_violations();\n}\n\n// Greedy improvement: push vertices higher\nvoid greedy_improve(mt19937& rng) {\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    \n    bool improved = true;\n    int max_passes = 20;\n    for (int pass = 0; pass < max_passes && improved; ++pass) {\n        improved = false;\n        \n        // Sort by A_v descending\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return A[a] > A[b];\n        });\n        \n        for (int v : order) {\n            if (L[v] < H) {\n                int new_L = L[v] + 1;\n                \n                // Check if we can support this level\n                int new_support = 0;\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) new_support++;\n                }\n                \n                if (new_support > 0) {\n                    // Check impact on neighbors at level new_L + 1\n                    bool can_move = true;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L + 1 && support_count[u] == 1) {\n                            can_move = false;\n                            break;\n                        }\n                    }\n                    \n                    if (can_move) {\n                        int old_L = L[v];\n                        \n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                support_count[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                support_count[u]++;\n                            }\n                        }\n                        \n                        support_count[v] = new_support;\n                        L[v] = new_L;\n                        current_score += A[v];\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Simulated Annealing with adaptive temperature\nvoid simulated_annealing(mt19937& rng, double time_limit) {\n    auto start_time = chrono::steady_clock::now();\n    \n    const long long PENALTY = 1000000000LL;\n    double temp = 100000.0;\n    double initial_temp = 100000.0;\n    int accepted = 0;\n    int total = 0;\n    \n    long long best_valid_score = (violations == 0) ? current_score : -1;\n    vector<int> best_L = (violations == 0) ? L : vector<int>();\n    vector<int> best_support = (violations == 0) ? support_count : vector<int>();\n    \n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = time_limit - elapsed;\n        \n        if (remaining < 0.03) break;\n        \n        // Adaptive cooling based on acceptance rate and time\n        double progress = elapsed / time_limit;\n        if (total > 100) {\n            double acceptance_rate = (double)accepted / total;\n            if (acceptance_rate > 0.5) {\n                temp *= 0.9998;  // Cool faster if accepting too much\n            } else if (acceptance_rate < 0.1) {\n                temp *= 1.0002;  // Warm up if accepting too little\n            } else {\n                temp *= 0.9999;\n            }\n        } else {\n            temp *= 0.9999;\n        }\n        \n        if (temp < 1.0) temp = 1.0;\n        if (temp > initial_temp) temp = initial_temp;\n        \n        // Select vertex with bias towards high A_v\n        int v;\n        {\n            vector<double> weights(N);\n            double sum_w = 0;\n            for (int i = 0; i < N; ++i) {\n                weights[i] = A[i] + 1;\n                sum_w += weights[i];\n            }\n            double r = uniform_real_distribution<double>(0, sum_w)(rng);\n            double cum = 0;\n            v = N - 1;\n            for (int i = 0; i < N; ++i) {\n                cum += weights[i];\n                if (r <= cum) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n        \n        // Pick delta (bias towards +1)\n        int delta = 1;\n        double up_prob = 0.75;\n        if (L[v] >= H) up_prob = 0.0;\n        if (uniform_real_distribution<double>(0, 1)(rng) > up_prob) {\n            delta = -1;\n        }\n        \n        int old_L = L[v];\n        int new_L = old_L + delta;\n        \n        if (new_L < 0 || new_L > H) {\n            iterations++;\n            total++;\n            continue;\n        }\n        if (new_L == old_L) {\n            iterations++;\n            total++;\n            continue;\n        }\n        \n        // Calculate delta_violations\n        int delta_violations = 0;\n        \n        bool v_supported_old = is_supported(v);\n        \n        int new_support_count_v = 0;\n        if (new_L > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == new_L - 1) {\n                    new_support_count_v++;\n                }\n            }\n        }\n        bool v_supported_new = (new_L == 0) || (new_support_count_v > 0);\n        \n        if (v_supported_old && !v_supported_new) delta_violations++;\n        if (!v_supported_old && v_supported_new) delta_violations--;\n        \n        vector<pair<int, int>> neighbor_changes;\n        \n        for (int u : adj[v]) {\n            int old_contrib = (L[u] == old_L + 1) ? 1 : 0;\n            int new_contrib = (L[u] == new_L + 1) ? 1 : 0;\n            int delta_sc = new_contrib - old_contrib;\n            \n            if (delta_sc != 0) {\n                bool u_supported_old = (L[u] == 0) || (support_count[u] > 0);\n                int predicted_sc = support_count[u] + delta_sc;\n                bool u_supported_new = (L[u] == 0) || (predicted_sc > 0);\n                \n                int v_delta = 0;\n                if (u_supported_old && !u_supported_new) v_delta = 1;\n                if (!u_supported_old && u_supported_new) v_delta = -1;\n                \n                if (v_delta != 0) {\n                    delta_violations += v_delta;\n                }\n                neighbor_changes.push_back({u, delta_sc});\n            }\n        }\n        \n        long long delta_score = (long long)(new_L - old_L) * A[v];\n        long long delta_cost = (long long)delta_violations * PENALTY - delta_score;\n        \n        bool accept = false;\n        if (delta_cost < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-(double)delta_cost / temp);\n            if ((double)uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            L[v] = new_L;\n            support_count[v] = new_support_count_v;\n            current_score += delta_score;\n            violations += delta_violations;\n            \n            for (auto& nc : neighbor_changes) {\n                support_count[nc.first] += nc.second;\n            }\n            \n            accepted++;\n            \n            if (violations == 0) {\n                if (current_score > best_valid_score) {\n                    best_valid_score = current_score;\n                    best_L = L;\n                    best_support = support_count;\n                }\n            }\n        }\n        \n        total++;\n        iterations++;\n        \n        if (iterations % 5000 == 0) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed >= time_limit) break;\n        }\n    }\n    \n    if (violations == 0 && current_score > best_valid_score) {\n        best_valid_score = current_score;\n        best_L = L;\n        best_support = support_count;\n    }\n    \n    if (!best_L.empty()) {\n        L = best_L;\n        support_count = best_support;\n        violations = 0;\n        current_score = best_valid_score;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> H)) return 0;\n    \n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    \n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n    \n    long long best_score = -1;\n    vector<int> best_L_final(N, 0);\n    vector<int> best_support_final(N, 0);\n    \n    auto total_start = chrono::steady_clock::now();\n    double total_time_limit = 1.9;\n    \n    // More restarts with diverse initialization\n    int num_restarts = 6;\n    double time_per_restart = total_time_limit / num_restarts;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + restart * 1000000);\n        \n        // Vary root fraction for diversity\n        double root_fraction = 0.08 + 0.04 * (restart % 3);\n        \n        initialize_bfs(rng, root_fraction);\n        fix_violations(rng);\n        simulated_annealing(rng, time_per_restart * 0.85);\n        \n        if (violations == 0) {\n            greedy_improve(rng);\n        }\n        \n        if (violations == 0 && current_score > best_score) {\n            best_score = current_score;\n            best_L_final = L;\n            best_support_final = support_count;\n        }\n        \n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - total_start).count();\n        if (elapsed >= total_time_limit) break;\n    }\n    \n    // Final greedy pass on best solution\n    if (!best_L_final.empty()) {\n        L = best_L_final;\n        support_count = best_support_final;\n        violations = 0;\n        current_score = best_score;\n        \n        mt19937 final_rng(chrono::steady_clock::now().time_since_epoch().count());\n        greedy_improve(final_rng);\n        best_L_final = L;\n    }\n    \n    // Reconstruct parents\n    vector<int> P(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (best_L_final[v] > 0) {\n            int target = best_L_final[v] - 1;\n            for (int u : adj[v]) {\n                if (best_L_final[u] == target) {\n                    P[v] = u;\n                    break;\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << P[i];\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n#include <queue>\n\nusing namespace std;\n\nconst char DIR_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char REVERSE_DIR[] = {'D', 'U', 'R', 'L'};\n\nstruct Candidate {\n    int k;\n    unsigned long long oni_mask;\n    int marginal_cost;\n    int gain;\n    double ratio;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<string> grid(N);\n    vector<pair<int, int>> onis;\n    vector<vector<bool>> is_fuku(N, vector<bool>(N, false));\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] == 'x') {\n                onis.push_back({i, j});\n            } else if (grid[i][j] == 'o') {\n                is_fuku[i][j] = true;\n            }\n        }\n    }\n\n    int num_onis = onis.size();\n    vector<vector<int>> oni_id_map(N, vector<int>(N, -1));\n    for (int i = 0; i < num_onis; ++i) {\n        oni_id_map[onis[i].first][onis[i].second] = i;\n    }\n\n    // Count how many operations can remove each Oni (difficulty score)\n    vector<int> oni_options(num_onis, 0);\n    \n    int num_lines = 4 * N;\n    vector<vector<Candidate>> line_candidates(num_lines);\n    vector<int> current_k(num_lines, 0);\n    vector<int> cand_ptr(num_lines, 0);\n\n    // Precompute candidates and count Oni options\n    for (int j = 0; j < N; ++j) {\n        // Col j Up (0)\n        int limit = N;\n        for (int r = 0; r < N; ++r) {\n            if (is_fuku[r][j]) { limit = r; break; }\n        }\n        unsigned long long mask = 0;\n        for (int k = 1; k <= limit; ++k) {\n            if (oni_id_map[k-1][j] != -1) {\n                int id = oni_id_map[k-1][j];\n                mask |= (1ULL << id);\n                oni_options[id]++;\n                line_candidates[0 * N + j].push_back({k, mask, 0, 0, 0.0});\n            }\n        }\n\n        // Col j Down (1)\n        limit = N;\n        for (int r = N - 1; r >= 0; --r) {\n            if (is_fuku[r][j]) { limit = N - 1 - r; break; }\n        }\n        vector<pair<int, int>> k_ids;\n        for (int r = N - 1; r >= N - limit; --r) {\n            if (oni_id_map[r][j] != -1) {\n                k_ids.push_back({N - r, oni_id_map[r][j]});\n            }\n        }\n        sort(k_ids.begin(), k_ids.end());\n        mask = 0;\n        for (const auto& p : k_ids) {\n            mask |= (1ULL << p.second);\n            oni_options[p.second]++;\n            line_candidates[1 * N + j].push_back({p.first, mask, 0, 0, 0.0});\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        // Row i Left (2)\n        int limit = N;\n        for (int c = 0; c < N; ++c) {\n            if (is_fuku[i][c]) { limit = c; break; }\n        }\n        vector<pair<int, int>> k_ids;\n        for (int c = 0; c < limit; ++c) {\n            if (oni_id_map[i][c] != -1) {\n                k_ids.push_back({c + 1, oni_id_map[i][c]});\n            }\n        }\n        sort(k_ids.begin(), k_ids.end());\n        unsigned long long mask = 0;\n        for (const auto& p : k_ids) {\n            mask |= (1ULL << p.second);\n            oni_options[p.second]++;\n            line_candidates[2 * N + i].push_back({p.first, mask, 0, 0, 0.0});\n        }\n\n        // Row i Right (3)\n        limit = N;\n        for (int c = N - 1; c >= 0; --c) {\n            if (is_fuku[i][c]) { limit = N - 1 - c; break; }\n        }\n        k_ids.clear();\n        for (int c = N - 1; c >= N - limit; --c) {\n            if (oni_id_map[i][c] != -1) {\n                k_ids.push_back({N - c, oni_id_map[i][c]});\n            }\n        }\n        sort(k_ids.begin(), k_ids.end());\n        mask = 0;\n        for (const auto& p : k_ids) {\n            mask |= (1ULL << p.second);\n            oni_options[p.second]++;\n            line_candidates[3 * N + i].push_back({p.first, mask, 0, 0, 0.0});\n        }\n    }\n\n    unsigned long long removed_mask = 0;\n    int removed_count = 0;\n    vector<bool> oni_removed(num_onis, false);\n\n    // Greedy with difficulty weighting\n    while (removed_count < num_onis) {\n        int best_line = -1;\n        int best_cand_idx = -1;\n        double best_score = -1e18;\n\n        for (int l = 0; l < num_lines; ++l) {\n            while (cand_ptr[l] < (int)line_candidates[l].size() && \n                   line_candidates[l][cand_ptr[l]].k <= current_k[l]) {\n                cand_ptr[l]++;\n            }\n\n            for (int idx = cand_ptr[l]; idx < (int)line_candidates[l].size(); ++idx) {\n                int k = line_candidates[l][idx].k;\n                unsigned long long mask = line_candidates[l][idx].oni_mask;\n                \n                unsigned long long new_onis = mask & ~removed_mask;\n                if (new_onis == 0) continue;\n                \n                int gain = __builtin_popcountll(new_onis);\n                long long cost = 2LL * (k - current_k[l]);\n                \n                // Calculate weighted gain based Oni difficulty\n                double weighted_gain = 0;\n                for (int i = 0; i < num_onis; ++i) {\n                    if ((new_onis >> i) & 1) {\n                        // Higher weight for Oni with fewer options\n                        weighted_gain += 1.0 / oni_options[i];\n                    }\n                }\n                \n                double score = weighted_gain / cost;\n                \n                if (score > best_score) {\n                    best_score = score;\n                    best_line = l;\n                    best_cand_idx = idx;\n                }\n            }\n        }\n\n        if (best_line == -1) break;\n\n        int k = line_candidates[best_line][best_cand_idx].k;\n        current_k[best_line] = k;\n        \n        unsigned long long covered = line_candidates[best_line][best_cand_idx].oni_mask;\n        unsigned long long newly_removed = covered & ~removed_mask;\n        \n        for (int i = 0; i < num_onis; ++i) {\n            if ((newly_removed >> i) & 1) {\n                oni_removed[i] = true;\n                removed_count++;\n            }\n        }\n        removed_mask |= covered;\n    }\n\n    // Post-processing: Try to reduce operations\n    // Check if we can reduce k values while still covering all Oni\n    for (int l = 0; l < num_lines; ++l) {\n        if (current_k[l] == 0) continue;\n        \n        // Try to find minimum k that still contributes\n        for (int idx = 0; idx < (int)line_candidates[l].size(); ++idx) {\n            if (line_candidates[l][idx].k >= current_k[l]) {\n                // Check if this candidate alone covers what we need from this line\n                // For now, keep current approach but mark for potential optimization\n                break;\n            }\n        }\n    }\n\n    // Output moves\n    vector<pair<char, int>> moves;\n    moves.reserve(1600);\n    for (int l = 0; l < num_lines; ++l) {\n        if (current_k[l] > 0) {\n            int dir = l / N;\n            int idx = l % N;\n            char d = DIR_CHARS[dir];\n            char rd = REVERSE_DIR[dir];\n            for (int s = 0; s < current_k[l]; ++s) moves.push_back({d, idx});\n            for (int s = 0; s < current_k[l]; ++s) moves.push_back({rd, idx});\n        }\n    }\n\n    for (const auto& mv : moves) {\n        cout << mv.first << \" \" << mv.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nint N;\nlong long L;\nvector<int> T;\n\n// Function to simulate the process and calculate error\nlong long simulate(const vector<int>& A, const vector<int>& B, vector<int>& counts) {\n    fill(counts.begin(), counts.end(), 0);\n    int cur = 0;\n    // L weeks\n    for (int k = 0; k < L; ++k) {\n        counts[cur]++;\n        int t = counts[cur];\n        if (t % 2 != 0) {\n            cur = A[cur];\n        } else {\n            cur = B[cur];\n        }\n    }\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(counts[i] - T[i]);\n    }\n    return error;\n}\n\n// Check connectivity from node 0 to all nodes with T[i] > 0\nbool is_connected(const vector<int>& A, const vector<int>& B) {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    q.push(0);\n    visited[0] = true;\n    int count = 0;\n    while(!q.empty()){\n        int u = q.front();\n        q.pop();\n        if (T[u] > 0) count++;\n        \n        // Outgoing edges\n        int v1 = A[u];\n        if (!visited[v1]) {\n            visited[v1] = true;\n            q.push(v1);\n        }\n        int v2 = B[u];\n        if (!visited[v2]) {\n            visited[v2] = true;\n            q.push(v2);\n        }\n    }\n    // Check if all important nodes are visited\n    for(int i=0; i<N; ++i){\n        if(T[i] > 0 && !visited[i]) return false;\n    }\n    return true;\n}\n\nvoid fix_connectivity(vector<int>& A, vector<int>& B, vector<long long>& load) {\n    // Repeatedly ensure all T[i]>0 are reachable from 0\n    // We do this by finding an unreachable important node and adding an edge to it from a reachable node\n    // We try to minimize the disturbance to the load balance\n    \n    while (true) {\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        q.push(0);\n        reachable[0] = true;\n        while(!q.empty()){\n            int u = q.front();\n            q.pop();\n            if(!reachable[A[u]]) { reachable[A[u]] = true; q.push(A[u]); }\n            if(!reachable[B[u]]) { reachable[B[u]] = true; q.push(B[u]); }\n        }\n        \n        int target = -1;\n        for(int i=0; i<N; ++i){\n            if(T[i] > 0 && !reachable[i]){\n                target = i;\n                break;\n            }\n        }\n        \n        if(target == -1) break; // All important nodes reachable\n        \n        // Find best edge to redirect to target\n        // We look for a reachable node u, and change one of its outgoing edges to target\n        // We want to minimize increase in |load[dest] - 2*T[dest]|\n        \n        long long min_cost = -1;\n        int best_u = -1;\n        int best_edge = -1; // 0 for A, 1 for B\n        int old_dest = -1;\n        \n        for(int u=0; u<N; ++u){\n            if(!reachable[u]) continue;\n            // Try changing A[u]\n            {\n                int w = A[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 0;\n                    old_dest = w;\n                }\n            }\n            // Try changing B[u]\n            {\n                int w = B[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 1;\n                    old_dest = w;\n                }\n            }\n        }\n        \n        if(best_u != -1){\n            // Apply change\n            if(best_edge == 0){\n                load[old_dest] -= T[best_u];\n                A[best_u] = target;\n                load[target] += T[best_u];\n            } else {\n                load[old_dest] -= T[best_u];\n                B[best_u] = target;\n                load[target] += T[best_u];\n            }\n        } else {\n            // Should not happen if there is at least one reachable node (0 is reachable)\n            // Fallback: force 0 to point to target\n            int w = A[0];\n            load[w] -= T[0];\n            A[0] = target;\n            load[target] += T[0];\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    T.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution construction using flow balance heuristic\n    // We have 2N items, each (T[i], i). We want to assign them to buckets 0..N-1\n    // such that sum of values in bucket j is close to 2*T[j].\n    \n    vector<pair<int, int>> items;\n    items.reserve(2 * N);\n    for (int i = 0; i < N; ++i) {\n        items.push_back({T[i], i});\n        items.push_back({T[i], i});\n    }\n    \n    // Sort items descending by value\n    sort(items.begin(), items.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n        return a.first > b.first;\n    });\n    \n    vector<long long> load(N, 0);\n    vector<int> A(N), B(N);\n    vector<vector<int>> outgoing(N); // Store assigned destinations for each source\n    \n    for (const auto& item : items) {\n        int val = item.first;\n        int src = item.second;\n        \n        // Find best bucket\n        int best_j = -1;\n        long long min_diff = -1;\n        \n        // To speed up, we can just scan all N. N=100 is small.\n        for (int j = 0; j < N; ++j) {\n            long long diff = abs(load[j] + val - 2LL * T[j]);\n            if (best_j == -1 || diff < min_diff) {\n                min_diff = diff;\n                best_j = j;\n            }\n        }\n        \n        load[best_j] += val;\n        outgoing[src].push_back(best_j);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        A[i] = outgoing[i][0];\n        B[i] = outgoing[i][1];\n    }\n    \n    // Fix connectivity\n    fix_connectivity(A, B, load);\n    \n    // Evaluate initial score\n    vector<int> counts(N);\n    long long current_score = simulate(A, B, counts);\n    long long best_score = current_score;\n    vector<int> best_A = A;\n    vector<int> best_B = B;\n    \n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    \n    double temp = 1000.0;\n    double cooling_rate = 0.9999;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        // Generate neighbor\n        int i = uniform_int_distribution<>(0, N - 1)(rng);\n        int type = uniform_int_distribution<>(0, 1)(rng); // 0 for A, 1 for B\n        int old_val = (type == 0) ? A[i] : B[i];\n        int new_val = uniform_int_distribution<>(0, N - 1)(rng);\n        \n        if (old_val == new_val) continue;\n        \n        // Apply change\n        if (type == 0) A[i] = new_val;\n        else B[i] = new_val;\n        \n        long long new_score = simulate(A, B, counts);\n        \n        double delta = (double)new_score - (double)current_score;\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_A = A;\n                best_B = B;\n            }\n        } else {\n            // Revert\n            if (type == 0) A[i] = old_val;\n            else B[i] = old_val;\n        }\n        \n        temp *= cooling_rate;\n        iter++;\n    }\n    \n    // Output best solution\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n#include <atcoder/dsu>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct City {\n    int id;\n    long long cx, cy;\n    int h_index;\n};\n\n// Hilbert curve functions for 2D spatial locality\nvoid rot(int n, int *x, int *y, int rx, int ry) {\n    if (ry == 0) {\n        if (rx == 1) {\n            *x = n - 1 - *x;\n            *y = n - 1 - *y;\n        }\n        std::swap(*x, *y);\n    }\n}\n\nint xy2d(int n, int x, int y) {\n    int rx, ry, s, d = 0;\n    for (s = n / 2; s > 0; s /= 2) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        rot(s, &x, &y, rx, ry);\n    }\n    return d;\n}\n\nstruct Edge {\n    int u, v;\n    long long d2;\n    bool queried;\n    int query_count;\n};\n\nstruct Group {\n    int id;\n    vector<City> cities;\n    vector<pair<int, int>> queried_edges;\n    map<pair<int,int>, int> edge_query_count;\n};\n\nlong long dist2(const City& a, const City& b) {\n    long long dx = a.cx - b.cx;\n    long long dy = a.cy - b.cy;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> G[i];\n    }\n\n    vector<City> cities(N);\n    vector<City> city_by_id(N);\n    const int H_N = 16384;\n\n    for (int i = 0; i < N; ++i) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cities[i].id = i;\n        cities[i].cx = (0LL + lx + rx) / 2;\n        cities[i].cy = (0LL + ly + ry) / 2;\n        cities[i].h_index = xy2d(H_N, (int)cities[i].cx, (int)cities[i].cy);\n        city_by_id[i] = cities[i];\n    }\n\n    // Sort by Hilbert index for spatial locality\n    sort(cities.begin(), cities.end(), [](const City& a, const City& b) {\n        return a.h_index < b.h_index;\n    });\n\n    // Partition into groups\n    vector<Group> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].id = i;\n        groups[i].cities.reserve(G[i]);\n        for (int j = 0; j < G[i]; ++j) {\n            if (cur < N) {\n                groups[i].cities.push_back(cities[cur++]);\n            }\n        }\n    }\n\n    int queries_used = 0;\n\n    // Process groups: small groups first (can get exact MST with 1 query)\n    vector<int> group_order(M);\n    iota(group_order.begin(), group_order.end(), 0);\n    sort(group_order.begin(), group_order.end(), [&](int a, int b) {\n        int sa = groups[a].cities.size();\n        int sb = groups[b].cities.size();\n        // Small groups (<=L) first, then by size descending\n        if (sa <= L && sb > L) return true;\n        if (sa > L && sb <= L) return false;\n        return sa > sb;\n    });\n\n    // Execute queries for each group\n    for (int idx : group_order) {\n        if (queries_used >= Q) break;\n        \n        Group& g = groups[idx];\n        int S = g.cities.size();\n        \n        if (S <= 1) continue;\n\n        // Sort cities in group by Hilbert index\n        sort(g.cities.begin(), g.cities.end(), [](const City& a, const City& b) {\n            return a.h_index < b.h_index;\n        });\n\n        if (S <= L) {\n            // Single query for exact MST\n            vector<int> chunk_ids;\n            chunk_ids.reserve(S);\n            for (const auto& c : g.cities) {\n                chunk_ids.push_back(c.id);\n            }\n\n            cout << \"? \" << S;\n            for (int id : chunk_ids) cout << \" \" << id;\n            cout << \"\\n\";\n            cout.flush();\n\n            for (int i = 0; i < S - 1; ++i) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                g.queried_edges.push_back({u, v});\n                g.edge_query_count[{u, v}]++;\n            }\n            queries_used++;\n        } else {\n            // Multiple queries with overlap\n            // Use overlap of 2 nodes for better connectivity\n            int overlap = 2;\n            int step = L - overlap;\n            if (step < 1) step = 1;\n            \n            // Calculate how many queries we can afford for this group\n            int max_queries_for_group = Q - queries_used;\n            \n            // Calculate queries needed for full coverage\n            int queries_needed = 0;\n            for (int start = 0; start < S; start += step) {\n                queries_needed++;\n                if (start + L >= S) break;\n            }\n            \n            int queries_to_use = min(queries_needed, max_queries_for_group);\n            \n            for (int q = 0; q < queries_to_use; ++q) {\n                if (queries_used >= Q) break;\n                \n                int start = q * step;\n                if (start >= S) break;\n                \n                int end = start + L;\n                if (end > S) end = S;\n                \n                // Ensure at least 2 cities in chunk\n                if (end - start < 2) {\n                    // Extend backwards if possible\n                    if (start > 0) {\n                        start = max(0, end - 2);\n                    } else {\n                        break;\n                    }\n                }\n                \n                if (end - start < 2) break;\n                \n                vector<int> chunk_ids;\n                chunk_ids.reserve(end - start);\n                for(int i = start; i < end; ++i) {\n                    chunk_ids.push_back(g.cities[i].id);\n                }\n\n                cout << \"? \" << chunk_ids.size();\n                for (int id : chunk_ids) cout << \" \" << id;\n                cout << \"\\n\";\n                cout.flush();\n                queries_used++;\n\n                int num_ret = chunk_ids.size() - 1;\n                for (int i = 0; i < num_ret; ++i) {\n                    int u, v;\n                    cin >> u >> v;\n                    if (u > v) swap(u, v);\n                    g.queried_edges.push_back({u, v});\n                    g.edge_query_count[{u, v}]++;\n                }\n                \n                // If we've covered to the end, stop\n                if (end == S) break;\n            }\n        }\n    }\n\n    // Output final answer\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        const Group& g = groups[i];\n        int S = g.cities.size();\n        \n        // Output cities\n        for (int j = 0; j < S; ++j) {\n            if (j > 0) cout << \" \";\n            cout << g.cities[j].id;\n        }\n        cout << \"\\n\";\n\n        if (S <= 1) continue;\n\n        // Build edge pool\n        vector<Edge> pool;\n        set<pair<int,int>> q_set(g.queried_edges.begin(), g.queried_edges.end());\n\n        // Add queried edges with high priority\n        for (const auto& p : g.queried_edges) {\n            const City& c1 = city_by_id[p.first];\n            const City& c2 = city_by_id[p.second];\n            int count = 1;\n            auto it = g.edge_query_count.find(p);\n            if (it != g.edge_query_count.end()) {\n                count = it->second;\n            }\n            pool.push_back({p.first, p.second, dist2(c1, c2), true, count});\n        }\n\n        // Add estimated edges (complete graph within group)\n        for (int j = 0; j < S; ++j) {\n            for (int k = j + 1; k < S; ++k) {\n                int u = g.cities[j].id;\n                int v = g.cities[k].id;\n                if (u > v) swap(u, v);\n                if (q_set.count({u, v})) continue;\n                \n                pool.push_back({u, v, dist2(g.cities[j], g.cities[k]), false, 0});\n            }\n        }\n\n        // Sort: queried first, then by query count, then by distance\n        sort(pool.begin(), pool.end(), [](const Edge& a, const Edge& b) {\n            if (a.queried != b.queried) return a.queried > b.queried;\n            if (a.query_count != b.query_count) return a.query_count > b.query_count;\n            return a.d2 < b.d2;\n        });\n\n        // Kruskal's algorithm\n        dsu group_dsu(N);\n        int count = 0;\n        for (const auto& e : pool) {\n            if (group_dsu.same(e.u, e.v)) continue;\n            group_dsu.merge(e.u, e.v);\n            cout << e.u << \" \" << e.v << \"\\n\";\n            count++;\n            if (count == S - 1) break;\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nstruct Action {\n    char type;\n    char dir;\n};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\nint N, M;\nbool has_block[20][20];\nint dist_map[20][20];\nPos parent_pos[20][20];\nAction parent_act[20][20];\n\nconst int INF = 1e9;\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// BFS to find shortest path from start to end\nint bfs(Pos start, Pos end, bool store_path) {\n    for(int i = 0; i < N; ++i) \n        for(int j = 0; j < N; ++j) \n            dist_map[i][j] = INF;\n    \n    queue<Pos> q;\n    dist_map[start.r][start.c] = 0;\n    q.push(start);\n    \n    while(!q.empty()) {\n        Pos curr = q.front();\n        q.pop();\n        \n        if (curr == end) return dist_map[curr.r][curr.c];\n        \n        int d = dist_map[curr.r][curr.c];\n        \n        // Try Move actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r + dr[i];\n            int nc = curr.c + dc[i];\n            if(is_valid(nr, nc) && !has_block[nr][nc]) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'M', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n        \n        // Try Slide actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r;\n            int nc = curr.c;\n            while(true) {\n                int nnr = nr + dr[i];\n                int nnc = nc + dc[i];\n                if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                    break;\n                }\n                nr = nnr;\n                nc = nnc;\n            }\n            if(nr != curr.r || nc != curr.c) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'S', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return INF;\n}\n\nvector<Action> get_path(Pos end) {\n    vector<Action> path;\n    Pos curr = end;\n    while(dist_map[curr.r][curr.c] != 0) {\n        path.push_back(parent_act[curr.r][curr.c]);\n        curr = parent_pos[curr.r][curr.c];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Simulate actions and update position and block state\nPos simulate_action(Pos curr, const Action& act, bool update_blocks = false) {\n    if(act.type == 'M') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r + dr[i];\n                int nc = curr.c + dc[i];\n                // Safety check - should never happen if BFS is correct\n                if(!is_valid(nr, nc) || has_block[nr][nc]) {\n                    cerr << \"ERROR: Invalid move at (\" << curr.r << \",\" << curr.c \n                         << \") direction \" << act.dir << endl;\n                    return curr;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'S') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r;\n                int nc = curr.c;\n                while(true) {\n                    int nnr = nr + dr[i];\n                    int nnc = nc + dc[i];\n                    if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                        break;\n                    }\n                    nr = nnr;\n                    nc = nnc;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'A') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int br = curr.r + dr[i];\n                int bc = curr.c + dc[i];\n                if(is_valid(br, bc)) {\n                    if(update_blocks) {\n                        has_block[br][bc] = !has_block[br][bc];\n                    }\n                }\n                return curr;\n            }\n        }\n    }\n    return curr;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    vector<Pos> points(M);\n    for(int i = 0; i < M; ++i) {\n        cin >> points[i].r >> points[i].c;\n    }\n    \n    // Initialize blocks\n    memset(has_block, 0, sizeof(has_block));\n    \n    Pos curr = points[0];\n    vector<Action> all_actions;\n    \n    for(int k = 0; k < M - 1; ++k) {\n        Pos target = points[k+1];\n        \n        // Get base path without adding blocks\n        int base_dist = bfs(curr, target, true);\n        vector<Action> base_path = get_path(target);\n        \n        int best_dist = base_dist;\n        vector<Action> best_path = base_path;\n        Pos best_S = {-1, -1};\n        Pos best_adj = {-1, -1};\n        int best_dir = -1;\n        \n        // Only try adding blocks if base path is long enough to justify it\n        if(base_dist > 3) {\n            // Candidate block positions around target\n            vector<Pos> candidates;\n            for(int i = 0; i < 4; ++i) {\n                int sr = target.r + dr[i];\n                int sc = target.c + dc[i];\n                if(is_valid(sr, sc) && !has_block[sr][sc] && !(sr == curr.r && sc == curr.c)) {\n                    candidates.push_back({sr, sc});\n                }\n            }\n            \n            for(const auto& S : candidates) {\n                // Try placing block from each adjacent cell\n                for(int i = 0; i < 4; ++i) {\n                    int ar = S.r + dr[i];\n                    int ac = S.c + dc[i];\n                    if(!is_valid(ar, ac) || has_block[ar][ac]) continue;\n                    if(ar == S.r && ac == S.c) continue;\n                    \n                    // Cost to reach adjacent cell\n                    int d1 = bfs(curr, {ar, ac}, false);\n                    if(d1 == INF || d1 > best_dist) continue;\n                    \n                    // Temporarily place block\n                    has_block[S.r][S.c] = true;\n                    \n                    // Cost to reach target from adjacent cell\n                    int d2 = bfs({ar, ac}, target, false);\n                    \n                    // Remove block\n                    has_block[S.r][S.c] = false;\n                    \n                    if(d2 == INF) continue;\n                    \n                    int total = d1 + 1 + d2;\n                    \n                    if(total < best_dist) {\n                        best_dist = total;\n                        best_S = S;\n                        best_adj = {ar, ac};\n                        best_dir = i;\n                    }\n                }\n            }\n        }\n        \n        // Execute the best plan\n        if(best_S.r != -1) {\n            // 1. Move to best_adj\n            bfs(curr, best_adj, true);\n            vector<Action> p1 = get_path(best_adj);\n            \n            // Validate path before adding\n            Pos temp = curr;\n            for(const auto& act : p1) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p1.begin(), p1.end());\n            curr = best_adj;\n            \n            // 2. Alter (Place block)\n            all_actions.push_back({'A', dir_char[best_dir]});\n            has_block[best_S.r][best_S.c] = true;\n            \n            // 3. Move to target\n            bfs(curr, target, true);\n            vector<Action> p2 = get_path(target);\n            \n            // Validate path before adding\n            temp = curr;\n            for(const auto& act : p2) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p2.begin(), p2.end());\n            curr = target;\n        } else {\n            // Execute base plan\n            // Validate path\n            Pos temp = curr;\n            for(const auto& act : base_path) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), base_path.begin(), base_path.end());\n            curr = target;\n        }\n    }\n    \n    // Final validation of all actions\n    Pos validate_pos = points[0];\n    for(const auto& act : all_actions) {\n        validate_pos = simulate_action(validate_pos, act, true);\n    }\n    \n    // Output all actions\n    for(const auto& act : all_actions) {\n        cout << act.type << \" \" << act.dir << \"\\n\";\n    }\n    \n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { \n        return (long long)max(0, x2 - x1) * max(0, y2 - y1); \n    }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n    bool overlaps(const Rect& other) const {\n        return !(x2 <= other.x1 || other.x2 <= x1 || y2 <= other.y1 || other.y2 <= y1);\n    }\n};\n\n// Calculate satisfaction score\ndouble calcSatisfaction(int desired, int actual) {\n    if (actual <= 0) return 0.0;\n    double ratio = (double)min(desired, actual) / max(desired, actual);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Calculate total satisfaction\ndouble totalSatisfaction(const vector<Company>& comps) {\n    double total = 0.0;\n    for (const auto& c : comps) {\n        int area = (c.c - c.a) * (c.d - c.b);\n        total += calcSatisfaction(c.r, area);\n    }\n    return total;\n}\n\n// Check if all companies in range are contained in rect\nbool allContained(const vector<Company>& comps, int idx, int end, \n                  int x1, int y1, int x2, int y2) {\n    for (int i = idx; i < end; i++) {\n        if (comps[i].x < x1 || comps[i].x >= x2 || \n            comps[i].y < y1 || comps[i].y >= y2) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Verify no overlaps exist\nbool verifyNoOverlap(const vector<Company>& comps) {\n    int n = comps.size();\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            Rect ri = {comps[i].a, comps[i].b, comps[i].c, comps[i].d};\n            Rect rj = {comps[j].a, comps[j].b, comps[j].c, comps[j].d};\n            if (ri.overlaps(rj)) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Verify all points are contained\nbool verifyPoints(const vector<Company>& comps) {\n    for (const auto& c : comps) {\n        if (c.x < c.a || c.x >= c.c || c.y < c.b || c.y >= c.d) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Verify all rectangles are valid\nbool verifyRects(const vector<Company>& comps) {\n    for (const auto& c : comps) {\n        if (c.a < 0 || c.b < 0 || c.c > 10000 || c.d > 10000) return false;\n        if (c.a >= c.c || c.b >= c.d) return false;\n    }\n    return true;\n}\n\n// Recursive space partitioning with guaranteed containment\nbool partition(vector<Company>& comps, int idx, int end, \n               int x1, int y1, int x2, int y2) {\n    int count = end - idx;\n    \n    if (count <= 0) return true;\n    if (x2 <= x1 || y2 <= y1) return false;\n    \n    // Verify all points are in current space\n    for (int i = idx; i < end; i++) {\n        if (comps[i].x < x1 || comps[i].x >= x2 || \n            comps[i].y < y1 || comps[i].y >= y2) {\n            return false;\n        }\n    }\n    \n    if (count == 1) {\n        comps[idx].a = x1;\n        comps[idx].b = y1;\n        comps[idx].c = x2;\n        comps[idx].d = y2;\n        return true;\n    }\n    \n    // Calculate cumulative areas\n    long long totalArea = 0;\n    for (int i = idx; i < end; i++) totalArea += comps[i].r;\n    \n    // Find split index based on area balance\n    int bestSplitIdx = idx + 1;\n    long long bestDiff = totalArea;\n    \n    long long leftArea = 0;\n    for (int i = idx; i < end - 1; i++) {\n        leftArea += comps[i].r;\n        long long diff = abs(leftArea * 2 - totalArea);\n        if (diff < bestDiff) {\n            bestDiff = diff;\n            bestSplitIdx = i + 1;\n        }\n    }\n    \n    int width = x2 - x1;\n    int height = y2 - y1;\n    \n    // Try vertical split first (if width >= height)\n    if (width >= height) {\n        for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                allContained(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                    partition(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n        \n        // Try horizontal split as fallback\n        for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                allContained(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                    partition(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n    } else {\n        // Try horizontal split first (if height > width)\n        for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                allContained(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                    partition(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n        \n        // Try vertical split as fallback\n        for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                allContained(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                    partition(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n    }\n    \n    // Try different split indices if best doesn't work\n    for (int splitIdx = idx + 1; splitIdx < end; splitIdx++) {\n        if (splitIdx == bestSplitIdx) continue;\n        \n        // Try vertical\n        for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n            if (allContained(comps, idx, splitIdx, x1, y1, splitPos, y2) &&\n                allContained(comps, splitIdx, end, splitPos, y1, x2, y2)) {\n                \n                if (partition(comps, idx, splitIdx, x1, y1, splitPos, y2) &&\n                    partition(comps, splitIdx, end, splitPos, y1, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n        \n        // Try horizontal\n        for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n            if (allContained(comps, idx, splitIdx, x1, y1, x2, splitPos) &&\n                allContained(comps, splitIdx, end, x1, splitPos, x2, y2)) {\n                \n                if (partition(comps, idx, splitIdx, x1, y1, x2, splitPos) &&\n                    partition(comps, splitIdx, end, x1, splitPos, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n    }\n    \n    // Fallback: minimum rectangles at points\n    for (int i = idx; i < end; i++) {\n        comps[i].a = comps[i].x;\n        comps[i].b = comps[i].y;\n        comps[i].c = comps[i].x + 1;\n        comps[i].d = comps[i].y + 1;\n    }\n    return true;\n}\n\n// Simple grid-based fallback that guarantees validity\nvoid gridLayout(vector<Company>& comps) {\n    int n = comps.size();\n    int cols = (int)ceil(sqrt(n));\n    int rows = (n + cols - 1) / cols;\n    int cellW = 10000 / cols;\n    int cellH = 10000 / rows;\n    \n    // Sort by y then x for grid assignment\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (comps[i].y != comps[j].y) return comps[i].y < comps[j].y;\n        return comps[i].x < comps[j].x;\n    });\n    \n    for (int i = 0; i < n; i++) {\n        int idx = order[i];\n        int col = i % cols;\n        int row = i / cols;\n        \n        comps[idx].a = col * cellW;\n        comps[idx].b = row * cellH;\n        comps[idx].c = (col + 1) * cellW;\n        comps[idx].d = (row + 1) * cellH;\n        \n        // Ensure bounds\n        comps[idx].a = max(0, min(9999, comps[idx].a));\n        comps[idx].b = max(0, min(9999, comps[idx].b));\n        comps[idx].c = max(1, min(10000, comps[idx].c));\n        comps[idx].d = max(1, min(10000, comps[idx].d));\n        if (comps[idx].c <= comps[idx].a) comps[idx].c = comps[idx].a + 1;\n        if (comps[idx].d <= comps[idx].b) comps[idx].d = comps[idx].b + 1;\n    }\n}\n\n// Try different sorting strategies and pick the best\nvector<Company> tryWithSorting(vector<Company> comps, \n                                function<bool(const Company&, const Company&)> cmp) {\n    sort(comps.begin(), comps.end(), cmp);\n    \n    bool success = partition(comps, 0, (int)comps.size(), 0, 0, 10000, 10000);\n    \n    // Ensure validity\n    for (int i = 0; i < (int)comps.size(); i++) {\n        if (comps[i].c <= comps[i].a) comps[i].c = comps[i].a + 1;\n        if (comps[i].d <= comps[i].b) comps[i].d = comps[i].b + 1;\n        comps[i].a = max(0, min(9999, comps[i].a));\n        comps[i].b = max(0, min(9999, comps[i].b));\n        comps[i].c = max(1, min(10000, comps[i].c));\n        comps[i].d = max(1, min(10000, comps[i].d));\n    }\n    \n    if (!success || !verifyNoOverlap(comps) || !verifyPoints(comps) || !verifyRects(comps)) {\n        gridLayout(comps);\n    }\n    \n    return comps;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n    }\n    \n    // Try multiple sorting strategies\n    vector<vector<Company>> candidates;\n    \n    // Strategy 1: Sort by x then y\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        if (a.x != b.x) return a.x < b.x;\n        return a.y < b.y;\n    }));\n    \n    // Strategy 2: Sort by y then x\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        if (a.y != b.y) return a.y < b.y;\n        return a.x < b.x;\n    }));\n    \n    // Strategy 3: Morton order\n    auto morton = [](int x, int y) -> long long {\n        long long result = 0;\n        for (int i = 0; i < 14; i++) {\n            result |= ((long long)(x & (1 << i)) << i);\n            result |= ((long long)(y & (1 << i)) << (i + 1));\n        }\n        return result;\n    };\n    candidates.push_back(tryWithSorting(companies, [&](const Company& a, const Company& b) {\n        return morton(a.x, a.y) < morton(b.x, b.y);\n    }));\n    \n    // Select best candidate\n    int bestIdx = 0;\n    double bestScore = totalSatisfaction(candidates[0]);\n    for (int i = 1; i < (int)candidates.size(); i++) {\n        double score = totalSatisfaction(candidates[i]);\n        if (score > bestScore) {\n            bestScore = score;\n            bestIdx = i;\n        }\n    }\n    \n    companies = candidates[bestIdx];\n    \n    // Final comprehensive validation\n    if (!verifyNoOverlap(companies) || !verifyPoints(companies) || !verifyRects(companies)) {\n        gridLayout(companies);\n    }\n    \n    // One more validation pass\n    for (int i = 0; i < n; i++) {\n        if (companies[i].a < 0) companies[i].a = 0;\n        if (companies[i].b < 0) companies[i].b = 0;\n        if (companies[i].c > 10000) companies[i].c = 10000;\n        if (companies[i].d > 10000) companies[i].d = 10000;\n        if (companies[i].c <= companies[i].a) companies[i].c = companies[i].a + 1;\n        if (companies[i].d <= companies[i].b) companies[i].d = companies[i].b + 1;\n    }\n    \n    // Output in original order\n    vector<tuple<int,int,int,int>> result(n);\n    for (const auto& comp : companies) {\n        result[comp.id] = {comp.a, comp.b, comp.c, comp.d};\n    }\n    \n    for (int i = 0; i < n; i++) {\n        auto [a, b, c, d] = result[i];\n        cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    int ci, cj;\n    int score;\n    string path;\n    vector<bool> tile_visited;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int si, sj;\n    cin >> si >> sj;\n    \n    vector<vector<int>> t(50, vector<int>(50));\n    int max_tile = 0;\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> t[i][j];\n            max_tile = max(max_tile, t[i][j]);\n        }\n    }\n    \n    vector<vector<int>> p(50, vector<int>(50));\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> p[i][j];\n        }\n    }\n    \n    // Directions: U, D, L, R\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    const char dc[] = {'U', 'D', 'L', 'R'};\n    \n    string best_path = \"\";\n    int best_score = 0;\n    \n    auto get_time = []() {\n        return chrono::duration<double>(chrono::steady_clock::now().time_since_epoch()).count();\n    };\n    \n    double start_time = get_time();\n    double time_limit = 1.95;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int strategy_count = 0;\n    \n    while (get_time() - start_time < time_limit) {\n        strategy_count++;\n        \n        // Vary strategy parameters\n        double greediness = 0.5 + 0.5 * sin(strategy_count * 0.1);\n        double exploration = 0.3 + 0.4 * ((double)rng() / rng.max());\n        int beam_width = 1 + (strategy_count % 5);\n        \n        vector<State> beam;\n        vector<bool> initial_visited(max_tile + 1, false);\n        initial_visited[t[si][sj]] = true;\n        beam.push_back({si, sj, p[si][sj], \"\", initial_visited});\n        \n        for (int step = 0; step < 2500 && get_time() - start_time < time_limit; step++) {\n            vector<State> next_beam;\n            \n            for (auto& state : beam) {\n                vector<tuple<int, int, int, int>> candidates; // {value, connectivity, randomness_score, direction}\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = state.ci + di[d];\n                    int nj = state.cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        int tile_id = t[ni][nj];\n                        if (!state.tile_visited[tile_id]) {\n                            // Calculate connectivity score (how many unvisited neighbors this tile has)\n                            int connectivity = 0;\n                            for (int d2 = 0; d2 < 4; d2++) {\n                                int nn_i = ni + di[d2];\n                                int nn_j = nj + dj[d2];\n                                if (nn_i >= 0 && nn_i < 50 && nn_j >= 0 && nn_j < 50) {\n                                    if (!state.tile_visited[t[nn_i][nn_j]]) {\n                                        connectivity++;\n                                    }\n                                }\n                            }\n                            \n                            int rand_score = rng() % 100;\n                            candidates.push_back({p[ni][nj], connectivity, rand_score, d});\n                        }\n                    }\n                }\n                \n                if (candidates.empty()) {\n                    if (state.score > best_score) {\n                        best_score = state.score;\n                        best_path = state.path;\n                    }\n                    continue;\n                }\n                \n                // Sort candidates by combined score\n                sort(candidates.begin(), candidates.end(), [greediness](const tuple<int,int,int,int>& a, const tuple<int,int,int,int>& b) {\n                    int score_a = (int)(get<0>(a) * greediness + get<1>(a) * (1 - greediness) * 0.5);\n                    int score_b = (int)(get<0>(b) * greediness + get<1>(b) * (1 - greediness) * 0.5);\n                    if (score_a != score_b) return score_a > score_b;\n                    return get<0>(a) > get<0>(b);\n                });\n                \n                // Select top candidates for beam\n                int select_count = min(beam_width, (int)candidates.size());\n                for (int i = 0; i < select_count; i++) {\n                    if ((double)rng() / rng.max() > exploration && i > 0) break;\n                    \n                    State new_state = state;\n                    int d = get<3>(candidates[i]);\n                    new_state.path += dc[d];\n                    new_state.ci += di[d];\n                    new_state.cj += dj[d];\n                    new_state.score += p[new_state.ci][new_state.cj];\n                    new_state.tile_visited[t[new_state.ci][new_state.cj]] = true;\n                    next_beam.push_back(new_state);\n                }\n            }\n            \n            if (next_beam.empty()) break;\n            \n            // Keep top states by score\n            sort(next_beam.begin(), next_beam.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(beam_width, (int)next_beam.size()); i++) {\n                beam.push_back(next_beam[i]);\n            }\n        }\n        \n        // Check final beam states\n        for (auto& state : beam) {\n            if (state.score > best_score) {\n                best_score = state.score;\n                best_path = state.path;\n            }\n        }\n        \n        // Occasionally try pure greedy for comparison\n        if (strategy_count % 20 == 0) {\n            vector<bool> tile_visited(max_tile + 1, false);\n            string path = \"\";\n            int ci = si, cj = sj;\n            int score = p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n            \n            while (get_time() - start_time < time_limit) {\n                pair<int, int> best_candidate = {-1, -1};\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = ci + di[d];\n                    int nj = cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        if (!tile_visited[t[ni][nj]]) {\n                            if (best_candidate.first == -1 || p[ni][nj] > best_candidate.first) {\n                                best_candidate = {p[ni][nj], d};\n                            }\n                        }\n                    }\n                }\n                \n                if (best_candidate.first == -1) break;\n                \n                int d = best_candidate.second;\n                path += dc[d];\n                ci += di[d];\n                cj += dj[d];\n                score += p[ci][cj];\n                tile_visited[t[ci][cj]] = true;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best_path = path;\n            }\n        }\n        \n        // Try randomized greedy with different seeds\n        if (strategy_count % 5 == 0) {\n            mt19937 local_rng(strategy_count * 1000 + rng());\n            vector<bool> tile_visited(max_tile + 1, false);\n            string path = \"\";\n            int ci = si, cj = sj;\n            int score = p[ci][cj];\n            tile_visited[t[ci][cj]] = true;\n            \n            double local_randomness = 0.1 + 0.6 * ((double)local_rng() / local_rng.max());\n            \n            while (get_time() - start_time < time_limit) {\n                vector<pair<int, int>> candidates;\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = ci + di[d];\n                    int nj = cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        if (!tile_visited[t[ni][nj]]) {\n                            candidates.push_back({p[ni][nj], d});\n                        }\n                    }\n                }\n                \n                if (candidates.empty()) break;\n                \n                sort(candidates.begin(), candidates.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n                    return a.first > b.first;\n                });\n                \n                int pick_idx = 0;\n                if (candidates.size() > 1 && (double)local_rng() / local_rng.max() < local_randomness) {\n                    pick_idx = local_rng() % min(3, (int)candidates.size());\n                }\n                \n                int d = candidates[pick_idx].second;\n                path += dc[d];\n                ci += di[d];\n                cj += dj[d];\n                score += p[ci][cj];\n                tile_visited[t[ci][cj]] = true;\n            }\n            \n            if (score > best_score) {\n                best_score = score;\n                best_path = path;\n            }\n        }\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <random>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Edge weights and visit counts\ndouble h_w[H][W-1];\ndouble v_w[H-1][W];\nint h_n[H][W-1];\nint v_n[H-1][W];\n\n// Row/column statistics for pattern detection\ndouble h_row_avg[H];\ndouble v_col_avg[W];\ndouble h_row_var[H];\ndouble v_col_var[W];\nint h_row_n[H];\nint v_col_n[W];\n\n// Confidence in weights\ndouble h_conf[H][W-1];\ndouble v_conf[H-1][W];\n\n// Recent prediction errors for adaptive exploration\nvector<double> recent_errors;\nconst int ERROR_WINDOW = 50;\n\nmt19937 rng(54321);\n\nvoid init() {\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W-1; ++j) {\n            h_w[i][j] = 5000.0;\n            h_n[i][j] = 1;\n            h_conf[i][j] = 0.05;\n        }\n        h_row_avg[i] = 5000.0;\n        h_row_var[i] = 0;\n        h_row_n[i] = 0;\n    }\n    for (int i = 0; i < H-1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_w[i][j] = 5000.0;\n            v_n[i][j] = 1;\n            v_conf[i][j] = 0.05;\n        }\n    }\n    for (int j = 0; j < W; ++j) {\n        v_col_avg[j] = 5000.0;\n        v_col_var[j] = 0;\n        v_col_n[j] = 0;\n    }\n    recent_errors.reserve(ERROR_WINDOW);\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nstring dijkstra(int sr, int sc, int tr, int tc, int query_num) {\n    vector<vector<double>> dist(H, vector<double>(W, 1e18));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> dir_to(H, vector<char>(W, 0));\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    \n    dist[sr][sc] = 0;\n    pq.push({0.0, sr, sc});\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char dchar[] = {'U', 'D', 'L', 'R'};\n    \n    // Base exploration bonus - faster decay for quicker convergence\n    double base_bonus = 700.0;\n    double explore_bonus = base_bonus * exp(-query_num / 200.0);\n    \n    // Boost exploration if recent errors are high\n    if (recent_errors.size() >= 10) {\n        double avg_error = 0;\n        for (double e : recent_errors) avg_error += e;\n        avg_error /= recent_errors.size();\n        if (avg_error > 0.07) {\n            explore_bonus *= 1.4;\n        }\n    }\n    \n    // Mild random perturbation for early exploration\n    bool perturb = (query_num < 80) && (rng() % 100 < 12);\n    \n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        \n        int r = top.r;\n        int c = top.c;\n        double d = top.dist;\n        \n        if (d > dist[r][c] + 1e-9) continue;\n        if (r == tr && c == tc) break;\n        \n        // Shuffle directions for exploration diversity\n        vector<int> dirs = {0, 1, 2, 3};\n        if (perturb) {\n            shuffle(dirs.begin(), dirs.end(), rng);\n        }\n        \n        for (int i : dirs) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                double weight = 0;\n                int n = 0;\n                double conf = 0;\n                \n                if (i == 0) { // U\n                    weight = v_w[r-1][c];\n                    n = v_n[r-1][c];\n                    conf = v_conf[r-1][c];\n                } else if (i == 1) { // D\n                    weight = v_w[r][c];\n                    n = v_n[r][c];\n                    conf = v_conf[r][c];\n                } else if (i == 2) { // L\n                    weight = h_w[r][c-1];\n                    n = h_n[r][c-1];\n                    conf = h_conf[r][c-1];\n                } else if (i == 3) { // R\n                    weight = h_w[r][c];\n                    n = h_n[r][c];\n                    conf = h_conf[r][c];\n                }\n                \n                // UCB-style exploration bonus\n                double visit_bonus = explore_bonus / sqrt(n + 1);\n                double conf_bonus = explore_bonus * (1.0 - conf) * 0.6;\n                double bonus = visit_bonus + conf_bonus;\n                double cost = max(100.0, weight - bonus);\n                \n                if (dist[r][c] + cost < dist[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + cost;\n                    parent[nr][nc] = {r, c};\n                    dir_to[nr][nc] = dchar[i];\n                    pq.push({dist[nr][nc], nr, nc});\n                }\n            }\n        }\n    }\n    \n    // Reconstruct path\n    string path = \"\";\n    int cr = tr, cc = tc;\n    while (cr != sr || cc != sc) {\n        char d = dir_to[cr][cc];\n        path += d;\n        int pr = parent[cr][cc].first;\n        int pc = parent[cr][cc].second;\n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Detect if row/column has M=2 pattern (bimodal distribution)\nbool detect_m2_pattern(const vector<double>& weights, const vector<int>& counts, double& threshold) {\n    vector<double> visited_weights;\n    for (size_t i = 0; i < weights.size(); ++i) {\n        if (counts[i] > 0) {\n            visited_weights.push_back(weights[i]);\n        }\n    }\n    \n    if (visited_weights.size() < 5) return false;\n    \n    sort(visited_weights.begin(), visited_weights.end());\n    \n    // Look for gap in sorted weights\n    double max_gap = 0;\n    int gap_idx = -1;\n    for (size_t i = 1; i < visited_weights.size(); ++i) {\n        double gap = visited_weights[i] - visited_weights[i-1];\n        if (gap > max_gap) {\n            max_gap = gap;\n            gap_idx = i;\n        }\n    }\n    \n    // If there's a significant gap, it's likely M=2\n    double mean = 0;\n    for (double w : visited_weights) mean += w;\n    mean /= visited_weights.size();\n    \n    if (max_gap > 800 && gap_idx > 0 && gap_idx < (int)visited_weights.size() - 1) {\n        threshold = (visited_weights[gap_idx] + visited_weights[gap_idx-1]) / 2.0;\n        return true;\n    }\n    \n    return false;\n}\n\nvoid smooth_weights() {\n    // Calculate variance and detect M=2 patterns for each row\n    vector<bool> h_is_m2(H, false);\n    vector<double> h_threshold(H, 0);\n    \n    for (int i = 0; i < H; ++i) {\n        if (h_row_n[i] < 5) continue;\n        \n        vector<double> weights;\n        vector<int> counts;\n        for (int j = 0; j < W-1; ++j) {\n            weights.push_back(h_w[i][j]);\n            counts.push_back(h_n[i][j]);\n        }\n        \n        // Calculate variance\n        double mean = h_row_avg[i];\n        double variance = 0;\n        int count = 0;\n        for (int j = 0; j < W-1; ++j) {\n            if (h_n[i][j] > 0) {\n                variance += (h_w[i][j] - mean) * (h_w[i][j] - mean);\n                count++;\n            }\n        }\n        h_row_var[i] = (count > 0) ? variance / count : 1000000;\n        \n        // Detect M=2 pattern\n        h_is_m2[i] = detect_m2_pattern(weights, counts, h_threshold[i]);\n    }\n    \n    // Calculate variance and detect M=2 patterns for each column\n    vector<bool> v_is_m2(W, false);\n    vector<double> v_threshold(W, 0);\n    \n    for (int j = 0; j < W; ++j) {\n        if (v_col_n[j] < 5) continue;\n        \n        vector<double> weights;\n        vector<int> counts;\n        for (int i = 0; i < H-1; ++i) {\n            weights.push_back(v_w[i][j]);\n            counts.push_back(v_n[i][j]);\n        }\n        \n        // Calculate variance\n        double mean = v_col_avg[j];\n        double variance = 0;\n        int count = 0;\n        for (int i = 0; i < H-1; ++i) {\n            if (v_n[i][j] > 0) {\n                variance += (v_w[i][j] - mean) * (v_w[i][j] - mean);\n                count++;\n            }\n        }\n        v_col_var[j] = (count > 0) ? variance / count : 1000000;\n        \n        // Detect M=2 pattern\n        v_is_m2[j] = detect_m2_pattern(weights, counts, v_threshold[j]);\n    }\n    \n    // Smooth horizontal weights\n    for (int i = 0; i < H; ++i) {\n        if (h_row_n[i] < 5) continue;\n        \n        double row_mean = h_row_avg[i];\n        \n        if (h_is_m2[i]) {\n            // M=2 pattern: only smooth within each mode\n            double mean1 = 0, mean2 = 0;\n            int count1 = 0, count2 = 0;\n            double thresh = h_threshold[i];\n            \n            for (int j = 0; j < W-1; ++j) {\n                if (h_n[i][j] > 0) {\n                    if (h_w[i][j] < thresh) {\n                        mean1 += h_w[i][j];\n                        count1++;\n                    } else {\n                        mean2 += h_w[i][j];\n                        count2++;\n                    }\n                }\n            }\n            \n            if (count1 > 0) mean1 /= count1;\n            if (count2 > 0) mean2 /= count2;\n            \n            for (int j = 0; j < W-1; ++j) {\n                if (h_n[i][j] > 0) {\n                    double target = (h_w[i][j] < thresh) ? mean1 : mean2;\n                    double smooth_factor = 0.08 * (1.0 - h_conf[i][j]);\n                    h_w[i][j] = (1.0 - smooth_factor) * h_w[i][j] + smooth_factor * target;\n                }\n            }\n        } else {\n            // M=1 pattern: smooth toward row mean\n            for (int j = 0; j < W-1; ++j) {\n                if (h_n[i][j] > 0) {\n                    double smooth_factor = 0.10 * (1.0 - h_conf[i][j]);\n                    h_w[i][j] = (1.0 - smooth_factor) * h_w[i][j] + smooth_factor * row_mean;\n                }\n            }\n        }\n    }\n    \n    // Smooth vertical weights\n    for (int j = 0; j < W; ++j) {\n        if (v_col_n[j] < 5) continue;\n        \n        double col_mean = v_col_avg[j];\n        \n        if (v_is_m2[j]) {\n            // M=2 pattern: only smooth within each mode\n            double mean1 = 0, mean2 = 0;\n            int count1 = 0, count2 = 0;\n            double thresh = v_threshold[j];\n            \n            for (int i = 0; i < H-1; ++i) {\n                if (v_n[i][j] > 0) {\n                    if (v_w[i][j] < thresh) {\n                        mean1 += v_w[i][j];\n                        count1++;\n                    } else {\n                        mean2 += v_w[i][j];\n                        count2++;\n                    }\n                }\n            }\n            \n            if (count1 > 0) mean1 /= count1;\n            if (count2 > 0) mean2 /= count2;\n            \n            for (int i = 0; i < H-1; ++i) {\n                if (v_n[i][j] > 0) {\n                    double target = (v_w[i][j] < thresh) ? mean1 : mean2;\n                    double smooth_factor = 0.08 * (1.0 - v_conf[i][j]);\n                    v_w[i][j] = (1.0 - smooth_factor) * v_w[i][j] + smooth_factor * target;\n                }\n            }\n        } else {\n            // M=1 pattern: smooth toward column mean\n            for (int i = 0; i < H-1; ++i) {\n                if (v_n[i][j] > 0) {\n                    double smooth_factor = 0.10 * (1.0 - v_conf[i][j]);\n                    v_w[i][j] = (1.0 - smooth_factor) * v_w[i][j] + smooth_factor * col_mean;\n                }\n            }\n        }\n    }\n}\n\nvoid update_weights(const string& path, int sr, int sc, int observed_len, int query_num) {\n    if (path.empty()) return;\n    \n    int cr = sr, cc = sc;\n    double est_len = 0;\n    \n    struct EdgeRef {\n        bool is_h;\n        int r, c;\n        double old_weight;\n    };\n    vector<EdgeRef> path_edges;\n    \n    for (char d : path) {\n        int nr = cr, nc = cc;\n        if (d == 'U') { nr--; }\n        else if (d == 'D') { nr++; }\n        else if (d == 'L') { nc--; }\n        else if (d == 'R') { nc++; }\n        \n        double w = 0;\n        bool is_h = false;\n        int r = 0, c = 0;\n        \n        if (d == 'U') {\n            w = v_w[cr-1][cc];\n            is_h = false; r = cr-1; c = cc;\n        } else if (d == 'D') {\n            w = v_w[cr][cc];\n            is_h = false; r = cr; c = cc;\n        } else if (d == 'L') {\n            w = h_w[cr][cc-1];\n            is_h = true; r = cr; c = cc-1;\n        } else if (d == 'R') {\n            w = h_w[cr][cc];\n            is_h = true; r = cr; c = cc;\n        }\n        \n        est_len += w;\n        path_edges.push_back({is_h, r, c, w});\n        \n        cr = nr;\n        cc = nc;\n    }\n    \n    if (est_len < 1.0) return;\n    \n    // Calculate error ratio and track for adaptive exploration\n    double ratio = (double)observed_len / est_len;\n    double error = abs(ratio - 1.0);\n    recent_errors.push_back(error);\n    if (recent_errors.size() > ERROR_WINDOW) {\n        recent_errors.erase(recent_errors.begin());\n    }\n    \n    // Faster early learning, slower later\n    double error_magnitude = abs(ratio - 1.0);\n    double base_lr = 0.25 + 0.12 * error_magnitude;\n    double decay = exp(-query_num / 350.0);\n    double lr = base_lr * decay;\n    if (lr < 0.04) lr = 0.04;\n    \n    // Update each edge in the path\n    for (auto& edge : path_edges) {\n        double target_weight = edge.old_weight * ratio;\n        \n        if (edge.is_h) {\n            h_w[edge.r][edge.c] = (1.0 - lr) * h_w[edge.r][edge.c] + lr * target_weight;\n            h_n[edge.r][edge.c]++;\n            h_conf[edge.r][edge.c] = min(1.0, h_conf[edge.r][edge.c] + 0.06);\n            h_row_avg[edge.r] = (h_row_avg[edge.r] * h_row_n[edge.r] + h_w[edge.r][edge.c]) / (h_row_n[edge.r] + 1);\n            h_row_n[edge.r]++;\n            \n            if (h_w[edge.r][edge.c] < 1000) h_w[edge.r][edge.c] = 1000;\n            if (h_w[edge.r][edge.c] > 9000) h_w[edge.r][edge.c] = 9000;\n        } else {\n            v_w[edge.r][edge.c] = (1.0 - lr) * v_w[edge.r][edge.c] + lr * target_weight;\n            v_n[edge.r][edge.c]++;\n            v_conf[edge.r][edge.c] = min(1.0, v_conf[edge.r][edge.c] + 0.06);\n            v_col_avg[edge.c] = (v_col_avg[edge.c] * v_col_n[edge.c] + v_w[edge.r][edge.c]) / (v_col_n[edge.c] + 1);\n            v_col_n[edge.c]++;\n            \n            if (v_w[edge.r][edge.c] < 1000) v_w[edge.r][edge.c] = 1000;\n            if (v_w[edge.r][edge.c] > 9000) v_w[edge.r][edge.c] = 9000;\n        }\n    }\n    \n    // Propagate learning to nearby edges\n    for (auto& edge : path_edges) {\n        if (edge.is_h) {\n            for (int j = 0; j < W-1; ++j) {\n                if (j != edge.c && h_n[edge.r][j] < 3) {\n                    double prop_lr = (h_n[edge.r][j] < 2) ? lr * 0.35 : lr * 0.25;\n                    h_w[edge.r][j] = (1.0 - prop_lr) * h_w[edge.r][j] + prop_lr * h_w[edge.r][edge.c];\n                    h_conf[edge.r][j] = max(0.0, h_conf[edge.r][j] - 0.01);\n                }\n            }\n        } else {\n            for (int i = 0; i < H-1; ++i) {\n                if (i != edge.r && v_n[i][edge.c] < 3) {\n                    double prop_lr = (v_n[i][edge.c] < 2) ? lr * 0.35 : lr * 0.25;\n                    v_w[i][edge.c] = (1.0 - prop_lr) * v_w[i][edge.c] + prop_lr * v_w[edge.r][edge.c];\n                    v_conf[i][edge.c] = max(0.0, v_conf[i][edge.c] - 0.01);\n                }\n            }\n        }\n    }\n    \n    // Periodic smoothing (every 80 queries, less frequent)\n    if (query_num > 0 && query_num % 80 == 0) {\n        smooth_weights();\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    init();\n    \n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        string path = dijkstra(si, sj, ti, tj, k);\n        cout << path << \"\\n\" << flush;\n        \n        int observed;\n        cin >> observed;\n        \n        update_weights(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int MAX_M = 800;\nconst int MAX_LEN = 12;\n\nint M;\nchar grid[N][N];\nchar strings[MAX_M][MAX_LEN];\nuint8_t strLen[MAX_M];\nuint8_t strMatched[MAX_M];\nuint8_t strHasChar[MAX_M][8];  // strHasChar[si][c] = 1 if string si contains char c\n\ninline bool checkString(int si) {\n    int len = strLen[si];\n    const char* s = strings[si];\n    \n    // Horizontal\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool ok = true;\n            for (int k = 0; k < len; k++) {\n                char c = grid[i][(j + k) % N];\n                if (c != '.' && c != s[k]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    \n    // Vertical\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool ok = true;\n            for (int k = 0; k < len; k++) {\n                char c = grid[(i + k) % N][j];\n                if (c != '.' && c != s[k]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) return true;\n        }\n    }\n    \n    return false;\n}\n\nint countMatches() {\n    int cnt = 0;\n    for (int i = 0; i < M; i++) {\n        strMatched[i] = checkString(i);\n        if (strMatched[i]) cnt++;\n    }\n    return cnt;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N_in;\n    cin >> N_in >> M;\n    \n    for (int i = 0; i < M; i++) {\n        string tmp;\n        cin >> tmp;\n        strLen[i] = tmp.length();\n        for (int j = 0; j < strLen[i]; j++) {\n            strings[i][j] = tmp[j];\n            strHasChar[i][tmp[j] - 'A'] = 1;\n        }\n    }\n    \n    // Initialize grid\n    for (int i = 0; i < N; i++)\n        for (int j = 0; j < N; j++)\n            grid[i][j] = '.';\n    \n    // Multiple greedy passes with different orderings\n    int order[MAX_M];\n    for (int pass = 0; pass < 3; pass++) {\n        // Reset grid for passes 2 and 3\n        if (pass > 0) {\n            for (int i = 0; i < N; i++)\n                for (int j = 0; j < N; j++)\n                    grid[i][j] = '.';\n        }\n        \n        // Different ordering strategies\n        if (pass == 0) {\n            // Longest first\n            for (int i = 0; i < M; i++) order[i] = i;\n            sort(order, order + M, [&](int a, int b) {\n                return strLen[a] > strLen[b];\n            });\n        } else if (pass == 1) {\n            // Shortest first\n            for (int i = 0; i < M; i++) order[i] = i;\n            sort(order, order + M, [&](int a, int b) {\n                return strLen[a] < strLen[b];\n            });\n        } else {\n            // Random order\n            mt19937 rng(pass);\n            for (int i = 0; i < M; i++) order[i] = i;\n            shuffle(order, order + M, rng);\n        }\n        \n        // Greedy placement\n        for (int idx = 0; idx < M; idx++) {\n            int si = order[idx];\n            int len = strLen[si];\n            const char* s = strings[si];\n            \n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    // Horizontal\n                    bool canPlace = true;\n                    for (int k = 0; k < len; k++) {\n                        char c = grid[i][(j + k) % N];\n                        if (c != '.' && c != s[k]) {\n                            canPlace = false;\n                            break;\n                        }\n                    }\n                    if (canPlace) {\n                        for (int k = 0; k < len; k++)\n                            grid[i][(j + k) % N] = s[k];\n                        goto next_str;\n                    }\n                    \n                    // Vertical\n                    canPlace = true;\n                    for (int k = 0; k < len; k++) {\n                        char c = grid[(i + k) % N][j];\n                        if (c != '.' && c != s[k]) {\n                            canPlace = false;\n                            break;\n                        }\n                    }\n                    if (canPlace) {\n                        for (int k = 0; k < len; k++)\n                            grid[(i + k) % N][j] = s[k];\n                        goto next_str;\n                    }\n                }\n            }\n            next_str:;\n        }\n    }\n    \n    // Use best of the three passes (for now, just use last)\n    // Count initial matches\n    int totalMatches = 0;\n    for (int i = 0; i < M; i++) {\n        strMatched[i] = checkString(i);\n        if (strMatched[i]) totalMatches++;\n    }\n    \n    // Very light local search - only 1500 iterations\n    mt19937 rng(42);\n    int iterations = 1500;\n    \n    for (int iter = 0; iter < iterations; iter++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        char old = grid[i][j];\n        \n        char newChar;\n        if (old == '.') {\n            newChar = 'A' + (rng() % 8);\n        } else {\n            if (rng() % 8 == 0) {\n                newChar = '.';\n            } else {\n                newChar = 'A' + (rng() % 8);\n            }\n        }\n        \n        if (newChar == old) continue;\n        \n        grid[i][j] = newChar;\n        \n        // Only check strings that contain old or new character\n        int oldTotal = totalMatches;\n        static int affectedList[MAX_M];\n        int affectedCount = 0;\n        \n        for (int si = 0; si < M; si++) {\n            if (strHasChar[si][old - 'A'] || strHasChar[si][newChar - 'A']) {\n                affectedList[affectedCount++] = si;\n            }\n        }\n        \n        for (int k = 0; k < affectedCount; k++) {\n            int si = affectedList[k];\n            bool wasMatched = strMatched[si];\n            bool isMatched = checkString(si);\n            strMatched[si] = isMatched;\n            \n            if (wasMatched && !isMatched) totalMatches--;\n            else if (!wasMatched && isMatched) totalMatches++;\n        }\n        \n        int delta = totalMatches - oldTotal;\n        \n        bool accept = (delta >= 0);\n        if (!accept && delta < 0) {\n            double r = (double)(rng() % 10000) / 10000.0;\n            accept = (exp(delta / 5.0) > r);\n        }\n        \n        if (!accept) {\n            grid[i][j] = old;\n            // Restore\n            for (int k = 0; k < affectedCount; k++) {\n                int si = affectedList[k];\n                strMatched[si] = checkString(si);\n            }\n            totalMatches = 0;\n            for (int si = 0; si < M; si++)\n                if (strMatched[si]) totalMatches++;\n        }\n    }\n    \n    // Fill remaining '.' if all matched\n    if (totalMatches == M) {\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] = 'A' + (rng() % 8);\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++)\n            cout << grid[i][j];\n        cout << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nconst int MAX_N = 70;\nconst int MAX_SEGMENTS = 5000;\nconst long long INF = 1e18;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<Point> road_squares;\nint segment_h[MAX_N][MAX_N];\nint segment_v[MAX_N][MAX_N];\nint num_h_segments = 0;\nint num_v_segments = 0;\nint total_road_squares = 0;\nint total_segments = 0;\n\nvector<Point> key_points;\nmap<Point, int> point_to_idx;\nint num_key_points = 0;\nint start_idx = -1;\n\nconst int MAX_KP = 300;\nlong long dist_mat[MAX_KP][MAX_KP];\nbitset<MAX_SEGMENTS> coverage_mat[MAX_KP][MAX_KP];\nvector<Point> path_mat[MAX_KP][MAX_KP];\n\nlong long dist_from_kp[MAX_KP][MAX_N][MAX_N];\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\n\nbool is_road(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N && grid[r][c] != '#';\n}\n\nint get_cost(int r, int c) {\n    return grid[r][c] - '0';\n}\n\nvoid identify_segments() {\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            segment_h[i][j] = -1;\n            segment_v[i][j] = -1;\n        }\n    }\n\n    for(int i=0; i<N; ++i) {\n        int j = 0;\n        while(j < N) {\n            if (grid[i][j] == '#') { j++; continue; }\n            int start_j = j;\n            while(j < N && grid[i][j] != '#') j++;\n            for(int k=start_j; k<j; ++k) segment_h[i][k] = num_h_segments;\n            num_h_segments++;\n        }\n    }\n\n    for(int j=0; j<N; ++j) {\n        int i = 0;\n        while(i < N) {\n            if (grid[i][j] == '#') { i++; continue; }\n            int start_i = i;\n            while(i < N && grid[i][j] != '#') i++;\n            for(int k=start_i; k<i; ++k) segment_v[k][j] = num_v_segments;\n            num_v_segments++;\n        }\n    }\n    \n    total_segments = num_h_segments + num_v_segments;\n}\n\nvoid identify_key_points() {\n    set<Point> kp_set;\n    kp_set.insert({si, sj});\n\n    for(const auto& p : road_squares) {\n        int degree = 0;\n        for(int d=0; d<4; ++d) {\n            int nr = p.r + dr[d], nc = p.c + dc[d];\n            if(is_road(nr, nc)) degree++;\n        }\n        if(degree != 2) kp_set.insert(p);\n    }\n    \n    if((int)kp_set.size() > MAX_KP - 10) {\n        vector<Point> sorted_kp(kp_set.begin(), kp_set.end());\n        sort(sorted_kp.begin(), sorted_kp.end(), [&](const Point& a, const Point& b) {\n            return abs(a.r - si) + abs(a.c - sj) < abs(b.r - si) + abs(b.c - sj);\n        });\n        kp_set.clear();\n        for(int i=0; i<MAX_KP - 10 && i<(int)sorted_kp.size(); ++i) kp_set.insert(sorted_kp[i]);\n        kp_set.insert({si, sj});\n    }\n\n    for(const auto& p : kp_set) {\n        if(num_key_points >= MAX_KP) break;\n        point_to_idx[p] = num_key_points;\n        key_points.push_back(p);\n        if(p.r == si && p.c == sj) start_idx = num_key_points;\n        num_key_points++;\n    }\n}\n\nvoid compute_apsp() {\n    for(int i=0; i<num_key_points; ++i) {\n        for(int j=0; j<num_key_points; ++j) {\n            dist_mat[i][j] = INF;\n        }\n    }\n\n    static long long d_grid[MAX_N][MAX_N];\n    static bitset<MAX_SEGMENTS> c_grid[MAX_N][MAX_N];\n    static Point parent_grid[MAX_N][MAX_N];\n    static bool visited[MAX_N][MAX_N];\n\n    for(int src_idx = 0; src_idx < num_key_points; ++src_idx) {\n        Point src = key_points[src_idx];\n        \n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                d_grid[i][j] = INF;\n                visited[i][j] = false;\n                dist_from_kp[src_idx][i][j] = INF;\n            }\n        }\n\n        priority_queue<pair<long long, Point>, vector<pair<long long, Point>>, greater<pair<long long, Point>>> pq;\n        \n        d_grid[src.r][src.c] = 0;\n        dist_from_kp[src_idx][src.r][src.c] = 0;\n        c_grid[src.r][src.c].reset();\n        if(segment_h[src.r][src.c] >= 0 && segment_h[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_h[src.r][src.c]);\n        if(segment_v[src.r][src.c] >= 0 && segment_v[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_v[src.r][src.c]);\n        \n        pq.push({0, src});\n        parent_grid[src.r][src.c] = {-1, -1};\n        \n        while(!pq.empty()) {\n            long long cost = pq.top().first;\n            Point u = pq.top().second;\n            pq.pop();\n\n            if(visited[u.r][u.c]) continue;\n            visited[u.r][u.c] = true;\n\n            if(point_to_idx.count(u)) {\n                int v_idx = point_to_idx[u];\n                dist_mat[src_idx][v_idx] = cost;\n                coverage_mat[src_idx][v_idx] = c_grid[u.r][u.c];\n                \n                vector<Point> path;\n                Point curr = u;\n                while(curr.r != -1) {\n                    path.push_back(curr);\n                    if(curr.r == src.r && curr.c == src.c) break;\n                    curr = parent_grid[curr.r][curr.c];\n                }\n                reverse(path.begin(), path.end());\n                path_mat[src_idx][v_idx] = path;\n            }\n\n            for(int d=0; d<4; ++d) {\n                int nr = u.r + dr[d], nc = u.c + dc[d];\n                if(is_road(nr, nc)) {\n                    long long new_cost = cost + get_cost(nr, nc);\n\n                    if(new_cost < d_grid[nr][nc]) {\n                        d_grid[nr][nc] = new_cost;\n                        dist_from_kp[src_idx][nr][nc] = new_cost;\n                        c_grid[nr][nc] = c_grid[u.r][u.c];\n                        if(segment_h[nr][nc] >= 0 && segment_h[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_h[nr][nc]);\n                        if(segment_v[nr][nc] >= 0 && segment_v[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_v[nr][nc]);\n                        parent_grid[nr][nc] = u;\n                        pq.push({new_cost, {nr, nc}});\n                    }\n                }\n            }\n        }\n    }\n}\n\nvector<int> current_path;\nlong long current_dist = 0;\nbitset<MAX_SEGMENTS> current_cov;\nlong long best_dist = INF;\nvector<int> best_path;\nint best_coverage = 0;\n\nvoid ensure_start_end(vector<int>& path) {\n    if(path.empty()) {\n        path = {start_idx, start_idx};\n        return;\n    }\n    while(!path.empty() && path.front() != start_idx) path.erase(path.begin());\n    while(!path.empty() && path.back() != start_idx) path.pop_back();\n    if(path.empty()) path = {start_idx, start_idx};\n    else if((int)path.size() == 1) path.push_back(start_idx);\n}\n\nlong long calc_path_dist(const vector<int>& path) {\n    long long d = 0;\n    for(size_t i=0; i+1<path.size(); ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            d += dist_mat[path[i]][path[i+1]];\n    }\n    return d;\n}\n\nbitset<MAX_SEGMENTS> calc_path_cov(const vector<int>& path) {\n    bitset<MAX_SEGMENTS> c;\n    for(size_t i=0; i+1<path.size(); ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            c |= coverage_mat[path[i]][path[i+1]];\n    }\n    return c;\n}\n\nvoid update_state() {\n    current_dist = calc_path_dist(current_path);\n    current_cov = calc_path_cov(current_path);\n    best_coverage = (int)current_cov.count();\n}\n\nlong long energy() {\n    int covered_segs = (int)current_cov.count();\n    long long penalty = (long long)(total_segments - covered_segs) * 10000000LL;\n    return penalty + current_dist;\n}\n\n// Simple nearest-neighbor greedy initial solution\nvoid build_greedy_initial() {\n    vector<int> path = {start_idx};\n    vector<bool> visited(num_key_points, false);\n    if(start_idx >= 0) visited[start_idx] = true;\n    \n    int current = start_idx;\n    while(true) {\n        int best_next = -1;\n        long long best_d = INF;\n        \n        for(int kp = 0; kp < num_key_points; ++kp) {\n            if(visited[kp]) continue;\n            if(dist_mat[current][kp] < best_d) {\n                best_d = dist_mat[current][kp];\n                best_next = kp;\n            }\n        }\n        \n        if(best_next == -1 || best_d >= INF) break;\n        \n        visited[best_next] = true;\n        path.push_back(best_next);\n        current = best_next;\n    }\n    \n    path.push_back(start_idx);\n    current_path = path;\n    update_state();\n    best_path = current_path;\n    best_dist = current_dist;\n    best_coverage = (int)current_cov.count();\n}\n\nvoid solve_sa() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.7;\n\n    int iter = 0;\n    double temp = 50000.0;\n    double cooling = 0.9998;\n\n    while(true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        if(best_coverage >= total_segments && iter > 2000) {\n            if(time_limit - elapsed < 0.15) break;\n        }\n        \n        vector<int> next_path = current_path;\n        int type = rng() % 5;\n        \n        if((int)next_path.size() > 2) {\n            if(type == 0 && (int)next_path.size() > 3) {\n                int i = 1 + rng() % ((int)next_path.size() - 2);\n                int j = i + 1 + rng() % ((int)next_path.size() - 1 - i);\n                if(j >= (int)next_path.size() - 1) j = (int)next_path.size() - 2;\n                reverse(next_path.begin() + i, next_path.begin() + j + 1);\n            } else if(type == 1 && (int)next_path.size() > 3) {\n                int i = 1 + rng() % ((int)next_path.size() - 2);\n                int j = 1 + rng() % ((int)next_path.size() - 2);\n                swap(next_path[i], next_path[j]);\n            } else if(type == 2 || type == 3) {\n                int idx = 1 + rng() % ((int)next_path.size());\n                int kp = rng() % num_key_points;\n                next_path.insert(next_path.begin() + idx, kp);\n            } else {\n                if((int)next_path.size() > 3) {\n                    int idx = 1 + rng() % ((int)next_path.size() - 2);\n                    next_path.erase(next_path.begin() + idx);\n                }\n            }\n        } else {\n            int kp = rng() % num_key_points;\n            next_path.insert(next_path.begin() + 1, kp);\n        }\n\n        ensure_start_end(next_path);\n\n        long long next_dist = calc_path_dist(next_path);\n        if(next_dist >= INF) continue;\n        \n        bitset<MAX_SEGMENTS> next_cov = calc_path_cov(next_path);\n        int next_coverage = (int)next_cov.count();\n\n        long long current_energy = energy();\n        long long next_penalty = (long long)(total_segments - next_coverage) * 10000000LL;\n        long long next_energy = next_penalty + next_dist;\n\n        double delta = (double)(next_energy - current_energy);\n        bool accept = false;\n        if(delta < 0) accept = true;\n        else {\n            double prob = exp(-delta / temp);\n            if((double)rng() / rng.max() < prob) accept = true;\n        }\n\n        if(accept) {\n            current_path = next_path;\n            current_dist = next_dist;\n            current_cov = next_cov;\n        }\n        \n        if(next_coverage >= total_segments) {\n            if(next_dist < best_dist) {\n                best_dist = next_dist;\n                best_path = next_path;\n                best_coverage = next_coverage;\n            }\n        } else if(next_coverage > best_coverage) {\n            best_coverage = next_coverage;\n            best_path = next_path;\n            best_dist = next_dist;\n        }\n\n        temp *= cooling;\n        iter++;\n    }\n}\n\nvoid quick_greedy_fix() {\n    ensure_start_end(best_path);\n    \n    bitset<MAX_SEGMENTS> cov;\n    for(size_t i=0; i+1<best_path.size(); ++i) {\n        if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n            cov |= coverage_mat[best_path[i]][best_path[i+1]];\n    }\n    \n    if((int)cov.count() >= total_segments) return;\n\n    // Single pass, limited iterations\n    for(int fix_iter = 0; fix_iter < 50 && (int)cov.count() < total_segments; ++fix_iter) {\n        int missing_seg = -1;\n        for(int i=0; i<total_segments && i<MAX_SEGMENTS; ++i) {\n            if(!cov.test(i)) {\n                missing_seg = i;\n                break;\n            }\n        }\n        \n        if(missing_seg == -1) break;\n        \n        int best_kp = -1;\n        long long min_insert_cost = INF;\n        int best_pos = -1;\n\n        for(int kp=0; kp<num_key_points; ++kp) {\n            Point p = key_points[kp];\n            bool covers = (segment_h[p.r][p.c] == missing_seg || segment_v[p.r][p.c] == missing_seg);\n            \n            if(covers) {\n                for(size_t i=0; i+1<best_path.size(); ++i) {\n                    int u = best_path[i], v = best_path[i+1];\n                    if(u >= num_key_points || v >= num_key_points) continue;\n                    long long cost = dist_mat[u][kp] + dist_mat[kp][v] - dist_mat[u][v];\n                    if(cost < min_insert_cost) {\n                        min_insert_cost = cost;\n                        best_kp = kp;\n                        best_pos = (int)i + 1;\n                    }\n                }\n            }\n        }\n        \n        if(best_kp != -1 && best_pos != -1) {\n            best_path.insert(best_path.begin() + best_pos, best_kp);\n            ensure_start_end(best_path);\n            cov.reset();\n            for(size_t i=0; i+1<best_path.size(); ++i) {\n                if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n                    cov |= coverage_mat[best_path[i]][best_path[i+1]];\n            }\n        } else {\n            break;\n        }\n    }\n}\n\nvoid output_solution() {\n    ensure_start_end(best_path);\n    \n    if(best_path.empty() || best_path.front() != start_idx || best_path.back() != start_idx) {\n        cout << \"\" << endl;\n        return;\n    }\n    \n    string res = \"\";\n    Point curr = {si, sj};\n    for(size_t i=0; i+1<best_path.size(); ++i) {\n        int u = best_path[i], v = best_path[i+1];\n        if(u >= num_key_points || v >= num_key_points) continue;\n        const auto& segment = path_mat[u][v];\n        for(size_t k=1; k<segment.size(); ++k) {\n            Point next = segment[k];\n            if(next.r == curr.r + 1) res += 'D';\n            else if(next.r == curr.r - 1) res += 'U';\n            else if(next.c == curr.c + 1) res += 'R';\n            else if(next.c == curr.c - 1) res += 'L';\n            curr = next;\n        }\n    }\n    cout << res << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if(!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for(int i=0; i<N; ++i) cin >> grid[i];\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                total_road_squares++;\n            }\n        }\n    }\n\n    identify_segments();\n    identify_key_points();\n    compute_apsp();\n\n    build_greedy_initial();\n    solve_sa();\n    quick_greedy_fix();\n    output_solution();\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <numeric>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    \n    // Read initial input\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    // Read task difficulties\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    // Read dependencies\n    vector<vector<int>> deps(N);\n    vector<vector<int>> rev_deps(N);\n    vector<int> in_degree(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        deps[v].push_back(u);\n        rev_deps[u].push_back(v);\n        in_degree[v]++;\n    }\n    \n    // Skill estimates (start with reasonable guess based on task difficulty distribution)\n    vector<vector<double>> s_est(M, vector<double>(K, 35.0));\n    vector<int> s_obs_count(M, 0);\n    \n    // Task status: -1 = not started, 0 = in progress, 1 = completed\n    vector<int> task_status(N, -1);\n    \n    // Member tracking\n    vector<int> member_task(M, -1);\n    vector<int> member_start_day(M, -1);\n    \n    // Observations for learning: (task_id, observed_days)\n    vector<vector<pair<int, int>>> member_obs(M);\n    \n    // Task priority (estimated remaining tasks in dependency chain)\n    vector<int> task_priority(N, 0);\n    \n    // Calculate task priorities using reverse topological order\n    for (int i = N - 1; i >= 0; i--) {\n        task_priority[i] = 1;\n        for (int next : rev_deps[i]) {\n            task_priority[i] = max(task_priority[i], task_priority[next] + 1);\n        }\n    }\n    \n    int day = 0;\n    int completed_count = 0;\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(42);\n    \n    while (true) {\n        day++;\n        \n        // Read completion information\n        int n_completed;\n        cin >> n_completed;\n        \n        if (n_completed == -1) {\n            break;\n        }\n        \n        vector<int> completed_members(n_completed);\n        for (int i = 0; i < n_completed; i++) {\n            cin >> completed_members[i];\n            completed_members[i]--;\n        }\n        \n        // Process completions and update skill estimates\n        for (int member : completed_members) {\n            if (member_task[member] >= 0) {\n                int task = member_task[member];\n                int days_taken = day - member_start_day[member];\n                \n                task_status[task] = 1;\n                completed_count++;\n                \n                // Record observation\n                member_obs[member].push_back({task, days_taken});\n                s_obs_count[member]++;\n                \n                // Update skill estimate using observed data\n                // w = sum(max(0, d_k - s_k)) \u2248 days_taken (when w > 0)\n                // We try to adjust s_k to reduce the gap\n                if (days_taken > 1 && s_obs_count[member] <= 50) {\n                    // Early learning phase - more aggressive updates\n                    double learning_rate = 0.3 / min(10, s_obs_count[member]);\n                    \n                    for (int k = 0; k < K; k++) {\n                        double deficit = max(0.0, (double)d[task][k] - s_est[member][k]);\n                        // If task took long, increase skill estimate for skills where there was deficit\n                        if (deficit > 0) {\n                            s_est[member][k] += learning_rate * deficit * 0.5;\n                        }\n                        // Cap skill estimates reasonably\n                        s_est[member][k] = min(80.0, max(5.0, s_est[member][k]));\n                    }\n                }\n                \n                member_task[member] = -1;\n                member_start_day[member] = -1;\n            }\n        }\n        \n        // Check if all tasks completed\n        if (completed_count >= N) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Find ready tasks (all dependencies completed, not started)\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == -1) {\n                bool all_deps_done = true;\n                for (int dep : deps[i]) {\n                    if (task_status[dep] != 1) {\n                        all_deps_done = false;\n                        break;\n                    }\n                }\n                if (all_deps_done) {\n                    ready_tasks.push_back(i);\n                }\n            }\n        }\n        \n        // Find idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n        \n        if (idle_members.empty() || ready_tasks.empty()) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Calculate estimated completion time for each (member, task) pair\n        vector<vector<double>> est_time(M, vector<double>(N, 1e9));\n        for (int member : idle_members) {\n            for (int task : ready_tasks) {\n                double w = 0;\n                for (int k = 0; k < K; k++) {\n                    w += max(0.0, (double)d[task][k] - s_est[member][k]);\n                }\n                est_time[member][task] = (w == 0) ? 1.0 : max(1.0, w);\n            }\n        }\n        \n        // Greedy assignment: match tasks to members minimizing estimated time\n        // Prioritize high-priority tasks and good skill matches\n        vector<pair<int, int>> assignments;\n        vector<bool> task_assigned(ready_tasks.size(), false);\n        vector<bool> member_used(idle_members.size(), false);\n        \n        // Create assignment candidates with scores\n        vector<tuple<double, int, int, int>> candidates; // (score, priority, member_idx, task_idx)\n        for (size_t mi = 0; mi < idle_members.size(); mi++) {\n            for (size_t ti = 0; ti < ready_tasks.size(); ti++) {\n                int member = idle_members[mi];\n                int task = ready_tasks[ti];\n                double score = est_time[member][task] - task_priority[task] * 0.1;\n                candidates.push_back({score, task_priority[task], (int)mi, (int)ti});\n            }\n        }\n        \n        // Sort by score (lower is better)\n        sort(candidates.begin(), candidates.end());\n        \n        // Assign greedily\n        for (auto& [score, priority, mi, ti] : candidates) {\n            if (member_used[mi] || task_assigned[ti]) continue;\n            \n            int member = idle_members[mi];\n            int task = ready_tasks[ti];\n            \n            assignments.push_back({member + 1, task + 1});\n            member_used[mi] = true;\n            task_assigned[ti] = true;\n            \n            member_task[member] = task;\n            member_start_day[member] = day;\n            task_status[task] = 0;\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n        \n        // Output skill predictions for visualization (optional)\n        if (day % 50 == 1) {\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 << endl;\n            }\n            cout.flush();\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n    int order_id;\n    bool is_pickup;\n};\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nconst int OFFICE_X = 400, OFFICE_Y = 400;\nconst int NUM_ORDERS = 1000;\nconst int SELECT_COUNT = 50;\n\n// Global buffers to avoid reallocation\nstatic vector<bool> g_picked;\nstatic vector<bool> g_pickup_done;\nstatic vector<bool> g_delivery_done;\nstatic vector<pair<double, int>> g_scores;\nstatic vector<tuple<int, int, bool>> g_candidates;\n\nvoid init_buffers() {\n    g_picked.resize(NUM_ORDERS);\n    g_pickup_done.resize(NUM_ORDERS);\n    g_delivery_done.resize(NUM_ORDERS);\n    g_scores.reserve(NUM_ORDERS);\n    g_candidates.reserve(SELECT_COUNT * 2);\n}\n\nlong long calc_distance(const vector<Point>& route) {\n    long long 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\ninline bool is_valid_route(const vector<Point>& route) {\n    fill(g_picked.begin(), g_picked.end(), false);\n    for (const auto& p : route) {\n        if (p.order_id == -1) continue;\n        if (p.is_pickup) {\n            g_picked[p.order_id] = true;\n        } else {\n            if (!g_picked[p.order_id]) return false;\n        }\n    }\n    return true;\n}\n\n// Greedy nearest-neighbor route construction\nvector<Point> build_greedy_route(const vector<int>& selected, const vector<Order>& orders, mt19937& rng, double randomness = 0.3) {\n    vector<Point> route;\n    route.reserve(SELECT_COUNT * 2 + 2);\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    fill(g_pickup_done.begin(), g_pickup_done.end(), false);\n    fill(g_delivery_done.begin(), g_delivery_done.end(), false);\n    \n    int remaining = SELECT_COUNT * 2;\n    int cur_x = OFFICE_X, cur_y = OFFICE_Y;\n    \n    while (remaining > 0) {\n        g_candidates.clear();\n        \n        for (int idx : selected) {\n            if (!g_pickup_done[idx] && !g_delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].ax, orders[idx].ay);\n                int lookahead = manhattan(orders[idx].ax, orders[idx].ay, orders[idx].cx, orders[idx].cy);\n                g_candidates.emplace_back(dist + lookahead / 3, idx, true);\n            }\n            if (g_pickup_done[idx] && !g_delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].cx, orders[idx].cy);\n                int lookahead = manhattan(orders[idx].cx, orders[idx].cy, OFFICE_X, OFFICE_Y);\n                g_candidates.emplace_back(dist + lookahead / 4, idx, false);\n            }\n        }\n        \n        if (g_candidates.empty()) break;\n        \n        if (g_candidates.size() > 1) {\n            sort(g_candidates.begin(), g_candidates.end());\n            int k = min((int)g_candidates.size(), 2 + (int)(randomness * 6));\n            int choice = uniform_int_distribution<int>(0, k - 1)(rng);\n            auto [score, order_idx, is_pickup] = g_candidates[choice];\n            \n            if (is_pickup) {\n                route.push_back({orders[order_idx].ax, orders[order_idx].ay, order_idx, true});\n                g_pickup_done[order_idx] = true;\n                cur_x = orders[order_idx].ax;\n                cur_y = orders[order_idx].ay;\n            } else {\n                route.push_back({orders[order_idx].cx, orders[order_idx].cy, order_idx, false});\n                g_delivery_done[order_idx] = true;\n                cur_x = orders[order_idx].cx;\n                cur_y = orders[order_idx].cy;\n            }\n        } else {\n            auto [score, order_idx, is_pickup] = g_candidates[0];\n            if (is_pickup) {\n                route.push_back({orders[order_idx].ax, orders[order_idx].ay, order_idx, true});\n                g_pickup_done[order_idx] = true;\n            } else {\n                route.push_back({orders[order_idx].cx, orders[order_idx].cy, order_idx, false});\n                g_delivery_done[order_idx] = true;\n            }\n        }\n        remaining--;\n    }\n    \n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    return route;\n}\n\n// Angle-based route construction (all pickups sorted by angle, then deliveries)\nvector<Point> build_angle_route(const vector<int>& selected, const vector<Order>& orders) {\n    vector<Point> route;\n    route.reserve(SELECT_COUNT * 2 + 2);\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    // Sort pickups by angle from office\n    vector<pair<double, int>> pickups;\n    pickups.reserve(selected.size());\n    for (int idx : selected) {\n        double angle = atan2(orders[idx].ay - OFFICE_Y, orders[idx].ax - OFFICE_X);\n        pickups.emplace_back(angle, idx);\n    }\n    sort(pickups.begin(), pickups.end());\n    \n    for (auto& p : pickups) {\n        int idx = p.second;\n        route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n    }\n    \n    // Sort deliveries by angle from office\n    vector<pair<double, int>> deliveries;\n    deliveries.reserve(selected.size());\n    for (int idx : selected) {\n        double angle = atan2(orders[idx].cy - OFFICE_Y, orders[idx].cx - OFFICE_X);\n        deliveries.emplace_back(angle, idx);\n    }\n    sort(deliveries.begin(), deliveries.end());\n    \n    for (auto& p : deliveries) {\n        int idx = p.second;\n        route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n    }\n    \n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    return route;\n}\n\nvector<int> select_orders(const vector<Order>& orders, mt19937& rng, bool use_clustering = false) {\n    g_scores.clear();\n    \n    for (int i = 0; i < NUM_ORDERS; i++) {\n        int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n        int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n        int return_dist = manhattan(orders[i].cx, orders[i].cy, OFFICE_X, OFFICE_Y);\n        double score = pickup_dist + delivery_dist * 1.5 + return_dist;\n        score += uniform_real_distribution<double>(0, 50)(rng);\n        g_scores.emplace_back(score, i);\n    }\n    \n    sort(g_scores.begin(), g_scores.end());\n    \n    if (!use_clustering) {\n        vector<int> selected;\n        selected.reserve(SELECT_COUNT);\n        for (int i = 0; i < SELECT_COUNT; i++) {\n            selected.push_back(g_scores[i].second);\n        }\n        return selected;\n    }\n    \n    vector<int> selected;\n    selected.reserve(SELECT_COUNT);\n    static vector<bool> used;\n    if (used.size() != NUM_ORDERS) used.resize(NUM_ORDERS);\n    fill(used.begin(), used.end(), false);\n    \n    vector<pair<double, int>> candidates;\n    candidates.reserve(100);\n    for (int i = 0; i < min(100, NUM_ORDERS); i++) {\n        candidates.push_back(g_scores[i]);\n    }\n    \n    while ((int)selected.size() < SELECT_COUNT && !candidates.empty()) {\n        if (selected.empty()) {\n            selected.push_back(candidates[0].second);\n            used[candidates[0].second] = true;\n            candidates.erase(candidates.begin());\n        } else {\n            int best_idx = 0;\n            double best_score = 1e18;\n            \n            for (int i = 0; i < min(15, (int)candidates.size()); i++) {\n                int order_idx = candidates[i].second;\n                double min_dist = 1e18;\n                \n                for (int sel : selected) {\n                    double d = min({\n                        (double)manhattan(orders[order_idx].ax, orders[order_idx].ay, orders[sel].ax, orders[sel].ay),\n                        (double)manhattan(orders[order_idx].cx, orders[order_idx].cy, orders[sel].cx, orders[sel].cy)\n                    });\n                    min_dist = min(min_dist, d);\n                }\n                \n                double office_dist = manhattan(OFFICE_X, OFFICE_Y, orders[order_idx].ax, orders[order_idx].ay);\n                double combined = min_dist * 0.6 + office_dist * 0.4;\n                \n                if (combined < best_score) {\n                    best_score = combined;\n                    best_idx = i;\n                }\n            }\n            \n            selected.push_back(candidates[best_idx].second);\n            used[candidates[best_idx].second] = true;\n            candidates.erase(candidates.begin() + best_idx);\n        }\n    }\n    \n    while ((int)selected.size() < SELECT_COUNT && !candidates.empty()) {\n        selected.push_back(candidates.back().second);\n        candidates.pop_back();\n    }\n    \n    return selected;\n}\n\nbool try_swap_order(vector<int>& selected, vector<bool>& is_selected, const vector<Order>& orders, \n                    long long& best_dist, vector<Point>& best_route, mt19937& rng) {\n    int remove_idx = uniform_int_distribution<int>(0, SELECT_COUNT - 1)(rng);\n    int remove_order = selected[remove_idx];\n    \n    g_scores.clear();\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        if (!is_selected[i]) {\n            int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n            int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n            double score = pickup_dist + delivery_dist * 1.5;\n            g_scores.emplace_back(score, i);\n        }\n    }\n    sort(g_scores.begin(), g_scores.end());\n    \n    for (int try_idx = 0; try_idx < min(15, (int)g_scores.size()); try_idx++) {\n        int add_order = g_scores[try_idx].second;\n        \n        vector<int> new_selected = selected;\n        new_selected[remove_idx] = add_order;\n        \n        is_selected[remove_order] = false;\n        is_selected[add_order] = true;\n        \n        vector<Point> new_route = build_greedy_route(new_selected, orders, rng, 0.2);\n        long long new_dist = calc_distance(new_route);\n        \n        if (new_dist < best_dist) {\n            selected = new_selected;\n            best_dist = new_dist;\n            best_route = new_route;\n            return true;\n        } else {\n            is_selected[remove_order] = true;\n            is_selected[add_order] = false;\n        }\n    }\n    \n    return false;\n}\n\n// Adaptive simulated annealing with move type tracking\nvoid optimize_route_adaptive(vector<Point>& route, long long& best_dist, vector<Point>& best_route, \n                             mt19937& rng, const chrono::steady_clock::time_point& start_time, double end_time) {\n    double temperature = 12000.0;\n    int iterations = 0;\n    int no_improve_count = 0;\n    \n    // Track move success rates\n    vector<int> move_success = {0, 0, 0, 0}; // 2-opt, swap, relocate, 3-opt\n    vector<int> move_tried = {0, 0, 0, 0};\n    int move_type = 0;\n    \n    while (temperature > 0.5) {\n        iterations++;\n        \n        // Check time every 3000 iterations\n        if (iterations % 3000 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > end_time) break;\n        }\n        \n        // Adaptive move selection based on success rate\n        if (iterations % 500 == 0 && iterations > 500) {\n            vector<pair<double, int>> move_scores;\n            for (int i = 0; i < 4; i++) {\n                double rate = move_tried[i] > 0 ? (double)move_success[i] / move_tried[i] : 0.3;\n                move_scores.emplace_back(rate, i);\n            }\n            sort(move_scores.rbegin(), move_scores.rend());\n            \n            // Prefer successful moves but add randomness\n            int k = min(2, 4);\n            int choice = uniform_int_distribution<int>(0, k - 1)(rng);\n            move_type = move_scores[choice].second;\n        } else {\n            move_type = (move_type + 1) % 4;\n        }\n        \n        bool improved = false;\n        move_tried[move_type]++;\n        \n        if (move_type == 0) {\n            // 2-opt - most effective\n            int i = uniform_int_distribution<int>(1, (int)route.size() - 3)(rng);\n            int j = uniform_int_distribution<int>(i + 1, (int)route.size() - 2)(rng);\n            \n            vector<Point> new_route = route;\n            reverse(new_route.begin() + i, new_route.begin() + j + 1);\n            \n            if (is_valid_route(new_route)) {\n                long long new_dist = calc_distance(new_route);\n                double delta = new_dist - best_dist;\n                \n                if (delta < 0 || exp(-delta / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                    route = new_route;\n                    if (new_dist < best_dist) {\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                    }\n                }\n            }\n        } else if (move_type == 1) {\n            // Swap two points\n            int i = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            int j = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            \n            if (i != j) {\n                vector<Point> new_route = route;\n                swap(new_route[i], new_route[j]);\n                \n                if (is_valid_route(new_route)) {\n                    long long new_dist = calc_distance(new_route);\n                    if (new_dist < best_dist) {\n                        route = new_route;\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                    } else if (exp(-(new_dist - best_dist) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                        route = new_route;\n                    }\n                }\n            }\n        } else if (move_type == 2) {\n            // Relocate single point\n            int pos = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            int new_pos = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            \n            if (pos != new_pos) {\n                vector<Point> new_route = route;\n                Point p = new_route[pos];\n                new_route.erase(new_route.begin() + pos);\n                int insert_pos = new_pos;\n                if (insert_pos > pos) insert_pos--;\n                new_route.insert(new_route.begin() + insert_pos, p);\n                \n                if (is_valid_route(new_route)) {\n                    long long new_dist = calc_distance(new_route);\n                    if (new_dist < best_dist) {\n                        route = new_route;\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                    } else if (exp(-(new_dist - best_dist) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                        route = new_route;\n                    }\n                }\n            }\n        } else {\n            // 3-opt style - more powerful but less frequent\n            if (route.size() > 6) {\n                int i = uniform_int_distribution<int>(1, (int)route.size() - 5)(rng);\n                int j = uniform_int_distribution<int>(i + 1, (int)route.size() - 3)(rng);\n                int k = uniform_int_distribution<int>(j + 1, (int)route.size() - 2)(rng);\n                \n                vector<Point> new_route = route;\n                reverse(new_route.begin() + i, new_route.begin() + j + 1);\n                reverse(new_route.begin() + j + 1, new_route.begin() + k + 1);\n                \n                if (is_valid_route(new_route)) {\n                    long long new_dist = calc_distance(new_route);\n                    if (new_dist < best_dist) {\n                        route = new_route;\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                    }\n                }\n            }\n        }\n        \n        if (improved) {\n            move_success[move_type]++;\n            no_improve_count = 0;\n            temperature = min(12000.0, temperature * 1.2);\n        } else {\n            no_improve_count++;\n            if (no_improve_count > 6000) {\n                temperature *= 0.6;\n                no_improve_count = 0;\n            }\n        }\n        \n        temperature *= 0.9998;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    init_buffers();\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.95; // Use 97.5% of available time\n    \n    // Read input\n    vector<Order> orders(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n    }\n    \n    // 9 strategies with diverse parameters including angle-based routes\n    vector<tuple<long long, double, bool, bool>> strategies = {\n        {42, 0.3, false, false}, {123, 0.5, false, false}, {456, 0.2, false, false},\n        {789, 0.4, true, false}, {1000, 0.3, true, false}, {2000, 0.5, true, false},\n        {3000, 0.2, false, true}, {4000, 0.4, false, true}, {5000, 0.3, true, false}\n    };\n    \n    long long global_best_dist = LLONG_MAX;\n    vector<Point> global_best_route;\n    vector<int> global_best_selected;\n    \n    for (auto& [seed, randomness, use_clustering, use_angle] : strategies) {\n        auto iter_start = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(iter_start - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        mt19937 rng(seed);\n        \n        vector<int> selected = select_orders(orders, rng, use_clustering);\n        vector<bool> is_selected(NUM_ORDERS, false);\n        for (int idx : selected) is_selected[idx] = true;\n        \n        vector<Point> route;\n        if (use_angle) {\n            route = build_angle_route(selected, orders);\n        } else {\n            route = build_greedy_route(selected, orders, rng, randomness);\n        }\n        long long cur_dist = calc_distance(route);\n        \n        vector<Point> best_route = route;\n        long long best_dist = cur_dist;\n        \n        // 0.13s per seed for optimization\n        optimize_route_adaptive(route, best_dist, best_route, rng, start_time, elapsed + 0.13);\n        \n        // 22 order swap iterations with re-optimization\n        for (int swap_iter = 0; swap_iter < 22; swap_iter++) {\n            auto now = chrono::steady_clock::now();\n            double elapsed2 = chrono::duration<double>(now - start_time).count();\n            if (elapsed2 > TIME_LIMIT) break;\n            \n            if (try_swap_order(selected, is_selected, orders, best_dist, best_route, rng)) {\n                route = best_route;\n                optimize_route_adaptive(route, best_dist, best_route, rng, start_time, elapsed2 + 0.025);\n            }\n        }\n        \n        if (best_dist < global_best_dist) {\n            global_best_dist = best_dist;\n            global_best_route = best_route;\n            global_best_selected = selected;\n        }\n    }\n    \n    // Final intensive optimization on best solution\n    if (!global_best_route.empty()) {\n        mt19937 final_rng(99999);\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = max(0.1, TIME_LIMIT - elapsed);\n        \n        if (remaining > 0.1) {\n            vector<Point> route = global_best_route;\n            long long best_dist = global_best_dist;\n            vector<Point> best_route = global_best_route;\n            \n            optimize_route_adaptive(route, best_dist, best_route, final_rng, start_time, elapsed + remaining);\n            \n            if (best_dist < global_best_dist) {\n                global_best_dist = best_dist;\n                global_best_route = best_route;\n            }\n        }\n    }\n    \n    // Output\n    cout << SELECT_COUNT;\n    for (int idx : global_best_selected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << endl;\n    \n    cout << global_best_route.size();\n    for (auto& p : global_best_route) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\nstruct UnionFind {\n    vector<int> parent;\n    vector<int> size;\n    int components;\n    \n    UnionFind(int n) : parent(n), size(n, 1), components(n) {\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        }\n        return parent[x];\n    }\n    \n    bool unite(int x, int y) {\n        int px = find(x);\n        int py = find(y);\n        if (px == py) return false;\n        \n        if (size[px] < size[py]) swap(px, py);\n        parent[py] = px;\n        size[px] += size[py];\n        components--;\n        return true;\n    }\n    \n    bool same(int x, int y) {\n        return find(x) == find(y);\n    }\n    \n    int componentSize(int x) {\n        return size[find(x)];\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    const int TARGET_EDGES = N - 1;  // 399 edges for MST\n    \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    vector<pair<int, int>> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n    }\n    \n    UnionFind uf(N);\n    int edges_selected = 0;\n    int inter_component_selected = 0;\n    \n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first;\n        int v = edges[i].second;\n        \n        double dx = coords[u].first - coords[v].first;\n        double dy = coords[u].second - coords[v].second;\n        double d = round(sqrt(dx * dx + dy * dy));\n        if (d < 1) d = 1;\n        \n        bool different_components = !uf.same(u, v);\n        bool accept = false;\n        \n        int components_left = uf.components;\n        int edges_left = M - i;\n        int needed = components_left - 1;\n        \n        // Progress through the edge stream (0.0 to 1.0)\n        double progress = (double)i / M;\n        \n        // CRITICAL SAFETY: If we don't have enough edges left to connect, MUST accept\n        if (different_components && needed >= edges_left) {\n            accept = true;\n        }\n        // EMERGENCY MODE 1: Last 150 edges, accept ALL inter-component edges\n        else if (i >= M - 150 && different_components && components_left > 1) {\n            accept = true;\n        }\n        // EMERGENCY MODE 2: Last 300 edges, very lenient (2.9\u00d7d) - KEEP FROM AC VERSION\n        else if (i >= M - 300 && different_components && components_left > 1) {\n            if (l <= 2.9 * d) {\n                accept = true;\n            }\n        }\n        // EMERGENCY MODE 3: Last 500 edges, lenient (2.7\u00d7d) - KEEP FROM AC VERSION\n        else if (i >= M - 500 && different_components && components_left > 1) {\n            double threshold = 2.7 * d;\n            if (components_left > 30) threshold = 2.85 * d;\n            if (components_left > 80) threshold = 2.9 * d;\n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Late stage (500-900 from end): moderately lenient\n        else if (i >= M - 900 && different_components && components_left > 1) {\n            double threshold = 2.4 * d;\n            if (components_left > 50) threshold = 2.6 * d;\n            if (components_left > 100) threshold = 2.7 * d;\n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Mid stage (900-1400 from end): balanced - OPTIMIZE HERE\n        else if (i >= M - 1400 && different_components && components_left > 1) {\n            double threshold = 2.15 * d;\n            if (components_left > 80) threshold = 2.3 * d;\n            if (components_left > 150) threshold = 2.4 * d;\n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Normal mode: inter-component edges with progressive thresholds - OPTIMIZE HERE\n        else if (different_components) {\n            // Start at 2.0d and increase to 2.4d by 70% progress\n            double base_threshold = 2.0 + 0.4 * min(1.0, progress / 0.7);\n            double threshold = base_threshold * d;\n            \n            // Adjust based on components remaining\n            if (components_left > 200) {\n                threshold = min(threshold, 2.3 * d);\n            } else if (components_left > 100) {\n                threshold = min(threshold, 2.2 * d);\n            } else if (components_left > 50) {\n                threshold = min(threshold, 2.1 * d);\n            }\n            \n            // Adjust based on selection rate\n            int target_by_now = (int)(progress * (TARGET_EDGES + 40));\n            \n            if (inter_component_selected < target_by_now - 20) {\n                // Behind: be more lenient\n                threshold = min(threshold, 2.5 * d);\n            } else if (inter_component_selected > target_by_now + 25) {\n                // Ahead: be more selective\n                threshold = max(1.95 * d, threshold - 0.08 * d);\n            }\n            \n            // Prioritize edges connecting larger components\n            int size_u = uf.componentSize(u);\n            int size_v = uf.componentSize(v);\n            if (size_u + size_v > N * 0.5) {\n                threshold = min(threshold, 2.3 * d);\n            } else if (size_u + size_v > N * 0.25) {\n                threshold = min(threshold, 2.2 * d);\n            }\n            \n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Intra-component edges: selective\n        else {\n            double intra_threshold = 1.18 * d;\n            \n            // Slightly more lenient early\n            if (progress < 0.15) {\n                intra_threshold = 1.25 * d;\n            }\n            \n            if (l <= intra_threshold) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            cout << 1 << \"\\n\";\n            if (uf.unite(u, v)) {\n                inter_component_selected++;\n            }\n            edges_selected++;\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        \n        cout.flush();\n    }\n    \n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <cstring>\n\nusing namespace std;\n\n// Structure to represent a position\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\n// Global variables\nint N, M;\nvector<Pos> pets;\nvector<int> pet_types;\nvector<Pos> humans;\nbool walls[32][32]; // Global wall state\nint pet_sum[32][32]; // Prefix sum of pet positions\n\n// Target zone\nint target_r1, target_r2, target_c1, target_c2;\nbool zone_locked = false; // If true, don't search for new zone for a while\nint turns_since_rezone = 0;\n\n// Check bounds\nbool in_grid(int r, int c) {\n    return r >= 0 && r < 30 && c >= 0 && c < 30;\n}\n\n// Update prefix sum of pet positions\nvoid update_pet_sum() {\n    int grid[32][32] = {0};\n    for(const auto& p : pets) {\n        if (in_grid(p.r, p.c)) {\n            grid[p.r][p.c]++;\n        }\n    }\n    // Compute 2D prefix sum\n    memset(pet_sum, 0, sizeof(pet_sum));\n    for(int i=0; i<30; ++i) {\n        for(int j=0; j<30; ++j) {\n            pet_sum[i+1][j+1] = grid[i][j] + pet_sum[i][j+1] + pet_sum[i+1][j] - pet_sum[i][j];\n        }\n    }\n}\n\n// Count pets in rectangle [r1, r2] x [c1, c2] (0-based inclusive)\nint count_pets(int r1, int c1, int r2, int c2) {\n    if (r1 > r2 || c1 > c2) return 0;\n    r1 = max(0, r1); c1 = max(0, c1);\n    r2 = min(29, r2); c2 = min(29, c2);\n    return pet_sum[r2+1][c2+1] - pet_sum[r1][c2+1] - pet_sum[r2+1][c1] + pet_sum[r1][c1];\n}\n\n// Evaluate a zone\nint evaluate_zone(int r1, int r2, int c1, int c2) {\n    if (r1 > r2 || c1 > c2) return -2000000;\n    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n    \n    // Critical: No pets inside\n    if (count_pets(r1, c1, r2, c2) > 0) {\n        return -1000000; \n    }\n    \n    // Penalty for pets adjacent to perimeter\n    int pets_adjacent = 0;\n    for(const auto& p : pets) {\n        int closest_r = max(r1, min(r2, p.r));\n        int closest_c = max(c1, min(c2, p.c));\n        int dist = abs(p.r - closest_r) + abs(p.c - closest_c);\n        if (dist == 1) {\n            pets_adjacent++;\n        }\n    }\n    \n    return area - pets_adjacent * 10;\n}\n\nvoid find_best_zone() {\n    int best_score = -2000000;\n    int best_r1 = 5, best_r2 = 24, best_c1 = 5, best_c2 = 24;\n    \n    for (int r1 = 0; r1 < 30; ++r1) {\n        for (int r2 = r1; r2 < 30; ++r2) {\n            for (int c1 = 0; c1 < 30; ++c1) {\n                for (int c2 = c1; c2 < 30; ++c2) {\n                    int score = evaluate_zone(r1, r2, c1, c2);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1;\n                        best_r2 = r2;\n                        best_c1 = c1;\n                        best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n    \n    target_r1 = best_r1;\n    target_r2 = best_r2;\n    target_c1 = best_c1;\n    target_c2 = best_c2;\n    \n    if (best_score > -500000) {\n        zone_locked = true;\n        turns_since_rezone = 0;\n    } else {\n        zone_locked = false;\n    }\n}\n\n// Get perimeter cells of the target zone\nvector<Pos> get_perimeter() {\n    vector<Pos> cells;\n    for (int c = target_c1; c <= target_c2; ++c) {\n        cells.push_back({target_r1, c});\n        if (target_r2 != target_r1) cells.push_back({target_r2, c});\n    }\n    for (int r = target_r1 + 1; r < target_r2; ++r) {\n        cells.push_back({r, target_c1});\n        if (target_c2 != target_c1) cells.push_back({r, target_c2});\n    }\n    return cells;\n}\n\n// Check if building at (r, c) is safe\nbool can_build(int r, int c, const vector<Pos>& current_humans) {\n    if (!in_grid(r, c)) return false;\n    if (walls[r][c]) return false; // Already a wall\n    \n    // Check if any human is at this position\n    for (const auto& h : current_humans) {\n        if (h.r == r && h.c == c) {\n            return false;\n        }\n    }\n    \n    // Check if any pet is at this position\n    for (const auto& p : pets) {\n        if (p.r == r && p.c == c) {\n            return false;\n        }\n    }\n    \n    // Check adjacency to pets (cannot build adjacent to pets)\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    for (const auto& p : pets) {\n        for (int k = 0; k < 4; ++k) {\n            if (p.r + dr[k] == r && p.c + dc[k] == c) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// BFS for human movement avoiding walls\nPos get_next_move(Pos start, Pos target, const bool grid[32][32]) {\n    if (start == target) return start;\n    \n    queue<Pos> q;\n    q.push(start);\n    int dist[32][32];\n    Pos parent[32][32];\n    for(int i=0; i<32; ++i) for(int j=0; j<32; ++j) {\n        dist[i][j] = -1;\n        parent[i][j] = {-1, -1};\n    }\n    \n    dist[start.r][start.c] = 0;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    \n    while(!q.empty()){\n        Pos cur = q.front(); q.pop();\n        if (cur == target) break;\n        \n        for(int k=0; k<4; ++k){\n            int nr = cur.r + dr[k];\n            int nc = cur.c + dc[k];\n            if(in_grid(nr, nc) && !grid[nr][nc] && dist[nr][nc] == -1){\n                dist[nr][nc] = dist[cur.r][cur.c] + 1;\n                parent[nr][nc] = cur;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if (dist[target.r][target.c] == -1) return start;\n    \n    Pos curr = target;\n    while(parent[curr.r][curr.c] != start){\n        curr = parent[curr.r][curr.c];\n        if (curr.r == -1) return start;\n    }\n    return curr;\n}\n\nchar get_action_char(Pos from, Pos to) {\n    if (from == to) return '.';\n    if (to.r < from.r) return 'U';\n    if (to.r > from.r) return 'D';\n    if (to.c < from.c) return 'L';\n    if (to.c > from.c) return 'R';\n    return '.';\n}\n\nchar get_build_char(Pos from, Pos wall_pos) {\n    if (wall_pos.r < from.r) return 'u';\n    if (wall_pos.r > from.r) return 'd';\n    if (wall_pos.c < from.c) return 'l';\n    if (wall_pos.c > from.c) return 'r';\n    return '.';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N)) return 0;\n    pets.resize(N);\n    pet_types.resize(N);\n    for(int i=0; i<N; ++i){\n        cin >> pets[i].r >> pets[i].c >> pet_types[i];\n        pets[i].r--; pets[i].c--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for(int i=0; i<M; ++i){\n        cin >> humans[i].r >> humans[i].c;\n        humans[i].r--; humans[i].c--;\n    }\n    \n    memset(walls, 0, sizeof(walls));\n    \n    update_pet_sum();\n    find_best_zone();\n    \n    vector<Pos> perimeter = get_perimeter();\n    \n    for(int turn=0; turn<300; ++turn){\n        if (turn > 0) {\n            for(int i=0; i<N; ++i){\n                string s;\n                cin >> s;\n                if (s == \".\") continue;\n                for(char c : s){\n                    if (c == 'U') pets[i].r--;\n                    else if (c == 'D') pets[i].r++;\n                    else if (c == 'L') pets[i].c--;\n                    else if (c == 'R') pets[i].c++;\n                }\n            }\n            update_pet_sum();\n        }\n        \n        bool need_rezone = false;\n        if (!zone_locked) {\n            turns_since_rezone++;\n            if (turns_since_rezone >= 50) need_rezone = true;\n        }\n        \n        if (count_pets(target_r1, target_c1, target_r2, target_c2) > 0) {\n            need_rezone = true;\n            zone_locked = false;\n        }\n        \n        if (need_rezone) {\n            find_best_zone();\n            perimeter = get_perimeter();\n            turns_since_rezone = 0;\n        }\n        \n        bool temp_walls[32][32];\n        memcpy(temp_walls, walls, sizeof(walls));\n        \n        vector<char> human_actions(M, '.');\n        vector<Pos> next_human_pos(M);\n        vector<Pos> old_humans = humans;\n        \n        // Identify buildable segments (check against current human positions)\n        vector<int> buildable_indices;\n        for(size_t i=0; i<perimeter.size(); ++i){\n            if (!walls[perimeter[i].r][perimeter[i].c]) {\n                if (can_build(perimeter[i].r, perimeter[i].c, humans)) {\n                    buildable_indices.push_back(i);\n                }\n            }\n        }\n        \n        vector<bool> segment_taken(perimeter.size(), false);\n        vector<bool> human_assigned_build(M, false);\n        \n        for(int i=0; i<M; ++i){\n            int best_seg = -1;\n            int min_dist = 10000;\n            \n            for(int idx : buildable_indices){\n                if (segment_taken[idx]) continue;\n                int d = abs(humans[i].r - perimeter[idx].r) + abs(humans[i].c - perimeter[idx].c);\n                if (d < min_dist) {\n                    min_dist = d;\n                    best_seg = idx;\n                }\n            }\n            \n            Pos target;\n            if (best_seg != -1) {\n                segment_taken[best_seg] = true;\n                human_assigned_build[i] = true;\n                target = perimeter[best_seg];\n                \n                int dist = abs(humans[i].r - target.r) + abs(humans[i].c - target.c);\n                if (dist == 1) {\n                    // Re-check can_build with temp_walls and updated human positions\n                    // (other humans might move to this position this turn)\n                    bool can_build_now = true;\n                    if (temp_walls[target.r][target.c]) can_build_now = false;\n                    \n                    // Check if any OTHER human will be at this position\n                    for(int j=0; j<M; ++j){\n                        if (i == j) continue;\n                        // Check if human j is already there or will move there\n                        if (humans[j].r == target.r && humans[j].c == target.c) {\n                            can_build_now = false;\n                            break;\n                        }\n                    }\n                    \n                    // Check pet adjacency again\n                    if (can_build_now) {\n                        int dr[] = {-1, 1, 0, 0};\n                        int dc[] = {0, 0, -1, 1};\n                        for (const auto& p : pets) {\n                            for (int k = 0; k < 4; ++k) {\n                                if (p.r + dr[k] == target.r && p.c + dc[k] == target.c) {\n                                    can_build_now = false;\n                                    break;\n                                }\n                            }\n                            if (!can_build_now) break;\n                        }\n                    }\n                    \n                    if (can_build_now) {\n                        human_actions[i] = get_build_char(humans[i], target);\n                        temp_walls[target.r][target.c] = true;\n                        next_human_pos[i] = humans[i]; // Stay\n                    } else {\n                        // Cannot build, move closer or wait\n                        Pos next = get_next_move(humans[i], target, temp_walls);\n                        human_actions[i] = get_action_char(humans[i], next);\n                        next_human_pos[i] = next;\n                    }\n                } else {\n                    Pos next = get_next_move(humans[i], target, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                }\n            } else {\n                // No buildable segments available\n                bool all_built = true;\n                for(const auto& p : perimeter) {\n                    if (!walls[p.r][p.c]) {\n                        all_built = false;\n                        break;\n                    }\n                }\n                \n                if (all_built) {\n                    Pos center = {(target_r1 + target_r2)/2, (target_c1 + target_c2)/2};\n                    Pos next = get_next_move(humans[i], center, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                } else {\n                    // Wait for buildable segments to become available\n                    human_actions[i] = '.';\n                    next_human_pos[i] = humans[i];\n                }\n            }\n        }\n        \n        // Output\n        string out = \"\";\n        for(int i=0; i<M; ++i) out += human_actions[i];\n        cout << out << endl;\n        \n        // Update state\n        for(int i=0; i<M; ++i){\n            humans[i] = next_human_pos[i];\n            char act = human_actions[i];\n            if (act == 'u') walls[old_humans[i].r - 1][old_humans[i].c] = true;\n            else if (act == 'd') walls[old_humans[i].r + 1][old_humans[i].c] = true;\n            else if (act == 'l') walls[old_humans[i].r][old_humans[i].c - 1] = true;\n            else if (act == 'r') walls[old_humans[i].r][old_humans[i].c + 1] = true;\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\n// Global variables\nint SI, SJ, TI, TJ;\ndouble P;\nchar H[20][20]; // 20 x 19 (last column unused)\nchar V[20][20]; // 19 x 20 (last row unused)\n\n// Directions: U, D, L, R\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIRS[4] = {'U', 'D', 'L', 'R'};\n\n// Grid helpers\ninline int get_idx(int r, int c) { return r * 20 + c; }\ninline int get_r(int idx) { return idx / 20; }\ninline int get_c(int idx) { return idx % 20; }\n\ninline bool is_wall(int r, int c, int dir) {\n    int nr = r + DI[dir];\n    int nc = c + DJ[dir];\n    if (nr < 0 || nr >= 20 || nc < 0 || nc >= 20) return true;\n    if (dir == 0) return (r == 0 || V[r-1][c] == '1');\n    if (dir == 1) return (r == 19 || V[r][c] == '1');\n    if (dir == 2) return (c == 0 || H[r][c-1] == '1');\n    if (dir == 3) return (c == 19 || H[r][c] == '1');\n    return true;\n}\n\nconst int L = 200;\nint TARGET_IDX;\n\n// Global DP cache - use flat arrays for cache efficiency\ndouble dp[201][400];\nint active_count[201];\nint active_list[201][400];\ndouble D[201];\nchar S[201];\n\n// Work buffers (static to avoid allocation)\ndouble work_dp[400];\nint work_active[400];\nint work_token[400];\nint work_token_val = 0;\n\ndouble next_work_dp[400];\nint next_work_active[400];\nint next_work_token[400];\nint next_work_token_val = 0;\n\nconst double PROB_THRESHOLD = 1e-10;\n\ndouble compute_dp_from(int k, const char* current_S, double* out_D_suffix) {\n    work_token_val++;\n    next_work_token_val++;\n    \n    int w_count = 0;\n    for (int i = 0; i < active_count[k]; ++i) {\n        int idx = active_list[k][i];\n        double val = dp[k][idx];\n        if (val > PROB_THRESHOLD) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = D[k];\n    double score_suffix = 0.0;\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = current_S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        int nw_count = 0;\n        double total_mass = 0.0;\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = get_r(idx);\n            int c = get_c(idx);\n            \n            bool wall = is_wall(r, c, dir_idx);\n            \n            if (wall) {\n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob;\n            } else {\n                int nr = r + DI[dir_idx];\n                int nc = c + DJ[dir_idx];\n                int nidx = get_idx(nr, nc);\n                \n                // Stay (forget)\n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob * P;\n                \n                // Move\n                if (nidx == TARGET_IDX) {\n                    sim_D += prob * (1.0 - P);\n                } else {\n                    if (next_work_token[nidx] != next_work_token_val) {\n                        next_work_token[nidx] = next_work_token_val;\n                        next_work_dp[nidx] = 0.0;\n                        next_work_active[nw_count++] = nidx;\n                    }\n                    next_work_dp[nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        double D_next = sim_D;\n        if (t + 1 < L) {\n            score_suffix += D_next;\n        } else {\n            score_suffix += 201.0 * D_next;\n        }\n        \n        // Calculate total mass for early termination\n        total_mass = 0.0;\n        w_count = nw_count;\n        for(int i = 0; i < w_count; ++i) {\n            int idx = next_work_active[i];\n            work_dp[idx] = next_work_dp[idx];\n            work_active[i] = idx;\n            work_token[idx] = work_token_val;\n            total_mass += work_dp[idx];\n        }\n        \n        // Early termination: if most probability reached target\n        if (total_mass < PROB_THRESHOLD && D_next > 0.999) {\n            double remaining_D = D_next;\n            for (int rem = t + 2; rem < L; ++rem) {\n                score_suffix += remaining_D;\n            }\n            break;\n        }\n    }\n    \n    *out_D_suffix = score_suffix;\n    return sim_D;\n}\n\nvoid update_cache_from(int k) {\n    work_token_val++;\n    \n    int w_count = 0;\n    for (int i = 0; i < active_count[k]; ++i) {\n        int idx = active_list[k][i];\n        double val = dp[k][idx];\n        if (val > PROB_THRESHOLD) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = D[k];\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        static int global_next_token[400];\n        static int global_next_token_val = 0;\n        global_next_token_val++;\n        \n        active_count[t+1] = 0;\n        double next_D = sim_D;\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = get_r(idx);\n            int c = get_c(idx);\n            \n            bool wall = is_wall(r, c, dir_idx);\n            \n            if (wall) {\n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active_list[t+1][active_count[t+1]++] = idx;\n                }\n                dp[t+1][idx] += prob;\n            } else {\n                int nr = r + DI[dir_idx];\n                int nc = c + DJ[dir_idx];\n                int nidx = get_idx(nr, nc);\n                \n                // Stay\n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active_list[t+1][active_count[t+1]++] = idx;\n                }\n                dp[t+1][idx] += prob * P;\n                \n                // Move\n                if (nidx == TARGET_IDX) {\n                    next_D += prob * (1.0 - P);\n                } else {\n                    if (global_next_token[nidx] != global_next_token_val) {\n                        global_next_token[nidx] = global_next_token_val;\n                        dp[t+1][nidx] = 0.0;\n                        active_list[t+1][active_count[t+1]++] = nidx;\n                    }\n                    dp[t+1][nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        sim_D = next_D;\n        D[t+1] = sim_D;\n        \n        w_count = 0;\n        for (int i = 0; i < active_count[t+1]; ++i) {\n            int idx = active_list[t+1][i];\n            work_dp[idx] = dp[t+1][idx];\n            work_active[w_count++] = idx;\n            work_token[idx] = work_token_val;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> SI >> SJ >> TI >> TJ >> P)) return 0;\n    \n    for (int i = 0; i < 20; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < 19; ++j) H[i][j] = row[j];\n    }\n    for (int i = 0; i < 19; ++i) {\n        string row;\n        cin >> row;\n        for (int j = 0; j < 20; ++j) V[i][j] = row[j];\n    }\n    \n    TARGET_IDX = get_idx(TI, TJ);\n    \n    // BFS for shortest path\n    int dist[400];\n    int parent[400];\n    int parent_dir[400];\n    memset(dist, -1, sizeof(dist));\n    \n    queue<int> q;\n    int start_idx = get_idx(SI, SJ);\n    dist[start_idx] = 0;\n    q.push(start_idx);\n    \n    while(!q.empty()){\n        int idx = q.front(); q.pop();\n        if(idx == TARGET_IDX) break;\n        int r = get_r(idx), c = get_c(idx);\n        for(int d=0; d<4; ++d){\n            if(!is_wall(r, c, d)){\n                int nr = r + DI[d], nc = c + DJ[d];\n                int nidx = get_idx(nr, nc);\n                if(dist[nidx] == -1){\n                    dist[nidx] = dist[idx] + 1;\n                    parent[nidx] = idx;\n                    parent_dir[nidx] = d;\n                    q.push(nidx);\n                }\n            }\n        }\n    }\n    \n    // Construct initial path\n    string path = \"\";\n    if(dist[TARGET_IDX] != -1){\n        int curr = TARGET_IDX;\n        while(curr != start_idx){\n            path += DIRS[parent_dir[curr]];\n            curr = parent[curr];\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    // Fill S with repeated path\n    int path_len = path.length();\n    for(int i = 0; i < L; ++i){\n        S[i] = path[i % path_len];\n    }\n    S[L] = '\\0';\n    \n    // Initial DP Compute\n    memset(dp, 0, sizeof(dp));\n    memset(active_count, 0, sizeof(active_count));\n    \n    dp[0][start_idx] = 1.0;\n    active_list[0][0] = start_idx;\n    active_count[0] = 1;\n    D[0] = 0.0;\n    \n    update_cache_from(0);\n    \n    double current_score = 0.0;\n    for(int t=1; t<L; ++t) current_score += D[t];\n    current_score += 201.0 * D[L];\n    \n    double best_score = current_score;\n    string best_S(S, S + L);\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.8; // Reduced from 1.9\n    \n    double temp = 30.0;\n    int accepted = 0;\n    int total = 0;\n    \n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        // Adaptive temperature\n        if(total > 0 && total % 500 == 0){\n            double rate = (double)accepted / total;\n            if(rate > 0.4) temp *= 0.85;\n            else if(rate < 0.15) temp *= 1.15;\n            accepted = 0;\n            total = 0;\n        }\n        \n        // Single character mutation (fastest)\n        int k = uniform_int_distribution<int>(0, L-1)(rng);\n        char old_char = S[k];\n        \n        int old_dir = 0;\n        if(old_char == 'U') old_dir = 0;\n        else if(old_char == 'D') old_dir = 1;\n        else if(old_char == 'L') old_dir = 2;\n        else if(old_char == 'R') old_dir = 3;\n        \n        int new_dir = uniform_int_distribution<int>(0, 3)(rng);\n        while(new_dir == old_dir) {\n            new_dir = uniform_int_distribution<int>(0, 3)(rng);\n        }\n        \n        char new_char = DIRS[new_dir];\n        S[k] = new_char;\n        \n        double new_suffix_score;\n        compute_dp_from(k, S, &new_suffix_score);\n        \n        // Calculate prefix score\n        double prefix_score = 0.0;\n        for(int t=1; t<=k; ++t) {\n            prefix_score += D[t];\n        }\n        \n        double new_total_score = prefix_score + new_suffix_score;\n        double delta = new_total_score - current_score;\n        \n        if(delta > 0 || exp(delta / temp) > uniform_real_distribution<double>(0, 1)(rng)){\n            current_score = new_total_score;\n            update_cache_from(k);\n            accepted++;\n            \n            if(current_score > best_score){\n                best_score = current_score;\n                best_S = string(S, S + L);\n            }\n        } else {\n            S[k] = old_char;\n        }\n        \n        total++;\n        temp *= 0.99992;\n    }\n    \n    cout << best_S << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int MAX_STATES = N * N * 4 + 10;\n\n// Connection table: to[tile_type][entry_direction] = exit_direction\nconst int to_table[8][4] = {\n    {1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n    {1, 0, 3, 2}, {3, 2, 1, 0}, {2, -1, 0, -1}, {-1, 3, -1, 1},\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nint tiles[N][N];\nint rotation[N][N];\nint best_rotation[N][N];\n\ninline int get_tile(int i, int j) {\n    return (tiles[i][j] + rotation[i][j]) % 8;\n}\n\n// Find all loops and return two longest lengths\npair<int, int> find_two_longest_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    \n    int max1 = 0, max2 = 0;\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                if (!visited[i][j][d]) {\n                    int si = i, sj = j, sd = d;\n                    int ci = i, cj = j, cd = d;\n                    int length = 0;\n                    bool valid = true;\n                    \n                    do {\n                        int tile = get_tile(ci, cj);\n                        int d2 = to_table[tile][cd];\n                        \n                        if (d2 == -1) { valid = false; break; }\n                        ci += di[d2]; cj += dj[d2];\n                        if (ci < 0 || ci >= N || cj < 0 || cj >= N) { valid = false; break; }\n                        cd = (d2 + 2) % 4;\n                        length++;\n                        if (length > MAX_STATES) { valid = false; break; }\n                    } while (!(ci == si && cj == sj && cd == sd));\n                    \n                    if (valid && length > 0) {\n                        ci = si; cj = sj; cd = sd;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2]; cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == si && cj == sj && cd == sd));\n                        \n                        if (length > max1) { max2 = max1; max1 = length; }\n                        else if (length > max2) { max2 = length; }\n                    }\n                }\n            }\n        }\n    }\n    \n    return {max1, max2};\n}\n\nlong long calculate_score() {\n    auto [l1, l2] = find_two_longest_loops();\n    return (long long)l1 * l2;\n}\n\nint count_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    int count = 0;\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                if (!visited[i][j][d]) {\n                    int si = i, sj = j, sd = d;\n                    int ci = i, cj = j, cd = d;\n                    int length = 0;\n                    bool valid = true;\n                    \n                    do {\n                        int tile = get_tile(ci, cj);\n                        int d2 = to_table[tile][cd];\n                        if (d2 == -1) { valid = false; break; }\n                        ci += di[d2]; cj += dj[d2];\n                        if (ci < 0 || ci >= N || cj < 0 || cj >= N) { valid = false; break; }\n                        cd = (d2 + 2) % 4;\n                        length++;\n                        if (length > MAX_STATES) { valid = false; break; }\n                    } while (!(ci == si && cj == sj && cd == sd));\n                    \n                    if (valid && length > 0) {\n                        count++;\n                        ci = si; cj = sj; cd = sd;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2]; cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == si && cj == sj && cd == sd));\n                    }\n                }\n            }\n        }\n    }\n    \n    return count;\n}\n\nvoid initialize_random(mt19937_64& rng) {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            rotation[i][j] = uniform_int_distribution<>(0, 3)(rng);\n        }\n    }\n}\n\nlong long run_sa(mt19937_64& rng, double time_budget) {\n    initialize_random(rng);\n    \n    // Ensure at least 2 loops\n    int attempts = 0;\n    while (count_loops() < 2 && attempts < 15) {\n        initialize_random(rng);\n        attempts++;\n    }\n    \n    long long current_score = calculate_score();\n    long long best_score = current_score;\n    \n    if (current_score > 0) {\n        memcpy(best_rotation, rotation, sizeof(rotation));\n    }\n    \n    double temperature = 2500.0;\n    int no_improve = 0;\n    int total_moves = 0;\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        if (elapsed > time_budget) break;\n        \n        double remaining = time_budget - elapsed;\n        temperature = max(0.1, 500.0 * (remaining / time_budget));\n        \n        // Pick random tile\n        int i = uniform_int_distribution<>(0, N-1)(rng);\n        int j = uniform_int_distribution<>(0, N-1)(rng);\n        \n        int old_rot = rotation[i][j];\n        int new_rot = (old_rot + uniform_int_distribution<>(1, 3)(rng)) % 4;\n        rotation[i][j] = new_rot;\n        \n        long long new_score = calculate_score();\n        \n        if (new_score == 0) {\n            rotation[i][j] = old_rot;\n            continue;\n        }\n        \n        double delta = (double)(new_score - current_score);\n        bool accept = false;\n        \n        if (delta > 0) {\n            accept = true;\n        } else if (temperature > 0.1) {\n            double prob = exp(delta / temperature);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n                no_improve = 0;\n            } else {\n                no_improve++;\n            }\n        } else {\n            rotation[i][j] = old_rot;\n        }\n        \n        total_moves++;\n        \n        // Restart if stuck\n        if (no_improve > 8000 && temperature < 10.0) {\n            temperature = 400.0;\n            no_improve = 0;\n            // Randomize larger region\n            int ri = uniform_int_distribution<>(0, N-12)(rng);\n            int rj = uniform_int_distribution<>(0, N-12)(rng);\n            for (int x = ri; x < ri + 12 && x < N; x++) {\n                for (int y = rj; y < rj + 12 && y < N; y++) {\n                    rotation[x][y] = uniform_int_distribution<>(0, 3)(rng);\n                }\n            }\n            current_score = calculate_score();\n            if (current_score > best_score && current_score > 0) {\n                best_score = current_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n            }\n        }\n    }\n    \n    return best_score;\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        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            tiles[i][j] = s[j] - '0';\n            rotation[i][j] = 0;\n        }\n    }\n    \n    long long global_best = 0;\n    auto start_time = chrono::steady_clock::now();\n    const double total_time = 1.92;\n    \n    // More runs with moderate length\n    int num_runs = 8;\n    double time_per_run = (total_time - 0.2) / num_runs;  // Reserve 0.2s for final refinement\n    \n    for (int run = 0; run < num_runs; run++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > total_time - 0.25) break;\n        \n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count() + run * 2345678);\n        long long score = run_sa(rng, time_per_run);\n        \n        if (score > global_best && score > 0) {\n            global_best = score;\n        }\n    }\n    \n    // Final intensive refinement on best solution\n    if (global_best > 0) {\n        memcpy(rotation, best_rotation, sizeof(rotation));\n        long long current_score = global_best;\n        \n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count() + 888888);\n        \n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = total_time - elapsed - 0.03;\n        \n        if (remaining > 0.05) {\n            double temperature = 100.0;\n            int refine_iter = 0;\n            auto refine_start = chrono::steady_clock::now();\n            \n            while (true) {\n                auto now2 = chrono::steady_clock::now();\n                double refine_elapsed = chrono::duration<double>(now2 - refine_start).count();\n                if (refine_elapsed > remaining) break;\n                \n                // Try all 3 other rotations for random tile\n                int i = uniform_int_distribution<>(0, N-1)(rng);\n                int j = uniform_int_distribution<>(0, N-1)(rng);\n                \n                int old_rot = rotation[i][j];\n                bool improved = false;\n                \n                for (int try_rot = 0; try_rot < 4; try_rot++) {\n                    if (try_rot == old_rot) continue;\n                    rotation[i][j] = try_rot;\n                    long long new_score = calculate_score();\n                    \n                    if (new_score > current_score) {\n                        current_score = new_score;\n                        improved = true;\n                        if (new_score > global_best) {\n                            global_best = new_score;\n                            memcpy(best_rotation, rotation, sizeof(rotation));\n                        }\n                        old_rot = try_rot;\n                    }\n                }\n                \n                if (!improved) {\n                    rotation[i][j] = old_rot;\n                }\n                \n                temperature *= 0.9999;\n                refine_iter++;\n                \n                if (refine_iter > 500000) break;\n            }\n        }\n    }\n    \n    // Ensure valid output\n    if (global_best == 0) {\n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n        initialize_random(rng);\n        int attempts = 0;\n        while (calculate_score() == 0 && attempts < 50) {\n            initialize_random(rng);\n            attempts++;\n        }\n        memcpy(best_rotation, rotation, sizeof(rotation));\n    }\n    \n    // Output exactly 900 characters\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << best_rotation[i][j];\n        }\n    }\n    cout << '\\n';\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nvector<string> board;\nint empty_r, empty_c;\nstring moves = \"\";\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\nconst int opp_dir[] = {1, 0, 3, 2};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nint get_tile(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N) return -1;\n    if (board[r][c] == '0') return 0;\n    return hex_to_int(board[r][c]);\n}\n\nbool has_connection(int tile_val, int d) {\n    if (tile_val == 0) return false;\n    const int mask[] = {2, 8, 1, 4};\n    return (tile_val & mask[d]) != 0;\n}\n\nbool tiles_connect(int r1, int c1, int r2, int c2) {\n    int t1 = get_tile(r1, c1);\n    int t2 = get_tile(r2, c2);\n    if (t1 == 0 || t2 == 0) return false;\n    \n    if (r2 == r1 + 1) return has_connection(t1, 1) && has_connection(t2, 0);\n    if (r2 == r1 - 1) return has_connection(t1, 0) && has_connection(t2, 1);\n    if (c2 == c1 + 1) return has_connection(t1, 3) && has_connection(t2, 2);\n    if (c2 == c1 - 1) return has_connection(t1, 2) && has_connection(t2, 3);\n    return false;\n}\n\nvoid make_move(int d) {\n    int nr = empty_r + dr[d];\n    int nc = empty_c + dc[d];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return;\n    if ((int)moves.size() >= T - 2) return;\n    \n    swap(board[empty_r][empty_c], board[nr][nc]);\n    empty_r = nr;\n    empty_c = nc;\n    moves += dir_char[d];\n}\n\nvector<int> bfs_path(int sr, int sc, int tr, int tc) {\n    if (sr == tr && sc == tc) return {};\n    \n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> par(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<int>> par_d(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({sr, sc});\n    vis[sr][sc] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !vis[nr][nc]) {\n                vis[nr][nc] = true;\n                par[nr][nc] = {r, c};\n                par_d[nr][nc] = d;\n                q.push({nr, nc});\n                if (nr == tr && nc == tc) {\n                    vector<int> path;\n                    int cr = nr, cc = nc;\n                    while (cr != sr || cc != sc) {\n                        path.push_back(par_d[cr][cc]);\n                        tie(cr, cc) = par[cr][cc];\n                    }\n                    reverse(path.begin(), path.end());\n                    return path;\n                }\n            }\n        }\n    }\n    return {};\n}\n\nvoid move_empty_to(int tr, int tc) {\n    while (empty_r != tr || empty_c != tc) {\n        if ((int)moves.size() >= T - 10) break;\n        auto path = bfs_path(empty_r, empty_c, tr, tc);\n        if (path.empty()) break;\n        for (int d : path) {\n            if ((int)moves.size() >= T - 5) break;\n            make_move(d);\n        }\n    }\n}\n\nvoid move_tile_to(int& tile_r, int& tile_c, int tr, int tc) {\n    while (tile_r != tr || tile_c != tc) {\n        if ((int)moves.size() >= T - 20) break;\n        \n        int empty_tr, empty_tc, move_d;\n        if (tile_r < tr) { empty_tr = tile_r + 1; empty_tc = tile_c; move_d = 0; }\n        else if (tile_r > tr) { empty_tr = tile_r - 1; empty_tc = tile_c; move_d = 1; }\n        else if (tile_c < tc) { empty_tr = tile_r; empty_tc = tile_c + 1; move_d = 2; }\n        else { empty_tr = tile_r; empty_tc = tile_c - 1; move_d = 3; }\n        \n        if (empty_tr < 0 || empty_tr >= N || empty_tc < 0 || empty_tc >= N) break;\n        \n        move_empty_to(empty_tr, empty_tc);\n        if (empty_r == empty_tr && empty_c == empty_tc) {\n            make_move(move_d);\n            if (move_d == 0) tile_r++;\n            else if (move_d == 1) tile_r--;\n            else if (move_d == 2) tile_c++;\n            else if (move_d == 3) tile_c--;\n        } else break;\n    }\n}\n\nint calculate_tree_size() {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    int max_size = 0;\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == '0' || vis[i][j]) continue;\n            int size = 0;\n            queue<pair<int,int>> q;\n            q.push({i, j});\n            vis[i][j] = true;\n            while (!q.empty()) {\n                auto [r, c] = q.front(); q.pop();\n                size++;\n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr[d], nc = c + dc[d];\n                    if (nr >= 0 && nr < N && nc >= 0 && nc < N && !vis[nr][nc] && board[nr][nc] != '0') {\n                        if (tiles_connect(r, c, nr, nc)) {\n                            vis[nr][nc] = true;\n                            q.push({nr, nc});\n                        }\n                    }\n                }\n            }\n            max_size = max(max_size, size);\n        }\n    }\n    return max_size;\n}\n\nstruct Tile {\n    int value, r, c, id;\n};\n\nstruct Placement {\n    vector<int> assignment;\n    vector<pair<int,int>> positions;\n    int score;\n};\n\n// Try to build placement starting from a specific tile\nPlacement try_placement(const vector<Tile>& tiles, int start_tile, int start_pos, int total) {\n    Placement result;\n    result.assignment.assign(total, -1);\n    result.positions.resize(total);\n    result.score = 0;\n    \n    vector<bool> used(total, false);\n    vector<vector<bool>> placed(N, vector<bool>(N, false));\n    \n    // Target positions in snake pattern\n    vector<pair<int,int>> targets;\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)) targets.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (!(i == N-1 && j == N-1)) targets.push_back({i, j});\n            }\n        }\n    }\n    \n    // Place starting tile\n    result.assignment[start_pos] = start_tile;\n    result.positions[start_pos] = targets[start_pos];\n    used[start_tile] = true;\n    placed[targets[start_pos].first][targets[start_pos].second] = true;\n    result.score += __builtin_popcount(tiles[start_tile].value) * 10;\n    \n    // Grow tree by adding compatible tiles\n    for (int ti = 0; ti < total; ti++) {\n        if (ti == start_pos) continue;\n        \n        int tr = targets[ti].first, tc = targets[ti].second;\n        int best_tile = -1, best_score = -1e9;\n        \n        for (int tidx = 0; tidx < total; tidx++) {\n            if (used[tidx]) continue;\n            \n            int score = 0;\n            \n            // Check connections with placed neighbors\n            for (int d = 0; d < 4; d++) {\n                int pr = tr + dr[d], pc = tc + dc[d];\n                if (pr >= 0 && pr < N && pc >= 0 && pc < N && !(pr == N-1 && pc == N-1)) {\n                    if (placed[pr][pc]) {\n                        for (int nt = 0; nt < total; nt++) {\n                            if (result.assignment[nt] >= 0) {\n                                int at = targets[nt].first, ac = targets[nt].second;\n                                if (at == pr && ac == pc) {\n                                    int neighbor = result.assignment[nt];\n                                    int opp = opp_dir[d];\n                                    if (has_connection(tiles[tidx].value, d) && \n                                        has_connection(tiles[neighbor].value, opp)) {\n                                        score += 25;\n                                    }\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Distance penalty\n            int dist = abs(tiles[tidx].r - tr) + abs(tiles[tidx].c - tc);\n            score -= dist * 3;\n            \n            // Connection potential\n            score += __builtin_popcount(tiles[tidx].value) * 5;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_tile = tidx;\n            }\n        }\n        \n        if (best_tile >= 0) {\n            result.assignment[ti] = best_tile;\n            result.positions[ti] = targets[ti];\n            used[best_tile] = true;\n            placed[tr][tc] = true;\n            result.score += best_score;\n        }\n    }\n    \n    return result;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    \n    vector<Tile> tiles;\n    int tile_id = 0;\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; empty_c = j;\n            } else {\n                tiles.push_back({hex_to_int(board[i][j]), i, j, tile_id++});\n            }\n        }\n    }\n    \n    int total = N * N - 1;\n    \n    // Target positions in snake pattern\n    vector<pair<int,int>> targets;\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)) targets.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (!(i == N-1 && j == N-1)) targets.push_back({i, j});\n            }\n        }\n    }\n    \n    // Try multiple starting configurations\n    Placement best_placement;\n    best_placement.score = -1e9;\n    \n    // Try starting from different tiles and positions\n    vector<int> start_tiles;\n    for (int i = 0; i < total && i < 5; i++) start_tiles.push_back(i);\n    // Also try tiles with most connections\n    vector<pair<int,int>> by_conn;\n    for (int i = 0; i < total; i++) {\n        by_conn.push_back({__builtin_popcount(tiles[i].value), i});\n    }\n    sort(by_conn.rbegin(), by_conn.rend());\n    for (int i = 0; i < 3; i++) start_tiles.push_back(by_conn[i].second);\n    \n    vector<int> start_positions = {0, 1, total/2};\n    \n    for (int st : start_tiles) {\n        for (int sp : start_positions) {\n            if ((int)moves.size() >= T - 100) break;\n            Placement p = try_placement(tiles, st, sp, total);\n            if (p.score > best_placement.score) {\n                best_placement = p;\n            }\n        }\n    }\n    \n    // Execute best placement\n    for (int ti = 0; ti < total; ti++) {\n        if ((int)moves.size() >= T - 30) break;\n        if (best_placement.assignment[ti] < 0) continue;\n        \n        int tidx = best_placement.assignment[ti];\n        int tr = targets[ti].first, tc = targets[ti].second;\n        int tile_val = tiles[tidx].value;\n        \n        // Find current position\n        int cur_r = -1, cur_c = -1;\n        for (int i = 0; i < N && cur_r < 0; i++) {\n            for (int j = 0; j < N && cur_r < 0; j++) {\n                if (get_tile(i, j) == tile_val) {\n                    cur_r = i; cur_c = j;\n                }\n            }\n        }\n        if (cur_r < 0) continue;\n        \n        move_tile_to(cur_r, cur_c, tr, tc);\n    }\n    \n    move_empty_to(N-1, N-1);\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\nstruct Strawberry {\n    int id;\n    long long x, y;\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> lines;\n\nconst long long COORD_MIN = -1000000000LL;\nconst long long COORD_MAX = 1000000000LL;\n\nlong long clampCoord(long long v) {\n    if (v < COORD_MIN) return COORD_MIN;\n    if (v > COORD_MAX) return COORD_MAX;\n    return v;\n}\n\nint sideOfLine(const Line& l, long long x, long long y) {\n    __int128 dx1 = (__int128)l.qx - l.px;\n    __int128 dy1 = (__int128)l.qy - l.py;\n    __int128 dx2 = (__int128)x - l.px;\n    __int128 dy2 = (__int128)y - l.py;\n    __int128 cross = dx1 * dy2 - dy1 * dx2;\n    if (cross > 0) return 1;\n    if (cross < 0) return -1;\n    return 0;\n}\n\nbool isCut(int idx) {\n    for (const auto& l : lines) {\n        if (sideOfLine(l, strawberries[idx].x, strawberries[idx].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\nvector<string> getRegions() {\n    vector<string> region(N);\n    for (int i = 0; i < N; i++) {\n        if (isCut(i)) {\n            region[i] = \"CUT\";\n            continue;\n        }\n        string sig = \"\";\n        for (size_t j = 0; j < lines.size() && j < 60; j++) {\n            int s = sideOfLine(lines[j], strawberries[i].x, strawberries[i].y);\n            sig += (s == 1 ? \"L\" : (s == -1 ? \"R\" : \"0\"));\n        }\n        region[i] = sig;\n    }\n    return region;\n}\n\nint calculateScore() {\n    auto regions = getRegions();\n    map<string, int> pieceCount;\n    for (int i = 0; i < N; i++) {\n        if (regions[i] != \"CUT\") {\n            pieceCount[regions[i]]++;\n        }\n    }\n    \n    int score = 0;\n    for (int d = 1; d <= 10; d++) {\n        int b_d = 0;\n        for (auto& kv : pieceCount) {\n            if (kv.second == d) b_d++;\n        }\n        score += min(a[d], b_d);\n    }\n    return score;\n}\n\nlong long distSq(long long x1, long long y1, long long x2, long long y2) {\n    __int128 dx = (__int128)x1 - x2;\n    __int128 dy = (__int128)y1 - y2;\n    __int128 result = dx * dx + dy * dy;\n    if (result > (__int128)4e18) return 4000000000000000000LL;\n    return (long long)result;\n}\n\nLine createLineFromPoints(long long x1, long long y1, long long x2, long long y2) {\n    long long px = clampCoord(x1);\n    long long py = clampCoord(y1);\n    long long qx = clampCoord(x2);\n    long long qy = clampCoord(y2);\n    \n    if (px == qx && py == qy) {\n        qx = clampCoord(qx + 1);\n    }\n    \n    return Line{px, py, qx, qy};\n}\n\nLine createSeparatingLine(const vector<int>& group1, const vector<int>& group2) {\n    if (group1.empty() || group2.empty()) {\n        return createLineFromPoints(0, 0, 1, 0);\n    }\n    \n    long long cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0;\n    for (int idx : group1) {\n        cx1 += strawberries[idx].x;\n        cy1 += strawberries[idx].y;\n    }\n    for (int idx : group2) {\n        cx2 += strawberries[idx].x;\n        cy2 += strawberries[idx].y;\n    }\n    cx1 /= (long long)group1.size();\n    cy1 /= (long long)group1.size();\n    cx2 /= (long long)group2.size();\n    cy2 /= (long long)group2.size();\n    \n    long long mx = (cx1 + cx2) / 2;\n    long long my = (cy1 + cy2) / 2;\n    long long dx = cx2 - cx1;\n    long long dy = cy2 - cy1;\n    \n    if (dx == 0 && dy == 0) {\n        dx = 1;\n        dy = 0;\n    }\n    \n    long long scale = 500000;\n    long long px = mx - dy;\n    long long py = my + dx;\n    long long qx = mx + dy;\n    long long qy = my - dx;\n    \n    // Extend line to cake boundary\n    long long len = max(abs(qx - px), abs(qy - py));\n    if (len > 0) {\n        px = mx - dy * scale / len;\n        py = my + dx * scale / len;\n        qx = mx + dy * scale / len;\n        qy = my - dx * scale / len;\n    }\n    \n    return createLineFromPoints(px, py, qx, qy);\n}\n\n// Check if line cuts any strawberry\nbool lineCutsStrawberry(const Line& l) {\n    for (int k = 0; k < N; k++) {\n        if (sideOfLine(l, strawberries[k].x, strawberries[k].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\n// Check if two groups are already separated by existing lines\nbool groupsSeparated(const vector<int>& g1, const vector<int>& g2) {\n    if (g1.empty() || g2.empty()) return true;\n    \n    for (int idx1 : g1) {\n        for (int idx2 : g2) {\n            bool same = true;\n            for (const auto& l : lines) {\n                int s1 = sideOfLine(l, strawberries[idx1].x, strawberries[idx1].y);\n                int s2 = sideOfLine(l, strawberries[idx2].x, strawberries[idx2].y);\n                if (s1 != 0 && s2 != 0 && s1 != s2) {\n                    same = false;\n                    break;\n                }\n            }\n            if (same) return false;\n        }\n    }\n    return true;\n}\n\n// Distance-based clustering\nvector<vector<int>> clusterByDistance() {\n    vector<vector<int>> clusters;\n    vector<bool> used(N, false);\n    \n    // Create weighted demand list (prioritize higher demands)\n    vector<pair<int, int>> demands; // (size, priority)\n    for (int d = 1; d <= 10; d++) {\n        for (int i = 0; i < a[d]; i++) {\n            demands.push_back({d, a[d]});\n        }\n    }\n    sort(demands.rbegin(), demands.rend());\n    \n    // Find unassigned strawberry nearest to origin as seed\n    auto findSeed = [&]() -> int {\n        int best = -1;\n        long long bestDist = -1;\n        for (int i = 0; i < N; i++) {\n            if (used[i]) continue;\n            long long d = distSq(strawberries[i].x, strawberries[i].y, 0, 0);\n            if (best == -1 || d < bestDist) {\n                bestDist = d;\n                best = i;\n            }\n        }\n        return best;\n    };\n    \n    for (auto& demand : demands) {\n        if ((int)clusters.size() > K + 10) break;\n        \n        int seed = findSeed();\n        if (seed == -1) break;\n        \n        // Find nearest unassigned strawberries\n        vector<pair<long long, int>> candidates;\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) {\n                long long d = distSq(strawberries[seed].x, strawberries[seed].y,\n                                    strawberries[i].x, strawberries[i].y);\n                candidates.push_back({d, i});\n            }\n        }\n        sort(candidates.begin(), candidates.end());\n        \n        vector<int> cluster;\n        for (auto& cand : candidates) {\n            if ((int)cluster.size() >= demand.first) break;\n            cluster.push_back(cand.second);\n            used[cand.second] = true;\n        }\n        \n        if (!cluster.empty()) {\n            clusters.push_back(cluster);\n        }\n    }\n    \n    // Assign remaining\n    for (int i = 0; i < N; i++) {\n        if (!used[i]) {\n            if (!clusters.empty() && (int)clusters.back().size() < 10) {\n                clusters.back().push_back(i);\n            } else {\n                clusters.push_back({i});\n            }\n            used[i] = true;\n        }\n    }\n    \n    return clusters;\n}\n\nvoid generateLinesFromClusters(const vector<vector<int>>& clusters) {\n    lines.clear();\n    \n    for (size_t i = 0; i < clusters.size() && (int)lines.size() < K; i++) {\n        for (size_t j = i + 1; j < clusters.size() && (int)lines.size() < K; j++) {\n            if (groupsSeparated(clusters[i], clusters[j])) continue;\n            \n            Line l = createSeparatingLine(clusters[i], clusters[j]);\n            \n            if (!lineCutsStrawberry(l)) {\n                lines.push_back(l);\n            }\n        }\n    }\n}\n\n// Try adding a random line\nbool tryAddRandomLine() {\n    if ((int)lines.size() >= K) return false;\n    \n    int i1 = rand() % N;\n    int i2 = rand() % N;\n    while (i1 == i2) i2 = rand() % N;\n    \n    Line newLine = createSeparatingLine({i1}, {i2});\n    \n    if (!lineCutsStrawberry(newLine)) {\n        lines.push_back(newLine);\n        return true;\n    }\n    return false;\n}\n\n// Perturb an existing line\nvoid perturbLine(int idx) {\n    if (idx >= (int)lines.size()) return;\n    \n    Line& l = lines[idx];\n    long long dx = (rand() % 2001) - 1000;\n    long long dy = (rand() % 2001) - 1000;\n    \n    Line newLine = createLineFromPoints(l.px + dx, l.py + dy, l.qx + dx, l.qy + dy);\n    \n    if (!lineCutsStrawberry(newLine)) {\n        lines[idx] = newLine;\n    }\n}\n\n// Optimize using local search\nvoid optimize() {\n    int baseScore = calculateScore();\n    int noImprovement = 0;\n    \n    for (int iter = 0; iter < 500 && noImprovement < 100; iter++) {\n        int choice = rand() % 3;\n        \n        if (choice == 0 && (int)lines.size() < K) {\n            // Try adding a line\n            lines.push_back(createLineFromPoints(0, 0, 1, 0));\n            int newScore = calculateScore();\n            if (newScore >= baseScore) {\n                baseScore = newScore;\n                noImprovement = 0;\n            } else {\n                lines.pop_back();\n                noImprovement++;\n            }\n        } else if (choice == 1 && !lines.empty()) {\n            // Try perturbing a line\n            int idx = rand() % lines.size();\n            Line oldLine = lines[idx];\n            perturbLine(idx);\n            int newScore = calculateScore();\n            if (newScore >= baseScore) {\n                baseScore = newScore;\n                noImprovement = 0;\n            } else {\n                lines[idx] = oldLine;\n                noImprovement++;\n            }\n        } else {\n            // Try adding random line\n            if (tryAddRandomLine()) {\n                int newScore = calculateScore();\n                if (newScore >= baseScore) {\n                    baseScore = newScore;\n                    noImprovement = 0;\n                } else {\n                    lines.pop_back();\n                    noImprovement++;\n                }\n            } else {\n                noImprovement++;\n            }\n        }\n    }\n    \n    // Final cleanup: remove lines that don't help\n    for (int i = (int)lines.size() - 1; i >= 0; i--) {\n        Line removed = lines[i];\n        lines.erase(lines.begin() + i);\n        int newScore = calculateScore();\n        if (newScore < baseScore) {\n            lines.insert(lines.begin() + i, removed);\n        }\n        baseScore = calculateScore();\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    srand(42);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        strawberries[i].id = i;\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Cluster strawberries\n    auto clusters = clusterByDistance();\n    \n    // Generate separating lines\n    generateLinesFromClusters(clusters);\n    \n    // Optimize with local search\n    optimize();\n    \n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const auto& l : lines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nstruct Rect {\n    Point p[4];\n    long long weight;\n    int perimeter_len;\n    \n    bool operator<(const Rect& other) const {\n        if (weight != other.weight) return weight > other.weight;\n        return perimeter_len < other.perimeter_len;\n    }\n};\n\nint N, M;\nvector<Point> initial_dots;\nvector<vector<bool>> has_dot;\nvector<vector<bool>> used_h;  // horizontal edge from (x,y) to (x+1,y)\nvector<vector<bool>> used_v;  // vertical edge from (x,y) to (x,y+1)\nvector<vector<bool>> used_d1; // diagonal from (x,y) to (x+1,y+1)\nvector<vector<bool>> used_d2; // diagonal from (x,y) to (x+1,y-1)\n\nlong long total_weight_S = 0;\nvector<vector<long long>> weights;\ndouble center_c;\n\nvoid init_weights() {\n    center_c = (N - 1) / 2.0;\n    weights.assign(N, vector<long long>(N));\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (long long)round(pow(x - center_c, 2) + pow(y - center_c, 2) + 1);\n            weights[x][y] = w;\n            total_weight_S += w;\n        }\n    }\n}\n\nlong long get_weight(int x, int y) {\n    return weights[x][y];\n}\n\nbool is_inside(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there are dots on the line segment (excluding endpoints)\nbool has_dot_on_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps <= 1) return false;\n    \n    int sx = (dx > 0) - (dx < 0);\n    int sy = (dy > 0) - (dy < 0);\n    \n    for (int i = 1; i < steps; ++i) {\n        int cx = x1 + i * sx;\n        int cy = y1 + i * sy;\n        if (has_dot[cx][cy]) return true;\n    }\n    return false;\n}\n\n// Check if rectangle perimeter has dots (excluding the 4 corners)\nbool check_rect_perimeter_dots(const Rect& r) {\n    for (int i = 0; i < 4; ++i) {\n        if (has_dot_on_segment(r.p[i].x, r.p[i].y, r.p[(i+1)%4].x, r.p[(i+1)%4].y)) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Mark/check edges of rectangle. Returns false if any edge is already used.\nbool process_rect_edges(const Rect& r, bool mark) {\n    for (int i = 0; i < 4; ++i) {\n        int x1 = r.p[i].x, y1 = r.p[i].y;\n        int x2 = r.p[(i+1)%4].x, y2 = r.p[(i+1)%4].y;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        \n        if (steps == 0) return false;\n        \n        int sx = (dx > 0) - (dx < 0);\n        int sy = (dy > 0) - (dy < 0);\n        \n        // Validate edge direction\n        bool valid_dir = false;\n        if (sx == 1 && sy == 0) valid_dir = true;      // right\n        else if (sx == -1 && sy == 0) valid_dir = true; // left\n        else if (sx == 0 && sy == 1) valid_dir = true;  // up\n        else if (sx == 0 && sy == -1) valid_dir = true; // down\n        else if (sx == 1 && sy == 1) valid_dir = true;  // up-right\n        else if (sx == -1 && sy == -1) valid_dir = true;// down-left\n        else if (sx == 1 && sy == -1) valid_dir = true; // down-right\n        else if (sx == -1 && sy == 1) valid_dir = true; // up-left\n        else return false;\n        \n        for (int j = 0; j < steps; ++j) {\n            int cx = x1 + j * sx;\n            int cy = y1 + j * sy;\n            \n            bool used = false;\n            \n            if (sx == 1 && sy == 0) {\n                // Horizontal right: edge from (cx,cy) to (cx+1,cy)\n                if (cx < N-1 && cy >= 0 && cy < N) {\n                    if (used_h[cx][cy]) used = true;\n                    else if (mark) used_h[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == 0) {\n                // Horizontal left: edge from (cx-1,cy) to (cx,cy)\n                if (cx > 0 && cy >= 0 && cy < N) {\n                    if (used_h[cx-1][cy]) used = true;\n                    else if (mark) used_h[cx-1][cy] = true;\n                }\n            } else if (sx == 0 && sy == 1) {\n                // Vertical up: edge from (cx,cy) to (cx,cy+1)\n                if (cx >= 0 && cx < N && cy < N-1) {\n                    if (used_v[cx][cy]) used = true;\n                    else if (mark) used_v[cx][cy] = true;\n                }\n            } else if (sx == 0 && sy == -1) {\n                // Vertical down: edge from (cx,cy-1) to (cx,cy)\n                if (cx >= 0 && cx < N && cy > 0) {\n                    if (used_v[cx][cy-1]) used = true;\n                    else if (mark) used_v[cx][cy-1] = true;\n                }\n            } else if (sx == 1 && sy == 1) {\n                // Diagonal up-right: edge from (cx,cy) to (cx+1,cy+1)\n                if (cx < N-1 && cy < N-1) {\n                    if (used_d1[cx][cy]) used = true;\n                    else if (mark) used_d1[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == -1) {\n                // Diagonal down-left: edge from (cx-1,cy-1) to (cx,cy)\n                if (cx > 0 && cy > 0) {\n                    if (used_d1[cx-1][cy-1]) used = true;\n                    else if (mark) used_d1[cx-1][cy-1] = true;\n                }\n            } else if (sx == 1 && sy == -1) {\n                // Diagonal down-right: edge from (cx,cy) to (cx+1,cy-1)\n                if (cx < N-1 && cy > 0) {\n                    if (used_d2[cx][cy]) used = true;\n                    else if (mark) used_d2[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == 1) {\n                // Diagonal up-left: edge from (cx-1,cy+1) to (cx,cy)\n                if (cx > 0 && cy < N-1) {\n                    if (used_d2[cx-1][cy+1]) used = true;\n                    else if (mark) used_d2[cx-1][cy+1] = true;\n                }\n            }\n            \n            if (used) return false;\n        }\n    }\n    return true;\n}\n\n// Check if 4 points form a valid rectangle (axis-aligned or 45-degree)\nbool is_valid_rectangle(const Point& p1, const Point& p2, const Point& p3, const Point& p4) {\n    // Check all 4 edges have same direction type (all axis or all 45-deg)\n    auto get_edge_type = [](const Point& a, const Point& b) -> int {\n        int dx = b.x - a.x;\n        int dy = b.y - a.y;\n        if (dx == 0 || dy == 0) return 1; // axis-aligned\n        if (abs(dx) == abs(dy)) return 2; // 45-degree\n        return 0; // invalid\n    };\n    \n    int t1 = get_edge_type(p1, p2);\n    int t2 = get_edge_type(p2, p3);\n    int t3 = get_edge_type(p3, p4);\n    int t4 = get_edge_type(p4, p1);\n    \n    if (t1 == 0 || t2 == 0 || t3 == 0 || t4 == 0) return false;\n    if (t1 != t2 || t2 != t3 || t3 != t4) return false;\n    \n    // Check it's actually a rectangle (opposite sides equal, adjacent sides perpendicular)\n    long long dx1 = p2.x - p1.x, dy1 = p2.y - p1.y;\n    long long dx2 = p3.x - p2.x, dy2 = p3.y - p2.y;\n    long long dx3 = p4.x - p3.x, dy3 = p4.y - p3.y;\n    long long dx4 = p1.x - p4.x, dy4 = p1.y - p4.y;\n    \n    // Adjacent edges should be perpendicular\n    if (dx1 * dx2 + dy1 * dy2 != 0) return false;\n    if (dx2 * dx3 + dy2 * dy3 != 0) return false;\n    if (dx3 * dx4 + dy3 * dy4 != 0) return false;\n    if (dx4 * dx1 + dy4 * dy1 != 0) return false;\n    \n    return true;\n}\n\nvector<Rect> generate_candidates(const vector<Point>& active_dots) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    \n    for (int i = 0; i < S; ++i) {\n        for (int j = i + 1; j < S; ++j) {\n            Point A = active_dots[i];\n            Point B = active_dots[j];\n            \n            // Case 1: A, B are diagonal of axis-aligned rectangle\n            if (A.x != B.x && A.y != B.y) {\n                Point C1 = {A.x, B.y};\n                Point C2 = {B.x, A.y};\n                \n                // Target C1, sources: C2, B, A (in order around rectangle)\n                if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && \n                    is_inside(C2.x, C2.y) && has_dot[C2.x][C2.y]) {\n                    Rect r;\n                    r.p[0] = C1; r.p[1] = C2; r.p[2] = B; r.p[3] = A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                \n                // Target C2, sources: C1, A, B\n                if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && \n                    is_inside(C1.x, C1.y) && has_dot[C1.x][C1.y]) {\n                    Rect r;\n                    r.p[0] = C2; r.p[1] = C1; r.p[2] = A; r.p[3] = B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 2: A, B vertical side of 45-degree rectangle\n            if (A.x == B.x && (A.y + B.y) % 2 == 0) {\n                int my = (A.y + B.y) / 2;\n                int dist = abs(A.y - B.y) / 2;\n                Point C = {A.x - dist, my};\n                Point D = {A.x + dist, my};\n                \n                if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                    is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                    is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 3: A, B horizontal side of 45-degree rectangle\n            if (A.y == B.y && (A.x + B.x) % 2 == 0) {\n                int mx = (A.x + B.x) / 2;\n                int dist = abs(A.x - B.x) / 2;\n                Point C = {mx, A.y - dist};\n                Point D = {mx, A.y + dist};\n                \n                if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                    is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                    is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 4: Three corners form right angle, find 4th\n            for (int k = 0; k < S; ++k) {\n                if (k == i || k == j) continue;\n                Point C = active_dots[k];\n                \n                auto try_corner = [&](Point P1, Point P2, Point corner) {\n                    long long dx1 = P1.x - corner.x, dy1 = P1.y - corner.y;\n                    long long dx2 = P2.x - corner.x, dy2 = P2.y - corner.y;\n                    \n                    if (dx1*dx2 + dy1*dy2 != 0) return;\n                    \n                    bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                    bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                    if (!(axis || deg45)) return;\n                    \n                    Point D = {P1.x + P2.x - corner.x, P1.y + P2.y - corner.y};\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=corner; r.p[2]=P1; r.p[3]=P2;\n                        if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                            cands.push_back(r);\n                    }\n                };\n                \n                try_corner(A, B, A);\n                try_corner(A, B, B);\n                try_corner(A, B, C);\n            }\n        }\n    }\n    return cands;\n}\n\nvector<Rect> generate_candidates_with_new(const vector<Point>& active_dots, Point new_dot) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    \n    for (int i = 0; i < S; ++i) {\n        Point A = active_dots[i];\n        Point B = new_dot;\n        \n        // Diagonal cases\n        if (A.x != B.x && A.y != B.y) {\n            Point C1 = {A.x, B.y};\n            Point C2 = {B.x, A.y};\n            \n            if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && \n                is_inside(C2.x, C2.y) && has_dot[C2.x][C2.y]) {\n                Rect r; r.p[0]=C1; r.p[1]=C2; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && \n                is_inside(C1.x, C1.y) && has_dot[C1.x][C1.y]) {\n                Rect r; r.p[0]=C2; r.p[1]=C1; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        if (A.x == B.x && (A.y + B.y) % 2 == 0) {\n            int my = (A.y + B.y) / 2;\n            int dist = abs(A.y - B.y) / 2;\n            Point C = {A.x - dist, my};\n            Point D = {A.x + dist, my};\n            \n            if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        if (A.y == B.y && (A.x + B.x) % 2 == 0) {\n            int mx = (A.x + B.x) / 2;\n            int dist = abs(A.x - B.x) / 2;\n            Point C = {mx, A.y - dist};\n            Point D = {mx, A.y + dist};\n            \n            if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        // Three-corner cases\n        for (int k = 0; k < S; ++k) {\n            if (k == i) continue;\n            Point C = active_dots[k];\n            \n            auto try_corner = [&](Point P1, Point P2, Point corner) {\n                long long dx1 = P1.x - corner.x, dy1 = P1.y - corner.y;\n                long long dx2 = P2.x - corner.x, dy2 = P2.y - corner.y;\n                \n                if (dx1*dx2 + dy1*dy2 != 0) return;\n                \n                bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                if (!(axis || deg45)) return;\n                \n                Point D = {P1.x + P2.x - corner.x, P1.y + P2.y - corner.y};\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=corner; r.p[2]=P1; r.p[3]=P2;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            };\n            \n            try_corner(A, B, A);\n            try_corner(A, B, B);\n            try_corner(A, B, C);\n        }\n    }\n    return cands;\n}\n\nstruct Solution {\n    vector<Rect> ops;\n    long long score;\n};\n\nSolution solve_one(mt19937& rng) {\n    has_dot.assign(N, vector<bool>(N, false));\n    used_h.assign(N, vector<bool>(N, false));\n    used_v.assign(N, vector<bool>(N, false));\n    used_d1.assign(N, vector<bool>(N, false));\n    used_d2.assign(N, vector<bool>(N, false));\n    \n    vector<Point> active_dots = initial_dots;\n    for (auto& p : active_dots) has_dot[p.x][p.y] = true;\n    \n    vector<Rect> ops;\n    vector<Rect> candidates = generate_candidates(active_dots);\n    \n    while (true) {\n        vector<Rect> valid_cands;\n        valid_cands.reserve(candidates.size());\n        \n        for (auto& r : candidates) {\n            // Check target is empty\n            if (has_dot[r.p[0].x][r.p[0].y]) continue;\n            \n            // Check sources have dots\n            if (!has_dot[r.p[1].x][r.p[1].y]) continue;\n            if (!has_dot[r.p[2].x][r.p[2].y]) continue;\n            if (!has_dot[r.p[3].x][r.p[3].y]) continue;\n            \n            // Check no dots on perimeter\n            if (!check_rect_perimeter_dots(r)) continue;\n            \n            // Check edges not used\n            if (!process_rect_edges(r, false)) continue;\n            \n            r.weight = get_weight(r.p[0].x, r.p[0].y);\n            int len = 0;\n            for(int i=0; i<4; ++i) {\n                len += max(abs(r.p[i].x - r.p[(i+1)%4].x), \n                           abs(r.p[i].y - r.p[(i+1)%4].y));\n            }\n            r.perimeter_len = len;\n            valid_cands.push_back(r);\n        }\n        \n        if (valid_cands.empty()) break;\n        \n        // Add randomness\n        for(auto& r : valid_cands) {\n            r.weight += (rng() % 100);\n        }\n        sort(valid_cands.begin(), valid_cands.end());\n        \n        Rect best = valid_cands[0];\n        ops.push_back(best);\n        has_dot[best.p[0].x][best.p[0].y] = true;\n        active_dots.push_back(best.p[0]);\n        process_rect_edges(best, true);\n        \n        vector<Rect> new_cands = generate_candidates_with_new(active_dots, best.p[0]);\n        candidates.insert(candidates.end(), new_cands.begin(), new_cands.end());\n    }\n    \n    Solution sol;\n    sol.ops = ops;\n    long long current_weight_sum = 0;\n    for(int x=0; x<N; ++x) \n        for(int y=0; y<N; ++y) \n            if(has_dot[x][y]) current_weight_sum += weights[x][y];\n    \n    double score_d = 1e6 * (double)N * N / M * (double)current_weight_sum / total_weight_S;\n    sol.score = (long long)round(score_d);\n    \n    return sol;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> initial_dots[i].x >> initial_dots[i].y;\n    }\n    \n    init_weights();\n    \n    Solution best_sol;\n    best_sol.score = -1;\n    \n    auto start = chrono::steady_clock::now();\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 4.8) break;\n        \n        Solution sol = solve_one(rng);\n        if (sol.score > best_sol.score) {\n            best_sol = sol;\n        }\n    }\n    \n    cout << best_sol.ops.size() << \"\\n\";\n    for (const auto& op : best_sol.ops) {\n        cout << op.p[0].x << \" \" << op.p[0].y << \" \"\n             << op.p[1].x << \" \" << op.p[1].y << \" \"\n             << op.p[2].x << \" \" << op.p[2].y << \" \"\n             << op.p[3].x << \" \" << op.p[3].y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <utility>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nusing Grid = array<array<int, 10>, 10>;\n\n// Calculate sum of squares of connected component sizes\nlong long calculate_component_score(const Grid& g) {\n    long long score = 0;\n    bool visited[10][10];\n    memset(visited, 0, sizeof(visited));\n    int dr[] = {0, 0, 1, -1};\n    int dc[] = {1, -1, 0, 0};\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                pair<int, int> q[100];\n                int head = 0, tail = 0;\n                q[tail++] = {r, c};\n                visited[r][c] = true;\n                size++;\n                \n                while(head < tail){\n                    auto [cr, cc] = q[head++];\n                    for(int i=0; i<4; ++i){\n                        int nr = cr + dr[i];\n                        int nc = cc + dc[i];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                            if(!visited[nr][nc] && g[nr][nc] == flavor){\n                                visited[nr][nc] = true;\n                                size++;\n                                q[tail++] = {nr, nc};\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Count adjacent same-flavor pairs\nlong long calculate_adjacency_bonus(const Grid& g) {\n    long long score = 0;\n    int dr[] = {0, 1};\n    int dc[] = {1, 0};\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0) {\n                for(int i=0; i<2; ++i){\n                    int nr = r + dr[i];\n                    int nc = c + dc[i];\n                    if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                        if(g[nr][nc] == g[r][c]){\n                            score += 5;\n                        } else if (g[nr][nc] != 0) {\n                            score -= 2;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return score;\n}\n\n// Combined scoring function - simpler and faster\nlong long calculate_total_score(const Grid& g) {\n    return calculate_component_score(g) * 100 + calculate_adjacency_bonus(g);\n}\n\nGrid apply_tilt(const Grid& g, char dir) {\n    Grid ng;\n    for(auto& row : ng) row.fill(0);\n\n    if (dir == 'L' || dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            int write_idx = (dir == 'L') ? 0 : 9;\n            int step = (dir == 'L') ? 1 : -1;\n            int read_start = (dir == 'L') ? 0 : 9;\n            int read_end = (dir == 'L') ? 10 : -1;\n            \n            for (int c = read_start; c != read_end; c += step) {\n                if (g[r][c] != 0) {\n                    ng[r][write_idx] = g[r][c];\n                    write_idx += step;\n                }\n            }\n        }\n    } else {\n        for (int c = 0; c < 10; ++c) {\n            int write_idx = (dir == 'F') ? 0 : 9;\n            int step = (dir == 'F') ? 1 : -1;\n            int read_start = (dir == 'F') ? 0 : 9;\n            int read_end = (dir == 'F') ? 10 : -1;\n            \n            for (int r = read_start; r != read_end; r += step) {\n                if (g[r][c] != 0) {\n                    ng[write_idx][c] = g[r][c];\n                    write_idx += step;\n                }\n            }\n        }\n    }\n    return ng;\n}\n\nstruct MoveSequence {\n    string moves;\n    Grid final_grid;\n    long long score;\n};\n\n// Optimized beam search without diversity calculation\nvector<MoveSequence> beam_search(const Grid& g, int depth, int beam_width, int turn) {\n    vector<MoveSequence> current_beam;\n    current_beam.reserve(beam_width * 4);\n    char dirs[] = {'F', 'B', 'L', 'R'};\n    \n    // Initialize with single moves\n    for (char d : dirs) {\n        Grid ng = apply_tilt(g, d);\n        long long sc = calculate_total_score(ng);\n        current_beam.push_back({string(1, d), ng, sc});\n    }\n    \n    sort(current_beam.begin(), current_beam.end(), \n         [](const MoveSequence& a, const MoveSequence& b) {\n             return a.score > b.score;\n         });\n    \n    if ((int)current_beam.size() > beam_width) {\n        current_beam.resize(beam_width);\n    }\n    \n    // Expand for remaining depth\n    for (int d = 1; d < depth; ++d) {\n        vector<MoveSequence> next_beam;\n        next_beam.reserve(current_beam.size() * 3);\n        \n        for (const auto& seq : current_beam) {\n            for (char dir : dirs) {\n                char last = seq.moves.back();\n                // Avoid immediate reversal\n                if ((last == 'F' && dir == 'B') || (last == 'B' && dir == 'F') ||\n                    (last == 'L' && dir == 'R') || (last == 'R' && dir == 'L')) {\n                    continue;\n                }\n                \n                // Limit consecutive same directions\n                int same_count = 0;\n                for (int i = (int)seq.moves.size() - 1; i >= 0 && seq.moves[i] == dir; --i) {\n                    same_count++;\n                }\n                if (same_count >= 3) continue;\n                \n                Grid ng = apply_tilt(seq.final_grid, dir);\n                long long sc = calculate_total_score(ng);\n                next_beam.push_back({seq.moves + dir, ng, sc});\n            }\n        }\n        \n        sort(next_beam.begin(), next_beam.end(), \n             [](const MoveSequence& a, const MoveSequence& b) {\n                 return a.score > b.score;\n             });\n        \n        if ((int)next_beam.size() > beam_width) {\n            next_beam.resize(beam_width);\n        }\n        \n        current_beam = move(next_beam);\n    }\n    \n    return current_beam;\n}\n\nint main() {\n    cin.tie(NULL);\n    ios_base::sync_with_stdio(false);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) {\n        cin >> f[i];\n    }\n\n    Grid grid;\n    for(auto& row : grid) row.fill(0);\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        // Place the t-th candy\n        int count = 0;\n        bool placed = false;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    count++;\n                    if (count == p) {\n                        grid[r][c] = f[t];\n                        placed = true;\n                        break;\n                    }\n                }\n            }\n            if (placed) break;\n        }\n\n        if (t == 99) {\n            cout << \"F\" << endl;\n            break;\n        }\n\n        // Adaptive beam search - deeper when board is sparse\n        int depth, beam_width;\n        if (t < 15) {\n            depth = 5;\n            beam_width = 20;\n        } else if (t < 40) {\n            depth = 4;\n            beam_width = 16;\n        } else if (t < 70) {\n            depth = 3;\n            beam_width = 12;\n        } else {\n            depth = 2;\n            beam_width = 8;\n        }\n        \n        vector<MoveSequence> results = beam_search(grid, depth, beam_width, t);\n        \n        char best_dir = results[0].moves[0];\n        \n        cout << best_dir << endl;\n        grid = apply_tilt(grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nint M;\ndouble epsilon;\nint N;\nvector<string> graphs;\n\n// Parse graph string to adjacency matrix\nvector<vector<int>> parseGraph(const string& s, int n) {\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    int idx = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            adj[i][j] = adj[j][i] = s[idx++] - '0';\n        }\n    }\n    return adj;\n}\n\n// Convert adjacency matrix to graph string\nstring toGraphString(const vector<vector<int>>& adj, int n) {\n    string s;\n    s.reserve(n * (n - 1) / 2);\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Count edges\nint countEdges(const string& s) {\n    return count(s.begin(), s.end(), '1');\n}\n\n// Compute degree sequence (sorted)\nvector<int> degreeSequence(const vector<vector<int>>& adj, int n) {\n    vector<int> deg(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            deg[i] += adj[i][j];\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute degree sum of squares (more stable than full sequence)\nlong long degreeSumSquares(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d;\n    }\n    return sum;\n}\n\n// Count paths of length 2 (related to degree sum of squares)\nint countPaths2(const vector<vector<int>>& adj, int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        int deg = 0;\n        for (int j = 0; j < n; j++) {\n            deg += adj[i][j];\n        }\n        count += deg * (deg - 1) / 2;\n    }\n    return count;\n}\n\n// Compute optimal N - much more aggressive minimization\nint computeOptimalN(int m, double eps) {\n    // For each candidate N, check if we can separate M graphs\n    for (int n = 4; n <= 100; n++) {\n        int total_edges = n * (n - 1) / 2;\n        \n        // Expected noise: each edge flips with probability eps\n        double noise_std = sqrt(total_edges * eps * (1 - eps));\n        \n        // Need separation of at least 2-3 standard deviations between graphs\n        double min_sep = max(1.0, 2.5 * noise_std);\n        \n        // Can we fit M graphs in the edge count range?\n        // Use 80% of range to allow margin\n        double available = total_edges * 0.8;\n        double needed = (m - 1) * min_sep;\n        \n        if (needed <= available) {\n            // Additional constraint: prefer smaller N for easier cases\n            if (m <= 30 && eps <= 0.15 && n > 25) continue;\n            if (m <= 50 && eps <= 0.2 && n > 35) continue;\n            if (m <= 70 && eps <= 0.25 && n > 50) continue;\n            return n;\n        }\n    }\n    \n    return 100;\n}\n\n// Generate graph with specific properties\nstring generateGraph(int n, int target_edges, int seed, int type) {\n    mt19937 rng(seed);\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    \n    vector<pair<int, int>> edges;\n    edges.reserve(n * (n - 1) / 2);\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    }\n    \n    // Different construction strategies for variety\n    if (type == 0) {\n        // Random\n        shuffle(edges.begin(), edges.end(), rng);\n    } else if (type == 1) {\n        // Prefer edges with small index sum (creates dense region)\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.first + a.second < b.first + b.second;\n        });\n    } else if (type == 2) {\n        // Prefer edges that create degree variation\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return max(a.first, a.second) < max(b.first, b.second);\n        });\n    } else if (type == 3) {\n        // Prefer edges with small index difference (creates local clusters)\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return abs(a.first - a.second) < abs(b.first - b.second);\n        });\n    }\n    \n    int added = 0;\n    for (auto& [u, v] : edges) {\n        if (added >= target_edges) break;\n        adj[u][v] = adj[v][u] = 1;\n        added++;\n    }\n    \n    return toGraphString(adj, n);\n}\n\n// Generate M well-separated graphs\nvector<string> generateGraphs(int m, int n, double eps) {\n    vector<string> result;\n    result.reserve(m);\n    \n    int total_edges = n * (n - 1) / 2;\n    double noise_std = sqrt(total_edges * eps * (1 - eps));\n    int min_sep = max(1, (int)(3.0 * noise_std));\n    \n    // Edge count range\n    int min_edges = max(0, (int)(total_edges * 0.1));\n    int max_edges = min(total_edges, (int)(total_edges * 0.9));\n    int range = max_edges - min_edges;\n    \n    // Calculate step size\n    int step = max(min_sep, range / max(1, m - 1));\n    \n    for (int k = 0; k < m; k++) {\n        int edges = min_edges + k * step;\n        edges = max(min_edges, min(max_edges, edges));\n        \n        // Vary structure type\n        int type = k % 4;\n        string g = generateGraph(n, edges, k * 1234 + n, type);\n        result.push_back(g);\n    }\n    \n    return result;\n}\n\n// Graph signature\nstruct GraphSignature {\n    int edge_count;\n    long long degree_sum_sq;\n    int paths2;\n    vector<int> degree_seq;\n    int min_deg, max_deg;\n    \n    GraphSignature() {}\n    \n    GraphSignature(const string& s, int n) {\n        edge_count = countEdges(s);\n        auto adj = parseGraph(s, n);\n        degree_seq = degreeSequence(adj, n);\n        degree_sum_sq = degreeSumSquares(degree_seq);\n        paths2 = countPaths2(adj, n);\n        min_deg = degree_seq[0];\n        max_deg = degree_seq[n-1];\n    }\n};\n\n// Compute distance with noise-adaptive weighting\ndouble signatureDistance(const GraphSignature& s1, const GraphSignature& s2, double eps) {\n    double dist = 0;\n    \n    // Edge count - most important, weight increases with noise\n    double edge_weight = 5.0 + 20.0 * eps;\n    dist += abs(s1.edge_count - s2.edge_count) * edge_weight;\n    \n    // Degree sum of squares - stable under permutation\n    double dss_weight = 0.01 + 0.05 * eps;\n    dist += abs(s1.degree_sum_sq - s2.degree_sum_sq) * dss_weight;\n    \n    // Paths of length 2\n    double p2_weight = 0.02 + 0.03 * eps;\n    dist += abs(s1.paths2 - s2.paths2) * p2_weight;\n    \n    // Degree range\n    dist += abs(s1.min_deg - s2.min_deg) * 2.0;\n    dist += abs(s1.max_deg - s2.max_deg) * 2.0;\n    \n    // Full degree sequence (less weight under high noise)\n    double deg_seq_weight = max(0.1, 1.0 - eps);\n    for (size_t i = 0; i < s1.degree_seq.size(); i++) {\n        dist += abs(s1.degree_seq[i] - s2.degree_seq[i]) * deg_seq_weight;\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> M >> epsilon;\n    \n    // Compute optimal N\n    N = computeOptimalN(M, epsilon);\n    \n    // Generate graphs\n    graphs = generateGraphs(M, N, epsilon);\n    \n    // Precompute signatures\n    vector<GraphSignature> signatures(M);\n    for (int i = 0; i < M; i++) {\n        signatures[i] = GraphSignature(graphs[i], N);\n    }\n    \n    // Output\n    cout << N << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << graphs[i] << \"\\n\";\n    }\n    cout.flush();\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        GraphSignature h_sig(h, N);\n        \n        int best_idx = 0;\n        double best_dist = 1e18;\n        double second_best = 1e18;\n        \n        for (int i = 0; i < M; i++) {\n            double dist = signatureDistance(h_sig, signatures[i], epsilon);\n            if (dist < best_dist) {\n                second_best = best_dist;\n                best_dist = dist;\n                best_idx = i;\n            } else if (dist < second_best) {\n                second_best = dist;\n            }\n        }\n        \n        // Confidence check - if best is much better, trust it\n        // Otherwise, could add more sophisticated logic\n        cout << best_idx << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nconst long long INF = 1e18;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, int>>> adj(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\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    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    auto total_start = chrono::steady_clock::now();\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Conflict matrix W\n    vector<int> W(M * M, 0);\n    vector<int> edge_usage(M, 0);\n\n    // Strategic path sampling\n    int num_samples = 10000;\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 1);\n    shuffle(vertices.begin(), vertices.end(), rng);\n\n    auto w_start = chrono::steady_clock::now();\n    \n    for (int iter = 0; iter < num_samples; ++iter) {\n        if (iter % 500 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - w_start).count() > 700) break;\n        }\n        \n        int s = vertices[iter % N];\n        int t = vertices[(iter * 7 + 13) % N];\n        if (s == t) {\n            t = vertices[(iter + 1) % N];\n        }\n        \n        vector<long long> dist(N + 1, INF);\n        vector<int> par_edge(N + 1, -1);\n        vector<int> par_node(N + 1, -1);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n            for (auto [v, eid] : adj[u]) {\n                if (dist[u] + edges[eid].w < dist[v]) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    par_node[v] = u;\n                    par_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        if (dist[t] == INF) continue;\n\n        vector<int> path_edges;\n        int curr = t;\n        while (curr != s && par_edge[curr] != -1) {\n            path_edges.push_back(par_edge[curr]);\n            curr = par_node[curr];\n        }\n\n        for (int eid : path_edges) {\n            edge_usage[eid]++;\n        }\n        int L = path_edges.size();\n        for (int i = 0; i < L; ++i) {\n            for (int j = i + 1; j < L; ++j) {\n                int u = path_edges[i];\n                int v = path_edges[j];\n                // Reduced weight factor\n                int weight_factor = (edges[u].w + edges[v].w) / 5000 + 1;\n                W[u * M + v] += weight_factor;\n                W[v * M + u] += weight_factor;\n            }\n        }\n    }\n\n    // Edge importance\n    vector<long long> edge_importance(M, 0);\n    for (int i = 0; i < M; ++i) {\n        edge_importance[i] = (long long)edge_usage[i] * 50;\n        for (int j = 0; j < M; ++j) {\n            edge_importance[i] += W[i * M + j];\n        }\n    }\n\n    // Solve function\n    auto solve = [&](int seed_offset, int time_limit_ms) -> pair<vector<int>, long long> {\n        mt19937_64 local_rng(rng() + seed_offset);\n        \n        // Initial assignment\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return edge_importance[a] > edge_importance[b];\n        });\n        \n        for (int i = M - 1; i > 0; --i) {\n            int j = uniform_int_distribution<>(0, i)(local_rng);\n            swap(order[i], order[j]);\n        }\n\n        vector<int> assignment(M, -1);\n        vector<int> day_size(D, 0);\n        vector<vector<int>> day_edges(D);\n        \n        for (int e : order) {\n            int best_day = -1;\n            long long min_cost = -1;\n            \n            vector<int> day_order(D);\n            iota(day_order.begin(), day_order.end(), 0);\n            shuffle(day_order.begin(), day_order.end(), local_rng);\n            \n            for (int k : day_order) {\n                if (day_size[k] < K) {\n                    long long cost = 0;\n                    for (int other : day_edges[k]) {\n                        cost += W[e * M + other];\n                    }\n                    if (best_day == -1 || cost < min_cost) {\n                        min_cost = cost;\n                        best_day = k;\n                    }\n                }\n            }\n            \n            if (best_day != -1) {\n                assignment[e] = best_day;\n                day_edges[best_day].push_back(e);\n                day_size[best_day]++;\n            }\n        }\n\n        // Precompute C[k][e]\n        vector<long long> C(D * M, 0);\n        for (int k = 0; k < D; ++k) {\n            for (int e : day_edges[k]) {\n                for (int other = 0; other < M; ++other) {\n                    C[k * M + other] += W[e * M + other];\n                }\n            }\n        }\n        \n        long long current_cost = 0;\n        for (int k = 0; k < D; ++k) {\n            for (int i : day_edges[k]) {\n                for (int j : day_edges[k]) {\n                    if (i < j) current_cost += W[i * M + j];\n                }\n            }\n        }\n        \n        long long best_cost = current_cost;\n        vector<int> best_assignment = assignment;\n        vector<int> best_day_size = day_size;\n\n        // Simulated Annealing with swap moves\n        auto ls_start = chrono::steady_clock::now();\n        double temperature = 1000.0;\n        int moves = 0;\n        int max_moves = 600000;\n        int no_improve_count = 0;\n        int stagnation_reset = 0;\n        \n        while (moves < max_moves) {\n            if (moves % 5000 == 0) {\n                auto now = chrono::steady_clock::now();\n                auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - ls_start).count();\n                if (elapsed > time_limit_ms) break;\n                \n                if (no_improve_count > 30000) {\n                    stagnation_reset++;\n                    if (stagnation_reset < 3) {\n                        temperature *= 10; // Reheat\n                        no_improve_count = 0;\n                    }\n                }\n            }\n            \n            temperature *= 0.9999;\n            \n            int move_type = uniform_int_distribution<>(0, 10)(local_rng);\n            \n            if (move_type < 8) {\n                // Single edge move (80%)\n                int e = uniform_int_distribution<>(0, M - 1)(local_rng);\n                int k_old = assignment[e];\n                if (k_old < 0) { moves++; continue; }\n                \n                int k_new = uniform_int_distribution<>(0, D - 1)(local_rng);\n                if (k_new == k_old) { moves++; continue; }\n                if (day_size[k_new] >= K) { moves++; continue; }\n                \n                long long delta = C[k_new * M + e] - C[k_old * M + e];\n                \n                bool accept = (delta < 0) || (temperature > 0.1 && exp(-delta / temperature) > uniform_real_distribution<>(0, 1)(local_rng));\n                \n                if (accept) {\n                    assignment[e] = k_new;\n                    day_size[k_old]--;\n                    day_size[k_new]++;\n                    \n                    for (int other = 0; other < M; ++other) {\n                        long long w_val = W[e * M + other];\n                        C[k_old * M + other] -= w_val;\n                        C[k_new * M + other] += w_val;\n                    }\n                    \n                    current_cost += delta;\n                    if (current_cost < best_cost) {\n                        best_cost = current_cost;\n                        best_assignment = assignment;\n                        best_day_size = day_size;\n                        no_improve_count = 0;\n                    } else {\n                        no_improve_count++;\n                    }\n                } else {\n                    no_improve_count++;\n                }\n            } else {\n                // Swap move (20%)\n                int e1 = uniform_int_distribution<>(0, M - 1)(local_rng);\n                int e2 = uniform_int_distribution<>(0, M - 1)(local_rng);\n                if (e1 == e2) { moves++; continue; }\n                \n                int k1 = assignment[e1];\n                int k2 = assignment[e2];\n                if (k1 < 0 || k2 < 0 || k1 == k2) { moves++; continue; }\n                \n                // Calculate delta for swap\n                long long delta = 0;\n                \n                // e1 moves from k1 to k2\n                delta += C[k2 * M + e1] - C[k1 * M + e1];\n                // e2 moves from k2 to k1\n                delta += C[k1 * M + e2] - C[k2 * M + e2];\n                // But we double-counted W[e1][e2], fix it\n                delta -= 2 * W[e1 * M + e2];\n                \n                bool accept = (delta < 0) || (temperature > 0.1 && exp(-delta / temperature) > uniform_real_distribution<>(0, 1)(local_rng));\n                \n                if (accept) {\n                    assignment[e1] = k2;\n                    assignment[e2] = k1;\n                    \n                    // Update C for e1\n                    for (int other = 0; other < M; ++other) {\n                        long long w_val = W[e1 * M + other];\n                        C[k1 * M + other] -= w_val;\n                        C[k2 * M + other] += w_val;\n                    }\n                    // Update C for e2\n                    for (int other = 0; other < M; ++other) {\n                        long long w_val = W[e2 * M + other];\n                        C[k2 * M + other] -= w_val;\n                        C[k1 * M + other] += w_val;\n                    }\n                    \n                    current_cost += delta;\n                    if (current_cost < best_cost) {\n                        best_cost = current_cost;\n                        best_assignment = assignment;\n                        best_day_size = day_size;\n                        no_improve_count = 0;\n                    } else {\n                        no_improve_count++;\n                    }\n                } else {\n                    no_improve_count++;\n                }\n            }\n            \n            moves++;\n        }\n        \n        // Greedy final pass - properly update state\n        bool improved = true;\n        int greedy_iter = 0;\n        \n        // Rebuild C and day_size from best_assignment\n        fill(C.begin(), C.end(), 0);\n        fill(day_size.begin(), day_size.end(), 0);\n        assignment = best_assignment;\n        day_size = best_day_size;\n        \n        for (int k = 0; k < D; ++k) {\n            for (int e = 0; e < M; ++e) {\n                if (assignment[e] == k) {\n                    for (int other = 0; other < M; ++other) {\n                        C[k * M + other] += W[e * M + other];\n                    }\n                }\n            }\n        }\n        \n        current_cost = best_cost;\n        \n        while (improved && greedy_iter < 20) {\n            improved = false;\n            greedy_iter++;\n            \n            for (int e = 0; e < M; ++e) {\n                int k_old = assignment[e];\n                if (k_old < 0) continue;\n                \n                long long best_delta = 0;\n                int best_k = -1;\n                \n                for (int k = 0; k < D; ++k) {\n                    if (k == k_old) continue;\n                    if (day_size[k] >= K) continue;\n                    \n                    long long delta = C[k * M + e] - C[k_old * M + e];\n                    \n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_k = k;\n                    }\n                }\n                \n                if (best_k >= 0 && best_delta < 0) {\n                    assignment[e] = best_k;\n                    day_size[k_old]--;\n                    day_size[best_k]++;\n                    \n                    for (int other = 0; other < M; ++other) {\n                        long long w_val = W[e * M + other];\n                        C[k_old * M + other] -= w_val;\n                        C[best_k * M + other] += w_val;\n                    }\n                    \n                    current_cost += best_delta;\n                    if (current_cost < best_cost) {\n                        best_cost = current_cost;\n                        best_assignment = assignment;\n                        best_day_size = day_size;\n                    }\n                    improved = true;\n                }\n            }\n        }\n        \n        return {best_assignment, best_cost};\n    };\n\n    // Try multiple initial solutions with intensification\n    vector<int> best_assignment;\n    long long best_cost = -1;\n    \n    int num_restarts = 3;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        int time_per_restart = 1400;\n        \n        // Give more time to later restarts if we found a good solution\n        if (restart > 0 && best_cost > 0) {\n            time_per_restart = 1600;\n        }\n        \n        auto [assignment, cost] = solve(restart * 1000000, time_per_restart);\n        \n        if (best_cost < 0 || cost < best_cost) {\n            best_cost = cost;\n            best_assignment = assignment;\n        }\n        \n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - total_start).count() > 5700) break;\n    }\n\n    // Output\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;\n\nint D;\nvector<string> f1, r1, f2, r2;\nvector<vector<vector<bool>>> valid1, valid2;\nvector<vector<vector<int>>> b1, b2;\n\nstruct Block {\n    vector<tuple<int,int,int>> cells;\n    int id;\n    bool usedIn1 = false;\n    bool usedIn2 = false;\n    \n    void normalize() {\n        if (cells.empty()) return;\n        int minX = 100, minY = 100, minZ = 100;\n        for (auto& cell : cells) {\n            minX = min(minX, get<0>(cell));\n            minY = min(minY, get<1>(cell));\n            minZ = min(minZ, get<2>(cell));\n        }\n        for (auto& cell : cells) {\n            get<0>(cell) -= minX;\n            get<1>(cell) -= minY;\n            get<2>(cell) -= minZ;\n        }\n        sort(cells.begin(), cells.end());\n    }\n};\n\nvector<Block> blocks;\n\n// 24 rotation matrices\nint rotations_24[24][3][3] = {\n    {{1,0,0},{0,1,0},{0,0,1}}, {{0,-1,0},{1,0,0},{0,0,1}}, {{-1,0,0},{0,-1,0},{0,0,1}}, {{0,1,0},{-1,0,0},{0,0,1}},\n    {{1,0,0},{0,0,-1},{0,1,0}}, {{0,0,1},{1,0,0},{0,1,0}}, {{-1,0,0},{0,0,1},{0,1,0}}, {{0,0,-1},{-1,0,0},{0,1,0}},\n    {{1,0,0},{0,0,1},{0,-1,0}}, {{0,0,-1},{1,0,0},{0,-1,0}}, {{-1,0,0},{0,0,-1},{0,-1,0}}, {{0,0,1},{-1,0,0},{0,-1,0}},\n    {{0,1,0},{0,0,1},{1,0,0}}, {{0,0,-1},{0,1,0},{1,0,0}}, {{0,-1,0},{0,0,-1},{1,0,0}}, {{0,0,1},{0,-1,0},{1,0,0}},\n    {{0,1,0},{0,0,-1},{-1,0,0}}, {{0,0,1},{0,1,0},{-1,0,0}}, {{0,-1,0},{0,0,1},{-1,0,0}}, {{0,0,-1},{0,-1,0},{-1,0,0}},\n    {{0,-1,0},{1,0,0},{0,0,1}}, {{1,0,0},{0,0,1},{0,1,0}}, {{0,1,0},{-1,0,0},{0,0,1}}, {{-1,0,0},{0,0,-1},{0,1,0}}\n};\n\nvector<tuple<int,int,int>> getNeighbors(int x, int y, int z) {\n    vector<tuple<int,int,int>> neighbors;\n    int dx[] = {1, -1, 0, 0, 0, 0};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {0, 0, 0, 0, 1, -1};\n    \n    for (int d = 0; d < 6; d++) {\n        int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n        if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D) {\n            neighbors.emplace_back(nx, ny, nz);\n        }\n    }\n    return neighbors;\n}\n\ntuple<int,int,int> rotateCell(int x, int y, int z, int rot) {\n    int nx = rotations_24[rot][0][0]*x + rotations_24[rot][0][1]*y + rotations_24[rot][0][2]*z;\n    int ny = rotations_24[rot][1][0]*x + rotations_24[rot][1][1]*y + rotations_24[rot][1][2]*z;\n    int nz = rotations_24[rot][2][0]*x + rotations_24[rot][2][1]*y + rotations_24[rot][2][2]*z;\n    return make_tuple(nx, ny, nz);\n}\n\nbool canPlace(const vector<tuple<int,int,int>>& shape, int bx, int by, int bz, int rot,\n              const vector<vector<vector<bool>>>& valid,\n              const vector<vector<vector<bool>>>& placed) {\n    int x0 = get<0>(shape[0]), y0 = get<1>(shape[0]), z0 = get<2>(shape[0]);\n    for (const auto& cell : shape) {\n        int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n        auto rotated = rotateCell(x - x0, y - y0, z - z0, rot);\n        int px = bx + get<0>(rotated), py = by + get<1>(rotated), pz = bz + get<2>(rotated);\n        if (px < 0 || px >= D || py < 0 || py >= D || pz < 0 || pz >= D) return false;\n        if (placed[px][py][pz]) return false;\n        if (!valid[px][py][pz]) return false;\n    }\n    return true;\n}\n\nvoid placeBlock(const vector<tuple<int,int,int>>& shape, int bx, int by, int bz, int rot,\n                int blockId,\n                vector<vector<vector<bool>>>& placed,\n                vector<vector<vector<int>>>& b) {\n    int x0 = get<0>(shape[0]), y0 = get<1>(shape[0]), z0 = get<2>(shape[0]);\n    for (const auto& cell : shape) {\n        int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n        auto rotated = rotateCell(x - x0, y - y0, z - z0, rot);\n        int px = bx + get<0>(rotated), py = by + get<1>(rotated), pz = bz + get<2>(rotated);\n        placed[px][py][pz] = true;\n        b[px][py][pz] = blockId;\n    }\n}\n\nvector<tuple<int,int,int>> growRegion(int sx, int sy, int sz, int maxSize,\n                                       const vector<vector<vector<bool>>>& valid,\n                                       const vector<vector<vector<bool>>>& placed) {\n    vector<tuple<int,int,int>> region;\n    queue<tuple<int,int,int>> q;\n    set<tuple<int,int,int>> visited;\n    \n    q.emplace(sx, sy, sz);\n    visited.emplace(sx, sy, sz);\n    \n    while (!q.empty() && (int)region.size() < maxSize) {\n        auto cur = q.front();\n        q.pop();\n        region.emplace_back(cur);\n        \n        for (auto neighbor : getNeighbors(get<0>(cur), get<1>(cur), get<2>(cur))) {\n            if (visited.count(neighbor)) continue;\n            int nx = get<0>(neighbor), ny = get<1>(neighbor), nz = get<2>(neighbor);\n            if (!valid[nx][ny][nz]) continue;\n            if (placed[nx][ny][nz]) continue;\n            \n            visited.emplace(neighbor);\n            q.emplace(neighbor);\n        }\n    }\n    \n    return region;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    f1.resize(D); r1.resize(D);\n    f2.resize(D); r2.resize(D);\n    \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    valid1.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    valid2.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    b1.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    b2.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') valid1[x][y][z] = true;\n                if (f2[z][x] == '1' && r2[z][y] == '1') valid2[x][y][z] = true;\n            }\n        }\n    }\n    \n    vector<vector<vector<bool>>> placed1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> placed2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    int blockId = 0;\n    \n    // Phase 1: Create shared blocks from common positions\n    vector<tuple<int,int,int>> common;\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++)\n                if (valid1[x][y][z] && valid2[x][y][z])\n                    common.emplace_back(x, y, z);\n    \n    sort(common.begin(), common.end(), [&](const auto& a, const auto& b) {\n        int x1 = get<0>(a), y1 = get<1>(a), z1 = get<2>(a);\n        int x2 = get<0>(b), y2 = get<1>(b), z2 = get<2>(b);\n        int c1 = 0, c2 = 0;\n        for (auto n : getNeighbors(x1, y1, z1)) {\n            int nx = get<0>(n), ny = get<1>(n), nz = get<2>(n);\n            if (valid1[nx][ny][nz] && valid2[nx][ny][nz]) c1++;\n        }\n        for (auto n : getNeighbors(x2, y2, z2)) {\n            int nx = get<0>(n), ny = get<1>(n), nz = get<2>(n);\n            if (valid1[nx][ny][nz] && valid2[nx][ny][nz]) c2++;\n        }\n        return c1 > c2;\n    });\n    \n    for (const auto& seed : common) {\n        int sx = get<0>(seed), sy = get<1>(seed), sz = get<2>(seed);\n        if (placed1[sx][sy][sz] || placed2[sx][sy][sz]) continue;\n        \n        int targetSize = min(8, max(3, (int)common.size() / 10 + 3));\n        auto region = growRegion(sx, sy, sz, targetSize, valid1, placed1);\n        \n        bool canPlace2 = true;\n        for (const auto& cell : region) {\n            int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n            if (!valid2[x][y][z] || placed2[x][y][z]) {\n                canPlace2 = false;\n                break;\n            }\n        }\n        \n        if (!canPlace2 || (int)region.size() < 2) {\n            region = growRegion(sx, sy, sz, min(4, targetSize/2), valid1, placed1);\n            canPlace2 = true;\n            for (const auto& cell : region) {\n                int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n                if (!valid2[x][y][z] || placed2[x][y][z]) {\n                    canPlace2 = false;\n                    break;\n                }\n            }\n        }\n        \n        if (region.empty()) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells = region;\n        block.normalize();\n        block.usedIn1 = true;\n        block.usedIn2 = canPlace2;\n        \n        for (const auto& cell : region) {\n            int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n            placed1[x][y][z] = true;\n            b1[x][y][z] = blockId;\n            if (canPlace2) {\n                placed2[x][y][z] = true;\n                b2[x][y][z] = blockId;\n            }\n        }\n        \n        blocks.push_back(block);\n    }\n    \n    // Phase 2: Try to match remaining positions between solutions\n    vector<tuple<int,int,int>> remaining1, remaining2;\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && !placed1[x][y][z]) remaining1.emplace_back(x, y, z);\n                if (valid2[x][y][z] && !placed2[x][y][z]) remaining2.emplace_back(x, y, z);\n            }\n    \n    for (const auto& seed : remaining1) {\n        int sx = get<0>(seed), sy = get<1>(seed), sz = get<2>(seed);\n        if (placed1[sx][sy][sz]) continue;\n        \n        for (int size = 3; size >= 2; size--) {\n            auto region = growRegion(sx, sy, sz, size, valid1, placed1);\n            if ((int)region.size() < size) continue;\n            \n            bool found = false;\n            int bestX = -1, bestY = -1, bestZ = -1, bestRot = 0;\n            \n            for (const auto& target : remaining2) {\n                int tx = get<0>(target), ty = get<1>(target), tz = get<2>(target);\n                if (placed2[tx][ty][tz]) continue;\n                for (int rot = 0; rot < 24 && !found; rot++) {\n                    if (canPlace(region, tx, ty, tz, rot, valid2, placed2)) {\n                        bestX = tx; bestY = ty; bestZ = tz; bestRot = rot;\n                        found = true;\n                    }\n                }\n                if (found) break;\n            }\n            \n            if (found) {\n                blockId++;\n                Block block;\n                block.id = blockId;\n                block.cells = region;\n                block.normalize();\n                block.usedIn1 = true;\n                block.usedIn2 = true;\n                \n                placeBlock(region, sx, sy, sz, 0, blockId, placed1, b1);\n                placeBlock(region, bestX, bestY, bestZ, bestRot, blockId, placed2, b2);\n                \n                blocks.push_back(block);\n                break;\n            }\n        }\n    }\n    \n    // Phase 3: Fill remaining positions with 1x1x1 blocks\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && !placed1[x][y][z]) {\n                    blockId++;\n                    Block block;\n                    block.id = blockId;\n                    block.cells.emplace_back(x, y, z);\n                    block.usedIn1 = true;\n                    block.usedIn2 = false;\n                    placed1[x][y][z] = true;\n                    b1[x][y][z] = blockId;\n                    blocks.push_back(block);\n                }\n                if (valid2[x][y][z] && !placed2[x][y][z]) {\n                    blockId++;\n                    Block block;\n                    block.id = blockId;\n                    block.cells.emplace_back(x, y, z);\n                    block.usedIn1 = false;\n                    block.usedIn2 = true;\n                    placed2[x][y][z] = true;\n                    b2[x][y][z] = blockId;\n                    blocks.push_back(block);\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << blockId << \"\\n\";\n    \n    bool first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b1[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b2[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\nint N, M, K;\nint vx[105], vy[105];\nint eu[305], ev[305], ew[305];\nint ax[5005], ay[5005];\nint adj[105][10];\nint adjCnt[105];\n\nint P[105];\nint B[305];\n\nbool reachable[105];\n\ninline int dist2(int x1, int y1, int x2, int y2) {\n    int dx = x1 - x2;\n    int dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nvoid updateReachable() {\n    memset(reachable, 0, sizeof(reachable));\n    int q[105];\n    int head = 0, tail = 0;\n    q[tail++] = 0;\n    reachable[0] = true;\n    \n    while (head < tail) {\n        int u = q[head++];\n        for (int i = 0; i < adjCnt[u]; i++) {\n            int ej = adj[u][i];\n            if (B[ej]) {\n                int v = (eu[ej] == u) ? ev[ej] : eu[ej];\n                if (!reachable[v]) {\n                    reachable[v] = true;\n                    q[tail++] = v;\n                }\n            }\n        }\n    }\n}\n\nint countCovered() {\n    int count = 0;\n    bool covered[5005];\n    memset(covered, 0, sizeof(bool) * K);\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i] || P[i] == 0) continue;\n        int p2 = P[i] * P[i];\n        for (int k = 0; k < K; k++) {\n            if (!covered[k] && dist2(vx[i], vy[i], ax[k], ay[k]) <= p2) {\n                covered[k] = true;\n                count++;\n            }\n        }\n    }\n    return count;\n}\n\nlong long calculateCost() {\n    long long cost = 0;\n    for (int i = 0; i < N; i++) cost += 1LL * P[i] * P[i];\n    for (int j = 0; j < M; j++) if (B[j]) cost += ew[j];\n    return cost;\n}\n\nvoid buildInitialTree() {\n    memset(B, 0, sizeof(B));\n    memset(P, 0, sizeof(P));\n    \n    bool visited[105] = {false};\n    int q[105];\n    int head = 0, tail = 0;\n    q[tail++] = 0;\n    visited[0] = true;\n    \n    int parentEdge[105];\n    memset(parentEdge, -1, sizeof(parentEdge));\n    \n    while (head < tail) {\n        int u = q[head++];\n        for (int i = 0; i < adjCnt[u]; i++) {\n            int ej = adj[u][i];\n            int v = (eu[ej] == u) ? ev[ej] : eu[ej];\n            if (!visited[v]) {\n                visited[v] = true;\n                parentEdge[v] = ej;\n                q[tail++] = v;\n            }\n        }\n    }\n    \n    for (int i = 1; i < N; i++) {\n        if (parentEdge[i] >= 0) B[parentEdge[i]] = 1;\n    }\n}\n\nvoid setPForCoverage() {\n    updateReachable();\n    for (int i = 0; i < N; i++) if (!reachable[i]) P[i] = 0;\n    \n    bool covered[5005];\n    memset(covered, 0, sizeof(bool) * K);\n    \n    // Simple greedy: for each uncovered resident, find closest reachable vertex\n    for (int k = 0; k < K; k++) {\n        if (covered[k]) continue;\n        \n        int bestI = -1, bestD2 = 1e9;\n        for (int i = 0; i < N; i++) {\n            if (!reachable[i]) continue;\n            int d2 = dist2(vx[i], vy[i], ax[k], ay[k]);\n            if (d2 < bestD2) {\n                bestD2 = d2;\n                bestI = i;\n            }\n        }\n        \n        if (bestI >= 0 && bestD2 <= 25000000) {\n            int needed = (int)ceil(sqrt(bestD2));\n            if (needed > P[bestI]) P[bestI] = needed;\n            covered[k] = true;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    for (int i = 0; i < N; i++) cin >> vx[i] >> vy[i];\n    \n    memset(adjCnt, 0, sizeof(adjCnt));\n    for (int j = 0; j < M; j++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        eu[j] = u; ev[j] = v; ew[j] = w;\n        adj[u][adjCnt[u]++] = j;\n        adj[v][adjCnt[v]++] = j;\n    }\n    \n    for (int k = 0; k < K; k++) cin >> ax[k] >> ay[k];\n    \n    buildInitialTree();\n    setPForCoverage();\n    \n    int bestCovered = countCovered();\n    long long bestCost = calculateCost();\n    \n    mt19937 rng(42);\n    \n    // Very few iterations\n    for (int iter = 0; iter < 50; iter++) {\n        int edgeIdx = rng() % M;\n        int oldB = B[edgeIdx];\n        B[edgeIdx] = 1 - oldB;\n        \n        updateReachable();\n        int covered = countCovered();\n        long long cost = calculateCost();\n        \n        if (covered > bestCovered || (covered == bestCovered && cost < bestCost)) {\n            bestCovered = covered;\n            bestCost = cost;\n        } else {\n            B[edgeIdx] = oldB;\n        }\n    }\n    \n    setPForCoverage();\n    \n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\n\nstruct Coord {\n    int x, y;\n    bool operator==(const Coord& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n};\n\nint grid[N][N];\nCoord pos[TOTAL_BALLS];\n\n// 6 adjacent directions\nconst int DX[6] = {-1, -1, 0, 0, 1, 1};\nconst int DY[6] = {-1, 0, -1, 1, 0, 1};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nbool areAdjacent(Coord c1, Coord c2) {\n    int dx = abs(c1.x - c2.x);\n    int dy = abs(c1.y - c2.y);\n    if (dx > 1) return false;\n    if (dx == 0) return dy == 1;\n    return dy == 0 || dy == 1;\n}\n\n// Calculate which tier a ball should be in based on its value\nint getTargetTier(int value) {\n    // Balls 0-29 should be in tier 0-4 (top 5 tiers have 15 balls)\n    // Distribute balls across tiers based on value\n    int tier = 0;\n    int count = 0;\n    for (int t = 0; t < N; t++) {\n        int tierSize = t + 1;\n        if (count + tierSize > value) {\n            return t;\n        }\n        count += tierSize;\n    }\n    return N - 1;\n}\n\n// Simple heuristic movement toward target\nvoid moveToward(Coord& current, Coord target) {\n    if (current == target) return;\n    \n    // Prefer moving toward target tier first\n    if (current.x < target.x) {\n        // Move down\n        for (int i = 0; i < 6; i++) {\n            int nx = current.x + DX[i];\n            int ny = current.y + DY[i];\n            if (isValid(nx, ny) && nx > current.x) {\n                // Check if this move gets us closer\n                if (abs(nx - target.x) + abs(ny - target.y) < \n                    abs(current.x - target.x) + abs(current.y - target.y)) {\n                    current = {nx, ny};\n                    return;\n                }\n            }\n        }\n    } else if (current.x > target.x) {\n        // Move up\n        for (int i = 0; i < 6; i++) {\n            int nx = current.x + DX[i];\n            int ny = current.y + DY[i];\n            if (isValid(nx, ny) && nx < current.x) {\n                if (abs(nx - target.x) + abs(ny - target.y) < \n                    abs(current.x - target.x) + abs(current.y - target.y)) {\n                    current = {nx, ny};\n                    return;\n                }\n            }\n        }\n    }\n    \n    // Same tier, adjust y\n    if (current.y < target.y) {\n        for (int i = 0; i < 6; i++) {\n            int nx = current.x + DX[i];\n            int ny = current.y + DY[i];\n            if (isValid(nx, ny) && ny > current.y) {\n                if (abs(nx - target.x) + abs(ny - target.y) < \n                    abs(current.x - target.x) + abs(current.y - target.y)) {\n                    current = {nx, ny};\n                    return;\n                }\n            }\n        }\n    } else if (current.y > target.y) {\n        for (int i = 0; i < 6; i++) {\n            int nx = current.x + DX[i];\n            int ny = current.y + DY[i];\n            if (isValid(nx, ny) && ny < current.y) {\n                if (abs(nx - target.x) + abs(ny - target.y) < \n                    abs(current.x - target.x) + abs(current.y - target.y)) {\n                    current = {nx, ny};\n                    return;\n                }\n            }\n        }\n    }\n}\n\nvector<tuple<int,int,int,int>> operations;\n\nvoid swapBalls(Coord c1, Coord c2) {\n    if (c1 == c2 || !areAdjacent(c1, c2)) return;\n    if (operations.size() >= 10000) return;\n    \n    operations.push_back({c1.x, c1.y, c2.x, c2.y});\n    \n    int val1 = grid[c1.x][c1.y];\n    int val2 = grid[c2.x][c2.y];\n    \n    grid[c1.x][c1.y] = val2;\n    grid[c2.x][c2.y] = val1;\n    \n    pos[val1] = c2;\n    pos[val2] = c1;\n}\n\n// Move ball toward target tier using heuristic\nvoid moveBallToTier(int value, int targetTier) {\n    Coord current = pos[value];\n    \n    if (current.x == targetTier) return; // Already in correct tier\n    \n    int maxSteps = 30;\n    while (current.x != targetTier && operations.size() < 5000 && maxSteps > 0) {\n        Coord target = {targetTier, min(current.y, targetTier)};\n        Coord next = current;\n        moveToward(next, target);\n        \n        if (next == current) break; // Can't move\n        \n        if (areAdjacent(current, next)) {\n            swapBalls(current, next);\n            current = pos[value];\n        } else {\n            // Need to find path\n            break;\n        }\n        maxSteps--;\n    }\n}\n\n// BFS for when heuristic fails\nvector<Coord> findPath(Coord start, Coord end) {\n    if (start == end) return {start};\n    \n    queue<Coord> q;\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<Coord>> parent(N, vector<Coord>(N, {-1, -1}));\n    \n    visited[start.x][start.y] = true;\n    q.push(start);\n    \n    while (!q.empty()) {\n        Coord curr = q.front();\n        q.pop();\n        \n        if (curr == end) {\n            vector<Coord> path;\n            Coord c = end;\n            while (c != start) {\n                path.push_back(c);\n                c = parent[c.x][c.y];\n            }\n            path.push_back(start);\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int i = 0; i < 6; i++) {\n            int nx = curr.x + DX[i];\n            int ny = curr.y + DY[i];\n            if (isValid(nx, ny) && !visited[nx][ny]) {\n                visited[nx][ny] = true;\n                parent[nx][ny] = curr;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return {};\n}\n\nvoid moveBall(Coord& current, Coord target) {\n    while (current != target && operations.size() < 5000) {\n        auto path = findPath(current, target);\n        if (path.size() < 2) break;\n        \n        Coord next = path[1];\n        swapBalls(current, next);\n        current = pos[grid[current.x][current.y]];\n    }\n}\n\nint countViolations() {\n    int E = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (grid[x][y] > grid[x + 1][y]) E++;\n            if (grid[x][y] > grid[x + 1][y + 1]) E++;\n        }\n    }\n    return E;\n}\n\n// Efficient violation fixing - focus on worst violations first\nvoid fixViolations() {\n    for (int pass = 0; pass < 15 && operations.size() < 9500; pass++) {\n        bool changed = false;\n        int E = countViolations();\n        if (E == 0) break;\n        \n        // Find and fix violations from top to bottom\n        for (int x = 0; x < N - 1 && operations.size() < 9500; x++) {\n            for (int y = 0; y <= x && operations.size() < 9500; y++) {\n                int curr = grid[x][y];\n                int left = grid[x + 1][y];\n                int right = grid[x + 1][y + 1];\n                \n                // Fix violation with smaller child first\n                if (curr > left && curr > right) {\n                    // Both violations - swap with smaller\n                    if (left <= right && areAdjacent({x, y}, {x + 1, y})) {\n                        swapBalls({x, y}, {x + 1, y});\n                        changed = true;\n                    } else if (areAdjacent({x, y}, {x + 1, y + 1})) {\n                        swapBalls({x, y}, {x + 1, y + 1});\n                        changed = true;\n                    }\n                } else if (curr > left && areAdjacent({x, y}, {x + 1, y})) {\n                    swapBalls({x, y}, {x + 1, y});\n                    changed = true;\n                } else if (curr > right && areAdjacent({x, y}, {x + 1, y + 1})) {\n                    swapBalls({x, y}, {x + 1, y + 1});\n                    changed = true;\n                }\n            }\n        }\n        \n        if (!changed) break;\n    }\n}\n\n// Bottom-up heapify\nvoid heapify() {\n    for (int x = N - 2; x >= 0 && operations.size() < 9800; x--) {\n        for (int y = 0; y <= x && operations.size() < 9800; y++) {\n            int curr = grid[x][y];\n            int left = grid[x + 1][y];\n            int right = grid[x + 1][y + 1];\n            \n            if (curr > left || curr > right) {\n                if (left < right && areAdjacent({x, y}, {x + 1, y})) {\n                    swapBalls({x, y}, {x + 1, y});\n                } else if (areAdjacent({x, y}, {x + 1, y + 1})) {\n                    swapBalls({x, y}, {x + 1, y + 1});\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n            pos[grid[x][y]] = {x, y};\n        }\n    }\n    \n    // Group balls by target tier\n    vector<vector<int>> tierBalls(N);\n    for (int v = 0; v < TOTAL_BALLS; v++) {\n        int tier = getTargetTier(v);\n        tierBalls[tier].push_back(v);\n    }\n    \n    // Move balls to their target tiers (smallest values to top tiers)\n    for (int tier = 0; tier < N && operations.size() < 5000; tier++) {\n        for (int value : tierBalls[tier]) {\n            if (operations.size() >= 5000) break;\n            moveBallToTier(value, tier);\n        }\n    }\n    \n    // Apply heapify from bottom up\n    heapify();\n    \n    // Fix remaining violations\n    fixViolations();\n    \n    // Final cleanup if needed\n    if (countViolations() > 0) {\n        heapify();\n        fixViolations();\n    }\n    \n    // Output\n    cout << operations.size() << \"\\n\";\n    for (auto& op : operations) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = 4;\n\nstruct Container {\n    int id;\n    int r, c;\n};\n\nint grid[D][D];  // -1: empty, -2: obstacle, >=0: container id\nint dist_from_entrance[D][D];\nvector<pair<int, int>> empty_squares;\nvector<Container> containers;\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\nbool isValid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D && grid[r][c] != -2;\n}\n\n// BFS to find all reachable empty squares from entrance\nvector<vector<bool>> computeReachable() {\n    vector<vector<bool>> reachable(D, vector<bool>(D, false));\n    queue<pair<int, int>> q;\n    \n    q.push({ENTRANCE_R, ENTRANCE_C});\n    reachable[ENTRANCE_R][ENTRANCE_C] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && grid[nr][nc] == -1 && !reachable[nr][nc]) {\n                reachable[nr][nc] = true;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return reachable;\n}\n\n// Check if container at (r, c) is reachable (adjacent to reachable empty square)\nbool isContainerReachable(int r, int c) {\n    for (int i = 0; i < 4; i++) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        \n        if (isValid(nr, nc) && grid[nr][nc] == -1) {\n            auto reachable = computeReachable();\n            if (reachable[nr][nc]) return true;\n        }\n    }\n    return false;\n}\n\n// Check if placing container maintains connectivity for all existing containers\nbool canPlace(int r, int c) {\n    if (!isValid(r, c) || grid[r][c] != -1) return false;\n    \n    grid[r][c] = -3;  // Temporarily occupied\n    \n    bool ok = true;\n    for (const auto& cont : containers) {\n        if (!isContainerReachable(cont.r, cont.c)) {\n            ok = false;\n            break;\n        }\n    }\n    \n    grid[r][c] = -1;\n    return ok;\n}\n\nvoid computeDistances() {\n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            dist_from_entrance[i][j] = 1e9;\n        }\n    }\n    \n    queue<pair<int, int>> q;\n    q.push({ENTRANCE_R, ENTRANCE_C});\n    dist_from_entrance[ENTRANCE_R][ENTRANCE_C] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && dist_from_entrance[nr][nc] > dist_from_entrance[r][c] + 1) {\n                dist_from_entrance[nr][nc] = dist_from_entrance[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            grid[i][j] = -1;\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -2;\n    }\n    \n    computeDistances();\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            if (grid[i][j] == -1 && !(i == ENTRANCE_R && j == ENTRANCE_C)) {\n                empty_squares.push_back({i, j});\n            }\n        }\n    }\n    \n    sort(empty_squares.begin(), empty_squares.end(), [](const pair<int, int>& a, const pair<int, int>& b) {\n        return dist_from_entrance[a.first][a.second] < dist_from_entrance[b.first][b.second];\n    });\n    \n    int total_containers = D * D - 1 - N;\n    \n    for (int d = 0; d < total_containers; d++) {\n        int container_id;\n        cin >> container_id;\n        \n        int best_r = -1, best_c = -1;\n        int best_score = 1e9;\n        \n        for (const auto& [r, c] : empty_squares) {\n            if (grid[r][c] == -1 && canPlace(r, c)) {\n                int score = dist_from_entrance[r][c] * 100;\n                if (container_id < total_containers / 2) {\n                    score -= 50;  // Prefer closer for smaller IDs\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        grid[best_r][best_c] = container_id;\n        containers.push_back({container_id, best_r, best_c});\n        \n        cout << best_r << \" \" << best_c << endl;\n    }\n    \n    // Retrieval: output in order 0, 1, 2, ...\n    vector<bool> retrieved(total_containers, false);\n    vector<pair<int, int>> output_order;\n    \n    for (int target_id = 0; target_id < total_containers; target_id++) {\n        for (auto& cont : containers) {\n            if (cont.id == target_id && !retrieved[target_id]) {\n                if (isContainerReachable(cont.r, cont.c)) {\n                    output_order.push_back({cont.r, cont.c});\n                    retrieved[target_id] = true;\n                    grid[cont.r][cont.c] = -1;  // Remove container\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Output any remaining\n    for (auto& cont : containers) {\n        if (!retrieved[cont.id]) {\n            output_order.push_back({cont.r, cont.c});\n        }\n    }\n    \n    for (const auto& [r, c] : output_order) {\n        cout << r << \" \" << c << endl;\n    }\n    \n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <atcoder/all>\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nint grid[N][N];\nint adj[M + 1][M + 1];  // adjacency matrix\nint color_count[M + 1]; // count of each color\n\n// Check if a color region is connected using BFS\nbool check_connectivity(int c) {\n    vector<pair<int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == c) {\n                cells.push_back({i, j});\n            }\n        }\n    }\n    if (cells.empty()) return c == 0; // color 0 can be empty (connects through outside)\n    \n    // BFS from first cell\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    queue<pair<int, int>> q;\n    q.push(cells[0]);\n    visited[cells[0].first][cells[0].second] = true;\n    int count = 1;\n    \n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\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                !visited[ni][nj] && grid[ni][nj] == c) {\n                visited[ni][nj] = true;\n                count++;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return count == (int)cells.size();\n}\n\n// Check if all color regions are connected\nbool check_all_connectivity() {\n    for (int c = 1; c <= m; c++) {\n        if (!check_connectivity(c)) return false;\n    }\n    // Color 0 connectivity through outside is automatic if other colors are connected\n    return true;\n}\n\n// Build adjacency matrix from current grid\nvoid build_adjacency() {\n    memset(adj, 0, sizeof(adj));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    // Boundary touches color 0\n                    adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Get current adjacency from grid\nvoid get_current_adjacency(int cur_adj[M + 1][M + 1]) {\n    memset(cur_adj, 0, sizeof(int) * (M + 1) * (M + 1));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        cur_adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    cur_adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Check if adjacency is preserved\nbool check_adjacency_preserved() {\n    int cur_adj[M + 1][M + 1];\n    get_current_adjacency(cur_adj);\n    \n    for (int c1 = 0; c1 <= m; c1++) {\n        for (int c2 = c1 + 1; c2 <= m; c2++) {\n            if (adj[c1][c2] != cur_adj[c1][c2]) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Count color 0 squares\nint count_zeros() {\n    int cnt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == 0) cnt++;\n        }\n    }\n    return cnt;\n}\n\n// Try to fill a 0 cell with a color\nbool try_fill_zero(int i, int j, int c) {\n    if (grid[i][j] != 0) return false;\n    \n    int old = grid[i][j];\n    grid[i][j] = c;\n    \n    // Check connectivity\n    if (!check_connectivity(c)) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    // Check adjacency preservation\n    if (!check_adjacency_preserved()) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    return true;\n}\n\n// Get colors adjacent to position (i, j)\nvector<int> get_adjacent_colors(int i, int j) {\n    vector<int> colors;\n    vector<bool> seen(M + 1, false);\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\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            int c = grid[ni][nj];\n            if (c != 0 && !seen[c]) {\n                seen[c] = true;\n                colors.push_back(c);\n            }\n        } else {\n            if (!seen[0]) {\n                seen[0] = true;\n                colors.push_back(0);\n            }\n        }\n    }\n    return colors;\n}\n\n// Check if filling (i,j) with color c would create unwanted adjacency\nbool would_create_bad_adjacency(int i, int j, int c) {\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int d = 0; d < 4; d++) {\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        int neighbor_c;\n        if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n            neighbor_c = grid[ni][nj];\n        } else {\n            neighbor_c = 0;\n        }\n        \n        if (neighbor_c != c && neighbor_c != 0) {\n            // Check if c and neighbor_c should be adjacent\n            if (!adj[min(c, neighbor_c)][max(c, neighbor_c)]) {\n                return true; // Would create unwanted adjacency\n            }\n        }\n    }\n    return false;\n}\n\n// Check if filling (i,j) with color c would miss required adjacency\nbool would_miss_adjacency(int i, int j, int c) {\n    // This is harder to check locally, skip for now\n    return false;\n}\n\n// Greedy fill zeros\nvoid greedy_fill() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        vector<tuple<int, int, int>> candidates;\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    vector<int> adj_colors = get_adjacent_colors(i, j);\n                    for (int c : adj_colors) {\n                        if (c == 0) continue;\n                        if (!would_create_bad_adjacency(i, j, c)) {\n                            candidates.push_back({i, j, c});\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try candidates in random order\n        shuffle(candidates.begin(), candidates.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count()));\n        \n        for (auto [i, j, c] : candidates) {\n            if (grid[i][j] == 0 && try_fill_zero(i, j, c)) {\n                changed = true;\n                break; // Restart to be safe\n            }\n        }\n    }\n}\n\n// Simulated annealing style local search\nvoid local_search() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 5000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find a 0 cell\n        vector<pair<int, int>> zeros;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    zeros.push_back({i, j});\n                }\n            }\n        }\n        \n        if (zeros.empty()) break;\n        \n        auto [i, j] = zeros[rng() % zeros.size()];\n        vector<int> adj_colors = get_adjacent_colors(i, j);\n        \n        if (adj_colors.empty()) continue;\n        \n        int c = adj_colors[rng() % adj_colors.size()];\n        if (c == 0) continue;\n        \n        if (try_fill_zero(i, j, c)) {\n            // Success, continue\n        }\n    }\n}\n\n// Compact regions by moving boundary cells\nvoid compact_regions() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 3000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find boundary cells (colored cells adjacent to 0)\n        vector<tuple<int, int, int>> boundaries; // i, j, color\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0) {\n                    int di[] = {0, 0, 1, -1};\n                    int dj[] = {1, -1, 0, 0};\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 && grid[ni][nj] == 0) {\n                            boundaries.push_back({i, j, grid[i][j]});\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (boundaries.empty()) break;\n        \n        auto [i, j, c] = boundaries[rng() % boundaries.size()];\n        \n        // Try to expand into adjacent 0\n        int di[] = {0, 0, 1, -1};\n        int dj[] = {1, -1, 0, 0};\n        \n        vector<pair<int, int>> adjacent_zeros;\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 && grid[ni][nj] == 0) {\n                adjacent_zeros.push_back({ni, nj});\n            }\n        }\n        \n        if (adjacent_zeros.empty()) continue;\n        \n        auto [ni, nj] = adjacent_zeros[rng() % adjacent_zeros.size()];\n        \n        if (!would_create_bad_adjacency(ni, nj, c)) {\n            int old = grid[ni][nj];\n            grid[ni][nj] = c;\n            \n            if (check_connectivity(c) && check_adjacency_preserved()) {\n                // Keep the change\n            } else {\n                grid[ni][nj] = old;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    \n    int zeros = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> grid[i][j];\n            if (grid[i][j] == 0) zeros++;\n            color_count[grid[i][j]]++;\n        }\n    }\n    \n    // Build target adjacency from input\n    build_adjacency();\n    \n    // Phase 1: Greedy fill\n    greedy_fill();\n    \n    // Phase 2: Local search\n    local_search();\n    \n    // Phase 3: Compact regions\n    compact_regions();\n    \n    // Phase 4: Final greedy pass\n    greedy_fill();\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cout << grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Estimate weights through comparisons\n    // Use a reference-based approach: compare each item against a reference set\n    vector<double> estimated_weight(N, 1.0);\n    vector<int> win_count(N, 0);\n    vector<int> lose_count(N, 0);\n    \n    // Phase 1: Pairwise comparisons to build relative ranking\n    // Use tournament-style comparisons\n    int queries_used = 0;\n    \n    // First, do pairwise comparisons between items\n    // Compare item i vs item j by putting them on opposite sides\n    for (int i = 0; i < N && queries_used < Q; i++) {\n        for (int j = i + 1; j < N && queries_used < Q; j++) {\n            // Compare single items\n            cout << \"1 1 \" << i << \" \" << j << endl;\n            queries_used++;\n            \n            string result;\n            cin >> result;\n            \n            if (result == \">\") {\n                win_count[i]++;\n                lose_count[j]++;\n            } else if (result == \"<\") {\n                lose_count[i]++;\n                win_count[j]++;\n            }\n            // \"=\" means equal, no change\n        }\n    }\n    \n    // Calculate estimated weights based on win/loss ratio\n    for (int i = 0; i < N; i++) {\n        int total = win_count[i] + lose_count[i];\n        if (total > 0) {\n            estimated_weight[i] = 1.0 + (double)win_count[i] / total;\n        }\n    }\n    \n    // If we have remaining queries, do more refined comparisons\n    // Compare items against groups to get better estimates\n    while (queries_used < Q) {\n        // Pick two random items to compare\n        static mt19937 rng(42);\n        int i = rng() % N;\n        int j = rng() % N;\n        if (i == j) continue;\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        if (result == \">\") {\n            estimated_weight[i] += 0.1;\n            estimated_weight[j] -= 0.05;\n        } else if (result == \"<\") {\n            estimated_weight[i] -= 0.05;\n            estimated_weight[j] += 0.1;\n        }\n    }\n    \n    // Phase 2: Partition items into D sets\n    // Use greedy approach: sort by estimated weight, assign to lightest bin\n    \n    // Create indices sorted by estimated weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return estimated_weight[a] > estimated_weight[b];\n    });\n    \n    // Initialize D bins\n    vector<vector<int>> bins(D);\n    vector<double> bin_weight(D, 0.0);\n    \n    // Greedy assignment: assign heaviest items first to lightest bin\n    for (int idx : indices) {\n        // Find bin with minimum current weight\n        int min_bin = 0;\n        for (int d = 1; d < D; d++) {\n            if (bin_weight[d] < bin_weight[min_bin]) {\n                min_bin = d;\n            }\n        }\n        bins[min_bin].push_back(idx);\n        bin_weight[min_bin] += estimated_weight[idx];\n    }\n    \n    // Phase 3: Local optimization to reduce variance\n    // Try swapping items between bins to reduce variance\n    auto calc_variance = [&]() -> double {\n        double mean = 0.0;\n        for (double w : bin_weight) mean += w;\n        mean /= D;\n        double var = 0.0;\n        for (double w : bin_weight) {\n            double diff = w - mean;\n            var += diff * diff;\n        }\n        return var / D;\n    };\n    \n    // Local search optimization\n    bool improved = true;\n    int max_iterations = 1000;\n    int iteration = 0;\n    \n    while (improved && iteration < max_iterations) {\n        improved = false;\n        iteration++;\n        \n        double current_var = calc_variance();\n        \n        // Try swapping pairs of items between different bins\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = d1 + 1; d2 < D && !improved; d2++) {\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    for (int j = 0; j < (int)bins[d2].size() && !improved; j++) {\n                        int item1 = bins[d1][i];\n                        int item2 = bins[d2][j];\n                        \n                        // Calculate new weights if we swap\n                        double new_w1 = bin_weight[d1] - estimated_weight[item1] + estimated_weight[item2];\n                        double new_w2 = bin_weight[d2] - estimated_weight[item2] + estimated_weight[item1];\n                        \n                        // Check if this reduces variance\n                        double mean = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            if (d == d1) mean += new_w1;\n                            else if (d == d2) mean += new_w2;\n                            else mean += bin_weight[d];\n                        }\n                        mean /= D;\n                        \n                        double new_var = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                            double diff = w - mean;\n                            new_var += diff * diff;\n                        }\n                        new_var /= D;\n                        \n                        if (new_var < current_var - 1e-9) {\n                            // Perform swap\n                            swap(bins[d1][i], bins[d2][j]);\n                            bin_weight[d1] = new_w1;\n                            bin_weight[d2] = new_w2;\n                            improved = true;\n                            current_var = new_var;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Also try moving single items\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = 0; d2 < D && !improved; d2++) {\n                if (d1 == d2) continue;\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    int item = bins[d1][i];\n                    \n                    double new_w1 = bin_weight[d1] - estimated_weight[item];\n                    double new_w2 = bin_weight[d2] + estimated_weight[item];\n                    \n                    double mean = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        if (d == d1) mean += new_w1;\n                        else if (d == d2) mean += new_w2;\n                        else mean += bin_weight[d];\n                    }\n                    mean /= D;\n                    \n                    double new_var = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                        double diff = w - mean;\n                        new_var += diff * diff;\n                    }\n                    new_var /= D;\n                    \n                    if (new_var < current_var - 1e-9) {\n                        bins[d1].erase(bins[d1].begin() + i);\n                        bins[d2].push_back(item);\n                        bin_weight[d1] = new_w1;\n                        bin_weight[d2] = new_w2;\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Create output assignment\n    vector<int> assignment(N);\n    for (int d = 0; d < D; d++) {\n        for (int item : bins[d]) {\n            assignment[item] = d;\n        }\n    }\n    \n    // Output final assignment\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    int boxes_per_stack = n / m;\n    \n    vector<vector<int>> stacks(m);\n    vector<pair<int, int>> pos(n + 1);\n    vector<int> move_count(n + 1, 0);\n    \n    for (int i = 0; i < m; i++) {\n        stacks[i].resize(boxes_per_stack);\n        for (int j = 0; j < boxes_per_stack; j++) {\n            cin >> stacks[i][j];\n            pos[stacks[i][j]] = {i, j};\n        }\n    }\n    \n    vector<pair<int, int>> operations;\n    \n    auto update_positions = [&](int stack_idx) {\n        for (int h = 0; h < (int)stacks[stack_idx].size(); h++) {\n            pos[stacks[stack_idx][h]] = {stack_idx, h};\n        }\n    };\n    \n    auto get_urgency = [&](int box, int current_v) -> int {\n        if (box < current_v) return 10000;\n        return box - current_v;\n    };\n    \n    auto find_best_stack = [&](int source_idx, int box_to_move, int current_v) -> int {\n        int best_stack = -1;\n        double best_score = 1e18;\n        \n        int urgency = get_urgency(box_to_move, current_v);\n        int boxes_remaining = n - current_v + 1;\n        \n        // Keep the thresholds that worked well\n        int tier1_threshold = max(3, min(6, boxes_remaining / 25));\n        int tier2_threshold = max(10, min(20, boxes_remaining / 8));\n        \n        for (int s = 0; s < m; s++) {\n            if (s == source_idx) continue;\n            \n            double score = 0;\n            int stack_size = stacks[s].size();\n            \n            // Tier 1: Very urgent (1-6) - must be easily accessible\n            if (urgency <= tier1_threshold) {\n                score += stack_size * 8.0;\n                if (stack_size > 0) score += 25.0;\n                if (stack_size == 0) score -= 15.0;\n            }\n            // Tier 2: Soon (7-20) - should be accessible\n            else if (urgency <= tier2_threshold) {\n                score += stack_size * 4.0;\n                if (stack_size > 12) score += 15.0;\n            }\n            // Tier 3: Later (21+) - can go anywhere, prefer larger stacks\n            else {\n                score += stack_size * 1.5;\n                int late_boxes = 0;\n                for (int h = 0; h < stack_size; h++) {\n                    if (get_urgency(stacks[s][h], current_v) > tier2_threshold) {\n                        late_boxes++;\n                    }\n                }\n                score -= late_boxes * 1.0;\n            }\n            \n            // Analyze destination contents\n            int very_urgent = 0, urgent = 0;\n            double chain_bonus = 0;\n            \n            for (int h = 0; h < stack_size; h++) {\n                int box_in_dest = stacks[s][h];\n                int dest_urgency = get_urgency(box_in_dest, current_v);\n                \n                if (dest_urgency <= tier1_threshold) very_urgent++;\n                else if (dest_urgency <= tier2_threshold) urgent++;\n                \n                // Penalty for burying urgent boxes (moderate, not too harsh)\n                if (dest_urgency <= tier2_threshold && urgency > dest_urgency) {\n                    score += (tier2_threshold - dest_urgency) * 3.0;\n                }\n                \n                // Bonus for grouping similar urgency (within 4)\n                if (urgency <= tier2_threshold && dest_urgency <= tier2_threshold) {\n                    if (abs(urgency - dest_urgency) <= 4) {\n                        score -= 5.0;\n                    }\n                }\n                \n                // Chain bonus for consecutive boxes\n                if (abs(box_to_move - box_in_dest) == 1) {\n                    chain_bonus += 6.0;\n                }\n                if (abs(box_to_move - box_in_dest) == 2) {\n                    chain_bonus += 3.0;\n                }\n            }\n            \n            score -= chain_bonus;\n            \n            // Move count consideration (moderate penalties)\n            if (move_count[box_to_move] >= 2) {\n                if (urgency > tier2_threshold) {\n                    score -= 8.0;\n                } else {\n                    score += 5.0;\n                }\n            }\n            if (move_count[box_to_move] >= 3) {\n                score += 10.0;\n            }\n            \n            // Urgent box grouping\n            if (urgency <= tier2_threshold) {\n                if (urgent > 0 || very_urgent > 0) {\n                    score -= (urgent + very_urgent) * 2.5;\n                }\n            } else {\n                if (very_urgent > 0) {\n                    score += very_urgent * 4.0;\n                }\n            }\n            \n            // Stack height balancing (back to 35, which worked better)\n            if (stack_size > 35) {\n                score += (stack_size - 35) * 5.0;\n            }\n            \n            // Block detection\n            int soon_needed_in_stack = 0;\n            for (int h = 0; h < stack_size; h++) {\n                if (get_urgency(stacks[s][h], current_v) <= 10) {\n                    soon_needed_in_stack++;\n                }\n            }\n            if (urgency > 10 && soon_needed_in_stack >= 2) {\n                score += 6.0;\n            }\n            \n            // Small tiebreaker\n            score += (s * 0.0001);\n            \n            if (score < best_score) {\n                best_score = score;\n                best_stack = s;\n            }\n        }\n        \n        if (best_stack == -1) {\n            for (int s = 0; s < m; s++) {\n                if (s != source_idx) {\n                    best_stack = s;\n                    break;\n                }\n            }\n        }\n        \n        return best_stack;\n    };\n    \n    for (int v = 1; v <= n; v++) {\n        auto [stack_idx, height_idx] = pos[v];\n        \n        if (height_idx == (int)stacks[stack_idx].size() - 1) {\n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        } else {\n            while ((int)stacks[stack_idx].size() - 1 > height_idx) {\n                int top_box = stacks[stack_idx].back();\n                int dest_stack = find_best_stack(stack_idx, top_box, v);\n                \n                operations.push_back({top_box, dest_stack + 1});\n                stacks[stack_idx].pop_back();\n                stacks[dest_stack].push_back(top_box);\n                move_count[top_box]++;\n                \n                update_positions(stack_idx);\n                update_positions(dest_stack);\n            }\n            \n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        }\n    }\n    \n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\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 DI[4] = {0, 1, 0, -1};\nconst int DJ[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nbool canMove(int i, int j, int dir) {\n    int ni = i + DI[dir];\n    int nj = j + DJ[dir];\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    if (dir == 0) return v[i][j] == '0';\n    else if (dir == 1) return h[i][j] == '0';\n    else if (dir == 2) return v[i][nj] == '0';\n    else return h[ni][j] == '0';\n}\n\nvector<int> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parentDir(N, vector<int>(N, -1));\n    \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();\n        q.pop();\n        \n        if (i == ti && j == tj) break;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    parent[ni][nj] = {i, j};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (dist[ti][tj] == -1) return {};\n    \n    vector<int> path;\n    int ci = ti, cj = tj;\n    while (ci != si || cj != sj) {\n        path.push_back(parentDir[ci][cj]);\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Build BFS tree and create tour by traversing each edge twice\nstring buildBFSTour() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parentDir(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({0, 0});\n    visited[0][0] = true;\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    visited[ni][nj] = true;\n                    parent[ni][nj] = {i, j};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    // Build adjacency list for BFS tree - use 3D vector\n    vector<vector<vector<pair<int,int>>>> children(N, vector<vector<pair<int,int>>>(N));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (parent[i][j].first != -1) {\n                int pi = parent[i][j].first;\n                int pj = parent[i][j].second;\n                children[pi][pj].push_back({i, j});\n            }\n        }\n    }\n    \n    // DFS on BFS tree to create tour\n    string tour;\n    function<void(int, int)> dfsTour = [&](int i, int j) {\n        for (auto& child : children[i][j]) {\n            int ni = child.first;\n            int nj = child.second;\n            int dir = -1;\n            for (int d = 0; d < 4; d++) {\n                if (i + DI[d] == ni && j + DJ[d] == nj) {\n                    dir = d;\n                    break;\n                }\n            }\n            if (dir != -1) {\n                tour += DIR_CHAR[dir];\n                dfsTour(ni, nj);\n                tour += DIR_CHAR[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfsTour(0, 0);\n    return tour;\n}\n\n// Check if all cells are visited\nbool checkCoverage(const string& route) {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int ci = 0, cj = 0;\n    visited[0][0] = true;\n    \n    for (char c : route) {\n        int dir;\n        if (c == 'R') dir = 0;\n        else if (c == 'D') dir = 1;\n        else if (c == 'L') dir = 2;\n        else dir = 3;\n        ci += DI[dir];\n        cj += DJ[dir];\n        visited[ci][cj] = true;\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!visited[i][j]) return false;\n        }\n    }\n    return true;\n}\n\n// Get final position after following route\npair<int,int> getFinalPos(const string& route) {\n    int ci = 0, cj = 0;\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n    }\n    return {ci, cj};\n}\n\n// Get all positions visited in route\nvector<pair<int,int>> getRoutePositions(const string& route) {\n    vector<pair<int,int>> positions;\n    int ci = 0, cj = 0;\n    positions.push_back({ci, cj});\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n        positions.push_back({ci, cj});\n    }\n    return positions;\n}\n\n// Calculate visit count for each cell\nvector<vector<int>> getVisitCount(const string& route) {\n    vector<vector<int>> count(N, vector<int>(N, 0));\n    int ci = 0, cj = 0;\n    count[0][0] = 1;\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n        count[ci][cj]++;\n    }\n    return count;\n}\n\n// Optimize route by inserting extra visits to high-dirt cells\nstring optimizeRoute(string baseRoute, int maxLen) {\n    if ((int)baseRoute.size() >= maxLen - 1000) return baseRoute;\n    \n    vector<vector<int>> visitCount = getVisitCount(baseRoute);\n    vector<pair<int,int>> routePositions = getRoutePositions(baseRoute);\n    \n    // Calculate priority: high dirt + low visit count\n    vector<tuple<double, int, int>> priorities;\n    long long totalDirt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            totalDirt += d[i][j];\n        }\n    }\n    \n    double avgDirt = (double)totalDirt / (N * N);\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            double priority = (double)d[i][j] / (visitCount[i][j] + 1);\n            if (d[i][j] > avgDirt * 1.2) {\n                priorities.push_back({priority, i, j});\n            }\n        }\n    }\n    \n    sort(priorities.begin(), priorities.end(), greater<tuple<double,int,int>>());\n    \n    string result = baseRoute;\n    int budget = maxLen - (int)result.size() - 500;\n    \n    for (auto& [pri, ti, tj] : priorities) {\n        if (budget <= 20) break;\n        \n        // Find position in route closest to target cell\n        int bestPos = -1;\n        int bestDist = 1e9;\n        \n        for (int pos = 0; pos < (int)routePositions.size(); pos++) {\n            int dist = abs(routePositions[pos].first - ti) + abs(routePositions[pos].second - tj);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestPos = pos;\n            }\n        }\n        \n        if (bestPos == -1) continue;\n        \n        int pi = routePositions[bestPos].first;\n        int pj = routePositions[bestPos].second;\n        \n        vector<int> pathTo = bfsPath(pi, pj, ti, tj);\n        if (pathTo.empty()) continue;\n        \n        vector<int> pathBack = bfsPath(ti, tj, pi, pj);\n        if (pathBack.empty()) continue;\n        \n        int pathLen = pathTo.size() + pathBack.size();\n        if (pathLen > budget) continue;\n        \n        string insert;\n        for (int dir : pathTo) insert += DIR_CHAR[dir];\n        for (int dir : pathBack) insert += DIR_CHAR[dir];\n        \n        result.insert(bestPos, insert);\n        budget -= pathLen;\n        \n        // Update route positions\n        routePositions = getRoutePositions(result);\n    }\n    \n    return result;\n}\n\n// Create frequency-based route with multiple passes\nstring buildFrequencyRoute(int maxLen) {\n    vector<tuple<int, int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cells.push_back({d[i][j], i, j});\n        }\n    }\n    sort(cells.begin(), cells.end(), greater<tuple<int,int,int>>());\n    \n    long long totalDirt = 0;\n    for (auto& [dirt, i, j] : cells) {\n        totalDirt += dirt;\n    }\n    \n    string baseTour = buildBFSTour();\n    \n    if ((int)baseTour.size() > maxLen - 1000) {\n        return baseTour;\n    }\n    \n    string result = baseTour;\n    int budget = maxLen - (int)result.size() - 500;\n    \n    pair<int,int> pos = getFinalPos(result);\n    int ci = pos.first, cj = pos.second;\n    \n    int pass = 0;\n    while (budget > 50 && pass < 10) {\n        for (auto& [dirt, ti, tj] : cells) {\n            if (budget <= 50) break;\n            if (dirt < totalDirt / (N * N)) break;\n            \n            vector<int> pathTo = bfsPath(ci, cj, ti, tj);\n            if (pathTo.empty()) continue;\n            \n            vector<int> pathBack = bfsPath(ti, tj, ci, cj);\n            if (pathBack.empty()) continue;\n            \n            int pathLen = pathTo.size() + pathBack.size();\n            if (pathLen > budget) continue;\n            \n            for (int dir : pathTo) {\n                result += DIR_CHAR[dir];\n                ci += DI[dir];\n                cj += DJ[dir];\n            }\n            for (int dir : pathBack) {\n                result += DIR_CHAR[dir];\n                ci += DI[dir];\n                cj += DJ[dir];\n            }\n            \n            budget -= pathLen;\n        }\n        pass++;\n    }\n    \n    // Return to start\n    if (ci != 0 || cj != 0) {\n        vector<int> pathHome = bfsPath(ci, cj, 0, 0);\n        for (int dir : pathHome) {\n            result += DIR_CHAR[dir];\n        }\n    }\n    \n    return result;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N;\n    \n    h.resize(N - 1);\n    for (int i = 0; i < N - 1; i++) {\n        cin >> h[i];\n    }\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> v[i];\n    }\n    \n    d.resize(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    }\n    \n    int maxLen = 100000;\n    \n    // Strategy 1: BFS tree tour + optimization\n    string route1 = buildBFSTour();\n    route1 = optimizeRoute(route1, maxLen);\n    \n    // Strategy 2: Frequency-based route\n    string route2 = buildFrequencyRoute(maxLen);\n    \n    // Pick best valid route\n    vector<pair<string, int>> candidates;\n    \n    if (checkCoverage(route1) && (int)route1.size() <= maxLen) {\n        candidates.push_back({route1, (int)route1.size()});\n    }\n    if (checkCoverage(route2) && (int)route2.size() <= maxLen) {\n        candidates.push_back({route2, (int)route2.size()});\n    }\n    \n    string bestRoute;\n    if (candidates.empty()) {\n        bestRoute = buildBFSTour();\n    } else {\n        sort(candidates.begin(), candidates.end(), \n             [](const auto& a, const auto& b) { return a.second < b.second; });\n        bestRoute = candidates[0].first;\n    }\n    \n    // Final validation\n    if (!checkCoverage(bestRoute)) {\n        bestRoute = buildBFSTour();\n    }\n    \n    // Ensure ends at (0,0)\n    pair<int,int> finalPos = getFinalPos(bestRoute);\n    if (finalPos.first != 0 || finalPos.second != 0) {\n        vector<int> pathHome = bfsPath(finalPos.first, finalPos.second, 0, 0);\n        for (int dir : pathHome) {\n            bestRoute += DIR_CHAR[dir];\n        }\n    }\n    \n    // Final length check\n    if ((int)bestRoute.size() > maxLen) {\n        bestRoute = buildBFSTour();\n    }\n    \n    cout << bestRoute << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, si, sj;\nvector<string> A;\nvector<string> t;\nvector<vector<pair<int,int>>> charPos(26);\nint overlap[200][200];\nmt19937 rng;\n\n// Precompute: min cost to reach character c from position (r, c)\nint minCostFromPos[15][15][26];\n// Best position to type character c from position (r, c)\npair<int,int> bestPosFromPos[15][15][26];\n\nvoid precomputePosCosts() {\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            for (int ch = 0; ch < 26; ch++) {\n                int minD = 1e9;\n                pair<int,int> bestP = {r, c};\n                for (auto [nr, nc] : charPos[ch]) {\n                    int d = abs(r - nr) + abs(c - nc) + 1;\n                    if (d < minD) {\n                        minD = d;\n                        bestP = {nr, nc};\n                    }\n                }\n                minCostFromPos[r][c][ch] = minD;\n                bestPosFromPos[r][c][ch] = bestP;\n            }\n        }\n    }\n}\n\n// Get character at position in word sequence\ninline int getChar(const vector<int>& order, int pos, int& wordIdx, int& charIdx) {\n    int cumLen = 0;\n    for (size_t w = 0; w < order.size(); w++) {\n        int prevOverlap = (w == 0) ? 0 : overlap[order[w-1]][order[w]];\n        int wordLen = 5 - prevOverlap;\n        if (pos < cumLen + wordLen) {\n            wordIdx = order[w];\n            charIdx = prevOverlap + (pos - cumLen);\n            return t[wordIdx][charIdx] - 'A';\n        }\n        cumLen += wordLen;\n    }\n    return -1;\n}\n\n// Build word order to character sequence mapping\nstruct CharSeq {\n    vector<int> wordIdx;  // Which word this char belongs to\n    vector<int> charIdx;  // Which char in that word\n    vector<int> ch;       // Character value\n    int totalLen;\n};\n\nCharSeq buildCharSeq(const vector<int>& order) {\n    CharSeq seq;\n    seq.totalLen = 0;\n    \n    for (size_t w = 0; w < order.size(); w++) {\n        int prevOverlap = (w == 0) ? 0 : overlap[order[w-1]][order[w]];\n        for (int i = prevOverlap; i < 5; i++) {\n            seq.wordIdx.push_back(order[w]);\n            seq.charIdx.push_back(i);\n            seq.ch.push_back(t[order[w]][i] - 'A');\n            seq.totalLen++;\n        }\n    }\n    return seq;\n}\n\n// Fast cost estimation with position tracking\nlong long calcCost(const vector<int>& order) {\n    if (order.empty()) return 0;\n    \n    long long cost = 0;\n    int curR = si, curC = sj;\n    \n    for (size_t w = 0; w < order.size(); w++) {\n        int prevOverlap = (w == 0) ? 0 : overlap[order[w-1]][order[w]];\n        for (int i = prevOverlap; i < 5; i++) {\n            int ch = t[order[w]][i] - 'A';\n            auto [bestR, bestC] = bestPosFromPos[curR][curC][ch];\n            cost += minCostFromPos[curR][curC][ch];\n            curR = bestR;\n            curC = bestC;\n        }\n    }\n    \n    return cost;\n}\n\n// Incremental cost update for swap move\nlong long calcCostDelta(const vector<int>& order, const CharSeq& seq, \n                        int swapI, int swapJ, long long currentCost) {\n    if (swapI == swapJ) return 0;\n    \n    // For swap, we need to recalculate from min(swapI, swapJ) word boundary\n    // This is complex, so just recalculate full cost for now\n    // Optimization: cache word boundaries\n    \n    vector<int> newOrder = order;\n    swap(newOrder[swapI], newOrder[swapJ]);\n    return calcCost(newOrder) - currentCost;\n}\n\n// Optimized position selection for final string with multiple passes\nvector<pair<int,int>> optimizePositions(const string& s) {\n    int L = s.size();\n    if (L == 0) return {};\n    \n    vector<pair<int,int>> path(L);\n    int curI = si, curJ = sj;\n    \n    // Initial greedy pass\n    for (int i = 0; i < L; i++) {\n        int idx = s[i] - 'A';\n        auto [bestI, bestJ] = bestPosFromPos[curI][curJ][idx];\n        path[i] = {bestI, bestJ};\n        curI = bestI;\n        curJ = bestJ;\n    }\n    \n    // Multiple local optimization passes\n    for (int pass = 0; pass < 8; pass++) {\n        bool changed = false;\n        for (int i = 0; i < L; i++) {\n            int idx = s[i] - 'A';\n            int bestI = path[i].first;\n            int bestJ = path[i].second;\n            \n            int prevI = (i == 0) ? si : path[i-1].first;\n            int prevJ = (i == 0) ? sj : path[i-1].second;\n            \n            int nextI = (i == L-1) ? -1 : path[i+1].first;\n            int nextJ = (i == L-1) ? -1 : path[i+1].second;\n            \n            int currentCost = abs(bestI - prevI) + abs(bestJ - prevJ) + 1;\n            if (nextI != -1) {\n                currentCost += abs(nextI - bestI) + abs(nextJ - bestJ) + 1;\n            }\n            \n            for (auto [ni, nj] : charPos[idx]) {\n                int newCost = abs(ni - prevI) + abs(nj - prevJ) + 1;\n                if (nextI != -1) {\n                    newCost += abs(nextI - ni) + abs(nextJ - nj) + 1;\n                }\n                \n                if (newCost < currentCost) {\n                    currentCost = newCost;\n                    bestI = ni;\n                    bestJ = nj;\n                    changed = true;\n                }\n            }\n            path[i] = {bestI, bestJ};\n        }\n        if (!changed) break;\n    }\n    \n    return path;\n}\n\n// Build string from order (for final output)\nstring buildString(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s;\n    s.reserve(M * 5);\n    s = t[order[0]];\n    for (size_t i = 1; i < order.size(); i++) {\n        int ov = overlap[order[i-1]][order[i]];\n        s.append(t[order[i]].substr(ov));\n    }\n    return s;\n}\n\n// Greedy initialization with overlap heuristic\nvector<int> greedyInit(int startWord) {\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    \n    order.push_back(startWord);\n    used[startWord] = true;\n    \n    for (int i = 1; i < M; i++) {\n        int bestNext = -1;\n        int bestScore = -1e9;\n        int lastW = order.back();\n        \n        for (int j = 0; j < M; j++) {\n            if (!used[j]) {\n                int ov = overlap[lastW][j];\n                int addedLen = 5 - ov;\n                int score = ov * 100 - addedLen * 10;\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestNext = j;\n                }\n            }\n        }\n        \n        if (bestNext != -1) {\n            used[bestNext] = true;\n            order.push_back(bestNext);\n        }\n    }\n    return order;\n}\n\n// Greedy with position-aware scoring\nvector<int> greedyPositionAware(int startWord) {\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    \n    order.push_back(startWord);\n    used[startWord] = true;\n    \n    int curR = si, curC = sj;\n    \n    for (int i = 1; i < M; i++) {\n        int bestNext = -1;\n        double bestScore = -1e18;\n        int lastW = order.back();\n        \n        for (int j = 0; j < M; j++) {\n            if (!used[j]) {\n                int ov = overlap[lastW][j];\n                int addedLen = 5 - ov;\n                \n                // Estimate movement cost for added characters\n                long long moveCost = 0;\n                int estR = curR, estC = curC;\n                for (int k = ov; k < 5; k++) {\n                    int ch = t[j][k] - 'A';\n                    moveCost += minCostFromPos[estR][estC][ch];\n                    auto [nr, nc] = bestPosFromPos[estR][estC][ch];\n                    estR = nr;\n                    estC = nc;\n                }\n                \n                double score = ov * 150.0 - addedLen * 20.0 - moveCost * 0.05;\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestNext = j;\n                }\n            }\n        }\n        \n        if (bestNext != -1) {\n            used[bestNext] = true;\n            order.push_back(bestNext);\n            \n            // Update position\n            int ov = overlap[order[order.size()-2]][bestNext];\n            for (int k = ov; k < 5; k++) {\n                int ch = t[bestNext][k] - 'A';\n                auto [nr, nc] = bestPosFromPos[curR][curC][ch];\n                curR = nr;\n                curC = nc;\n            }\n        }\n    }\n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    A.resize(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n    \n    t.resize(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            charPos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    precomputePosCosts();\n    \n    // Precompute overlaps\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i == j) continue;\n            int maxOv = 0;\n            for (int ov = 1; ov < 5; ov++) {\n                bool match = true;\n                for (int k = 0; k < ov; k++) {\n                    if (t[i][5 - ov + k] != t[j][k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) maxOv = ov;\n            }\n            overlap[i][j] = maxOv;\n        }\n    }\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> bestOrder;\n    long long bestCost = 1e18;\n    \n    double timeLimit = 1.92;\n    \n    // Phase 1: Multiple greedy starts (both types)\n    int numGreedy = min(M, 30);\n    for (int i = 0; i < numGreedy; i++) {\n        vector<int> order = greedyInit(i);\n        long long cost = calcCost(order);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOrder = order;\n        }\n        \n        if (i % 5 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - startTime).count() > timeLimit * 0.15) break;\n        }\n    }\n    \n    // Add position-aware greedy\n    for (int i = 0; i < min(M, 15); i++) {\n        vector<int> order = greedyPositionAware(i);\n        long long cost = calcCost(order);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOrder = order;\n        }\n        \n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - startTime).count() > timeLimit * 0.25) break;\n    }\n    \n    // Phase 2: Simulated Annealing with accurate cost evaluation\n    vector<int> currentOrder = bestOrder;\n    long long currentCost = bestCost;\n    \n    double temp = 2000.0;\n    double cooling = 0.99985;\n    long long iterations = 0;\n    long long maxIterations = 200000;\n    int accepted = 0;\n    \n    while (iterations < maxIterations) {\n        if (iterations % 3000 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > timeLimit) break;\n            \n            // Adaptive cooling based on acceptance rate\n            double acceptRate = (double)accepted / 3000.0;\n            if (acceptRate < 0.1) {\n                temp *= 1.5;  // Increase temp if stuck\n            } else if (acceptRate > 0.5) {\n                cooling = 0.9998;  // Cool faster if too many accepts\n            }\n            accepted = 0;\n        }\n        \n        vector<int> neighbor = currentOrder;\n        int move = rng() % 4;\n        \n        if (move == 0) {\n            // Swap two elements\n            int i = rng() % M;\n            int j = rng() % M;\n            swap(neighbor[i], neighbor[j]);\n        } else if (move == 1) {\n            // Insert: move element from i to position j\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i != j) {\n                int val = neighbor[i];\n                neighbor.erase(neighbor.begin() + i);\n                neighbor.insert(neighbor.begin() + j, val);\n            }\n        } else if (move == 2) {\n            // Reverse segment\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i > j) swap(i, j);\n            if (j - i > 1) {\n                reverse(neighbor.begin() + i, neighbor.begin() + j + 1);\n            }\n        } else {\n            // Swap adjacent (local move)\n            int i = rng() % (M - 1);\n            swap(neighbor[i], neighbor[i + 1]);\n        }\n        \n        long long neighborCost = calcCost(neighbor);\n        double delta = (double)(neighborCost - currentCost);\n        \n        if (delta < 0 || (temp > 0.1 && exp(-delta / temp) > (double)rng() / rng.max())) {\n            currentOrder = neighbor;\n            currentCost = neighborCost;\n            accepted++;\n            if (currentCost < bestCost) {\n                bestCost = currentCost;\n                bestOrder = currentOrder;\n            }\n        }\n        \n        temp *= cooling;\n        iterations++;\n    }\n    \n    // Final construction with optimized positions\n    string finalStr = buildString(bestOrder);\n    vector<pair<int,int>> path = optimizePositions(finalStr);\n    \n    if ((int)path.size() > 5000) path.resize(5000);\n    \n    for (auto [i, j] : path) {\n        cout << i << \" \" << j << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst double EPS = 1e-10;\nconst double INF = 1e100;\n\nstruct Field {\n    int id;\n    vector<pair<int, int>> shape;\n    int h, w;\n    vector<pair<int, int>> valid_positions;\n};\n\nint N, M;\ndouble epsilon;\nvector<Field> fields;\nvector<double> probs;\nvector<vector<int>> drill_results;\nvector<double> row_obs;\nvector<double> col_obs;\n\ninline int idx(int k, int r, int c) {\n    return k * N * N + r * N + c;\n}\n\n// Precompute which positions cover which cells\nvector<vector<vector<vector<pair<int, int>>>>> cover_map;\n\nvoid build_cover_map() {\n    cover_map.assign(M, vector<vector<vector<pair<int, int>>>>(N, vector<vector<pair<int, int>>>(N)));\n    for (int k = 0; k < M; ++k) {\n        for (auto [r, c] : fields[k].valid_positions) {\n            for (auto [si, sj] : fields[k].shape) {\n                int i = r + si;\n                int j = c + sj;\n                if (i >= 0 && i < N && j >= 0 && j < N) {\n                    cover_map[k][i][j].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\nvoid init_probs() {\n    probs.assign(M * N * N, 0.0);\n    for (int k = 0; k < M; ++k) {\n        double count = (double)fields[k].valid_positions.size();\n        if (count < EPS) count = 1.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] = 1.0 / count;\n        }\n    }\n}\n\ndouble get_marginal(int k, int i, int j) {\n    double p = 0.0;\n    for (auto [r, c] : cover_map[k][i][j]) {\n        p += probs[idx(k, r, c)];\n    }\n    return min(1.0, max(0.0, p));\n}\n\n// Update based on drill result at (i, j) with value V\nvoid update_drill(int i, int j, int V) {\n    vector<double> q(M);\n    for (int k = 0; k < M; ++k) {\n        q[k] = get_marginal(k, i, j);\n    }\n    \n    // Compute P(S=V) and P(S=V | X_k=1), P(S=V | X_k=0) using DP\n    // First compute full distribution\n    vector<double> dp(M + 1, 0.0);\n    dp[0] = 1.0;\n    \n    for (int k = 0; k < M; ++k) {\n        for (int s = k + 1; s >= 1; --s) {\n            dp[s] = dp[s] * (1.0 - q[k]) + dp[s-1] * q[k];\n        }\n        dp[0] = dp[0] * (1.0 - q[k]);\n    }\n    \n    double prob_S_V = (V <= M) ? dp[V] : 0.0;\n    if (prob_S_V < EPS) prob_S_V = EPS;\n    \n    // Update each field\n    for (int k = 0; k < M; ++k) {\n        // Compute distribution without field k\n        vector<double> dp_without(M, 0.0);\n        dp_without[0] = 1.0;\n        \n        for (int other = 0; other < M; ++other) {\n            if (other == k) continue;\n            double p = q[other];\n            for (int s = other; s >= 1; --s) {\n                dp_without[s] = dp_without[s] * (1.0 - p) + dp_without[s-1] * p;\n            }\n            dp_without[0] = dp_without[0] * (1.0 - p);\n        }\n        \n        double prob_S_V_given_1 = (V > 0 && V - 1 < M) ? dp_without[V - 1] : 0.0;\n        double prob_S_V_given_0 = (V < M) ? dp_without[V] : 0.0;\n        \n        double num_1 = prob_S_V_given_1 * q[k];\n        double num_0 = prob_S_V_given_0 * (1.0 - q[k]);\n        double denom = num_1 + num_0;\n        \n        double new_q;\n        if (denom < EPS) {\n            new_q = q[k];\n        } else {\n            new_q = num_1 / denom;\n        }\n        new_q = min(1.0, max(0.0, new_q));\n        \n        // Update probs for field k\n        double old_q = q[k];\n        if (abs(old_q - new_q) < EPS) continue;\n        \n        double f1 = (old_q > EPS) ? (new_q / old_q) : 1.0;\n        double f0 = (old_q < 1.0 - EPS) ? ((1.0 - new_q) / (1.0 - old_q)) : 1.0;\n        \n        f1 = min(INF, max(1.0/INF, f1));\n        f0 = min(INF, max(1.0/INF, f0));\n        \n        double sum_p = 0.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            bool covers = false;\n            for (auto [si, sj] : fields[k].shape) {\n                if (r + si == i && c + sj == j) {\n                    covers = true;\n                    break;\n                }\n            }\n            \n            if (covers) {\n                probs[idx(k, r, c)] *= f1;\n            } else {\n                probs[idx(k, r, c)] *= f0;\n            }\n            probs[idx(k, r, c)] = min(INF, max(EPS, probs[idx(k, r, c)]));\n            sum_p += probs[idx(k, r, c)];\n        }\n        \n        if (sum_p < EPS) sum_p = EPS;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] /= sum_p;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> epsilon)) return 1;\n    \n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        fields[k].id = k;\n        int d;\n        cin >> d;\n        fields[k].shape.resize(d);\n        int max_i = -1, max_j = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> fields[k].shape[i].first >> fields[k].shape[i].second;\n            max_i = max(max_i, fields[k].shape[i].first);\n            max_j = max(max_j, fields[k].shape[i].second);\n        }\n        fields[k].h = max_i + 1;\n        fields[k].w = max_j + 1;\n        for (int r = 0; r <= N - fields[k].h; ++r) {\n            for (int c = 0; c <= N - fields[k].w; ++c) {\n                fields[k].valid_positions.push_back({r, c});\n            }\n        }\n    }\n    \n    build_cover_map();\n    init_probs();\n    \n    drill_results.assign(N, vector<int>(N, -1));\n    row_obs.assign(N, 0.0);\n    col_obs.assign(N, 0.0);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // 1. Query all rows\n    for (int i = 0; i < N; ++i) {\n        cout << \"q \" << N;\n        for (int j = 0; j < N; ++j) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << \"\\n\" << flush;\n        cin >> row_obs[i];\n    }\n    \n    // 2. Query all columns\n    for (int j = 0; j < N; ++j) {\n        cout << \"q \" << N;\n        for (int i = 0; i < N; ++i) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << \"\\n\" << flush;\n        cin >> col_obs[j];\n    }\n    \n    // 3. Simple belief update from row/col observations\n    // For each cell, estimate probability based on row/col sums\n    vector<vector<double>> cell_prob(N, vector<double>(N, 0.5));\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // Simple heuristic: average contribution from row and col\n            double row_avg = row_obs[i] / N;\n            double col_avg = col_obs[j] / N;\n            cell_prob[i][j] = min(1.0, max(0.0, (row_avg + col_avg) / 2.0));\n        }\n    }\n    \n    // 4. Iterative drilling with entropy-based selection\n    int ops_count = 2 * N;\n    int max_ops = 2 * N * N;\n    \n    while (ops_count < max_ops) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break;\n        \n        int best_i = -1, best_j = -1;\n        double max_entropy = -1.0;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drill_results[i][j] != -1) continue;\n                \n                // Use cell_prob as estimate\n                double p = cell_prob[i][j];\n                // Refine with marginal probabilities\n                double p_marginal = 0.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal(k, i, j);\n                    p_marginal = 1.0 - (1.0 - p_marginal) * (1.0 - q);\n                }\n                p = (p + p_marginal) / 2.0;\n                \n                if (p < EPS) p = EPS;\n                if (p > 1.0 - EPS) p = 1.0 - EPS;\n                \n                double H = -p * log2(p) - (1.0 - p) * log2(1.0 - p);\n                if (H > max_entropy) {\n                    max_entropy = H;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1 || max_entropy < 0.1) break;\n        \n        cout << \"q 1 \" << best_i << \" \" << best_j << \"\\n\" << flush;\n        int val;\n        cin >> val;\n        drill_results[best_i][best_j] = val;\n        ops_count++;\n        \n        // Update cell probabilities based on drill\n        if (val > 0) {\n            cell_prob[best_i][best_j] = 1.0;\n            // Boost nearby cells\n            for (int di = -2; di <= 2; ++di) {\n                for (int dj = -2; dj <= 2; ++dj) {\n                    int ni = best_i + di;\n                    int nj = best_j + dj;\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (drill_results[ni][nj] == -1) {\n                            cell_prob[ni][nj] = min(1.0, cell_prob[ni][nj] + 0.1);\n                        }\n                    }\n                }\n            }\n        } else {\n            cell_prob[best_i][best_j] = 0.0;\n        }\n        \n        // Update belief state\n        update_drill(best_i, best_j, val);\n    }\n    \n    // 5. Construct answer\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool has_oil = false;\n            if (drill_results[i][j] != -1) {\n                has_oil = (drill_results[i][j] > 0);\n            } else {\n                double p_empty = 1.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal(k, i, j);\n                    p_empty *= (1.0 - q);\n                }\n                double p_marginal = 1.0 - p_empty;\n                double p_combined = (p_marginal + cell_prob[i][j]) / 2.0;\n                has_oil = (p_combined > 0.5);\n            }\n            \n            if (has_oil) {\n                ans.push_back({i, j});\n            }\n        }\n    }\n    \n    // 6. Submit answer\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << \"\\n\" << flush;\n    \n    int resp;\n    cin >> resp;\n    \n    // If wrong, we could try again but for now just exit\n    (void)resp;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int W = 1000;\nconst double TIME_LIMIT = 2.85;\n\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const { return (long long)(r1 - r0) * (c1 - c0); }\n};\n\nstruct Node {\n    int id;\n    bool is_leaf;\n    int left = -1, right = -1;\n    int res_id = -1;\n    long long target_area = 0;\n    \n    int r0, c0, r1, c1;\n    int cut_pos = 0;\n    int cut_type = 0;\n    \n    int prev_cut_pos = 0;\n    int prev_cut_type = 0;\n};\n\nstruct Solver {\n    int D, N;\n    vector<vector<int>> A;\n    vector<Node> tree;\n    vector<Rect> prev_day_rects;\n    mt19937 rng;\n    chrono::steady_clock::time_point start_time;\n    \n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    }\n    \n    void run() {\n        start_time = chrono::steady_clock::now();\n        \n        int W_in;\n        if (!(cin >> W_in >> D >> N)) return;\n        \n        A.resize(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        prev_day_rects.resize(N);\n        \n        // Build tree\n        tree.resize(2 * N - 1);\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].id = i;\n            if (i >= N - 1) {\n                tree[i].is_leaf = true;\n                tree[i].res_id = i - (N - 1);\n            } else {\n                tree[i].is_leaf = false;\n                tree[i].left = 2 * i + 1;\n                tree[i].right = 2 * i + 2;\n                tree[i].cut_type = (i % 2);\n            }\n        }\n        \n        // Day 0\n        assign_reservations(0);\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n        output_day(0);\n        \n        // Subsequent days\n        for (int d = 1; d < D; ++d) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            solve_day(d);\n            output_day(d);\n        }\n    }\n    \n    void assign_reservations(int d) {\n        vector<pair<int, int>> requests;\n        for (int k = 0; k < N; ++k) {\n            requests.push_back({A[d][k], k});\n        }\n        sort(requests.begin(), requests.end());\n        \n        vector<pair<long long, int>> leaf_areas;\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            long long area = (long long)(tree[leaf_idx].r1 - tree[leaf_idx].r0) * \n                            (tree[leaf_idx].c1 - tree[leaf_idx].c0);\n            leaf_areas.push_back({area, leaf_idx});\n        }\n        sort(leaf_areas.begin(), leaf_areas.end());\n        \n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = leaf_areas[i].second;\n            int k = requests[i].second;\n            tree[leaf_idx].res_id = k;\n            tree[leaf_idx].target_area = A[d][k];\n        }\n    }\n    \n    void solve_day(int d) {\n        (void)d; // Suppress unused warning\n        assign_reservations(d);\n        layout(0, 0, 0, W, W);\n        \n        double best_cost = calc_total_cost();\n        vector<Node> best_tree = tree;\n        \n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = TIME_LIMIT - elapsed;\n        double time_per_day = TIME_LIMIT / D;\n        \n        // Adaptive iterations based on remaining time\n        int max_iterations = 30000;\n        if (remaining < time_per_day * 0.3) max_iterations = 5000;\n        else if (remaining < time_per_day * 0.7) max_iterations = 15000;\n        else if (remaining > time_per_day * 1.5) max_iterations = 60000;\n        \n        // Adaptive cooling\n        double initial_temp = 5000.0;\n        double final_temp = 0.1;\n        double cooling_rate = pow(final_temp / initial_temp, 1.0 / max_iterations);\n        \n        double temperature = initial_temp;\n        int no_improve_count = 0;\n        int restart_threshold = max_iterations / 10;\n        \n        for (int iter = 0; iter < max_iterations; ++iter) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT) break;\n            \n            // Multiple mutation types with different probabilities\n            int mutation_type = uniform_int_distribution<>(0, 100)(rng);\n            \n            // Variables to track what was modified for revert\n            int node_idx = -1;\n            int leaf1 = -1, leaf2 = -1;\n            Node saved_node;\n            int saved_left = -1, saved_right = -1;\n            int saved_res1 = -1, saved_res2 = -1;\n            bool modified = false;\n            \n            if (mutation_type < 30) {\n                // Swap children (30%)\n                node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n                saved_node = tree[node_idx];\n                saved_left = tree[node_idx].left;\n                saved_right = tree[node_idx].right;\n                swap(tree[node_idx].left, tree[node_idx].right);\n                modified = true;\n            } else if (mutation_type < 60) {\n                // Flip cut type (30%)\n                node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n                saved_node = tree[node_idx];\n                tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n                modified = true;\n            } else if (mutation_type < 85) {\n                // Swap leaf assignments (25%)\n                leaf1 = uniform_int_distribution<>(N - 1, 2 * N - 2)(rng);\n                leaf2 = uniform_int_distribution<>(N - 1, 2 * N - 2)(rng);\n                if (leaf1 != leaf2) {\n                    saved_res1 = tree[leaf1].res_id;\n                    saved_res2 = tree[leaf2].res_id;\n                    long long saved_area1 = tree[leaf1].target_area;\n                    long long saved_area2 = tree[leaf2].target_area;\n                    swap(tree[leaf1].res_id, tree[leaf2].res_id);\n                    swap(tree[leaf1].target_area, tree[leaf2].target_area);\n                    // Store areas for revert\n                    saved_node.target_area = saved_area1;\n                    saved_node.res_id = saved_res1;\n                    modified = true;\n                }\n            } else {\n                // Random cut type + swap (15%)\n                node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n                saved_node = tree[node_idx];\n                saved_left = tree[node_idx].left;\n                saved_right = tree[node_idx].right;\n                swap(tree[node_idx].left, tree[node_idx].right);\n                tree[node_idx].cut_type = uniform_int_distribution<>(0, 1)(rng);\n                modified = true;\n            }\n            \n            if (!modified) continue;\n            \n            layout(0, 0, 0, W, W);\n            double new_cost = calc_total_cost();\n            \n            // Simulated annealing acceptance\n            double delta = new_cost - best_cost;\n            bool accept = false;\n            if (delta < -1e-9) {\n                accept = true;\n                no_improve_count = 0;\n            } else if (delta < 1e-9) {\n                accept = true;\n            } else {\n                double prob = exp(-delta / temperature);\n                if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                    accept = true;\n                }\n            }\n            \n            if (accept) {\n                if (new_cost < best_cost - 1e-9) {\n                    best_cost = new_cost;\n                    best_tree = tree;\n                }\n            } else {\n                // Revert\n                if (mutation_type < 30 || mutation_type >= 85) {\n                    tree[node_idx] = saved_node;\n                    tree[node_idx].left = saved_left;\n                    tree[node_idx].right = saved_right;\n                } else if (mutation_type < 60) {\n                    tree[node_idx] = saved_node;\n                } else if (leaf1 != leaf2) {\n                    swap(tree[leaf1].res_id, tree[leaf2].res_id);\n                    swap(tree[leaf1].target_area, tree[leaf2].target_area);\n                }\n            }\n            \n            temperature *= cooling_rate;\n            no_improve_count++;\n            \n            // Restart if stuck\n            if (no_improve_count > restart_threshold && temperature < initial_temp * 0.1) {\n                temperature = initial_temp * 0.5;\n                no_improve_count = 0;\n            }\n        }\n        \n        tree = best_tree;\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n    }\n    \n    void layout(int u, int r0, int c0, int r1, int c1) {\n        tree[u].r0 = r0;\n        tree[u].c0 = c0;\n        tree[u].r1 = r1;\n        tree[u].c1 = c1;\n        \n        if (tree[u].is_leaf) return;\n        \n        int left = tree[u].left;\n        int right = tree[u].right;\n        long long area_l = get_subtree_area(left);\n        long long area_r = get_subtree_area(right);\n        long long total = area_l + area_r;\n        \n        int width = c1 - c0;\n        int height = r1 - r0;\n        \n        int actual_cut_type = tree[u].cut_type;\n        if (width <= 1) {\n            actual_cut_type = 1;\n        } else if (height <= 1) {\n            actual_cut_type = 0;\n        }\n        \n        if (actual_cut_type == 0) {\n            int min_cut = c0 + 1;\n            int max_cut = c1 - 1;\n            \n            if (min_cut > max_cut) {\n                tree[u].cut_pos = c0 + 1;\n            } else {\n                if (total == 0) {\n                    tree[u].cut_pos = (min_cut + max_cut) / 2;\n                } else {\n                    long long w_l = (width * area_l + total / 2) / total;\n                    if (w_l < 1) w_l = 1;\n                    if (w_l > width - 1) w_l = width - 1;\n                    tree[u].cut_pos = c0 + w_l;\n                    if (tree[u].cut_pos < min_cut) tree[u].cut_pos = min_cut;\n                    if (tree[u].cut_pos > max_cut) tree[u].cut_pos = max_cut;\n                }\n            }\n            \n            layout(left, r0, c0, r1, tree[u].cut_pos);\n            layout(right, r0, tree[u].cut_pos, r1, c1);\n        } else {\n            int min_cut = r0 + 1;\n            int max_cut = r1 - 1;\n            \n            if (min_cut > max_cut) {\n                tree[u].cut_pos = r0 + 1;\n            } else {\n                if (total == 0) {\n                    tree[u].cut_pos = (min_cut + max_cut) / 2;\n                } else {\n                    long long h_l = (height * area_l + total / 2) / total;\n                    if (h_l < 1) h_l = 1;\n                    if (h_l > height - 1) h_l = height - 1;\n                    tree[u].cut_pos = r0 + h_l;\n                    if (tree[u].cut_pos < min_cut) tree[u].cut_pos = min_cut;\n                    if (tree[u].cut_pos > max_cut) tree[u].cut_pos = max_cut;\n                }\n            }\n            \n            layout(left, r0, c0, tree[u].cut_pos, c1);\n            layout(right, tree[u].cut_pos, c0, r1, c1);\n        }\n    }\n    \n    long long get_subtree_area(int u) {\n        if (tree[u].is_leaf) return tree[u].target_area;\n        return get_subtree_area(tree[u].left) + get_subtree_area(tree[u].right);\n    }\n    \n    double calc_total_cost() {\n        double cost = 0;\n        \n        // Area penalty (100x shortfall)\n        for (int i = N - 1; i < 2 * N - 1; ++i) {\n            long long actual_area = (long long)(tree[i].r1 - tree[i].r0) * (tree[i].c1 - tree[i].c0);\n            if (actual_area < tree[i].target_area) {\n                cost += 100.0 * (tree[i].target_area - actual_area);\n            }\n        }\n        \n        // Partition movement cost\n        for (int i = 0; i < N - 1; ++i) {\n            if (tree[i].cut_type != tree[i].prev_cut_type) {\n                int span_old = (tree[i].prev_cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                int span_new = (tree[i].cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                cost += span_old + span_new;\n            } else {\n                int pos_diff = abs(tree[i].cut_pos - tree[i].prev_cut_pos);\n                int span = (tree[i].cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                cost += 2.0 * pos_diff * span;\n            }\n        }\n        \n        return cost;\n    }\n    \n    void update_prev_info() {\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].prev_cut_pos = tree[i].cut_pos;\n            tree[i].prev_cut_type = tree[i].cut_type;\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            prev_day_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, \n                                tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n    }\n    \n    void output_day(int) {\n        vector<Rect> current_rects(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            current_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, \n                               tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n        \n        for (int k = 0; k < N; ++k) {\n            cout << current_rects[k].r0 << \" \" << current_rects[k].c0 << \" \" \n                 << current_rects[k].r1 << \" \" << current_rects[k].c1 << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver solver;\n    solver.run();\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long MOD = 998244353;\n\nstruct Operation {\n    int m, p, q;\n    \n    bool operator==(const Operation& other) const {\n        return m == other.m && p == other.p && q == other.q;\n    }\n    \n    bool operator!=(const Operation& other) const {\n        return !(*this == other);\n    }\n    \n    bool operator<(const Operation& other) const {\n        if (m != other.m) return m < other.m;\n        if (p != other.p) return p < other.p;\n        return q < other.q;\n    }\n};\n\nint N, M, K;\nvector<vector<long long>> a;\nvector<vector<vector<long long>>> s;\n\n// Safe modulo that handles negative numbers\ninline long long safeMod(long long x) {\n    long long r = x % MOD;\n    return r < 0 ? r + MOD : r;\n}\n\n// Current board state (cumulative additions from operations)\nvector<vector<long long>> board;\n\n// Current modulo values for each cell\nvector<vector<long long>> mod_vals;\n\n// Current total score\nlong long current_score;\n\n// Current operations\nvector<Operation> ops;\n\n// Initialize board state from operations\nvoid resetBoard() {\n    board.assign(N, vector<long long>(N, 0));\n    mod_vals.resize(N, vector<long long>(N));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            mod_vals[i][j] = safeMod(a[i][j]);\n        }\n    }\n    \n    current_score = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            current_score += mod_vals[i][j];\n        }\n    }\n    \n    // Apply all operations\n    for (const auto& op : ops) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                int r = op.p + i;\n                int c = op.q + j;\n                long long old_mod = mod_vals[r][c];\n                board[r][c] += s[op.m][i][j];\n                mod_vals[r][c] = safeMod(board[r][c] + a[r][c]);\n                current_score += mod_vals[r][c] - old_mod;\n            }\n        }\n    }\n}\n\n// Calculate delta if we change operation at index idx to new_op\nlong long calculateDelta(int idx, const Operation& new_op) {\n    const auto& old_op = ops[idx];\n    long long delta = 0;\n    \n    // Track affected cells using a small array (max 18 unique cells)\n    bool visited[9][9] = {};\n    vector<pair<int, int>> affected;\n    affected.reserve(18);\n    \n    // Old operation cells\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = old_op.p + i;\n            int c = old_op.q + j;\n            if (!visited[r][c]) {\n                visited[r][c] = true;\n                affected.emplace_back(r, c);\n            }\n        }\n    }\n    \n    // New operation cells\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = new_op.p + i;\n            int c = new_op.q + j;\n            if (!visited[r][c]) {\n                visited[r][c] = true;\n                affected.emplace_back(r, c);\n            }\n        }\n    }\n    \n    for (const auto& [r, c] : affected) {\n        long long old_mod = mod_vals[r][c];\n        long long new_val = board[r][c] + a[r][c];\n        \n        // Remove old operation contribution\n        if (r >= old_op.p && r < old_op.p + 3 && c >= old_op.q && c < old_op.q + 3) {\n            new_val -= s[old_op.m][r - old_op.p][c - old_op.q];\n        }\n        // Add new operation contribution\n        if (r >= new_op.p && r < new_op.p + 3 && c >= new_op.q && c < new_op.q + 3) {\n            new_val += s[new_op.m][r - new_op.p][c - new_op.q];\n        }\n        \n        long long new_mod = safeMod(new_val);\n        delta += new_mod - old_mod;\n    }\n    \n    return delta;\n}\n\n// Actually change operation at index idx\nvoid changeOp(int idx, const Operation& new_op) {\n    const auto& old_op = ops[idx];\n    \n    // Remove old operation\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = old_op.p + i;\n            int c = old_op.q + j;\n            long long old_mod = mod_vals[r][c];\n            board[r][c] -= s[old_op.m][i][j];\n            mod_vals[r][c] = safeMod(board[r][c] + a[r][c]);\n            current_score += mod_vals[r][c] - old_mod;\n        }\n    }\n    \n    // Update operation\n    ops[idx] = new_op;\n    \n    // Add new operation\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = new_op.p + i;\n            int c = new_op.q + j;\n            long long old_mod = mod_vals[r][c];\n            board[r][c] += s[new_op.m][i][j];\n            mod_vals[r][c] = safeMod(board[r][c] + a[r][c]);\n            current_score += mod_vals[r][c] - old_mod;\n        }\n    }\n}\n\n// Greedy initialization (deterministic best)\nvector<Operation> greedyInit() {\n    vector<Operation> result;\n    result.reserve(K);\n    \n    vector<vector<long long>> cur_board = a;\n    vector<vector<long long>> cur_mod(N, vector<long long>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cur_mod[i][j] = safeMod(cur_board[i][j]);\n        }\n    }\n    \n    for (int op = 0; op < K; op++) {\n        long long best_delta = LLONG_MIN;\n        int best_m = 0, best_p = 0, best_q = 0;\n        \n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    long long delta = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            long long old_mod = cur_mod[p + i][q + j];\n                            long long new_mod = safeMod(cur_board[p + i][q + j] + s[m][i][j]);\n                            delta += new_mod - old_mod;\n                        }\n                    }\n                    \n                    if (delta > best_delta) {\n                        best_delta = delta;\n                        best_m = m;\n                        best_p = p;\n                        best_q = q;\n                    }\n                }\n            }\n        }\n        \n        result.push_back({best_m, best_p, best_q});\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cur_board[best_p + i][best_q + j] += s[best_m][i][j];\n                cur_mod[best_p + i][best_q + j] = safeMod(cur_board[best_p + i][best_q + j]);\n            }\n        }\n    }\n    \n    return result;\n}\n\n// Local search with tabu list\nvoid localSearch(int iterations, mt19937& rng) {\n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    \n    // Tabu list: recently changed operations (index, old_operation)\n    queue<pair<int, Operation>> tabu;\n    unordered_set<long long> tabu_set;\n    int tabu_size = 20;\n    \n    auto makeTabuHash = [](int idx, const Operation& op) -> long long {\n        return ((long long)idx << 20) ^ (op.m << 10) ^ (op.p << 5) ^ op.q;\n    };\n    \n    int no_improve = 0;\n    for (int iter = 0; iter < iterations && no_improve < iterations / 10; iter++) {\n        bool improved = false;\n        \n        // Try changing one operation\n        for (int trial = 0; trial < 150; trial++) {\n            int idx = dist_op(rng);\n            Operation new_op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n            \n            // Check tabu\n            long long hash_val = makeTabuHash(idx, ops[idx]);\n            if (tabu_set.count(hash_val)) continue;\n            \n            long long delta = calculateDelta(idx, new_op);\n            if (delta > 0) {\n                // Add to tabu\n                if ((int)tabu.size() >= tabu_size) {\n                    auto old = tabu.front();\n                    tabu.pop();\n                    tabu_set.erase(makeTabuHash(old.first, old.second));\n                }\n                tabu.push({idx, ops[idx]});\n                tabu_set.insert(hash_val);\n                \n                changeOp(idx, new_op);\n                improved = true;\n                no_improve = 0;\n            }\n        }\n        \n        // Try swapping two operations\n        for (int trial = 0; trial < 80; trial++) {\n            int idx1 = dist_op(rng);\n            int idx2 = dist_op(rng);\n            if (idx1 == idx2) continue;\n            \n            long long score_before = current_score;\n            \n            Operation op1 = ops[idx1];\n            Operation op2 = ops[idx2];\n            \n            changeOp(idx1, op2);\n            changeOp(idx2, op1);\n            \n            if (current_score > score_before) {\n                improved = true;\n                no_improve = 0;\n            } else {\n                changeOp(idx2, op2);\n                changeOp(idx1, op1);\n            }\n        }\n        \n        if (!improved) no_improve++;\n    }\n}\n\n// Simulated annealing\nvoid simulatedAnnealing(double time_limit, mt19937& rng) {\n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_score = current_score;\n    vector<Operation> best_ops = ops;\n    \n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double temperature = 100000.0;\n    double cooling_rate = 0.99985;\n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        int idx = dist_op(rng);\n        Operation old_op = ops[idx];\n        Operation new_op = old_op;\n        \n        int change_type = dist_op(rng) % 3;\n        if (change_type == 0) {\n            new_op.m = dist_m(rng);\n        } else if (change_type == 1) {\n            new_op.p = dist_p(rng);\n        } else {\n            new_op.q = dist_q(rng);\n        }\n        \n        long long delta = calculateDelta(idx, new_op);\n        double accept_prob = exp((double)delta / temperature);\n        \n        if (delta > 0 || dist_real(rng) < accept_prob) {\n            changeOp(idx, new_op);\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ops = ops;\n            }\n        }\n        \n        temperature *= cooling_rate;\n        iterations++;\n        \n        if (iterations % 20000 == 0 && temperature < 0.01) break;\n    }\n    \n    // Restore best\n    if (best_score > current_score) {\n        ops = best_ops;\n        resetBoard();\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    a.assign(N, vector<long long>(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    s.assign(M, vector<vector<long long>>(3, vector<long long>(3)));\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> s[m][i][j];\n            }\n        }\n    }\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_budget = 1.95;\n    \n    vector<Operation> global_best_ops;\n    long long global_best_score = -1;\n    \n    // Balanced restarts (15 instead of 18)\n    int num_restarts = 15;\n    for (int restart = 0; restart < num_restarts; restart++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_budget * 0.95) break;\n        \n        double remaining = time_budget - elapsed;\n        double time_per_restart = remaining / max(1, num_restarts - restart);\n        \n        unsigned seed = restart * 12345 + (unsigned)chrono::steady_clock::now().time_since_epoch().count();\n        mt19937 rng(seed);\n        \n        // Greedy initialization (deterministic best)\n        ops = greedyInit();\n        resetBoard();\n        \n        // Local search with tabu\n        localSearch(3000, rng);\n        \n        // Simulated annealing with adaptive time\n        double sa_time = min(0.2, time_per_restart * 0.6);\n        simulatedAnnealing(sa_time, rng);\n        \n        if (current_score > global_best_score) {\n            global_best_score = current_score;\n            global_best_ops = ops;\n        }\n    }\n    \n    // Output\n    cout << global_best_ops.size() << \"\\n\";\n    for (const auto& op : global_best_ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nconst int N = 5;\nconst int MAX_TURNS = 10000;\n\nstruct State {\n    int container[N][N]; // -1 if empty, otherwise container number\n    int crane_row[5];    // current row of each crane\n    int crane_col[5];    // current col of each crane\n    int crane_holding[5]; // -1 if not holding, otherwise container number\n    int next_receive[5]; // next container index to receive at each gate\n    vector<int> dispatched[5]; // containers dispatched from each gate\n};\n\nint get_target_row(int container_num) {\n    return container_num / N;\n}\n\nint get_target_col(int container_num) {\n    return N - 1;\n}\n\nbool can_move_small(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return false;\n    return state.container[row][col] == -1;\n}\n\nbool can_move_large(int row, int col, const State& state) {\n    if (row < 0 || row >= N || col < 0 || col >= N) return true;\n    return true; // Large crane can move over containers\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\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    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            state.container[i][j] = -1;\n        }\n        state.crane_row[i] = i;\n        state.crane_col[i] = 0;\n        state.crane_holding[i] = -1;\n        state.next_receive[i] = 0;\n        state.dispatched[i].clear();\n    }\n    \n    // Output strings for each crane\n    vector<string> actions(N, \"\");\n    \n    // Track which containers need to be dispatched from each gate\n    vector<vector<int>> target_containers(N);\n    for (int c = 0; c < N * N; c++) {\n        target_containers[c / N].push_back(c);\n    }\n    \n    // Simple greedy strategy: move containers from left to right\n    // Large crane (0) handles row 0, small cranes handle their rows\n    // Use columns 1-3 as buffer\n    \n    int turn = 0;\n    int total_dispatched = 0;\n    \n    while (turn < MAX_TURNS && total_dispatched < N * N) {\n        string turn_actions(N, '.');\n        bool any_action = false;\n        \n        // Step 1: Receive containers (simulated - happens automatically)\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && \n                state.container[i][0] == -1 && \n                state.crane_holding[0] == -1) { // Check if crane 0 not blocking\n                // Container arrives at gate\n                // This happens automatically in the simulation\n            }\n        }\n        \n        // Step 2: Plan crane actions\n        for (int c = 0; c < N; c++) {\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            int holding = state.crane_holding[c];\n            \n            char action = '.';\n            \n            if (holding == -1) {\n                // Not holding - try to pick up a container\n                if (state.container[r][col] != -1) {\n                    // Pick up container\n                    action = 'P';\n                    any_action = true;\n                } else {\n                    // Move towards containers or dispatch gates\n                    bool is_large = (c == 0);\n                    \n                    // Priority: go to left side to pick up, then right to dispatch\n                    int target_col = 0;\n                    int target_row = r;\n                    \n                    // Look for containers to pick up\n                    bool found_container = false;\n                    for (int j = 0; j < N && !found_container; j++) {\n                        for (int i = 0; i < N && !found_container; i++) {\n                            if (state.container[i][j] != -1) {\n                                int container = state.container[i][j];\n                                int target_r = get_target_row(container);\n                                if (c == target_r || (c == 0 && target_r == 0)) {\n                                    target_row = i;\n                                    target_col = j;\n                                    found_container = true;\n                                }\n                            }\n                        }\n                    }\n                    \n                    if (!found_container) {\n                        // Go to left side to wait for new containers\n                        target_col = 0;\n                    }\n                    \n                    // Move towards target\n                    if (col < target_col) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_col) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_row) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_row) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            } else {\n                // Holding a container - try to dispatch it\n                int target_r = get_target_row(holding);\n                int target_c = get_target_col(holding);\n                \n                if (r == target_r && col == target_c) {\n                    // At dispatch gate - release\n                    action = 'Q';\n                    any_action = true;\n                } else {\n                    // Move towards dispatch gate\n                    bool is_large = (c == 0);\n                    \n                    if (col < target_c) {\n                        if (is_large || can_move_small(r, col + 1, state)) {\n                            action = 'R';\n                            any_action = true;\n                        }\n                    } else if (col > target_c) {\n                        if (is_large || can_move_small(r, col - 1, state)) {\n                            action = 'L';\n                            any_action = true;\n                        }\n                    } else if (r < target_r) {\n                        if (is_large || can_move_small(r + 1, col, state)) {\n                            action = 'D';\n                            any_action = true;\n                        }\n                    } else if (r > target_r) {\n                        if (is_large || can_move_small(r - 1, col, state)) {\n                            action = 'U';\n                            any_action = true;\n                        }\n                    }\n                }\n            }\n            \n            turn_actions[c] = action;\n        }\n        \n        // If no actions, break to avoid infinite loop\n        if (!any_action && total_dispatched < N * N) {\n            // Try to do something - at least move cranes\n            for (int c = 0; c < N; c++) {\n                if (state.crane_col[c] < N - 1) {\n                    turn_actions[c] = 'R';\n                }\n            }\n        }\n        \n        // Apply actions (simplified simulation)\n        for (int c = 0; c < N; c++) {\n            char action = turn_actions[c];\n            int r = state.crane_row[c];\n            int col = state.crane_col[c];\n            \n            if (action == 'P' && state.crane_holding[c] == -1 && state.container[r][col] != -1) {\n                state.crane_holding[c] = state.container[r][col];\n                state.container[r][col] = -1;\n            } else if (action == 'Q' && state.crane_holding[c] != -1 && state.container[r][col] == -1) {\n                state.container[r][col] = state.crane_holding[c];\n                state.crane_holding[c] = -1;\n            } else if (action == 'R' && col < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col + 1] == -1) {\n                    state.crane_col[c]++;\n                }\n            } else if (action == 'L' && col > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r][col - 1] == -1) {\n                    state.crane_col[c]--;\n                }\n            } else if (action == 'D' && r < N - 1) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r + 1][col] == -1) {\n                    state.crane_row[c]++;\n                }\n            } else if (action == 'U' && r > 0) {\n                bool is_large = (c == 0);\n                if (is_large || state.container[r - 1][col] == -1) {\n                    state.crane_row[c]--;\n                }\n            }\n        }\n        \n        // Step 3: Dispatch containers at right edge\n        for (int i = 0; i < N; i++) {\n            if (state.container[i][N - 1] != -1) {\n                int container = state.container[i][N - 1];\n                state.dispatched[i].push_back(container);\n                state.container[i][N - 1] = -1;\n                total_dispatched++;\n            }\n        }\n        \n        // Simulate container arrival at left edge\n        for (int i = 0; i < N; i++) {\n            if (state.next_receive[i] < N && state.container[i][0] == -1) {\n                // Check if any crane is holding at this position\n                bool crane_blocking = false;\n                for (int c = 0; c < N; c++) {\n                    if (state.crane_row[c] == i && state.crane_col[c] == 0 && state.crane_holding[c] != -1) {\n                        crane_blocking = true;\n                        break;\n                    }\n                }\n                if (!crane_blocking) {\n                    state.container[i][0] = A[i][state.next_receive[i]];\n                    state.next_receive[i]++;\n                }\n            }\n        }\n        \n        // Record actions\n        for (int c = 0; c < N; c++) {\n            actions[c] += turn_actions[c];\n        }\n        \n        turn++;\n        \n        // Safety break\n        if (turn >= 5000) break;\n    }\n    \n    // Pad all strings to same length\n    size_t max_len = 0;\n    for (int i = 0; i < N; i++) {\n        max_len = max(max_len, actions[i].size());\n    }\n    for (int i = 0; i < N; i++) {\n        while (actions[i].size() < max_len) {\n            actions[i] += '.';\n        }\n    }\n    \n    // Output\n    for (int i = 0; i < N; i++) {\n        cout << actions[i] << \"\\n\";\n    }\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\n// Structure to represent a cell with non-zero height\nstruct Cell {\n    int r, c;\n    int h;\n    int id;\n};\n\nint N;\nvector<vector<int>> H;\nvector<string> ops;\nint curr_r, curr_c;\nlong long current_load;\n\n// Helper to record an operation\nvoid add_op(const string& s) {\n    ops.push_back(s);\n}\n\n// Helper to move the truck to a target coordinate and record moves\nvoid move_to(int tr, int tc) {\n    while (curr_r < tr) {\n        add_op(\"D\");\n        curr_r++;\n    }\n    while (curr_r > tr) {\n        add_op(\"U\");\n        curr_r--;\n    }\n    while (curr_c < tc) {\n        add_op(\"R\");\n        curr_c++;\n    }\n    while (curr_c > tc) {\n        add_op(\"L\");\n        curr_c--;\n    }\n}\n\n// Manhattan distance\nint dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nint main() {\n    // Optimize I/O operations\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    H.assign(N, vector<int>(N));\n    vector<Cell> sources;\n    vector<Cell> sinks;\n\n    // Read input and classify cells into sources (h > 0) and sinks (h < 0)\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n            if (H[i][j] > 0) {\n                sources.push_back({i, j, H[i][j], i * N + j});\n            } else if (H[i][j] < 0) {\n                sinks.push_back({i, j, H[i][j], i * N + j});\n            }\n        }\n    }\n\n    curr_r = 0;\n    curr_c = 0;\n    current_load = 0;\n\n    // Continue until all sources are processed and truck is empty\n    while (!sources.empty() || current_load > 0) {\n        if (current_load == 0) {\n            // Truck is empty, need to pick up soil from a source.\n            // Heuristic: Select source u that minimizes:\n            // 100 * dist(curr, u) + (100 + h[u]) * dist(u, nearest_sink_to_u)\n            // This accounts for the empty travel to the source and the first loaded leg.\n            \n            int best_idx = -1;\n            long long best_score = -1;\n\n            for (int i = 0; i < (int)sources.size(); ++i) {\n                // Find nearest sink for this source\n                int min_d_sink = 1e9;\n                for (const auto& s : sinks) {\n                    int d = dist(sources[i].r, sources[i].c, s.r, s.c);\n                    if (d < min_d_sink) {\n                        min_d_sink = d;\n                    }\n                }\n                \n                int d1 = dist(curr_r, curr_c, sources[i].r, sources[i].c);\n                // Cost estimate: Empty travel + Loaded travel to first sink\n                // We use sources[i].h because we plan to load all soil from this source\n                long long score = 100LL * d1 + (100LL + sources[i].h) * min_d_sink;\n                \n                if (best_idx == -1 || score < best_score) {\n                    best_score = score;\n                    best_idx = i;\n                }\n            }\n\n            // Pick the best source\n            Cell u = sources[best_idx];\n            // Remove from sources list efficiently\n            sources[best_idx] = sources.back();\n            sources.pop_back();\n\n            // Move to source and load all soil\n            move_to(u.r, u.c);\n            long long amount = u.h;\n            add_op(\"+\" + to_string(amount));\n            current_load += amount;\n            H[u.r][u.c] = 0;\n        }\n\n        if (current_load > 0) {\n            // Truck has soil, need to deliver to a sink.\n            // Heuristic: Go to the nearest sink to minimize loaded travel cost.\n            int best_idx = -1;\n            int min_d = 1e9;\n\n            for (int i = 0; i < (int)sinks.size(); ++i) {\n                int d = dist(curr_r, curr_c, sinks[i].r, sinks[i].c);\n                if (d < min_d) {\n                    min_d = d;\n                    best_idx = i;\n                }\n            }\n\n            // Safety check, though sinks should not be empty if load > 0\n            if (best_idx == -1) break; \n\n            Cell v = sinks[best_idx];\n            \n            // Move to sink and unload as much as possible\n            move_to(v.r, v.c);\n            // Use H to get current demand, as sinks list stores initial h\n            long long amount = min(current_load, (long long)-H[v.r][v.c]);\n            add_op(\"-\" + to_string(amount));\n            current_load -= amount;\n            H[v.r][v.c] += amount;\n            \n            // If sink is satisfied (height becomes 0), remove from list\n            if (H[v.r][v.c] == 0) {\n                sinks[best_idx] = sinks.back();\n                sinks.pop_back();\n            }\n        }\n    }\n\n    // Output all operations\n    for (const auto& op : ops) {\n        cout << op << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    ios_base::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));\n    vector<int> values(seed_count, 0);\n    \n    // Read initial seeds\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n            values[i] += X[i][j];\n        }\n    }\n    \n    // Track maximum value for each criterion\n    vector<int> max_per_criterion(M, 0);\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            max_per_criterion[j] = max(max_per_criterion[j], X[i][j]);\n        }\n    }\n    \n    // Calculate criterion weights (higher max = more important)\n    vector<double> criterion_weight(M);\n    double total_max = 0;\n    for (int j = 0; j < M; j++) {\n        total_max += max_per_criterion[j];\n    }\n    for (int j = 0; j < M; j++) {\n        criterion_weight[j] = (total_max > 0) ? max_per_criterion[j] / total_max : 1.0 / M;\n    }\n    \n    // Neighbor information\n    int di[] = {-1, 1, 0, 0};\n    int dj[] = {0, 0, -1, 1};\n    \n    vector<vector<int>> neighbor_count(N, vector<int>(N, 0));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    neighbor_count[i][j]++;\n                }\n            }\n        }\n    }\n    \n    // Position priority: center first (most neighbors)\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    sort(positions.begin(), positions.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        if (neighbor_count[a.first][a.second] != neighbor_count[b.first][b.second]) {\n            return neighbor_count[a.first][a.second] > neighbor_count[b.first][b.second];\n        }\n        int dist_a = abs(a.first - (N-1)/2) + abs(a.second - (N-1)/2);\n        int dist_b = abs(b.first - (N-1)/2) + abs(b.second - (N-1)/2);\n        return dist_a < dist_b;\n    });\n    \n    for (int t = 0; t < T; t++) {\n        // Turn-dependent strategy\n        // Early turns (0-3): More exploration (criterion coverage)\n        // Middle turns (4-6): Balanced\n        // Late turns (7-9): Pure exploitation (total value)\n        double exploration_weight;\n        double exploitation_weight;\n        \n        if (t <= 3) {\n            exploration_weight = 0.7 - t * 0.1;\n            exploitation_weight = 1.0 - exploration_weight;\n        } else if (t <= 6) {\n            exploration_weight = 0.4 - (t - 3) * 0.1;\n            exploitation_weight = 1.0 - exploration_weight;\n        } else {\n            exploration_weight = 0.0;\n            exploitation_weight = 1.0;\n        }\n        \n        // Calculate seed scores\n        vector<double> seed_score(seed_count, 0);\n        \n        for (int i = 0; i < seed_count; i++) {\n            // Normalized total value score\n            double value_score = values[i] / 1500.0 * 1000;\n            \n            // Criterion coverage score (weighted by importance)\n            double coverage_score = 0;\n            for (int j = 0; j < M; j++) {\n                if (max_per_criterion[j] > 0) {\n                    double ratio = (double)X[i][j] / max_per_criterion[j];\n                    coverage_score += ratio * criterion_weight[j] * 1000;\n                }\n            }\n            \n            // Elite bonus: count criteria >= 85% of max\n            int elite_count = 0;\n            for (int j = 0; j < M; j++) {\n                if (max_per_criterion[j] > 0 && X[i][j] >= max_per_criterion[j] * 0.85) {\n                    elite_count++;\n                }\n            }\n            \n            // Exceptional bonus: count criteria >= 95% of max\n            int exceptional_count = 0;\n            for (int j = 0; j < M; j++) {\n                if (max_per_criterion[j] > 0 && X[i][j] >= max_per_criterion[j] * 0.95) {\n                    exceptional_count++;\n                }\n            }\n            \n            seed_score[i] = value_score * exploitation_weight + \n                           coverage_score * exploration_weight +\n                           elite_count * 80 +\n                           exceptional_count * 150;\n        }\n        \n        // Sort seeds by score (deterministic)\n        vector<int> indices(seed_count);\n        iota(indices.begin(), indices.end(), 0);\n        \n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            if (abs(seed_score[a] - seed_score[b]) > 0.1) {\n                return seed_score[a] > seed_score[b];\n            }\n            if (values[a] != values[b]) {\n                return values[a] > values[b];\n            }\n            return a < b;\n        });\n        \n        // Simple greedy placement - top seeds to top positions\n        vector<vector<int>> A(N, vector<int>(N, -1));\n        vector<bool> seed_used(seed_count, false);\n        \n        int seed_idx = 0;\n        for (const auto& pos : positions) {\n            int i = pos.first;\n            int j = pos.second;\n            \n            // Find best unused seed (try all, not just top 20)\n            while (seed_idx < seed_count && seed_used[indices[seed_idx]]) {\n                seed_idx++;\n            }\n            \n            if (seed_idx < seed_count) {\n                A[i][j] = indices[seed_idx];\n                seed_used[indices[seed_idx]] = true;\n                seed_idx++;\n            }\n        }\n        \n        // Output the placement\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 and update max per criterion\n        for (int i = 0; i < seed_count; i++) {\n            values[i] = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                values[i] += X[i][j];\n                max_per_criterion[j] = max(max_per_criterion[j], X[i][j]);\n            }\n        }\n        \n        // Recalculate criterion weights\n        total_max = 0;\n        for (int j = 0; j < M; j++) {\n            total_max += max_per_criterion[j];\n        }\n        for (int j = 0; j < M; j++) {\n            criterion_weight[j] = (total_max > 0) ? max_per_criterion[j] / total_max : 1.0 / M;\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\n// Get finger position given root position and direction\n// dir: 0=R, 1=U, 2=L, 3=D\nPoint getFingerPos(int root_r, int root_c, int dir, int length = 1) {\n    int dr[] = {0, -1, 0, 1};\n    int dc[] = {1, 0, -1, 0};\n    return {root_r + dr[dir] * length, root_c + dc[dir] * length};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M_in, V;\n    if (!(cin >> N >> M_in >> V)) return 0;\n\n    vector<string> S_grid(N), T_grid(N);\n    vector<Point> starts, targets;\n\n    for (int i = 0; i < N; ++i) cin >> S_grid[i];\n    for (int i = 0; i < N; ++i) cin >> T_grid[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (S_grid[i][j] == '1') starts.push_back({i, j});\n            if (T_grid[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n\n    // Output Arm Design: Star Graph with V vertices, edge length 1\n    int V_prime = V;\n    cout << V_prime << \"\\n\";\n    for (int i = 1; i < V_prime; ++i) {\n        cout << 0 << \" \" << 1 << \"\\n\";\n    }\n    // Root starts at (0, 0), all fingers initially point right (direction 0)\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // Track grid state internally - this MUST match judge's state\n    vector<vector<int>> has_takoyaki(N, vector<int>(N, 0));\n    vector<vector<int>> is_target(N, vector<int>(N, 0));\n    \n    for (auto& p : starts) has_takoyaki[p.r][p.c] = 1;\n    for (auto& p : targets) is_target[p.r][p.c] = 1;\n\n    // Count takoyaki already at targets (don't need to move these)\n    int already_done = 0;\n    for (auto& p : starts) {\n        if (is_target[p.r][p.c]) already_done++;\n    }\n\n    int M = starts.size() - already_done;\n    \n    if (M == 0) {\n        return 0;\n    }\n\n    // Simulation State\n    int cur_r = 0, cur_c = 0;\n    vector<int> holding(V_prime, 0); // 0 = not holding, 1 = holding\n    vector<int> finger_dir(V_prime, 0); // 0:R, 1:U, 2:L, 3:D (all start pointing right)\n\n    int total_turns = 0;\n    const int MAX_TURNS = 100000;\n    int takoyaki_moved = 0;\n\n    // Direction vectors: 0=R, 1=U, 2=L, 3=D\n    int dr[] = {0, -1, 0, 1};\n    int dc[] = {1, 0, -1, 0};\n    char moveChar[] = {'R', 'U', 'L', 'D'};\n\n    while (takoyaki_moved < M && total_turns < MAX_TURNS - 500) {\n        // Find a takoyaki that needs to be moved (has takoyaki but not at target)\n        Point pickup_pos = {-1, -1};\n        \n        for (int r = 0; r < N && pickup_pos.r == -1; ++r) {\n            for (int c = 0; c < N && pickup_pos.r == -1; ++c) {\n                if (has_takoyaki[r][c] == 1 && is_target[r][c] == 0) {\n                    pickup_pos = {r, c};\n                }\n            }\n        }\n        \n        if (pickup_pos.r == -1) break;\n        \n        // Find nearest empty target\n        Point drop_pos = {-1, -1};\n        int best_dist = 1e9;\n        for (int tr = 0; tr < N; ++tr) {\n            for (int tc = 0; tc < N; ++tc) {\n                if (is_target[tr][tc] == 1 && has_takoyaki[tr][tc] == 0) {\n                    int d = dist(pickup_pos, {tr, tc});\n                    if (d < best_dist) {\n                        best_dist = d;\n                        drop_pos = {tr, tc};\n                    }\n                }\n            }\n        }\n        \n        if (drop_pos.r == -1) break;\n        \n        // Find a free finger\n        int finger = -1;\n        for(int u = 1; u < V_prime; ++u) {\n            if(holding[u] == 0) {\n                finger = u;\n                break;\n            }\n        }\n        \n        if (finger == -1) break;\n        \n        // Calculate which direction the finger needs to point to reach pickup_pos from root\n        // We need: root + direction_vector = pickup_pos\n        // So: direction_vector = pickup_pos - root\n        int target_dir = -1;\n        for (int d = 0; d < 4; ++d) {\n            Point fp = getFingerPos(cur_r, cur_c, d, 1);\n            if (fp.r == pickup_pos.r && fp.c == pickup_pos.c) {\n                target_dir = d;\n                break;\n            }\n        }\n        \n        // If we can't reach pickup_pos from current root position, move root\n        if (target_dir == -1) {\n            // Find best root position adjacent to pickup_pos\n            int best_nr = -1, best_nc = -1;\n            int min_move_dist = 1e9;\n            \n            for(int d = 0; d < 4; ++d) {\n                int nr = pickup_pos.r - dr[d];\n                int nc = pickup_pos.c - dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d_move = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d_move < min_move_dist) {\n                        min_move_dist = d_move;\n                        best_nr = nr;\n                        best_nc = nc;\n                        target_dir = d;\n                    }\n                }\n            }\n            \n            if (best_nr == -1) break;\n            \n            // Move root to best position\n            while ((cur_r != best_nr || cur_c != best_nc) && total_turns < MAX_TURNS - 100) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                cout << cmd << \"\\n\";\n                total_turns++;\n            }\n        }\n        \n        // Rotate finger to target direction\n        while (finger_dir[finger] != target_dir && total_turns < MAX_TURNS - 100) {\n            string rot_cmd(2 * V_prime, '.');\n            int diff = (target_dir - finger_dir[finger] + 4) % 4;\n            if (diff == 1) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            } else if (diff == 3) {\n                rot_cmd[finger] = 'R';\n                finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n            } else if (diff == 2) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            }\n            cout << rot_cmd << \"\\n\";\n            total_turns++;\n        }\n        \n        // CRITICAL: Verify takoyaki exists at finger position BEFORE pickup\n        Point finger_pos = getFingerPos(cur_r, cur_c, finger_dir[finger], 1);\n        if (finger_pos.r >= 0 && finger_pos.r < N && finger_pos.c >= 0 && finger_pos.c < N &&\n            has_takoyaki[finger_pos.r][finger_pos.c] == 1) {\n            \n            // Grab\n            if (total_turns < MAX_TURNS - 100) {\n                string grab_cmd(2 * V_prime, '.');\n                grab_cmd[V_prime + finger] = 'P';\n                cout << grab_cmd << \"\\n\";\n                total_turns++;\n                holding[finger] = 1;\n                has_takoyaki[finger_pos.r][finger_pos.c] = 0;\n            }\n        }\n        \n        if (holding[finger] == 0) continue; // Failed to pick up\n        \n        // Now move to drop position\n        target_dir = -1;\n        for (int d = 0; d < 4; ++d) {\n            Point fp = getFingerPos(cur_r, cur_c, d, 1);\n            if (fp.r == drop_pos.r && fp.c == drop_pos.c) {\n                target_dir = d;\n                break;\n            }\n        }\n        \n        if (target_dir == -1) {\n            int best_nr = -1, best_nc = -1;\n            int min_move_dist = 1e9;\n            \n            for(int d = 0; d < 4; ++d) {\n                int nr = drop_pos.r - dr[d];\n                int nc = drop_pos.c - dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int d_move = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (d_move < min_move_dist) {\n                        min_move_dist = d_move;\n                        best_nr = nr;\n                        best_nc = nc;\n                        target_dir = d;\n                    }\n                }\n            }\n            \n            if (best_nr == -1) {\n                holding[finger] = 0;\n                continue;\n            }\n            \n            while ((cur_r != best_nr || cur_c != best_nc) && total_turns < MAX_TURNS - 100) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                cout << cmd << \"\\n\";\n                total_turns++;\n            }\n        }\n        \n        // Rotate finger to drop direction\n        while (finger_dir[finger] != target_dir && total_turns < MAX_TURNS - 100) {\n            string rot_cmd(2 * V_prime, '.');\n            int diff = (target_dir - finger_dir[finger] + 4) % 4;\n            if (diff == 1) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            } else if (diff == 3) {\n                rot_cmd[finger] = 'R';\n                finger_dir[finger] = (finger_dir[finger] + 3) % 4;\n            } else if (diff == 2) {\n                rot_cmd[finger] = 'L';\n                finger_dir[finger] = (finger_dir[finger] + 1) % 4;\n            }\n            cout << rot_cmd << \"\\n\";\n            total_turns++;\n        }\n        \n        // Drop\n        if (holding[finger] == 1 && total_turns < MAX_TURNS - 100) {\n            string drop_cmd(2 * V_prime, '.');\n            drop_cmd[V_prime + finger] = 'P';\n            cout << drop_cmd << \"\\n\";\n            total_turns++;\n            holding[finger] = 0;\n            has_takoyaki[drop_pos.r][drop_pos.c] = 1;\n            takoyaki_moved++;\n        }\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <map>\n#include <chrono>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n};\n\nstruct Fish {\n    int x, y;\n    int type;\n};\n\nint N;\nvector<Fish> fish;\n\nint G_SIZE;\nint CELL_SIZE;\nvector<vector<int>> grid_score;\nvector<vector<bool>> selected;\nvector<vector<vector<int>>> grid_fish;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\n\nauto start_time = chrono::steady_clock::now();\nconst int TIME_LIMIT_MS = 1900;\n\nbool time_ok() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration_cast<chrono::milliseconds>(now - start_time).count() < TIME_LIMIT_MS;\n}\n\nvoid read_input() {\n    cin >> N;\n    fish.resize(2 * N);\n    for (int i = 0; i < 2 * N; ++i) {\n        cin >> fish[i].x >> fish[i].y;\n        fish[i].type = (i < N) ? 0 : 1;\n    }\n}\n\nvoid build_grid(int G) {\n    G_SIZE = G;\n    CELL_SIZE = 100000 / G;\n    grid_score.assign(G, vector<int>(G, 0));\n    selected.assign(G, vector<bool>(G, false));\n    grid_fish.assign(G, vector<vector<int>>(G));\n\n    for (int i = 0; i < 2 * N; ++i) {\n        int gx = min(fish[i].x / CELL_SIZE, G - 1);\n        int gy = min(fish[i].y / CELL_SIZE, G - 1);\n        grid_fish[gx][gy].push_back(i);\n        if (fish[i].type == 0) grid_score[gx][gy]++;\n        else grid_score[gx][gy]--;\n    }\n}\n\nvoid fill_holes() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    queue<pair<int, int>> q;\n\n    for (int i = 0; i < G_SIZE; ++i) {\n        if (!selected[i][0]) { q.push({i, 0}); visited[i][0] = true; }\n        if (!selected[i][G_SIZE - 1]) { q.push({i, G_SIZE - 1}); visited[i][G_SIZE - 1] = true; }\n        if (!selected[0][i]) { q.push({0, i}); visited[0][i] = true; }\n        if (!selected[G_SIZE - 1][i]) { q.push({G_SIZE - 1, i}); visited[G_SIZE - 1][i] = true; }\n    }\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                if (!visited[nx][ny] && !selected[nx][ny]) {\n                    visited[nx][ny] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (!selected[i][j] && !visited[i][j]) {\n                selected[i][j] = true;\n            }\n        }\n    }\n}\n\nvector<vector<pair<int, int>>> get_components() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    vector<vector<pair<int, int>>> components;\n    \n    for (int i = 0; i < G_SIZE && time_ok(); ++i) {\n        for (int j = 0; j < G_SIZE && time_ok(); ++j) {\n            if (selected[i][j] && !visited[i][j]) {\n                vector<pair<int, int>> comp;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                comp.push_back({i, j});\n                \n                while(!q.empty() && time_ok()){\n                    auto [cx, cy] = q.front(); q.pop();\n                    for(int d=0; d<4; ++d){\n                        int nx = cx + dx[d];\n                        int ny = cy + dy[d];\n                        if(nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE){\n                            if(!visited[nx][ny] && selected[nx][ny]){\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                                comp.push_back({nx, ny});\n                            }\n                        }\n                    }\n                }\n                components.push_back(comp);\n            }\n        }\n    }\n    return components;\n}\n\nvoid ensure_connected_topk(int k) {\n    auto components = get_components();\n    if (components.empty()) return;\n    \n    vector<pair<long long, size_t>> comp_scores;\n    for (size_t i = 0; i < components.size(); ++i) {\n        long long s = 0;\n        for (auto [x, y] : components[i]) s += grid_score[x][y];\n        comp_scores.push_back({s, i});\n    }\n    \n    sort(comp_scores.rbegin(), comp_scores.rend());\n    \n    size_t best_idx = comp_scores[0].second;\n    \n    selected.assign(G_SIZE, vector<bool>(G_SIZE, false));\n    for (auto [x, y] : components[best_idx]) {\n        selected[x][y] = true;\n    }\n}\n\nvoid select_positive_cells(int expand_threshold) {\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (grid_score[i][j] > 0) {\n                selected[i][j] = true;\n            }\n        }\n    }\n    \n    for (int iter = 0; iter < 2 && time_ok(); ++iter) {\n        vector<vector<bool>> to_add(G_SIZE, vector<bool>(G_SIZE, false));\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (selected[i][j]) {\n                    for (int d = 0; d < 4; ++d) {\n                        int ni = i + dx[d];\n                        int nj = j + dy[d];\n                        if (ni >= 0 && ni < G_SIZE && nj >= 0 && nj < G_SIZE) {\n                            if (!selected[ni][nj] && grid_score[ni][nj] >= expand_threshold) {\n                                to_add[ni][nj] = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        bool changed = false;\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (to_add[i][j]) {\n                    selected[i][j] = true;\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n    }\n    \n    fill_holes();\n    ensure_connected_topk(1);\n}\n\nvector<Point> extract_polygon() {\n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    \n    auto add_edge = [&](pair<int, int> p1, pair<int, int> p2) {\n        adj[p1].push_back(p2);\n        adj[p2].push_back(p1);\n    };\n    \n    for (int i = 0; i <= G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            bool left = (i > 0 && selected[i-1][j]);\n            bool right = (i < G_SIZE && selected[i][j]);\n            if (left != right) {\n                int x = i * CELL_SIZE;\n                int y1 = j * CELL_SIZE;\n                int y2 = (j + 1) * CELL_SIZE;\n                add_edge({x, y1}, {x, y2});\n            }\n        }\n    }\n    \n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j <= G_SIZE; ++j) {\n            bool down = (j > 0 && selected[i][j-1]);\n            bool up = (j < G_SIZE && selected[i][j]);\n            if (down != up) {\n                int y = j * CELL_SIZE;\n                int x1 = i * CELL_SIZE;\n                int x2 = (i + 1) * CELL_SIZE;\n                add_edge({x1, y}, {x2, y});\n            }\n        }\n    }\n    \n    if (adj.empty()) return {};\n    \n    pair<int, int> start = {200000, 200000};\n    for (auto& kv : adj) {\n        if (kv.first.second < start.second || (kv.first.second == start.second && kv.first.first < start.first)) {\n            start = kv.first;\n        }\n    }\n    \n    vector<Point> poly;\n    pair<int, int> curr = start;\n    pair<int, int> prev = {-1000000, start.second};\n    \n    while (true) {\n        poly.push_back({curr.first, curr.second});\n        \n        auto& neighbors = adj[curr];\n        if (neighbors.size() != 2) return {};\n        \n        pair<int, int> next = (neighbors[0] == prev) ? neighbors[1] : neighbors[0];\n        \n        if (next == start) break;\n        \n        prev = curr;\n        curr = next;\n        \n        if (poly.size() > 2000) return {};\n    }\n    \n    if (poly.size() <= 4) return poly;\n    \n    vector<Point> simplified;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        Point p3 = poly[(i + 2) % poly.size()];\n        \n        bool collinear = (p1.x == p2.x && p2.x == p3.x) || (p1.y == p2.y && p2.y == p3.y);\n        \n        if (!collinear || i == 0) {\n            simplified.push_back(p2);\n        }\n    }\n    \n    if (simplified.size() < 4) return poly;\n    return simplified;\n}\n\nlong long grid_score_estimate() {\n    long long total = 0;\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (selected[i][j]) {\n                total += grid_score[i][j];\n            }\n        }\n    }\n    return total;\n}\n\nbool is_inside(const vector<Point>& poly, int px, int py) {\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x == p2.x) {\n            if (px == p1.x && py >= min(p1.y, p2.y) && py <= max(p1.y, p2.y)) return true;\n        } else {\n            if (py == p1.y && px >= min(p1.x, p2.x) && px <= max(p1.x, p2.x)) return true;\n        }\n    }\n    \n    bool inside = false;\n    for (size_t i = 0, j = poly.size() - 1; i < poly.size(); j = i++) {\n        if ((poly[i].y > py) != (poly[j].y > py)) {\n            long long val = (long long)(poly[j].x - poly[i].x) * (long long)(py - poly[i].y);\n            long long denom = (long long)(poly[j].y - poly[i].y);\n            long long rhs = (long long)poly[i].x * denom + val;\n            if (denom > 0) {\n                if ((long long)px * denom < rhs) inside = !inside;\n            } else {\n                if ((long long)px * denom > rhs) inside = !inside;\n            }\n        }\n    }\n    return inside;\n}\n\nlong long calculate_score(const vector<Point>& poly) {\n    long long a = 0, b = 0;\n    for (int i = 0; i < G_SIZE && time_ok(); ++i) {\n        for (int j = 0; j < G_SIZE && time_ok(); ++j) {\n            if (grid_fish[i][j].empty()) continue;\n            \n            int cx = i * CELL_SIZE + CELL_SIZE / 2;\n            int cy = j * CELL_SIZE + CELL_SIZE / 2;\n            \n            if (is_inside(poly, cx, cy)) {\n                for (int fidx : grid_fish[i][j]) {\n                    if (is_inside(poly, fish[fidx].x, fish[fidx].y)) {\n                        if (fish[fidx].type == 0) a++;\n                        else b++;\n                    }\n                }\n            }\n        }\n    }\n    return a - b;\n}\n\nvector<Point> make_small_rectangle(int gx, int gy, int size) {\n    int x1 = max(0, gx * CELL_SIZE);\n    int y1 = max(0, gy * CELL_SIZE);\n    int x2 = min(100000, (gx + size) * CELL_SIZE);\n    int y2 = min(100000, (gy + size) * CELL_SIZE);\n    \n    if (x2 <= x1 || y2 <= y1) return {};\n    \n    return {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    read_input();\n    \n    vector<Point> best_poly;\n    long long best_score = -1e18;\n    long long best_estimate = -1e18;\n    \n    // Extended grid sizes including very fine ones\n    vector<int> grids = {20, 30, 40, 50, 60, 80, 100, 150, 200, 250};\n    vector<int> thresholds = {-2, -1, 0};\n    \n    for (int G : grids) {\n        if (!time_ok()) break;\n        \n        build_grid(G);\n        \n        // Try different thresholds\n        for (int thresh : thresholds) {\n            if (!time_ok()) break;\n            \n            select_positive_cells(thresh);\n            \n            vector<Point> poly = extract_polygon();\n            if (poly.empty() || poly.size() < 4 || poly.size() > 1000) continue;\n            \n            long long perim = 0;\n            for (size_t i = 0; i < poly.size(); ++i) {\n                Point p1 = poly[i];\n                Point p2 = poly[(i + 1) % poly.size()];\n                perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n            }\n            if (perim > 400000) continue;\n            \n            long long estimate = grid_score_estimate();\n            \n            if (estimate > best_estimate - 100) {\n                long long score = calculate_score(poly);\n                if (score > best_score) {\n                    best_score = score;\n                    best_estimate = estimate;\n                    best_poly = poly;\n                }\n            }\n        }\n        \n        // Also try small rectangles around best cells for scattered distributions\n        if (G >= 100 && time_ok()) {\n            vector<pair<int, pair<int, int>>> cell_scores;\n            for (int i = 0; i < G_SIZE; ++i) {\n                for (int j = 0; j < G_SIZE; ++j) {\n                    if (grid_score[i][j] > 0) {\n                        cell_scores.push_back({grid_score[i][j], {i, j}});\n                    }\n                }\n            }\n            sort(cell_scores.rbegin(), cell_scores.rend());\n            \n            for (int k = 0; k < min(10, (int)cell_scores.size()) && time_ok(); ++k) {\n                auto [score, pos] = cell_scores[k];\n                auto [gi, gj] = pos;\n                \n                for (int sz = 1; sz <= 3; ++sz) {\n                    vector<Point> rect = make_small_rectangle(gi, gj, sz);\n                    if (rect.size() < 4) continue;\n                    \n                    long long perim = 0;\n                    for (size_t i = 0; i < rect.size(); ++i) {\n                        Point p1 = rect[i];\n                        Point p2 = rect[(i + 1) % rect.size()];\n                        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n                    }\n                    if (perim > 400000) continue;\n                    \n                    long long rect_score = calculate_score(rect);\n                    if (rect_score > best_score) {\n                        best_score = rect_score;\n                        best_poly = rect;\n                    }\n                }\n            }\n        }\n    }\n    \n    if (best_poly.empty() || best_poly.size() < 4) {\n        build_grid(100);\n        int best_i = 0, best_j = 0;\n        int best_cell_score = -1e9;\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (grid_score[i][j] > best_cell_score) {\n                    best_cell_score = grid_score[i][j];\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        selected.assign(G_SIZE, vector<bool>(G_SIZE, false));\n        selected[best_i][best_j] = true;\n        fill_holes();\n        best_poly = extract_polygon();\n        if (best_poly.size() < 4) {\n            best_poly = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};\n        }\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n};\n\nstruct Placement {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Solution {\n    vector<Placement> placements;\n    int score;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    vector<Rectangle> rects(N);\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n    }\n    \n    mt19937 rng(42);\n    \n    int best_score = 2000000000;\n    vector<Placement> best_placements;\n    \n    // Track top solutions for crossover\n    vector<Solution> top_solutions;\n    const int TOP_K = 10;\n    \n    // Track successful patterns per rectangle\n    vector<int> rot_wins(N, 0);  // Positive = rot 0 wins, Negative = rot 1 wins\n    vector<int> dir_wins(N, 0);  // Positive = 'U' wins, Negative = 'L' wins\n    \n    // Calculate rectangle properties\n    vector<int> area(N);\n    vector<double> aspect(N);\n    int total_area = 0;\n    for (int i = 0; i < N; i++) {\n        area[i] = rects[i].w_obs * rects[i].h_obs;\n        aspect[i] = (double)max(rects[i].w_obs, rects[i].h_obs) / \n                    min(rects[i].w_obs, rects[i].h_obs);\n        total_area += area[i];\n    }\n    \n    // Sort rectangles by area for analysis\n    vector<int> sorted_idx(N);\n    iota(sorted_idx.begin(), sorted_idx.end(), 0);\n    sort(sorted_idx.begin(), sorted_idx.end(), [&](int a, int b) {\n        return area[a] > area[b];\n    });\n    \n    for (int turn = 0; turn < T; turn++) {\n        vector<Placement> placements;\n        placements.reserve(N);\n        \n        double progress = (double)turn / T;\n        double temp = 1.0 - progress;\n        \n        // Strategy selection based on turn and randomness\n        int strategy;\n        if (turn < T / 8) {\n            // Early: maximum diversity\n            strategy = turn % 25;\n        } else if (turn < T / 3) {\n            // Early-mid: mix exploration and exploitation\n            if (rng() % 4 == 0 && !top_solutions.empty()) {\n                strategy = 100 + (rng() % min((int)top_solutions.size(), 3));\n            } else {\n                strategy = 25 + (turn % 15);\n            }\n        } else if (turn < T * 2 / 3) {\n            // Mid-late: more exploitation\n            if (rng() % 3 == 0 && !top_solutions.empty()) {\n                strategy = 100 + (rng() % min((int)top_solutions.size(), 5));\n            } else {\n                strategy = 40 + (turn % 10);\n            }\n        } else {\n            // Late: heavy exploitation with occasional exploration\n            if (rng() % 5 != 0 && !top_solutions.empty()) {\n                strategy = 100 + (rng() % min((int)top_solutions.size(), 5));\n            } else {\n                strategy = 50 + (turn % 8);\n            }\n        }\n        \n        // Generate placement based on strategy\n        if (strategy < 25) {\n            // Diverse base strategies\n            if (strategy == 0) {\n                // All U, no rotation\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, 'U', -1});\n                }\n            } else if (strategy == 1) {\n                // All U, rotate tall to wide\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    placements.push_back({i, rot, 'U', -1});\n                }\n            } else if (strategy == 2) {\n                // All U, rotate wide to tall\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                    placements.push_back({i, rot, 'U', -1});\n                }\n            } else if (strategy == 3) {\n                // All L, no rotation\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, 'L', -1});\n                }\n            } else if (strategy == 4) {\n                // All L, rotate tall to wide\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    placements.push_back({i, rot, 'L', -1});\n                }\n            } else if (strategy == 5) {\n                // Alternating U/L\n                for (int i = 0; i < N; i++) {\n                    char dir = (i % 2 == 0) ? 'U' : 'L';\n                    placements.push_back({i, 0, dir, -1});\n                }\n            } else if (strategy >= 6 && strategy <= 10) {\n                // Shelf packing with different sizes\n                int shelf = 2 + (strategy - 6) * 2;\n                for (int i = 0; i < N; i++) {\n                    int rot = 0;\n                    char dir = 'U';\n                    int ref = -1;\n                    if (i > 0 && i % shelf == 0) {\n                        dir = 'L';\n                        ref = i - 1;\n                    } else if (i > 0) {\n                        ref = i - 1;\n                    }\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy >= 11 && strategy <= 15) {\n                // Shelf packing with rotation optimization\n                int shelf = 3 + (strategy - 11) * 2;\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    char dir = 'U';\n                    int ref = -1;\n                    if (i > 0 && i % shelf == 0) {\n                        dir = 'L';\n                        ref = i - 1;\n                    } else if (i > 0) {\n                        ref = i - 1;\n                    }\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy >= 16 && strategy <= 20) {\n                // Variable shelf sizes\n                int base_shelf = 3 + (strategy - 16) * 2;\n                for (int i = 0; i < N; i++) {\n                    int shelf = base_shelf + (i / 10) % 3;\n                    int rot = (i % 2 == 0) ? 0 : 1;\n                    char dir = 'U';\n                    int ref = -1;\n                    if (i > 0 && i % shelf == 0) {\n                        dir = 'L';\n                        ref = i - 1;\n                    } else if (i > 0) {\n                        ref = i - 1;\n                    }\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy == 21) {\n                // Zigzag pattern\n                for (int i = 0; i < N; i++) {\n                    int row = i / 5;\n                    int rot = 0;\n                    char dir = 'U';\n                    int ref = -1;\n                    if (i > 0 && i % 5 == 0) {\n                        dir = (row % 2 == 0) ? 'L' : 'U';\n                        ref = i - 1;\n                    } else if (i > 0) {\n                        ref = i - 1;\n                    }\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy == 22) {\n                // Dense packing (small shelves)\n                for (int i = 0; i < N; i++) {\n                    int rot = 0;\n                    char dir = 'U';\n                    int ref = -1;\n                    if (i > 0 && i % 3 == 0) {\n                        dir = 'L';\n                        ref = i - 1;\n                    } else if (i > 0) {\n                        ref = i - 1;\n                    }\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else if (strategy == 23) {\n                // Sparse packing (large shelves)\n                for (int i = 0; i < N; i++) {\n                    int rot = 0;\n                    char dir = 'U';\n                    int ref = -1;\n                    if (i > 0 && i % 10 == 0) {\n                        dir = 'L';\n                        ref = i - 1;\n                    } else if (i > 0) {\n                        ref = i - 1;\n                    }\n                    placements.push_back({i, rot, dir, ref});\n                }\n            } else {\n                // Random with U bias\n                for (int i = 0; i < N; i++) {\n                    int rot = rng() % 2;\n                    char dir = (rng() % 5 < 4) ? 'U' : 'L';\n                    int ref = -1;\n                    if (i > 0 && rng() % 3 == 0) ref = i - 1;\n                    placements.push_back({i, rot, dir, ref});\n                }\n            }\n        } else if (strategy >= 25 && strategy < 40) {\n            // Intermediate strategies with varied parameters\n            int shelf = 2 + (strategy - 25) % 8;\n            int rot_mode = (strategy - 25) / 8;\n            \n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                if (rot_mode == 0) rot = 0;\n                else if (rot_mode == 1) rot = 1;\n                else if (rot_mode == 2) rot = i % 2;\n                else if (rot_mode == 3) rot = (i / 2) % 2;\n                else if (rot_mode == 4) rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                else if (rot_mode == 5) rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                else rot = rng() % 2;\n                \n                char dir = 'U';\n                int ref = -1;\n                if (i > 0 && i % shelf == 0) {\n                    dir = 'L';\n                    ref = i - 1;\n                } else if (i > 0) {\n                    ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy >= 40 && strategy < 50) {\n            // Advanced patterns\n            int pat = strategy - 40;\n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                char dir = 'U';\n                int ref = -1;\n                \n                if (pat == 0) {\n                    // Based on area ranking\n                    int rank = find(sorted_idx.begin(), sorted_idx.end(), i) - sorted_idx.begin();\n                    rot = (rank < N / 2) ? 0 : 1;\n                    if (i > 0 && i % 5 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 1) {\n                    // Based on aspect ratio\n                    rot = (aspect[i] > 1.5) ? 1 : 0;\n                    if (i > 0 && i % 4 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 2) {\n                    // Alternating shelf sizes\n                    int shelf = (i / 10) % 2 == 0 ? 4 : 6;\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 3) {\n                    // Gradient rotation\n                    rot = (i < N / 2) ? 0 : 1;\n                    if (i > 0 && i % 5 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 4) {\n                    // Mixed directions with references\n                    dir = (i % 4 == 0) ? 'L' : 'U';\n                    if (i > 0) ref = i - 1;\n                } else if (pat == 5) {\n                    // Dense with rotation\n                    rot = (i % 3 == 0) ? 1 : 0;\n                    if (i > 0 && i % 3 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 6) {\n                    // Pattern based on index mod\n                    rot = i % 3;\n                    if (rot >= 2) rot = 1;\n                    else rot = 0;\n                    if (i > 0 && i % 6 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 7) {\n                    // Alternating direction pattern\n                    dir = (i / 5) % 2 == 0 ? 'U' : 'L';\n                    if (i > 0 && i % 5 == 0 && dir == 'L') ref = i - 1;\n                    else if (i > 0) ref = i - 1;\n                } else if (pat == 8) {\n                    // Size-based grouping\n                    rot = (area[i] > total_area / N) ? 1 : 0;\n                    if (i > 0 && i % 5 == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else {\n                    // Random advanced\n                    int shelf = 4 + rng() % 4;\n                    rot = rng() % 2;\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy >= 100) {\n            // Mutate/crossover from top solutions\n            int sol_idx = strategy - 100;\n            if (sol_idx < (int)top_solutions.size() && !top_solutions.empty()) {\n                // Crossover between two solutions if available\n                if (top_solutions.size() >= 2 && rng() % 2 == 0) {\n                    int sol1 = rng() % min((int)top_solutions.size(), 3);\n                    int sol2 = (sol1 + 1 + rng() % min((int)top_solutions.size() - 1, 3)) % top_solutions.size();\n                    \n                    int crossover_point = rng() % N;\n                    for (int i = 0; i < N; i++) {\n                        if (i < crossover_point) {\n                            placements.push_back(top_solutions[sol1].placements[i]);\n                        } else {\n                            placements.push_back(top_solutions[sol2].placements[i]);\n                        }\n                    }\n                } else {\n                    placements = top_solutions[sol_idx].placements;\n                }\n                \n                // Mutate\n                int base_mut = max(1, N / 4);\n                int mutations = max(1, (int)(base_mut * temp));\n                \n                for (int m = 0; m < mutations; m++) {\n                    int idx = rng() % N;\n                    int change = rng() % 5;\n                    \n                    if (change == 0) {\n                        // Flip rotation\n                        placements[idx].r = 1 - placements[idx].r;\n                    } else if (change == 1) {\n                        // Flip direction\n                        placements[idx].d = (placements[idx].d == 'U') ? 'L' : 'U';\n                    } else if (change == 2 && idx > 0) {\n                        // Toggle reference\n                        placements[idx].b = (placements[idx].b == -1) ? idx - 1 : -1;\n                    } else if (change == 3) {\n                        // Use learned preference\n                        if (rot_wins[idx] > 0) placements[idx].r = 0;\n                        else if (rot_wins[idx] < 0) placements[idx].r = 1;\n                        else placements[idx].r = rng() % 2;\n                    } else {\n                        // Random change\n                        placements[idx].r = rng() % 2;\n                        placements[idx].d = (rng() % 3 < 2) ? 'U' : 'L';\n                    }\n                }\n            } else {\n                // Fallback\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, 'U', -1});\n                }\n            }\n        } else {\n            // Fallback random\n            for (int i = 0; i < N; i++) {\n                int rot = rng() % 2;\n                char dir = (rng() % 5 < 4) ? 'U' : 'L';\n                int ref = -1;\n                if (i > 0 && rng() % 4 == 0) ref = i - 1;\n                placements.push_back({i, rot, dir, ref});\n            }\n        }\n        \n        // Output\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read result\n        int W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        int score = W_prime + H_prime;\n        \n        // Update best\n        if (score < best_score) {\n            best_score = score;\n            best_placements = placements;\n        }\n        \n        // Update top-K solutions\n        Solution sol{placements, score};\n        top_solutions.push_back(sol);\n        sort(top_solutions.begin(), top_solutions.end(), \n             [](const Solution& a, const Solution& b) { return a.score < b.score; });\n        if ((int)top_solutions.size() > TOP_K) {\n            top_solutions.resize(TOP_K);\n        }\n        \n        // Update learned preferences\n        if (score < best_score + best_score / 10) {  // Only learn from good solutions\n            for (int i = 0; i < N; i++) {\n                if (placements[i].r == 0) rot_wins[i]++;\n                else rot_wins[i]--;\n                if (placements[i].d == 'U') dir_wins[i]++;\n                else dir_wins[i]--;\n            }\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n\nusing namespace std;\n\n// Global variables\nint N, M, H;\nvector<int> A;\nvector<vector<int>> adj;\nvector<int> L;\nvector<int> support_count;\nint violations = 0;\nlong long current_score = 0;\n\n// Check if v is supported\nbool is_supported(int v) {\n    if (L[v] == 0) return true;\n    return support_count[v] > 0;\n}\n\n// Count violations\nint count_violations() {\n    int cnt = 0;\n    for (int v = 0; v < N; ++v) {\n        if (!is_supported(v)) cnt++;\n    }\n    return cnt;\n}\n\n// Calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        score += (long long)(L[v] + 1) * A[v];\n    }\n    return score;\n}\n\n// Initialize with BFS from selected roots\nvoid initialize_bfs(mt19937& rng, double root_fraction = 0.1) {\n    L.assign(N, -1);\n    support_count.assign(N, 0);\n    \n    // Select roots based on A_v and degree with some randomness\n    vector<pair<double, int>> candidates;\n    for (int v = 0; v < N; ++v) {\n        double score = (double)A[v] * adj[v].size();\n        score *= (0.5 + uniform_real_distribution<double>(0, 1)(rng));\n        candidates.push_back({score, v});\n    }\n    sort(candidates.rbegin(), candidates.rend());\n    \n    int num_roots = max(1, (int)(N * root_fraction));\n    vector<int> roots;\n    for (int i = 0; i < num_roots && i < (int)candidates.size(); ++i) {\n        roots.push_back(candidates[i].second);\n    }\n    \n    // BFS from roots\n    queue<int> q;\n    for (int r : roots) {\n        L[r] = 0;\n        q.push(r);\n    }\n    \n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        \n        // Shuffle neighbors for diversity\n        vector<int> neighbors = adj[v];\n        shuffle(neighbors.begin(), neighbors.end(), rng);\n        \n        for (int u : neighbors) {\n            if (L[u] == -1 && L[v] < H) {\n                L[u] = L[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n    \n    // Handle unvisited vertices\n    for (int v = 0; v < N; ++v) {\n        if (L[v] == -1) L[v] = 0;\n    }\n    \n    // Calculate support counts\n    for (int v = 0; v < N; ++v) {\n        if (L[v] > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == L[v] - 1) {\n                    support_count[v]++;\n                }\n            }\n        }\n    }\n    \n    violations = count_violations();\n    current_score = calculate_score();\n}\n\n// Fix violations by reducing levels\nvoid fix_violations(mt19937& rng) {\n    int max_iter = N * 20;\n    for (int iter = 0; iter < max_iter && violations > 0; ++iter) {\n        vector<int> violated;\n        for (int v = 0; v < N; ++v) {\n            if (!is_supported(v)) {\n                violated.push_back(v);\n            }\n        }\n        if (violated.empty()) break;\n        \n        int v = violated[uniform_int_distribution<int>(0, violated.size() - 1)(rng)];\n        \n        if (L[v] > 0) {\n            int old_L = L[v];\n            int new_L = L[v] - 1;\n            \n            // Update neighbor support counts\n            for (int u : adj[v]) {\n                if (L[u] == old_L + 1) {\n                    support_count[u]--;\n                }\n                if (L[u] == new_L + 1) {\n                    support_count[u]++;\n                }\n            }\n            \n            // Update v's support\n            support_count[v] = 0;\n            if (new_L > 0) {\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) support_count[v]++;\n                }\n            }\n            \n            L[v] = new_L;\n            current_score -= A[v];\n        }\n    }\n    \n    violations = count_violations();\n}\n\n// Greedy improvement: push vertices higher\nvoid greedy_improve(mt19937& rng) {\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    \n    bool improved = true;\n    int max_passes = 20;\n    for (int pass = 0; pass < max_passes && improved; ++pass) {\n        improved = false;\n        \n        // Sort by A_v descending\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return A[a] > A[b];\n        });\n        \n        for (int v : order) {\n            if (L[v] < H) {\n                int new_L = L[v] + 1;\n                \n                // Check if we can support this level\n                int new_support = 0;\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) new_support++;\n                }\n                \n                if (new_support > 0) {\n                    // Check impact on neighbors at level new_L + 1\n                    bool can_move = true;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L + 1 && support_count[u] == 1) {\n                            can_move = false;\n                            break;\n                        }\n                    }\n                    \n                    if (can_move) {\n                        int old_L = L[v];\n                        \n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                support_count[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                support_count[u]++;\n                            }\n                        }\n                        \n                        support_count[v] = new_support;\n                        L[v] = new_L;\n                        current_score += A[v];\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Simulated Annealing with adaptive temperature\nvoid simulated_annealing(mt19937& rng, double time_limit) {\n    auto start_time = chrono::steady_clock::now();\n    \n    const long long PENALTY = 1000000000LL;\n    double temp = 100000.0;\n    double initial_temp = 100000.0;\n    int accepted = 0;\n    int total = 0;\n    \n    long long best_valid_score = (violations == 0) ? current_score : -1;\n    vector<int> best_L = (violations == 0) ? L : vector<int>();\n    vector<int> best_support = (violations == 0) ? support_count : vector<int>();\n    \n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = time_limit - elapsed;\n        \n        if (remaining < 0.03) break;\n        \n        // Adaptive cooling based on acceptance rate and time\n        double progress = elapsed / time_limit;\n        if (total > 100) {\n            double acceptance_rate = (double)accepted / total;\n            if (acceptance_rate > 0.5) {\n                temp *= 0.9998;  // Cool faster if accepting too much\n            } else if (acceptance_rate < 0.1) {\n                temp *= 1.0002;  // Warm up if accepting too little\n            } else {\n                temp *= 0.9999;\n            }\n        } else {\n            temp *= 0.9999;\n        }\n        \n        if (temp < 1.0) temp = 1.0;\n        if (temp > initial_temp) temp = initial_temp;\n        \n        // Select vertex with bias towards high A_v\n        int v;\n        {\n            vector<double> weights(N);\n            double sum_w = 0;\n            for (int i = 0; i < N; ++i) {\n                weights[i] = A[i] + 1;\n                sum_w += weights[i];\n            }\n            double r = uniform_real_distribution<double>(0, sum_w)(rng);\n            double cum = 0;\n            v = N - 1;\n            for (int i = 0; i < N; ++i) {\n                cum += weights[i];\n                if (r <= cum) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n        \n        // Pick delta (bias towards +1)\n        int delta = 1;\n        double up_prob = 0.75;\n        if (L[v] >= H) up_prob = 0.0;\n        if (uniform_real_distribution<double>(0, 1)(rng) > up_prob) {\n            delta = -1;\n        }\n        \n        int old_L = L[v];\n        int new_L = old_L + delta;\n        \n        if (new_L < 0 || new_L > H) {\n            iterations++;\n            total++;\n            continue;\n        }\n        if (new_L == old_L) {\n            iterations++;\n            total++;\n            continue;\n        }\n        \n        // Calculate delta_violations\n        int delta_violations = 0;\n        \n        bool v_supported_old = is_supported(v);\n        \n        int new_support_count_v = 0;\n        if (new_L > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == new_L - 1) {\n                    new_support_count_v++;\n                }\n            }\n        }\n        bool v_supported_new = (new_L == 0) || (new_support_count_v > 0);\n        \n        if (v_supported_old && !v_supported_new) delta_violations++;\n        if (!v_supported_old && v_supported_new) delta_violations--;\n        \n        vector<pair<int, int>> neighbor_changes;\n        \n        for (int u : adj[v]) {\n            int old_contrib = (L[u] == old_L + 1) ? 1 : 0;\n            int new_contrib = (L[u] == new_L + 1) ? 1 : 0;\n            int delta_sc = new_contrib - old_contrib;\n            \n            if (delta_sc != 0) {\n                bool u_supported_old = (L[u] == 0) || (support_count[u] > 0);\n                int predicted_sc = support_count[u] + delta_sc;\n                bool u_supported_new = (L[u] == 0) || (predicted_sc > 0);\n                \n                int v_delta = 0;\n                if (u_supported_old && !u_supported_new) v_delta = 1;\n                if (!u_supported_old && u_supported_new) v_delta = -1;\n                \n                if (v_delta != 0) {\n                    delta_violations += v_delta;\n                }\n                neighbor_changes.push_back({u, delta_sc});\n            }\n        }\n        \n        long long delta_score = (long long)(new_L - old_L) * A[v];\n        long long delta_cost = (long long)delta_violations * PENALTY - delta_score;\n        \n        bool accept = false;\n        if (delta_cost < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-(double)delta_cost / temp);\n            if ((double)uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            L[v] = new_L;\n            support_count[v] = new_support_count_v;\n            current_score += delta_score;\n            violations += delta_violations;\n            \n            for (auto& nc : neighbor_changes) {\n                support_count[nc.first] += nc.second;\n            }\n            \n            accepted++;\n            \n            if (violations == 0) {\n                if (current_score > best_valid_score) {\n                    best_valid_score = current_score;\n                    best_L = L;\n                    best_support = support_count;\n                }\n            }\n        }\n        \n        total++;\n        iterations++;\n        \n        if (iterations % 5000 == 0) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed >= time_limit) break;\n        }\n    }\n    \n    if (violations == 0 && current_score > best_valid_score) {\n        best_valid_score = current_score;\n        best_L = L;\n        best_support = support_count;\n    }\n    \n    if (!best_L.empty()) {\n        L = best_L;\n        support_count = best_support;\n        violations = 0;\n        current_score = best_valid_score;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> H)) return 0;\n    \n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    \n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n    \n    long long best_score = -1;\n    vector<int> best_L_final(N, 0);\n    vector<int> best_support_final(N, 0);\n    \n    auto total_start = chrono::steady_clock::now();\n    double total_time_limit = 1.9;\n    \n    // More restarts with diverse initialization\n    int num_restarts = 6;\n    double time_per_restart = total_time_limit / num_restarts;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + restart * 1000000);\n        \n        // Vary root fraction for diversity\n        double root_fraction = 0.08 + 0.04 * (restart % 3);\n        \n        initialize_bfs(rng, root_fraction);\n        fix_violations(rng);\n        simulated_annealing(rng, time_per_restart * 0.85);\n        \n        if (violations == 0) {\n            greedy_improve(rng);\n        }\n        \n        if (violations == 0 && current_score > best_score) {\n            best_score = current_score;\n            best_L_final = L;\n            best_support_final = support_count;\n        }\n        \n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - total_start).count();\n        if (elapsed >= total_time_limit) break;\n    }\n    \n    // Final greedy pass on best solution\n    if (!best_L_final.empty()) {\n        L = best_L_final;\n        support_count = best_support_final;\n        violations = 0;\n        current_score = best_score;\n        \n        mt19937 final_rng(chrono::steady_clock::now().time_since_epoch().count());\n        greedy_improve(final_rng);\n        best_L_final = L;\n    }\n    \n    // Reconstruct parents\n    vector<int> P(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (best_L_final[v] > 0) {\n            int target = best_L_final[v] - 1;\n            for (int u : adj[v]) {\n                if (best_L_final[u] == target) {\n                    P[v] = u;\n                    break;\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << P[i];\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n#include <random>\n\nusing namespace std;\n\nconst char DIR_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char REVERSE_DIR[] = {'D', 'U', 'R', 'L'};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<string> grid(N);\n    vector<pair<int, int>> onis;\n    vector<vector<bool>> is_fuku(N, vector<bool>(N, false));\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] == 'x') {\n                onis.push_back({i, j});\n            } else if (grid[i][j] == 'o') {\n                is_fuku[i][j] = true;\n            }\n        }\n    }\n\n    int num_onis = onis.size();\n    vector<vector<int>> oni_id_map(N, vector<int>(N, -1));\n    for (int i = 0; i < num_onis; ++i) {\n        oni_id_map[onis[i].first][onis[i].second] = i;\n    }\n\n    int num_lines = 4 * N;\n    vector<vector<pair<int, int>>> line_onis(num_lines);\n    vector<int> max_k(num_lines, 0);\n\n    // Precompute which Oni each line can remove at each k\n    for (int j = 0; j < N; ++j) {\n        // Col j Up (0)\n        int limit = N;\n        for (int r = 0; r < N; ++r) {\n            if (is_fuku[r][j]) { limit = r; break; }\n        }\n        max_k[0 * N + j] = limit;\n        for (int r = 0; r < limit; ++r) {\n            if (oni_id_map[r][j] != -1) {\n                line_onis[0 * N + j].push_back({r + 1, oni_id_map[r][j]});\n            }\n        }\n\n        // Col j Down (1)\n        limit = N;\n        for (int r = N - 1; r >= 0; --r) {\n            if (is_fuku[r][j]) { limit = N - 1 - r; break; }\n        }\n        max_k[1 * N + j] = limit;\n        for (int r = N - 1; r >= N - limit; --r) {\n            if (oni_id_map[r][j] != -1) {\n                line_onis[1 * N + j].push_back({N - r, oni_id_map[r][j]});\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        // Row i Left (2)\n        int limit = N;\n        for (int c = 0; c < N; ++c) {\n            if (is_fuku[i][c]) { limit = c; break; }\n        }\n        max_k[2 * N + i] = limit;\n        for (int c = 0; c < limit; ++c) {\n            if (oni_id_map[i][c] != -1) {\n                line_onis[2 * N + i].push_back({c + 1, oni_id_map[i][c]});\n            }\n        }\n\n        // Row i Right (3)\n        limit = N;\n        for (int c = N - 1; c >= 0; --c) {\n            if (is_fuku[i][c]) { limit = N - 1 - c; break; }\n        }\n        max_k[3 * N + i] = limit;\n        for (int c = N - 1; c >= N - limit; --c) {\n            if (oni_id_map[i][c] != -1) {\n                line_onis[3 * N + i].push_back({N - c, oni_id_map[i][c]});\n            }\n        }\n    }\n\n    // Sort each line's onis by k\n    for (int l = 0; l < num_lines; ++l) {\n        sort(line_onis[l].begin(), line_onis[l].end());\n    }\n\n    // Count options per Oni\n    vector<int> oni_options(num_onis, 0);\n    for (int l = 0; l < num_lines; ++l) {\n        for (const auto& p : line_onis[l]) {\n            oni_options[p.second]++;\n        }\n    }\n\n    // Function to check coverage\n    auto check_coverage = [&](const vector<int>& k_vals) -> bool {\n        vector<bool> covered(num_onis, false);\n        for (int l = 0; l < num_lines; ++l) {\n            for (const auto& p : line_onis[l]) {\n                if (p.first <= k_vals[l]) {\n                    covered[p.second] = true;\n                }\n            }\n        }\n        for (int i = 0; i < num_onis; ++i) {\n            if (!covered[i]) return false;\n        }\n        return true;\n    };\n\n    // Calculate total cost\n    auto calc_cost = [&](const vector<int>& k_vals) -> int {\n        int cost = 0;\n        for (int l = 0; l < num_lines; ++l) {\n            cost += 2 * k_vals[l];\n        }\n        return cost;\n    };\n\n    // Greedy selection with difficulty weighting and randomization\n    auto run_greedy = [&](mt19937& rng, double weight_power) -> vector<int> {\n        vector<int> selected_k(num_lines, 0);\n        vector<bool> oni_removed(num_onis, false);\n        int removed_count = 0;\n\n        // Create weighted options\n        vector<double> oni_weights(num_onis);\n        for (int i = 0; i < num_onis; ++i) {\n            oni_weights[i] = pow(1.0 / oni_options[i], weight_power);\n        }\n\n        while (removed_count < num_onis) {\n            int best_line = -1;\n            int best_k = -1;\n            double best_score = -1e18;\n\n            // Randomize line order for tie-breaking\n            vector<int> line_order(num_lines);\n            for (int l = 0; l < num_lines; ++l) line_order[l] = l;\n            shuffle(line_order.begin(), line_order.end(), rng);\n\n            for (int li = 0; li < num_lines; ++li) {\n                int l = line_order[li];\n                for (int try_k = selected_k[l] + 1; try_k <= max_k[l]; ++try_k) {\n                    double weighted_gain = 0;\n                    for (const auto& p : line_onis[l]) {\n                        if (p.first <= try_k && p.first > selected_k[l] && !oni_removed[p.second]) {\n                            weighted_gain += oni_weights[p.second];\n                        }\n                    }\n                    \n                    if (weighted_gain > 0) {\n                        long long cost = 2LL * (try_k - selected_k[l]);\n                        double score = weighted_gain / cost + (rng() % 1000) * 1e-9;\n                        if (score > best_score) {\n                            best_score = score;\n                            best_line = l;\n                            best_k = try_k;\n                        }\n                    }\n                }\n            }\n\n            if (best_line == -1) break;\n\n            for (const auto& p : line_onis[best_line]) {\n                if (p.first <= best_k && !oni_removed[p.second]) {\n                    oni_removed[p.second] = true;\n                    removed_count++;\n                }\n            }\n            selected_k[best_line] = best_k;\n        }\n\n        return selected_k;\n    };\n\n    // Post-processing optimization\n    auto optimize = [&](vector<int>& selected_k) -> void {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            \n            // Try removing each operation entirely\n            for (int l = 0; l < num_lines; ++l) {\n                if (selected_k[l] == 0) continue;\n                \n                int original_k = selected_k[l];\n                selected_k[l] = 0;\n                \n                if (check_coverage(selected_k)) {\n                    improved = true;\n                } else {\n                    selected_k[l] = original_k;\n                }\n            }\n            \n            // Try reducing k values\n            for (int l = 0; l < num_lines; ++l) {\n                if (selected_k[l] == 0) continue;\n                \n                int original_k = selected_k[l];\n                \n                for (int try_k = selected_k[l] - 1; try_k >= 0; --try_k) {\n                    selected_k[l] = try_k;\n                    \n                    if (check_coverage(selected_k)) {\n                        improved = true;\n                        break;\n                    } else {\n                        selected_k[l] = original_k;\n                    }\n                }\n            }\n        }\n    };\n\n    // Local search\n    auto local_search = [&](vector<int>& selected_k, mt19937& rng) -> void {\n        int best_cost = calc_cost(selected_k);\n        \n        for (int iter = 0; iter < 1000; ++iter) {\n            int l1 = rng() % num_lines;\n            int l2 = rng() % num_lines;\n            \n            if (l1 == l2) continue;\n            \n            int orig_k1 = selected_k[l1];\n            int orig_k2 = selected_k[l2];\n            \n            bool found_better = false;\n            \n            for (int d1 = -3; d1 <= 3 && !found_better; ++d1) {\n                for (int d2 = -3; d2 <= 3 && !found_better; ++d2) {\n                    if (d1 == 0 && d2 == 0) continue;\n                    \n                    int new_k1 = max(0, min(max_k[l1], orig_k1 + d1));\n                    int new_k2 = max(0, min(max_k[l2], orig_k2 + d2));\n                    \n                    if (new_k1 == orig_k1 && new_k2 == orig_k2) continue;\n                    \n                    selected_k[l1] = new_k1;\n                    selected_k[l2] = new_k2;\n                    \n                    if (check_coverage(selected_k)) {\n                        int new_cost = calc_cost(selected_k);\n                        if (new_cost < best_cost) {\n                            best_cost = new_cost;\n                            found_better = true;\n                        }\n                    }\n                    \n                    if (!found_better) {\n                        selected_k[l1] = orig_k1;\n                        selected_k[l2] = orig_k2;\n                    }\n                }\n            }\n        }\n    };\n\n    // Run multiple greedy searches with different parameters\n    vector<int> best_k(num_lines, 0);\n    int best_cost = 1e9;\n\n    for (int seed = 0; seed < 5; ++seed) {\n        for (double wp = 0.5; wp <= 2.0; wp += 0.5) {\n            mt19937 rng(seed * 1000 + (int)(wp * 100));\n            \n            vector<int> selected_k = run_greedy(rng, wp);\n            optimize(selected_k);\n            local_search(selected_k, rng);\n            optimize(selected_k);\n            \n            int cost = calc_cost(selected_k);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_k = selected_k;\n            }\n        }\n    }\n\n    // Output moves\n    vector<pair<char, int>> moves;\n    moves.reserve(1600);\n    for (int l = 0; l < num_lines; ++l) {\n        if (best_k[l] > 0) {\n            int dir = l / N;\n            int idx = l % N;\n            char d = DIR_CHARS[dir];\n            char rd = REVERSE_DIR[dir];\n            for (int s = 0; s < best_k[l]; ++s) moves.push_back({d, idx});\n            for (int s = 0; s < best_k[l]; ++s) moves.push_back({rd, idx});\n        }\n    }\n\n    for (const auto& mv : moves) {\n        cout << mv.first << \" \" << mv.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nint N;\nlong long L;\nvector<int> T;\n\n// Function to simulate the process and calculate error\nlong long simulate(const vector<int>& A, const vector<int>& B, vector<int>& counts) {\n    fill(counts.begin(), counts.end(), 0);\n    int cur = 0;\n    // L weeks\n    for (int k = 0; k < L; ++k) {\n        counts[cur]++;\n        int t = counts[cur];\n        if (t % 2 != 0) {\n            cur = A[cur];\n        } else {\n            cur = B[cur];\n        }\n    }\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(counts[i] - T[i]);\n    }\n    return error;\n}\n\n// Check connectivity from node 0 to all nodes with T[i] > 0\nbool is_connected(const vector<int>& A, const vector<int>& B) {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    q.push(0);\n    visited[0] = true;\n    int count = 0;\n    while(!q.empty()){\n        int u = q.front();\n        q.pop();\n        if (T[u] > 0) count++;\n        \n        // Outgoing edges\n        int v1 = A[u];\n        if (!visited[v1]) {\n            visited[v1] = true;\n            q.push(v1);\n        }\n        int v2 = B[u];\n        if (!visited[v2]) {\n            visited[v2] = true;\n            q.push(v2);\n        }\n    }\n    // Check if all important nodes are visited\n    for(int i=0; i<N; ++i){\n        if(T[i] > 0 && !visited[i]) return false;\n    }\n    return true;\n}\n\nvoid fix_connectivity(vector<int>& A, vector<int>& B, vector<long long>& load) {\n    // Repeatedly ensure all T[i]>0 are reachable from 0\n    // We do this by finding an unreachable important node and adding an edge to it from a reachable node\n    // We try to minimize the disturbance to the load balance\n    \n    while (true) {\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        q.push(0);\n        reachable[0] = true;\n        while(!q.empty()){\n            int u = q.front();\n            q.pop();\n            if(!reachable[A[u]]) { reachable[A[u]] = true; q.push(A[u]); }\n            if(!reachable[B[u]]) { reachable[B[u]] = true; q.push(B[u]); }\n        }\n        \n        int target = -1;\n        for(int i=0; i<N; ++i){\n            if(T[i] > 0 && !reachable[i]){\n                target = i;\n                break;\n            }\n        }\n        \n        if(target == -1) break; // All important nodes reachable\n        \n        // Find best edge to redirect to target\n        // We look for a reachable node u, and change one of its outgoing edges to target\n        // We want to minimize increase in |load[dest] - 2*T[dest]|\n        \n        long long min_cost = -1;\n        int best_u = -1;\n        int best_edge = -1; // 0 for A, 1 for B\n        int old_dest = -1;\n        \n        for(int u=0; u<N; ++u){\n            if(!reachable[u]) continue;\n            // Try changing A[u]\n            {\n                int w = A[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 0;\n                    old_dest = w;\n                }\n            }\n            // Try changing B[u]\n            {\n                int w = B[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 1;\n                    old_dest = w;\n                }\n            }\n        }\n        \n        if(best_u != -1){\n            // Apply change\n            if(best_edge == 0){\n                load[old_dest] -= T[best_u];\n                A[best_u] = target;\n                load[target] += T[best_u];\n            } else {\n                load[old_dest] -= T[best_u];\n                B[best_u] = target;\n                load[target] += T[best_u];\n            }\n        } else {\n            // Should not happen if there is at least one reachable node (0 is reachable)\n            // Fallback: force 0 to point to target\n            int w = A[0];\n            load[w] -= T[0];\n            A[0] = target;\n            load[target] += T[0];\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    T.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution construction using flow balance heuristic\n    // We have 2N items, each (T[i], i). We want to assign them to buckets 0..N-1\n    // such that sum of values in bucket j is close to 2*T[j].\n    \n    vector<pair<int, int>> items;\n    items.reserve(2 * N);\n    for (int i = 0; i < N; ++i) {\n        items.push_back({T[i], i});\n        items.push_back({T[i], i});\n    }\n    \n    // Sort items descending by value\n    sort(items.begin(), items.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n        return a.first > b.first;\n    });\n    \n    vector<long long> load(N, 0);\n    vector<int> A(N), B(N);\n    vector<vector<int>> outgoing(N); // Store assigned destinations for each source\n    \n    for (const auto& item : items) {\n        int val = item.first;\n        int src = item.second;\n        \n        // Find best bucket\n        int best_j = -1;\n        long long min_diff = -1;\n        \n        // To speed up, we can just scan all N. N=100 is small.\n        for (int j = 0; j < N; ++j) {\n            long long diff = abs(load[j] + val - 2LL * T[j]);\n            if (best_j == -1 || diff < min_diff) {\n                min_diff = diff;\n                best_j = j;\n            }\n        }\n        \n        load[best_j] += val;\n        outgoing[src].push_back(best_j);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        A[i] = outgoing[i][0];\n        B[i] = outgoing[i][1];\n    }\n    \n    // Fix connectivity\n    fix_connectivity(A, B, load);\n    \n    // Evaluate initial score\n    vector<int> counts(N);\n    long long current_score = simulate(A, B, counts);\n    long long best_score = current_score;\n    vector<int> best_A = A;\n    vector<int> best_B = B;\n    \n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    \n    double temp = 1000.0;\n    double cooling_rate = 0.9999;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        // Generate neighbor\n        int i = uniform_int_distribution<>(0, N - 1)(rng);\n        int type = uniform_int_distribution<>(0, 1)(rng); // 0 for A, 1 for B\n        int old_val = (type == 0) ? A[i] : B[i];\n        int new_val = uniform_int_distribution<>(0, N - 1)(rng);\n        \n        if (old_val == new_val) continue;\n        \n        // Apply change\n        if (type == 0) A[i] = new_val;\n        else B[i] = new_val;\n        \n        long long new_score = simulate(A, B, counts);\n        \n        double delta = (double)new_score - (double)current_score;\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_A = A;\n                best_B = B;\n            }\n        } else {\n            // Revert\n            if (type == 0) A[i] = old_val;\n            else B[i] = old_val;\n        }\n        \n        temp *= cooling_rate;\n        iter++;\n    }\n    \n    // Output best solution\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n#include <atcoder/dsu>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct City {\n    int id;\n    long long cx, cy;\n    int h_index;\n};\n\n// Hilbert curve functions for 2D spatial locality\nvoid rot(int n, int *x, int *y, int rx, int ry) {\n    if (ry == 0) {\n        if (rx == 1) {\n            *x = n - 1 - *x;\n            *y = n - 1 - *y;\n        }\n        std::swap(*x, *y);\n    }\n}\n\nint xy2d(int n, int x, int y) {\n    int rx, ry, s, d = 0;\n    for (s = n / 2; s > 0; s /= 2) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        rot(s, &x, &y, rx, ry);\n    }\n    return d;\n}\n\nstruct Edge {\n    int u, v;\n    long long d2;\n    bool queried;\n    int query_count;\n};\n\nstruct Group {\n    int id;\n    vector<City> cities;\n    vector<pair<int, int>> queried_edges;\n    map<pair<int,int>, int> edge_query_count;\n};\n\nlong long dist2(const City& a, const City& b) {\n    long long dx = a.cx - b.cx;\n    long long dy = a.cy - b.cy;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> G[i];\n    }\n\n    vector<City> cities(N);\n    vector<City> city_by_id(N);\n    const int H_N = 16384;\n\n    for (int i = 0; i < N; ++i) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cities[i].id = i;\n        cities[i].cx = (0LL + lx + rx) / 2;\n        cities[i].cy = (0LL + ly + ry) / 2;\n        cities[i].h_index = xy2d(H_N, (int)cities[i].cx, (int)cities[i].cy);\n        city_by_id[i] = cities[i];\n    }\n\n    // Sort by Hilbert index for spatial locality\n    sort(cities.begin(), cities.end(), [](const City& a, const City& b) {\n        return a.h_index < b.h_index;\n    });\n\n    // Partition into groups\n    vector<Group> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].id = i;\n        groups[i].cities.reserve(G[i]);\n        for (int j = 0; j < G[i] && cur < N; ++j) {\n            groups[i].cities.push_back(cities[cur++]);\n        }\n    }\n\n    int queries_used = 0;\n\n    // Process groups: small groups first (can get exact MST with 1 query)\n    vector<int> group_order(M);\n    iota(group_order.begin(), group_order.end(), 0);\n    sort(group_order.begin(), group_order.end(), [&](int a, int b) {\n        int sa = groups[a].cities.size();\n        int sb = groups[b].cities.size();\n        // Small groups (<=L) first\n        if (sa <= L && sb > L) return true;\n        if (sa > L && sb <= L) return false;\n        // Then larger groups first (need more queries)\n        return sa > sb;\n    });\n\n    // First pass: query all small groups (size <= L)\n    for (int idx : group_order) {\n        if (queries_used >= Q) break;\n        \n        Group& g = groups[idx];\n        int S = g.cities.size();\n        \n        if (S <= 1 || S > L) continue;\n\n        // Sort cities in group by Hilbert index\n        sort(g.cities.begin(), g.cities.end(), [](const City& a, const City& b) {\n            return a.h_index < b.h_index;\n        });\n\n        vector<int> chunk_ids;\n        chunk_ids.reserve(S);\n        for (const auto& c : g.cities) {\n            chunk_ids.push_back(c.id);\n        }\n\n        cout << \"? \" << S;\n        for (int id : chunk_ids) cout << \" \" << id;\n        cout << \"\\n\";\n        cout.flush();\n\n        for (int i = 0; i < S - 1; ++i) {\n            int u, v;\n            cin >> u >> v;\n            if (u > v) swap(u, v);\n            g.queried_edges.push_back({u, v});\n            g.edge_query_count[{u, v}]++;\n        }\n        queries_used++;\n    }\n\n    // Second pass: distribute remaining queries to large groups\n    int remaining_queries = Q - queries_used;\n    \n    // Calculate queries needed for each large group\n    vector<pair<int, int>> large_group_queries;\n    for (int idx : group_order) {\n        int S = groups[idx].cities.size();\n        if (S <= L) continue;\n        \n        // Calculate queries needed for full coverage with overlap\n        int overlap = max(2, L / 4);\n        int step = L - overlap;\n        if (step < 1) step = 1;\n        int queries_needed = (S - 1 + step - 1) / step;\n        \n        large_group_queries.push_back({idx, queries_needed});\n    }\n    \n    // Allocate queries proportionally\n    int total_needed = 0;\n    for (auto& p : large_group_queries) {\n        total_needed += p.second;\n    }\n    \n    vector<int> queries_allocated(M, 0);\n    int allocated = 0;\n    \n    if (total_needed > 0 && remaining_queries > 0) {\n        for (auto& p : large_group_queries) {\n            if (allocated >= remaining_queries) break;\n            int idx = p.first;\n            int share = (p.second * remaining_queries) / total_needed;\n            if (share == 0 && remaining_queries - allocated > 0) share = 1;\n            queries_allocated[idx] = share;\n            allocated += share;\n        }\n    }\n    \n    // Distribute any remaining queries to largest groups\n    for (auto& p : large_group_queries) {\n        if (allocated >= remaining_queries) break;\n        queries_allocated[p.first]++;\n        allocated++;\n    }\n    \n    // Execute queries for large groups\n    for (int idx : group_order) {\n        Group& g = groups[idx];\n        int S = g.cities.size();\n        if (S <= L) continue;\n        \n        int num_queries = queries_allocated[idx];\n        if (num_queries <= 0 || queries_used >= Q) continue;\n        \n        // Sort cities in group by Hilbert index\n        sort(g.cities.begin(), g.cities.end(), [](const City& a, const City& b) {\n            return a.h_index < b.h_index;\n        });\n        \n        // Adaptive overlap based on L\n        int overlap = max(2, L / 4);\n        int step = L - overlap;\n        if (step < 1) step = 1;\n        \n        int queries_to_exec = min(num_queries, (S - 1 + step - 1) / step);\n        \n        for (int q = 0; q < queries_to_exec && queries_used < Q; ++q) {\n            int start = q * step;\n            if (start >= S) break;\n            \n            int end = start + L;\n            if (end > S) end = S;\n            \n            // Ensure at least 2 cities\n            if (end - start < 2) {\n                if (start > 0) {\n                    start = max(0, end - 2);\n                } else {\n                    break;\n                }\n            }\n            \n            if (end - start < 2) break;\n            \n            vector<int> chunk_ids;\n            chunk_ids.reserve(end - start);\n            for(int i = start; i < end; ++i) {\n                chunk_ids.push_back(g.cities[i].id);\n            }\n\n            cout << \"? \" << chunk_ids.size();\n            for (int id : chunk_ids) cout << \" \" << id;\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n\n            int num_ret = chunk_ids.size() - 1;\n            for (int i = 0; i < num_ret; ++i) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                g.queried_edges.push_back({u, v});\n                g.edge_query_count[{u, v}]++;\n            }\n            \n            if (end == S) break;\n        }\n    }\n\n    // Third pass: use any remaining queries on largest groups with offset\n    for (int idx : group_order) {\n        if (queries_used >= Q) break;\n        \n        Group& g = groups[idx];\n        int S = g.cities.size();\n        if (S <= L) continue;\n        \n        int overlap = max(2, L / 4);\n        int step = L - overlap;\n        if (step < 1) step = 1;\n        \n        // Try offset query\n        int start = step / 2;\n        if (start >= S - 1) continue;\n        \n        int end = min(S, start + L);\n        if (end - start < 2) continue;\n        \n        vector<int> chunk_ids;\n        for(int i = start; i < end; ++i) {\n            chunk_ids.push_back(g.cities[i].id);\n        }\n\n        cout << \"? \" << chunk_ids.size();\n        for (int id : chunk_ids) cout << \" \" << id;\n        cout << \"\\n\";\n        cout.flush();\n        queries_used++;\n\n        int num_ret = chunk_ids.size() - 1;\n        for (int i = 0; i < num_ret; ++i) {\n            int u, v;\n            cin >> u >> v;\n            if (u > v) swap(u, v);\n            g.queried_edges.push_back({u, v});\n            g.edge_query_count[{u, v}]++;\n        }\n    }\n\n    // Output final answer\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        const Group& g = groups[i];\n        int S = g.cities.size();\n        \n        // Output cities\n        for (int j = 0; j < S; ++j) {\n            if (j > 0) cout << \" \";\n            cout << g.cities[j].id;\n        }\n        cout << \"\\n\";\n\n        if (S <= 1) continue;\n\n        // Build edge pool - use complete graph within group\n        vector<Edge> pool;\n        set<pair<int,int>> q_set(g.queried_edges.begin(), g.queried_edges.end());\n\n        // Add queried edges with high priority\n        for (const auto& p : g.queried_edges) {\n            const City& c1 = city_by_id[p.first];\n            const City& c2 = city_by_id[p.second];\n            int count = 1;\n            auto it = g.edge_query_count.find(p);\n            if (it != g.edge_query_count.end()) {\n                count = it->second;\n            }\n            pool.push_back({p.first, p.second, dist2(c1, c2), true, count});\n        }\n\n        // Add all estimated edges (complete graph within group)\n        for (int j = 0; j < S; ++j) {\n            for (int k = j + 1; k < S; ++k) {\n                int u = g.cities[j].id;\n                int v = g.cities[k].id;\n                if (u > v) swap(u, v);\n                if (q_set.count({u, v})) continue;\n                \n                pool.push_back({u, v, dist2(g.cities[j], g.cities[k]), false, 0});\n            }\n        }\n\n        // Sort: queried first, then by query count, then by distance, then lexicographic\n        sort(pool.begin(), pool.end(), [](const Edge& a, const Edge& b) {\n            if (a.queried != b.queried) return a.queried > b.queried;\n            if (a.query_count != b.query_count) return a.query_count > b.query_count;\n            if (a.d2 != b.d2) return a.d2 < b.d2;\n            // Lexicographic tie-breaking (matching judge)\n            if (a.u != b.u) return a.u < b.u;\n            return a.v < b.v;\n        });\n\n        // Kruskal's algorithm\n        dsu group_dsu(N);\n        int count = 0;\n        for (const auto& e : pool) {\n            if (group_dsu.same(e.u, e.v)) continue;\n            group_dsu.merge(e.u, e.v);\n            cout << e.u << \" \" << e.v << \"\\n\";\n            count++;\n            if (count == S - 1) break;\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nstruct Action {\n    char type;\n    char dir;\n};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\nint N, M;\nbool has_block[20][20];\nint dist_map[20][20];\nPos parent_pos[20][20];\nAction parent_act[20][20];\n\nconst int INF = 1e9;\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// BFS to find shortest path from start to end\nint bfs(Pos start, Pos end, bool store_path) {\n    for(int i = 0; i < N; ++i) \n        for(int j = 0; j < N; ++j) \n            dist_map[i][j] = INF;\n    \n    queue<Pos> q;\n    dist_map[start.r][start.c] = 0;\n    q.push(start);\n    \n    while(!q.empty()) {\n        Pos curr = q.front();\n        q.pop();\n        \n        if (curr == end) return dist_map[curr.r][curr.c];\n        \n        int d = dist_map[curr.r][curr.c];\n        \n        // Try Move actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r + dr[i];\n            int nc = curr.c + dc[i];\n            if(is_valid(nr, nc) && !has_block[nr][nc]) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'M', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n        \n        // Try Slide actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r;\n            int nc = curr.c;\n            while(true) {\n                int nnr = nr + dr[i];\n                int nnc = nc + dc[i];\n                if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                    break;\n                }\n                nr = nnr;\n                nc = nnc;\n            }\n            if(nr != curr.r || nc != curr.c) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'S', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return INF;\n}\n\nvector<Action> get_path(Pos end) {\n    vector<Action> path;\n    Pos curr = end;\n    while(dist_map[curr.r][curr.c] != 0) {\n        path.push_back(parent_act[curr.r][curr.c]);\n        curr = parent_pos[curr.r][curr.c];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Simulate actions and update position and block state\nPos simulate_action(Pos curr, const Action& act, bool update_blocks = false) {\n    if(act.type == 'M') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r + dr[i];\n                int nc = curr.c + dc[i];\n                // Safety check - should never happen if BFS is correct\n                if(!is_valid(nr, nc) || has_block[nr][nc]) {\n                    cerr << \"ERROR: Invalid move at (\" << curr.r << \",\" << curr.c \n                         << \") direction \" << act.dir << endl;\n                    return curr;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'S') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r;\n                int nc = curr.c;\n                while(true) {\n                    int nnr = nr + dr[i];\n                    int nnc = nc + dc[i];\n                    if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                        break;\n                    }\n                    nr = nnr;\n                    nc = nnc;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'A') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int br = curr.r + dr[i];\n                int bc = curr.c + dc[i];\n                if(is_valid(br, bc)) {\n                    if(update_blocks) {\n                        has_block[br][bc] = !has_block[br][bc];\n                    }\n                }\n                return curr;\n            }\n        }\n    }\n    return curr;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    vector<Pos> points(M);\n    for(int i = 0; i < M; ++i) {\n        cin >> points[i].r >> points[i].c;\n    }\n    \n    // Initialize blocks\n    memset(has_block, 0, sizeof(has_block));\n    \n    Pos curr = points[0];\n    vector<Action> all_actions;\n    \n    for(int k = 0; k < M - 1; ++k) {\n        Pos target = points[k+1];\n        \n        // Get base path without adding blocks\n        int base_dist = bfs(curr, target, true);\n        vector<Action> base_path = get_path(target);\n        \n        int best_dist = base_dist;\n        vector<Action> best_path = base_path;\n        Pos best_S = {-1, -1};\n        Pos best_adj = {-1, -1};\n        int best_dir = -1;\n        \n        // Only try adding blocks if base path is long enough to justify it\n        if(base_dist > 3) {\n            // Candidate block positions around target\n            vector<Pos> candidates;\n            for(int i = 0; i < 4; ++i) {\n                int sr = target.r + dr[i];\n                int sc = target.c + dc[i];\n                if(is_valid(sr, sc) && !has_block[sr][sc] && !(sr == curr.r && sc == curr.c)) {\n                    candidates.push_back({sr, sc});\n                }\n            }\n            \n            for(const auto& S : candidates) {\n                // Try placing block from each adjacent cell\n                for(int i = 0; i < 4; ++i) {\n                    int ar = S.r + dr[i];\n                    int ac = S.c + dc[i];\n                    if(!is_valid(ar, ac) || has_block[ar][ac]) continue;\n                    if(ar == S.r && ac == S.c) continue;\n                    \n                    // Cost to reach adjacent cell\n                    int d1 = bfs(curr, {ar, ac}, false);\n                    if(d1 == INF || d1 > best_dist) continue;\n                    \n                    // Temporarily place block\n                    has_block[S.r][S.c] = true;\n                    \n                    // Cost to reach target from adjacent cell\n                    int d2 = bfs({ar, ac}, target, false);\n                    \n                    // Remove block\n                    has_block[S.r][S.c] = false;\n                    \n                    if(d2 == INF) continue;\n                    \n                    int total = d1 + 1 + d2;\n                    \n                    if(total < best_dist) {\n                        best_dist = total;\n                        best_S = S;\n                        best_adj = {ar, ac};\n                        best_dir = i;\n                    }\n                }\n            }\n        }\n        \n        // Execute the best plan\n        if(best_S.r != -1) {\n            // 1. Move to best_adj\n            bfs(curr, best_adj, true);\n            vector<Action> p1 = get_path(best_adj);\n            \n            // Validate path before adding\n            Pos temp = curr;\n            for(const auto& act : p1) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p1.begin(), p1.end());\n            curr = best_adj;\n            \n            // 2. Alter (Place block)\n            all_actions.push_back({'A', dir_char[best_dir]});\n            has_block[best_S.r][best_S.c] = true;\n            \n            // 3. Move to target\n            bfs(curr, target, true);\n            vector<Action> p2 = get_path(target);\n            \n            // Validate path before adding\n            temp = curr;\n            for(const auto& act : p2) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p2.begin(), p2.end());\n            curr = target;\n        } else {\n            // Execute base plan\n            // Validate path\n            Pos temp = curr;\n            for(const auto& act : base_path) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), base_path.begin(), base_path.end());\n            curr = target;\n        }\n    }\n    \n    // Final validation of all actions\n    Pos validate_pos = points[0];\n    for(const auto& act : all_actions) {\n        validate_pos = simulate_action(validate_pos, act, true);\n    }\n    \n    // Output all actions\n    for(const auto& act : all_actions) {\n        cout << act.type << \" \" << act.dir << \"\\n\";\n    }\n    \n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Company {\n    int id;\n    int x, y, r;\n    int a, b, c, d;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    long long area() const { \n        return (long long)max(0, x2 - x1) * max(0, y2 - y1); \n    }\n    bool contains(int x, int y) const {\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n    bool overlaps(const Rect& other) const {\n        return !(x2 <= other.x1 || other.x2 <= x1 || y2 <= other.y1 || other.y2 <= y1);\n    }\n};\n\n// Calculate satisfaction score\ndouble calcSatisfaction(int desired, int actual) {\n    if (actual <= 0) return 0.0;\n    double ratio = (double)min(desired, actual) / max(desired, actual);\n    return 1.0 - (1.0 - ratio) * (1.0 - ratio);\n}\n\n// Calculate total satisfaction\ndouble totalSatisfaction(const vector<Company>& comps) {\n    double total = 0.0;\n    for (const auto& c : comps) {\n        int area = (c.c - c.a) * (c.d - c.b);\n        total += calcSatisfaction(c.r, area);\n    }\n    return total;\n}\n\n// Check if all companies in range are contained in rect\nbool allContained(const vector<Company>& comps, int idx, int end, \n                  int x1, int y1, int x2, int y2) {\n    for (int i = idx; i < end; i++) {\n        if (comps[i].x < x1 || comps[i].x >= x2 || \n            comps[i].y < y1 || comps[i].y >= y2) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Verify no overlaps exist\nbool verifyNoOverlap(const vector<Company>& comps) {\n    int n = comps.size();\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            Rect ri = {comps[i].a, comps[i].b, comps[i].c, comps[i].d};\n            Rect rj = {comps[j].a, comps[j].b, comps[j].c, comps[j].d};\n            if (ri.overlaps(rj)) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Verify all points are contained\nbool verifyPoints(const vector<Company>& comps) {\n    for (const auto& c : comps) {\n        if (c.x < c.a || c.x >= c.c || c.y < c.b || c.y >= c.d) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Verify all rectangles are valid\nbool verifyRects(const vector<Company>& comps) {\n    for (const auto& c : comps) {\n        if (c.a < 0 || c.b < 0 || c.c > 10000 || c.d > 10000) return false;\n        if (c.a >= c.c || c.b >= c.d) return false;\n    }\n    return true;\n}\n\n// Recursive space partitioning with guaranteed containment\nbool partition(vector<Company>& comps, int idx, int end, \n               int x1, int y1, int x2, int y2) {\n    int count = end - idx;\n    \n    if (count <= 0) return true;\n    if (x2 <= x1 || y2 <= y1) return false;\n    \n    for (int i = idx; i < end; i++) {\n        if (comps[i].x < x1 || comps[i].x >= x2 || \n            comps[i].y < y1 || comps[i].y >= y2) {\n            return false;\n        }\n    }\n    \n    if (count == 1) {\n        comps[idx].a = x1;\n        comps[idx].b = y1;\n        comps[idx].c = x2;\n        comps[idx].d = y2;\n        return true;\n    }\n    \n    long long totalArea = 0;\n    for (int i = idx; i < end; i++) totalArea += comps[i].r;\n    \n    int bestSplitIdx = idx + 1;\n    long long bestDiff = totalArea;\n    \n    long long leftArea = 0;\n    for (int i = idx; i < end - 1; i++) {\n        leftArea += comps[i].r;\n        long long diff = abs(leftArea * 2 - totalArea);\n        if (diff < bestDiff) {\n            bestDiff = diff;\n            bestSplitIdx = i + 1;\n        }\n    }\n    \n    int width = x2 - x1;\n    int height = y2 - y1;\n    \n    if (width >= height) {\n        for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                allContained(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                    partition(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n        \n        for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                allContained(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                    partition(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n    } else {\n        for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                allContained(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, x2, splitPos) &&\n                    partition(comps, bestSplitIdx, end, x1, splitPos, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n        \n        for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n            if (allContained(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                allContained(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                \n                if (partition(comps, idx, bestSplitIdx, x1, y1, splitPos, y2) &&\n                    partition(comps, bestSplitIdx, end, splitPos, y1, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n    }\n    \n    for (int splitIdx = idx + 1; splitIdx < end; splitIdx++) {\n        if (splitIdx == bestSplitIdx) continue;\n        \n        for (int splitPos = x1 + 1; splitPos < x2; splitPos++) {\n            if (allContained(comps, idx, splitIdx, x1, y1, splitPos, y2) &&\n                allContained(comps, splitIdx, end, splitPos, y1, x2, y2)) {\n                \n                if (partition(comps, idx, splitIdx, x1, y1, splitPos, y2) &&\n                    partition(comps, splitIdx, end, splitPos, y1, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n        \n        for (int splitPos = y1 + 1; splitPos < y2; splitPos++) {\n            if (allContained(comps, idx, splitIdx, x1, y1, x2, splitPos) &&\n                allContained(comps, splitIdx, end, x1, splitPos, x2, y2)) {\n                \n                if (partition(comps, idx, splitIdx, x1, y1, x2, splitPos) &&\n                    partition(comps, splitIdx, end, x1, splitPos, x2, y2)) {\n                    return true;\n                }\n            }\n        }\n    }\n    \n    for (int i = idx; i < end; i++) {\n        comps[i].a = comps[i].x;\n        comps[i].b = comps[i].y;\n        comps[i].c = comps[i].x + 1;\n        comps[i].d = comps[i].y + 1;\n    }\n    return true;\n}\n\n// Check if two rectangles share an edge (full or partial)\nbool shareEdge(const Company& a, const Company& b, int& boundaryType) {\n    boundaryType = 0;\n    \n    if (a.c == b.a || b.c == a.a) {\n        if (max(a.b, b.b) < min(a.d, b.d)) {\n            boundaryType = 1;\n            return true;\n        }\n    }\n    \n    if (a.d == b.b || b.d == a.b) {\n        if (max(a.a, b.a) < min(a.c, b.c)) {\n            boundaryType = 2;\n            return true;\n        }\n    }\n    \n    return false;\n}\n\n// Calculate optimization priority for a pair\ndouble calcPriority(const Company& a, const Company& b) {\n    int areaA = (a.c - a.a) * (a.d - a.b);\n    int areaB = (b.c - b.a) * (b.d - b.b);\n    \n    double ratioA = (double)areaA / a.r;\n    double ratioB = (double)areaB / b.r;\n    \n    // Higher priority for pairs where both are far from target\n    double mismatchA = abs(1.0 - ratioA);\n    double mismatchB = abs(1.0 - ratioB);\n    \n    // Also consider satisfaction gradient (derivative of satisfaction function)\n    double gradA = (ratioA < 1.0) ? 2.0 * (1.0 - ratioA) : 2.0 * (ratioA - 1.0) / (ratioA * ratioA);\n    double gradB = (ratioB < 1.0) ? 2.0 * (1.0 - ratioB) : 2.0 * (ratioB - 1.0) / (ratioB * ratioB);\n    \n    return (mismatchA + mismatchB) * (gradA + gradB);\n}\n\n// Three-phase boundary optimization\nvoid optimizeBoundaries(vector<Company>& comps, double timeLimit) {\n    auto startTime = chrono::high_resolution_clock::now();\n    \n    int n = comps.size();\n    \n    // Phase 1: Coarse adjustments (\u00b110, \u00b15)\n    for (int iter = 0; iter < 500; iter++) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        if (elapsed > timeLimit * 0.3) break;\n        \n        bool improved = false;\n        double currentScore = totalSatisfaction(comps);\n        \n        vector<pair<double, pair<int,int>>> pairs;\n        for (int i = 0; i < n; i++) {\n            for (int j = i + 1; j < n; j++) {\n                int boundaryType;\n                if (shareEdge(comps[i], comps[j], boundaryType)) {\n                    pairs.push_back({calcPriority(comps[i], comps[j]), {i, j}});\n                }\n            }\n        }\n        sort(pairs.rbegin(), pairs.rend());\n        \n        for (auto& p : pairs) {\n            if (improved) break;\n            int i = p.second.first;\n            int j = p.second.second;\n            \n            int boundaryType;\n            shareEdge(comps[i], comps[j], boundaryType);\n            if (boundaryType == 0) continue;\n            \n            vector<int> deltas = {10, -10, 5, -5};\n            \n            for (int delta : deltas) {\n                if (delta == 0) continue;\n                \n                vector<Company> temp = comps;\n                \n                if (boundaryType == 1) {\n                    if (temp[i].c == temp[j].a) {\n                        temp[i].c += delta;\n                        temp[j].a += delta;\n                    } else {\n                        temp[j].c += delta;\n                        temp[i].a += delta;\n                    }\n                } else {\n                    if (temp[i].d == temp[j].b) {\n                        temp[i].d += delta;\n                        temp[j].b += delta;\n                    } else {\n                        temp[j].d += delta;\n                        temp[i].b += delta;\n                    }\n                }\n                \n                bool valid = true;\n                for (int k = 0; k < n; k++) {\n                    if (temp[k].c <= temp[k].a || temp[k].d <= temp[k].b) {\n                        valid = false; break;\n                    }\n                    if (temp[k].a < 0 || temp[k].b < 0 || \n                        temp[k].c > 10000 || temp[k].d > 10000) {\n                        valid = false; break;\n                    }\n                    if (temp[k].x < temp[k].a || temp[k].x >= temp[k].c ||\n                        temp[k].y < temp[k].b || temp[k].y >= temp[k].d) {\n                        valid = false; break;\n                    }\n                }\n                \n                if (valid) {\n                    for (int k = 0; k < n && valid; k++) {\n                        for (int l = k + 1; l < n && valid; l++) {\n                            Rect rk = {temp[k].a, temp[k].b, temp[k].c, temp[k].d};\n                            Rect rl = {temp[l].a, temp[l].b, temp[l].c, temp[l].d};\n                            if (rk.overlaps(rl)) valid = false;\n                        }\n                    }\n                }\n                \n                if (valid) {\n                    double newScore = totalSatisfaction(temp);\n                    if (newScore > currentScore + 0.001) {\n                        comps = temp;\n                        currentScore = newScore;\n                        improved = true;\n                    }\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Phase 2: Medium adjustments (\u00b13, \u00b12)\n    for (int iter = 0; iter < 500; iter++) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        if (elapsed > timeLimit * 0.7) break;\n        \n        bool improved = false;\n        double currentScore = totalSatisfaction(comps);\n        \n        for (int i = 0; i < n && !improved; i++) {\n            for (int j = i + 1; j < n && !improved; j++) {\n                int boundaryType;\n                if (!shareEdge(comps[i], comps[j], boundaryType)) continue;\n                \n                vector<int> deltas = {3, -3, 2, -2};\n                \n                for (int delta : deltas) {\n                    if (delta == 0) continue;\n                    \n                    vector<Company> temp = comps;\n                    \n                    if (boundaryType == 1) {\n                        if (temp[i].c == temp[j].a) {\n                            temp[i].c += delta;\n                            temp[j].a += delta;\n                        } else {\n                            temp[j].c += delta;\n                            temp[i].a += delta;\n                        }\n                    } else {\n                        if (temp[i].d == temp[j].b) {\n                            temp[i].d += delta;\n                            temp[j].b += delta;\n                        } else {\n                            temp[j].d += delta;\n                            temp[i].b += delta;\n                        }\n                    }\n                    \n                    bool valid = true;\n                    for (int k = 0; k < n; k++) {\n                        if (temp[k].c <= temp[k].a || temp[k].d <= temp[k].b) {\n                            valid = false; break;\n                        }\n                        if (temp[k].a < 0 || temp[k].b < 0 || \n                            temp[k].c > 10000 || temp[k].d > 10000) {\n                            valid = false; break;\n                        }\n                        if (temp[k].x < temp[k].a || temp[k].x >= temp[k].c ||\n                            temp[k].y < temp[k].b || temp[k].y >= temp[k].d) {\n                            valid = false; break;\n                        }\n                    }\n                    \n                    if (valid) {\n                        for (int k = 0; k < n && valid; k++) {\n                            for (int l = k + 1; l < n && valid; l++) {\n                                Rect rk = {temp[k].a, temp[k].b, temp[k].c, temp[k].d};\n                                Rect rl = {temp[l].a, temp[l].b, temp[l].c, temp[l].d};\n                                if (rk.overlaps(rl)) valid = false;\n                            }\n                        }\n                    }\n                    \n                    if (valid) {\n                        double newScore = totalSatisfaction(temp);\n                        if (newScore > currentScore + 0.0005) {\n                            comps = temp;\n                            currentScore = newScore;\n                            improved = true;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n    \n    // Phase 3: Fine adjustments (\u00b11)\n    for (int iter = 0; iter < 500; iter++) {\n        auto currentTime = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(currentTime - startTime).count();\n        if (elapsed > timeLimit) break;\n        \n        bool improved = false;\n        double currentScore = totalSatisfaction(comps);\n        \n        for (int i = 0; i < n && !improved; i++) {\n            for (int j = i + 1; j < n && !improved; j++) {\n                int boundaryType;\n                if (!shareEdge(comps[i], comps[j], boundaryType)) continue;\n                \n                vector<int> deltas = {1, -1};\n                \n                for (int delta : deltas) {\n                    if (delta == 0) continue;\n                    \n                    vector<Company> temp = comps;\n                    \n                    if (boundaryType == 1) {\n                        if (temp[i].c == temp[j].a) {\n                            temp[i].c += delta;\n                            temp[j].a += delta;\n                        } else {\n                            temp[j].c += delta;\n                            temp[i].a += delta;\n                        }\n                    } else {\n                        if (temp[i].d == temp[j].b) {\n                            temp[i].d += delta;\n                            temp[j].b += delta;\n                        } else {\n                            temp[j].d += delta;\n                            temp[i].b += delta;\n                        }\n                    }\n                    \n                    bool valid = true;\n                    for (int k = 0; k < n; k++) {\n                        if (temp[k].c <= temp[k].a || temp[k].d <= temp[k].b) {\n                            valid = false; break;\n                        }\n                        if (temp[k].a < 0 || temp[k].b < 0 || \n                            temp[k].c > 10000 || temp[k].d > 10000) {\n                            valid = false; break;\n                        }\n                        if (temp[k].x < temp[k].a || temp[k].x >= temp[k].c ||\n                            temp[k].y < temp[k].b || temp[k].y >= temp[k].d) {\n                            valid = false; break;\n                        }\n                    }\n                    \n                    if (valid) {\n                        for (int k = 0; k < n && valid; k++) {\n                            for (int l = k + 1; l < n && valid; l++) {\n                                Rect rk = {temp[k].a, temp[k].b, temp[k].c, temp[k].d};\n                                Rect rl = {temp[l].a, temp[l].b, temp[l].c, temp[l].d};\n                                if (rk.overlaps(rl)) valid = false;\n                            }\n                        }\n                    }\n                    \n                    if (valid) {\n                        double newScore = totalSatisfaction(temp);\n                        if (newScore > currentScore + 0.0001) {\n                            comps = temp;\n                            currentScore = newScore;\n                            improved = true;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (!improved) break;\n    }\n}\n\n// Simple grid-based fallback\nvoid gridLayout(vector<Company>& comps) {\n    int n = comps.size();\n    int cols = (int)ceil(sqrt(n));\n    int rows = (n + cols - 1) / cols;\n    int cellW = 10000 / cols;\n    int cellH = 10000 / rows;\n    \n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (comps[i].y != comps[j].y) return comps[i].y < comps[j].y;\n        return comps[i].x < comps[j].x;\n    });\n    \n    for (int i = 0; i < n; i++) {\n        int idx = order[i];\n        int col = i % cols;\n        int row = i / cols;\n        \n        comps[idx].a = col * cellW;\n        comps[idx].b = row * cellH;\n        comps[idx].c = (col + 1) * cellW;\n        comps[idx].d = (row + 1) * cellH;\n        \n        comps[idx].a = max(0, min(9999, comps[idx].a));\n        comps[idx].b = max(0, min(9999, comps[idx].b));\n        comps[idx].c = max(1, min(10000, comps[idx].c));\n        comps[idx].d = max(1, min(10000, comps[idx].d));\n        if (comps[idx].c <= comps[idx].a) comps[idx].c = comps[idx].a + 1;\n        if (comps[idx].d <= comps[idx].b) comps[idx].d = comps[idx].b + 1;\n    }\n}\n\n// Try different sorting strategies\nvector<Company> tryWithSorting(vector<Company> comps, \n                                function<bool(const Company&, const Company&)> cmp) {\n    sort(comps.begin(), comps.end(), cmp);\n    \n    bool success = partition(comps, 0, (int)comps.size(), 0, 0, 10000, 10000);\n    \n    for (int i = 0; i < (int)comps.size(); i++) {\n        if (comps[i].c <= comps[i].a) comps[i].c = comps[i].a + 1;\n        if (comps[i].d <= comps[i].b) comps[i].d = comps[i].b + 1;\n        comps[i].a = max(0, min(9999, comps[i].a));\n        comps[i].b = max(0, min(9999, comps[i].b));\n        comps[i].c = max(1, min(10000, comps[i].c));\n        comps[i].d = max(1, min(10000, comps[i].d));\n    }\n    \n    if (!success || !verifyNoOverlap(comps) || !verifyPoints(comps) || !verifyRects(comps)) {\n        gridLayout(comps);\n    }\n    \n    return comps;\n}\n\nint main() {\n    auto startTime = chrono::high_resolution_clock::now();\n    \n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n;\n    cin >> n;\n    \n    vector<Company> companies(n);\n    for (int i = 0; i < n; i++) {\n        companies[i].id = i;\n        cin >> companies[i].x >> companies[i].y >> companies[i].r;\n    }\n    \n    vector<vector<Company>> candidates;\n    \n    // Strategy 1: Sort by x then y\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        if (a.x != b.x) return a.x < b.x;\n        return a.y < b.y;\n    }));\n    \n    // Strategy 2: Sort by y then x\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        if (a.y != b.y) return a.y < b.y;\n        return a.x < b.x;\n    }));\n    \n    // Strategy 3: Morton order\n    auto morton = [](int x, int y) -> long long {\n        long long result = 0;\n        for (int i = 0; i < 14; i++) {\n            result |= ((long long)(x & (1 << i)) << i);\n            result |= ((long long)(y & (1 << i)) << (i + 1));\n        }\n        return result;\n    };\n    candidates.push_back(tryWithSorting(companies, [&](const Company& a, const Company& b) {\n        return morton(a.x, a.y) < morton(b.x, b.y);\n    }));\n    \n    // Strategy 4: Sort by area (larger first)\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        return a.r > b.r;\n    }));\n    \n    // Strategy 5: Sort by area (smaller first)\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        return a.r < b.r;\n    }));\n    \n    // Strategy 6: Sort by x+y (diagonal)\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        return (a.x + a.y) < (b.x + b.y);\n    }));\n    \n    // Strategy 7: Sort by distance from origin\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        return (a.x * a.x + a.y * a.y) < (b.x * b.x + b.y * b.y);\n    }));\n    \n    // Strategy 8: Sort by x primarily\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        return a.x < b.x;\n    }));\n    \n    // Strategy 9: Sort by y primarily\n    candidates.push_back(tryWithSorting(companies, [](const Company& a, const Company& b) {\n        return a.y < b.y;\n    }));\n    \n    // Strategy 10: Reverse Morton order\n    candidates.push_back(tryWithSorting(companies, [&](const Company& a, const Company& b) {\n        return morton(a.x, a.y) > morton(b.x, b.y);\n    }));\n    \n    // Select best candidate\n    int bestIdx = 0;\n    double bestScore = totalSatisfaction(candidates[0]);\n    for (int i = 1; i < (int)candidates.size(); i++) {\n        double score = totalSatisfaction(candidates[i]);\n        if (score > bestScore) {\n            bestScore = score;\n            bestIdx = i;\n        }\n    }\n    \n    companies = candidates[bestIdx];\n    \n    // Calculate remaining time for optimization\n    auto currentTime = chrono::high_resolution_clock::now();\n    double elapsed = chrono::duration<double>(currentTime - startTime).count();\n    double remainingTime = max(2.0, 4.8 - elapsed);\n    \n    // Apply three-phase boundary optimization\n    optimizeBoundaries(companies, remainingTime);\n    \n    // Final validation\n    if (!verifyNoOverlap(companies) || !verifyPoints(companies) || !verifyRects(companies)) {\n        gridLayout(companies);\n    }\n    \n    // Final bounds check\n    for (int i = 0; i < n; i++) {\n        companies[i].a = max(0, min(9999, companies[i].a));\n        companies[i].b = max(0, min(9999, companies[i].b));\n        companies[i].c = max(1, min(10000, companies[i].c));\n        companies[i].d = max(1, min(10000, companies[i].d));\n        if (companies[i].c <= companies[i].a) companies[i].c = companies[i].a + 1;\n        if (companies[i].d <= companies[i].b) companies[i].d = companies[i].b + 1;\n    }\n    \n    // Output in original order\n    vector<tuple<int,int,int,int>> result(n);\n    for (const auto& comp : companies) {\n        result[comp.id] = {comp.a, comp.b, comp.c, comp.d};\n    }\n    \n    for (int i = 0; i < n; i++) {\n        auto [a, b, c, d] = result[i];\n        cout << a << \" \" << b << \" \" << c << \" \" << d << \"\\n\";\n    }\n    \n    return 0;\n}","ahc002":"#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;\n    cin >> si >> sj;\n    \n    vector<vector<int>> t(50, vector<int>(50));\n    int max_tile = 0;\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> t[i][j];\n            max_tile = max(max_tile, t[i][j]);\n        }\n    }\n    \n    vector<vector<int>> p(50, vector<int>(50));\n    for (int i = 0; i < 50; i++) {\n        for (int j = 0; j < 50; j++) {\n            cin >> p[i][j];\n        }\n    }\n    \n    // Directions: U, D, L, R\n    const int di[] = {-1, 1, 0, 0};\n    const int dj[] = {0, 0, -1, 1};\n    const char dc[] = {'U', 'D', 'L', 'R'};\n    \n    string best_path = \"\";\n    int best_score = 0;\n    \n    // Keep track of top paths for extension\n    vector<pair<string, int>> top_paths;\n    \n    auto get_time = []() {\n        return chrono::duration<double>(chrono::steady_clock::now().time_since_epoch()).count();\n    };\n    \n    double start_time = get_time();\n    double time_limit = 1.99;\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    // Pre-allocate visited array for reuse\n    vector<char> temp_visited(max_tile + 1);\n    \n    // Validate path and return score (-1 if invalid)\n    auto validate_and_score = [&](const string& path) -> int {\n        if (path.empty()) {\n            return p[si][sj];\n        }\n        \n        fill(temp_visited.begin(), temp_visited.end(), 0);\n        int ci = si, cj = sj;\n        int score = p[ci][cj];\n        temp_visited[t[ci][cj]] = 1;\n        \n        for (char c : path) {\n            int d;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            else return -1;\n            \n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            \n            if (ni < 0 || ni >= 50 || nj < 0 || nj >= 50) return -1;\n            if (temp_visited[t[ni][nj]]) return -1;\n            \n            ci = ni;\n            cj = nj;\n            score += p[ci][cj];\n            temp_visited[t[ci][cj]] = 1;\n        }\n        \n        return score;\n    };\n    \n    // Update best path with validation\n    auto update_best = [&](const string& path) {\n        if (path.empty()) return;\n        int score = validate_and_score(path);\n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n            \n            // Add to top paths\n            top_paths.push_back({path, score});\n            sort(top_paths.begin(), top_paths.end(), [](const auto& a, const auto& b) {\n                return a.second > b.second;\n            });\n            if (top_paths.size() > 5) top_paths.pop_back();\n        }\n    };\n    \n    // Fast greedy search\n    auto greedy_search = [&](int seed, double randomness, int top_k) -> string {\n        if (get_time() - start_time >= time_limit) return \"\";\n        \n        mt19937 local_rng(seed);\n        fill(temp_visited.begin(), temp_visited.end(), 0);\n        string path;\n        path.reserve(400);\n        \n        int ci = si, cj = sj;\n        temp_visited[t[ci][cj]] = 1;\n        \n        while (get_time() - start_time < time_limit) {\n            pair<int, int> candidates[4];\n            int cand_count = 0;\n            \n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n                if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                    int tile_id = t[ni][nj];\n                    if (!temp_visited[tile_id]) {\n                        int val = p[ni][nj];\n                        int unvisited_neighbors = 0;\n                        for (int d2 = 0; d2 < 4; d2++) {\n                            int nn_i = ni + di[d2];\n                            int nn_j = nj + dj[d2];\n                            if (nn_i >= 0 && nn_i < 50 && nn_j >= 0 && nn_j < 50) {\n                                if (!temp_visited[t[nn_i][nn_j]]) {\n                                    unvisited_neighbors++;\n                                }\n                            }\n                        }\n                        val += unvisited_neighbors * 20;  // Increased weight\n                        candidates[cand_count++] = {val, d};\n                    }\n                }\n            }\n            \n            if (cand_count == 0) break;\n            \n            // Sort candidates\n            for (int i = 0; i < cand_count - 1; i++) {\n                for (int j = i + 1; j < cand_count; j++) {\n                    if (candidates[j].first > candidates[i].first) {\n                        swap(candidates[i], candidates[j]);\n                    }\n                }\n            }\n            \n            int pick_idx = 0;\n            if (cand_count > 1 && (double)local_rng() / local_rng.max() < randomness) {\n                pick_idx = local_rng() % min(top_k, cand_count);\n            }\n            \n            int d = candidates[pick_idx].second;\n            path += dc[d];\n            ci += di[d];\n            cj += dj[d];\n            temp_visited[t[ci][cj]] = 1;\n        }\n        \n        return path;\n    };\n    \n    // Beam state\n    struct BeamState {\n        int ci, cj;\n        int score;\n        vector<char> tile_visited;\n        string path;\n    };\n    \n    // Beam search\n    auto beam_search = [&](int beam_width, double randomness, int top_k, int seed) -> string {\n        if (get_time() - start_time >= time_limit) return \"\";\n        \n        mt19937 local_rng(seed);\n        vector<BeamState> beam;\n        beam.reserve(beam_width);\n        \n        BeamState initial;\n        initial.ci = si;\n        initial.cj = sj;\n        initial.score = p[si][sj];\n        initial.tile_visited.assign(max_tile + 1, 0);\n        initial.tile_visited[t[si][sj]] = 1;\n        initial.path = \"\";\n        initial.path.reserve(400);\n        beam.push_back(move(initial));\n        \n        for (int step = 0; step < 600 && get_time() - start_time < time_limit; step++) {\n            vector<BeamState> next_beam;\n            next_beam.reserve(beam_width * 2);\n            \n            for (auto& state : beam) {\n                if (get_time() - start_time >= time_limit) break;\n                \n                pair<int, int> candidates[4];\n                int cand_count = 0;\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = state.ci + di[d];\n                    int nj = state.cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        int tile_id = t[ni][nj];\n                        if (!state.tile_visited[tile_id]) {\n                            int val = p[ni][nj];\n                            int unvisited_neighbors = 0;\n                            for (int d2 = 0; d2 < 4; d2++) {\n                                int nn_i = ni + di[d2];\n                                int nn_j = nj + dj[d2];\n                                if (nn_i >= 0 && nn_i < 50 && nn_j >= 0 && nn_j < 50) {\n                                    if (!state.tile_visited[t[nn_i][nn_j]]) {\n                                        unvisited_neighbors++;\n                                    }\n                                }\n                            }\n                            val += unvisited_neighbors * 20;\n                            candidates[cand_count++] = {val, d};\n                        }\n                    }\n                }\n                \n                if (cand_count == 0) continue;\n                \n                // Sort candidates\n                for (int i = 0; i < cand_count - 1; i++) {\n                    for (int j = i + 1; j < cand_count; j++) {\n                        if (candidates[j].first > candidates[i].first) {\n                            swap(candidates[i], candidates[j]);\n                        }\n                    }\n                }\n                \n                int select_count = min(top_k, cand_count);\n                for (int i = 0; i < select_count; i++) {\n                    if (i > 0 && (double)local_rng() / local_rng.max() > randomness) break;\n                    if (get_time() - start_time >= time_limit) break;\n                    if ((int)next_beam.size() >= beam_width * 3) break;\n                    \n                    BeamState new_state;\n                    int d = candidates[i].second;\n                    int ni = state.ci + di[d];\n                    int nj = state.cj + dj[d];\n                    \n                    new_state.ci = ni;\n                    new_state.cj = nj;\n                    new_state.score = state.score + p[ni][nj];\n                    new_state.tile_visited = state.tile_visited;\n                    new_state.tile_visited[t[ni][nj]] = 1;\n                    new_state.path = state.path;\n                    new_state.path.push_back(dc[d]);\n                    \n                    next_beam.push_back(move(new_state));\n                }\n            }\n            \n            if (next_beam.empty()) break;\n            \n            if ((int)next_beam.size() > beam_width) {\n                partial_sort(next_beam.begin(), next_beam.begin() + beam_width, next_beam.end(),\n                    [](const BeamState& a, const BeamState& b) {\n                        return a.score > b.score;\n                    });\n                next_beam.resize(beam_width);\n            }\n            \n            beam = move(next_beam);\n        }\n        \n        string best_p = \"\";\n        int best_s = 0;\n        for (auto& state : beam) {\n            if (state.score > best_s) {\n                best_s = state.score;\n                best_p = state.path;\n            }\n        }\n        \n        return best_p;\n    };\n    \n    // Safe path extension from intermediate points\n    auto extend_path = [&](const string& base_path, int seed) -> string {\n        if (get_time() - start_time >= time_limit || base_path.empty()) return \"\";\n        \n        mt19937 local_rng(seed);\n        \n        // Get positions along the path\n        vector<pair<int, int>> positions;\n        fill(temp_visited.begin(), temp_visited.end(), 0);\n        int ci = si, cj = sj;\n        temp_visited[t[ci][cj]] = 1;\n        positions.push_back({ci, cj});\n        \n        for (char c : base_path) {\n            int d = (c == 'U' ? 0 : c == 'D' ? 1 : c == 'L' ? 2 : 3);\n            ci += di[d];\n            cj += dj[d];\n            if (!temp_visited[t[ci][cj]]) {\n                positions.push_back({ci, cj});\n                temp_visited[t[ci][cj]] = 1;\n            }\n        }\n        \n        string best_extended = base_path;\n        int best_extended_score = validate_and_score(base_path);\n        if (best_extended_score < 0) best_extended_score = 0;\n        \n        // Try extending from many positions\n        int extend_attempts = min(50, (int)positions.size());\n        for (int att = 0; att < extend_attempts && get_time() - start_time < time_limit; att++) {\n            int pos_idx = local_rng() % positions.size();\n            int restart_i = positions[pos_idx].first;\n            int restart_j = positions[pos_idx].second;\n            \n            // Build visited state up to this point\n            fill(temp_visited.begin(), temp_visited.end(), 0);\n            int ri = si, rj = sj;\n            temp_visited[t[ri][rj]] = 1;\n            string prefix;\n            prefix.reserve(base_path.size());\n            \n            for (char c : base_path) {\n                int d = (c == 'U' ? 0 : c == 'D' ? 1 : c == 'L' ? 2 : 3);\n                ri += di[d];\n                rj += dj[d];\n                prefix += c;\n                temp_visited[t[ri][rj]] = 1;\n                if (ri == restart_i && rj == restart_j) break;\n            }\n            \n            // Calculate prefix score\n            int prefix_score = validate_and_score(prefix);\n            if (prefix_score < 0) continue;\n            \n            // Extend from restart point\n            vector<char> ext_visited = temp_visited;\n            string extension;\n            extension.reserve(100);\n            int ext_ci = restart_i, ext_cj = restart_j;\n            \n            while (get_time() - start_time < time_limit) {\n                pair<int, int> candidates[4];\n                int cand_count = 0;\n                \n                for (int d = 0; d < 4; d++) {\n                    int ni = ext_ci + di[d];\n                    int nj = ext_cj + dj[d];\n                    if (ni >= 0 && ni < 50 && nj >= 0 && nj < 50) {\n                        int tile_id = t[ni][nj];\n                        if (!ext_visited[tile_id]) {\n                            candidates[cand_count++] = {p[ni][nj], d};\n                        }\n                    }\n                }\n                \n                if (cand_count == 0) break;\n                \n                // Sort\n                for (int i = 0; i < cand_count - 1; i++) {\n                    for (int j = i + 1; j < cand_count; j++) {\n                        if (candidates[j].first > candidates[i].first) {\n                            swap(candidates[i], candidates[j]);\n                        }\n                    }\n                }\n                \n                int pick_idx = (att % 3 == 0) ? 0 : (local_rng() % min(3, cand_count));\n                int d = candidates[pick_idx].second;\n                extension += dc[d];\n                ext_ci += di[d];\n                ext_cj += dj[d];\n                ext_visited[t[ext_ci][ext_cj]] = 1;\n            }\n            \n            string candidate = prefix + extension;\n            int candidate_score = validate_and_score(candidate);\n            if (candidate_score > best_extended_score) {\n                best_extended_score = candidate_score;\n                best_extended = candidate;\n            }\n        }\n        \n        return best_extended;\n    };\n    \n    int iter = 0;\n    \n    // Phase 1: Diverse greedy searches (35% of time)\n    while (get_time() - start_time < time_limit * 0.35) {\n        iter++;\n        double randomness = 0.1 + 0.6 * ((double)rng() / rng.max());\n        int top_k = 2 + (iter % 7);\n        int seed = rng();\n        \n        string path = greedy_search(seed, randomness, top_k);\n        update_best(path);\n    }\n    \n    // Phase 2: Beam search with varying widths (35% of time)\n    while (get_time() - start_time < time_limit * 0.7) {\n        int beam_width = 1 + (rng() % 8);  // 1-8\n        double randomness = 0.15 + 0.5 * ((double)rng() / rng.max());\n        int top_k = 2 + (rng() % 5);\n        int seed = rng();\n        \n        string path = beam_search(beam_width, randomness, top_k, seed);\n        update_best(path);\n    }\n    \n    // Phase 3: Path extension from top paths (20% of time)\n    if (!top_paths.empty()) {\n        while (get_time() - start_time < time_limit * 0.9) {\n            // Extend from random top path\n            int path_idx = rng() % top_paths.size();\n            string ext_path = extend_path(top_paths[path_idx].first, rng());\n            update_best(ext_path);\n        }\n    }\n    \n    // Phase 4: Final intensive search (remaining time)\n    while (get_time() - start_time < time_limit) {\n        double randomness = 0.15 + 0.5 * ((double)rng() / rng.max());\n        int top_k = 2 + (rng() % 5);\n        int seed = rng();\n        \n        string path = greedy_search(seed, randomness, top_k);\n        update_best(path);\n    }\n    \n    // Final validation\n    int final_score = validate_and_score(best_path);\n    if (final_score < 0) {\n        best_path = \"\";\n    }\n    \n    cout << best_path << endl;\n    \n    return 0;\n}","ahc003":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <algorithm>\n#include <random>\n\nusing namespace std;\n\nconst int H = 30;\nconst int W = 30;\n\n// Edge weights and visit counts\ndouble h_w[H][W-1];\ndouble v_w[H-1][W];\nint h_n[H][W-1];\nint v_n[H-1][W];\n\n// Row/column statistics for pattern detection\ndouble h_row_avg[H];\ndouble v_col_avg[W];\ndouble h_row_var[H];\ndouble v_col_var[W];\nint h_row_n[H];\nint v_col_n[W];\n\n// Pattern type: 0=unknown, 1=M=1 (uniform), 2=M=2 (bimodal)\nint h_pattern[H];\nint v_pattern[W];\ndouble h_threshold[H];\ndouble v_threshold[W];\ndouble pattern_confidence[H + W];\n\n// Confidence in weights\ndouble h_conf[H][W-1];\ndouble v_conf[H-1][W];\n\n// Per-edge prediction error tracking\ndouble h_error_sum[H][W-1];\ndouble v_error_sum[H-1][W];\nint h_error_count[H][W-1];\nint v_error_count[H-1][W];\n\n// Recent prediction errors for adaptive exploration\nvector<double> recent_errors;\nconst int ERROR_WINDOW = 50;\n\nmt19937 rng(54321);\n\nvoid init() {\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W-1; ++j) {\n            h_w[i][j] = 5000.0;\n            h_n[i][j] = 1;\n            h_conf[i][j] = 0.05;\n            h_error_sum[i][j] = 0;\n            h_error_count[i][j] = 0;\n        }\n        h_row_avg[i] = 5000.0;\n        h_row_var[i] = 0;\n        h_row_n[i] = 0;\n        h_pattern[i] = 0;\n        h_threshold[i] = 5000.0;\n        pattern_confidence[i] = 0;\n    }\n    for (int i = 0; i < H-1; ++i) {\n        for (int j = 0; j < W; ++j) {\n            v_w[i][j] = 5000.0;\n            v_n[i][j] = 1;\n            v_conf[i][j] = 0.05;\n            v_error_sum[i][j] = 0;\n            v_error_count[i][j] = 0;\n        }\n    }\n    for (int j = 0; j < W; ++j) {\n        v_col_avg[j] = 5000.0;\n        v_col_var[j] = 0;\n        v_col_n[j] = 0;\n        v_pattern[j] = 0;\n        v_threshold[j] = 5000.0;\n        pattern_confidence[H + j] = 0;\n    }\n    recent_errors.reserve(ERROR_WINDOW);\n}\n\nstruct State {\n    double dist;\n    int r, c;\n    bool operator>(const State& other) const {\n        return dist > other.dist;\n    }\n};\n\nstring dijkstra(int sr, int sc, int tr, int tc, int query_num) {\n    vector<vector<double>> dist(H, vector<double>(W, 1e18));\n    vector<vector<pair<int, int>>> parent(H, vector<pair<int, int>>(W, {-1, -1}));\n    vector<vector<char>> dir_to(H, vector<char>(W, 0));\n    \n    priority_queue<State, vector<State>, greater<State>> pq;\n    \n    dist[sr][sc] = 0;\n    pq.push({0.0, sr, sc});\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    char dchar[] = {'U', 'D', 'L', 'R'};\n    \n    // Base exploration bonus - more aggressive early, faster convergence\n    double base_bonus = 1100.0;\n    double explore_bonus = base_bonus * exp(-query_num / 130.0);\n    \n    // Boost exploration if recent errors are high\n    if (recent_errors.size() >= 10) {\n        double avg_error = 0;\n        for (double e : recent_errors) avg_error += e;\n        avg_error /= recent_errors.size();\n        if (avg_error > 0.05) {\n            explore_bonus *= 1.7;\n        }\n    }\n    \n    // Random perturbation for early exploration\n    bool perturb = (query_num < 100) && (rng() % 100 < 20);\n    \n    while (!pq.empty()) {\n        State top = pq.top();\n        pq.pop();\n        \n        int r = top.r;\n        int c = top.c;\n        double d = top.dist;\n        \n        if (d > dist[r][c] + 1e-9) continue;\n        if (r == tr && c == tc) break;\n        \n        // Shuffle directions for exploration diversity\n        vector<int> dirs = {0, 1, 2, 3};\n        if (perturb) {\n            shuffle(dirs.begin(), dirs.end(), rng);\n        }\n        \n        for (int i : dirs) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (nr >= 0 && nr < H && nc >= 0 && nc < W) {\n                double weight = 0;\n                int n = 0;\n                double conf = 0;\n                \n                if (i == 0) { // U\n                    weight = v_w[r-1][c];\n                    n = v_n[r-1][c];\n                    conf = v_conf[r-1][c];\n                } else if (i == 1) { // D\n                    weight = v_w[r][c];\n                    n = v_n[r][c];\n                    conf = v_conf[r][c];\n                } else if (i == 2) { // L\n                    weight = h_w[r][c-1];\n                    n = h_n[r][c-1];\n                    conf = h_conf[r][c-1];\n                } else if (i == 3) { // R\n                    weight = h_w[r][c];\n                    n = h_n[r][c];\n                    conf = h_conf[r][c];\n                }\n                \n                // UCB-style exploration bonus\n                double visit_bonus = explore_bonus / sqrt(n + 1);\n                double conf_bonus = explore_bonus * (1.0 - conf) * 0.9;\n                double bonus = visit_bonus + conf_bonus;\n                double cost = max(100.0, weight - bonus);\n                \n                if (dist[r][c] + cost < dist[nr][nc]) {\n                    dist[nr][nc] = dist[r][c] + cost;\n                    parent[nr][nc] = {r, c};\n                    dir_to[nr][nc] = dchar[i];\n                    pq.push({dist[nr][nc], nr, nc});\n                }\n            }\n        }\n    }\n    \n    // Reconstruct path\n    string path = \"\";\n    int cr = tr, cc = tc;\n    while (cr != sr || cc != sc) {\n        char d = dir_to[cr][cc];\n        path += d;\n        int pr = parent[cr][cc].first;\n        int pc = parent[cr][cc].second;\n        cr = pr;\n        cc = pc;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Detect M=2 pattern using multiple criteria\nint detect_pattern(const vector<double>& weights, const vector<int>& counts, double& threshold, double& confidence) {\n    vector<double> visited_weights;\n    for (size_t i = 0; i < weights.size(); ++i) {\n        if (counts[i] > 0) {\n            visited_weights.push_back(weights[i]);\n        }\n    }\n    \n    if (visited_weights.size() < 8) {\n        confidence = 0.3;\n        return 0;\n    }\n    \n    sort(visited_weights.begin(), visited_weights.end());\n    \n    double mean = 0;\n    for (double w : visited_weights) mean += w;\n    mean /= visited_weights.size();\n    \n    double variance = 0;\n    for (double w : visited_weights) {\n        variance += (w - mean) * (w - mean);\n    }\n    variance /= visited_weights.size();\n    \n    double max_gap = 0;\n    int gap_idx = -1;\n    for (size_t i = 1; i < visited_weights.size(); ++i) {\n        double gap = visited_weights[i] - visited_weights[i-1];\n        if (gap > max_gap) {\n            max_gap = gap;\n            gap_idx = i;\n        }\n    }\n    \n    if (max_gap > 700 && gap_idx > 0 && gap_idx < (int)visited_weights.size() - 1) {\n        int cluster1_size = gap_idx;\n        int cluster2_size = visited_weights.size() - gap_idx;\n        \n        if (cluster1_size >= (int)visited_weights.size() * 0.25 && \n            cluster2_size >= (int)visited_weights.size() * 0.25) {\n            \n            double mean1 = 0, mean2 = 0;\n            for (int i = 0; i < gap_idx; i++) mean1 += visited_weights[i];\n            for (size_t i = gap_idx; i < visited_weights.size(); i++) mean2 += visited_weights[i];\n            mean1 /= cluster1_size;\n            mean2 /= cluster2_size;\n            \n            double within_var = 0;\n            for (int i = 0; i < gap_idx; i++) {\n                within_var += (visited_weights[i] - mean1) * (visited_weights[i] - mean1);\n            }\n            for (size_t i = gap_idx; i < visited_weights.size(); i++) {\n                within_var += (visited_weights[i] - mean2) * (visited_weights[i] - mean2);\n            }\n            within_var /= visited_weights.size();\n            \n            double variance_ratio = within_var / (variance + 1);\n            if (variance_ratio < 0.4) {\n                threshold = (visited_weights[gap_idx] + visited_weights[gap_idx-1]) / 2.0;\n                confidence = min(1.0, 0.5 + 0.5 * (0.4 - variance_ratio) / 0.4);\n                return 2;\n            }\n        }\n    }\n    \n    if (variance < 250000) {\n        confidence = min(1.0, 0.5 + 0.5 * (250000 - variance) / 250000);\n        return 1;\n    }\n    \n    confidence = 0.3;\n    return 0;\n}\n\nvoid smooth_weights() {\n    for (int i = 0; i < H; ++i) {\n        if (h_row_n[i] < 8) continue;\n        \n        vector<double> weights;\n        vector<int> counts;\n        for (int j = 0; j < W-1; ++j) {\n            weights.push_back(h_w[i][j]);\n            counts.push_back(h_n[i][j]);\n        }\n        \n        double mean = h_row_avg[i];\n        double variance = 0;\n        int count = 0;\n        for (int j = 0; j < W-1; ++j) {\n            if (h_n[i][j] > 0) {\n                variance += (h_w[i][j] - mean) * (h_w[i][j] - mean);\n                count++;\n            }\n        }\n        h_row_var[i] = (count > 0) ? variance / count : 1000000;\n        \n        double conf = 0;\n        h_pattern[i] = detect_pattern(weights, counts, h_threshold[i], conf);\n        pattern_confidence[i] = conf;\n    }\n    \n    for (int j = 0; j < W; ++j) {\n        if (v_col_n[j] < 8) continue;\n        \n        vector<double> weights;\n        vector<int> counts;\n        for (int i = 0; i < H-1; ++i) {\n            weights.push_back(v_w[i][j]);\n            counts.push_back(v_n[i][j]);\n        }\n        \n        double mean = v_col_avg[j];\n        double variance = 0;\n        int count = 0;\n        for (int i = 0; i < H-1; ++i) {\n            if (v_n[i][j] > 0) {\n                variance += (v_w[i][j] - mean) * (v_w[i][j] - mean);\n                count++;\n            }\n        }\n        v_col_var[j] = (count > 0) ? variance / count : 1000000;\n        \n        double conf = 0;\n        v_pattern[j] = detect_pattern(weights, counts, v_threshold[j], conf);\n        pattern_confidence[H + j] = conf;\n    }\n    \n    for (int i = 0; i < H; ++i) {\n        if (h_row_n[i] < 8) continue;\n        \n        double smooth_base = 0.08 * pattern_confidence[i];\n        if (smooth_base < 0.02) smooth_base = 0.02;\n        \n        if (h_pattern[i] == 2 && pattern_confidence[i] > 0.5) {\n            double mean1 = 0, mean2 = 0;\n            int count1 = 0, count2 = 0;\n            double thresh = h_threshold[i];\n            \n            for (int j = 0; j < W-1; ++j) {\n                if (h_n[i][j] > 0) {\n                    if (h_w[i][j] < thresh) {\n                        mean1 += h_w[i][j];\n                        count1++;\n                    } else {\n                        mean2 += h_w[i][j];\n                        count2++;\n                    }\n                }\n            }\n            \n            if (count1 > 0) mean1 /= count1;\n            if (count2 > 0) mean2 /= count2;\n            \n            for (int j = 0; j < W-1; ++j) {\n                double target = (h_w[i][j] < thresh) ? mean1 : mean2;\n                double smooth_factor = smooth_base * (1.0 - h_conf[i][j]);\n                h_w[i][j] = (1.0 - smooth_factor) * h_w[i][j] + smooth_factor * target;\n            }\n        } else if (h_pattern[i] == 1 && pattern_confidence[i] > 0.5) {\n            double row_mean = h_row_avg[i];\n            for (int j = 0; j < W-1; ++j) {\n                double smooth_factor = smooth_base * 1.2 * (1.0 - h_conf[i][j]);\n                h_w[i][j] = (1.0 - smooth_factor) * h_w[i][j] + smooth_factor * row_mean;\n            }\n        } else {\n            // Unknown pattern: very gentle smoothing (2%)\n            double row_mean = h_row_avg[i];\n            for (int j = 0; j < W-1; ++j) {\n                double smooth_factor = 0.02 * (1.0 - h_conf[i][j]);\n                h_w[i][j] = (1.0 - smooth_factor) * h_w[i][j] + smooth_factor * row_mean;\n            }\n        }\n    }\n    \n    for (int j = 0; j < W; ++j) {\n        if (v_col_n[j] < 8) continue;\n        \n        double smooth_base = 0.08 * pattern_confidence[H + j];\n        if (smooth_base < 0.02) smooth_base = 0.02;\n        \n        if (v_pattern[j] == 2 && pattern_confidence[H + j] > 0.5) {\n            double mean1 = 0, mean2 = 0;\n            int count1 = 0, count2 = 0;\n            double thresh = v_threshold[j];\n            \n            for (int i = 0; i < H-1; ++i) {\n                if (v_n[i][j] > 0) {\n                    if (v_w[i][j] < thresh) {\n                        mean1 += v_w[i][j];\n                        count1++;\n                    } else {\n                        mean2 += v_w[i][j];\n                        count2++;\n                    }\n                }\n            }\n            \n            if (count1 > 0) mean1 /= count1;\n            if (count2 > 0) mean2 /= count2;\n            \n            for (int i = 0; i < H-1; ++i) {\n                double target = (v_w[i][j] < thresh) ? mean1 : mean2;\n                double smooth_factor = smooth_base * (1.0 - v_conf[i][j]);\n                v_w[i][j] = (1.0 - smooth_factor) * v_w[i][j] + smooth_factor * target;\n            }\n        } else if (v_pattern[j] == 1 && pattern_confidence[H + j] > 0.5) {\n            double col_mean = v_col_avg[j];\n            for (int i = 0; i < H-1; ++i) {\n                double smooth_factor = smooth_base * 1.2 * (1.0 - v_conf[i][j]);\n                v_w[i][j] = (1.0 - smooth_factor) * v_w[i][j] + smooth_factor * col_mean;\n            }\n        } else {\n            // Unknown pattern: very gentle smoothing (2%)\n            double col_mean = v_col_avg[j];\n            for (int i = 0; i < H-1; ++i) {\n                double smooth_factor = 0.02 * (1.0 - v_conf[i][j]);\n                v_w[i][j] = (1.0 - smooth_factor) * v_w[i][j] + smooth_factor * col_mean;\n            }\n        }\n    }\n}\n\nvoid update_weights(const string& path, int sr, int sc, int observed_len, int query_num) {\n    if (path.empty()) return;\n    \n    int cr = sr, cc = sc;\n    double est_len = 0;\n    \n    struct EdgeRef {\n        bool is_h;\n        int r, c;\n        double old_weight;\n    };\n    vector<EdgeRef> path_edges;\n    \n    for (char d : path) {\n        int nr = cr, nc = cc;\n        if (d == 'U') { nr--; }\n        else if (d == 'D') { nr++; }\n        else if (d == 'L') { nc--; }\n        else if (d == 'R') { nc++; }\n        \n        double w = 0;\n        bool is_h = false;\n        int r = 0, c = 0;\n        \n        if (d == 'U') {\n            w = v_w[cr-1][cc];\n            is_h = false; r = cr-1; c = cc;\n        } else if (d == 'D') {\n            w = v_w[cr][cc];\n            is_h = false; r = cr; c = cc;\n        } else if (d == 'L') {\n            w = h_w[cr][cc-1];\n            is_h = true; r = cr; c = cc-1;\n        } else if (d == 'R') {\n            w = h_w[cr][cc];\n            is_h = true; r = cr; c = cc;\n        }\n        \n        est_len += w;\n        path_edges.push_back({is_h, r, c, w});\n        \n        cr = nr;\n        cc = nc;\n    }\n    \n    if (est_len < 1.0) return;\n    \n    double ratio = (double)observed_len / est_len;\n    double error = abs(ratio - 1.0);\n    recent_errors.push_back(error);\n    if (recent_errors.size() > ERROR_WINDOW) {\n        recent_errors.erase(recent_errors.begin());\n    }\n    \n    double error_magnitude = abs(ratio - 1.0);\n    \n    // Calculate base learning rate before edge loop - higher initial rate\n    double base_lr = 0.28 + 0.12 * error_magnitude;\n    double decay = exp(-query_num / 320.0);\n    double lr = base_lr * decay;\n    if (lr < 0.04) lr = 0.04;\n    \n    // Update each edge in the path\n    for (auto& edge : path_edges) {\n        double target_weight = edge.old_weight * ratio;\n        \n        // Per-edge adaptive learning rate based on prediction history\n        double edge_error_rate = 0;\n        if (edge.is_h) {\n            if (h_error_count[edge.r][edge.c] > 0) {\n                edge_error_rate = h_error_sum[edge.r][edge.c] / h_error_count[edge.r][edge.c];\n            }\n        } else {\n            if (v_error_count[edge.r][edge.c] > 0) {\n                edge_error_rate = v_error_sum[edge.r][edge.c] / v_error_count[edge.r][edge.c];\n            }\n        }\n        \n        double edge_lr_boost = 1.0 + 0.5 * edge_error_rate;\n        double edge_lr = lr * edge_lr_boost;\n        \n        if (edge.is_h) {\n            h_w[edge.r][edge.c] = (1.0 - edge_lr) * h_w[edge.r][edge.c] + edge_lr * target_weight;\n            h_n[edge.r][edge.c]++;\n            h_conf[edge.r][edge.c] = min(1.0, h_conf[edge.r][edge.c] + 0.06);\n            h_row_avg[edge.r] = (h_row_avg[edge.r] * h_row_n[edge.r] + h_w[edge.r][edge.c]) / (h_row_n[edge.r] + 1);\n            h_row_n[edge.r]++;\n            \n            h_error_sum[edge.r][edge.c] += error;\n            h_error_count[edge.r][edge.c]++;\n            \n            if (h_w[edge.r][edge.c] < 1000) h_w[edge.r][edge.c] = 1000;\n            if (h_w[edge.r][edge.c] > 9000) h_w[edge.r][edge.c] = 9000;\n        } else {\n            v_w[edge.r][edge.c] = (1.0 - edge_lr) * v_w[edge.r][edge.c] + edge_lr * target_weight;\n            v_n[edge.r][edge.c]++;\n            v_conf[edge.r][edge.c] = min(1.0, v_conf[edge.r][edge.c] + 0.06);\n            v_col_avg[edge.c] = (v_col_avg[edge.c] * v_col_n[edge.c] + v_w[edge.r][edge.c]) / (v_col_n[edge.c] + 1);\n            v_col_n[edge.c]++;\n            \n            v_error_sum[edge.r][edge.c] += error;\n            v_error_count[edge.r][edge.c]++;\n            \n            if (v_w[edge.r][edge.c] < 1000) v_w[edge.r][edge.c] = 1000;\n            if (v_w[edge.r][edge.c] > 9000) v_w[edge.r][edge.c] = 9000;\n        }\n    }\n    \n    // Propagate learning to nearby edges based on detected pattern\n    for (auto& edge : path_edges) {\n        if (edge.is_h) {\n            int pattern = h_pattern[edge.r];\n            double pat_conf = pattern_confidence[edge.r];\n            for (int j = 0; j < W-1; ++j) {\n                if (j != edge.c && h_n[edge.r][j] < 3) {\n                    double prop_lr = 0;\n                    if (pattern == 2 && pat_conf > 0.5) {\n                        prop_lr = (h_w[edge.r][j] < h_threshold[edge.r]) ? \n                                  ((h_w[edge.r][edge.c] < h_threshold[edge.r]) ? lr * 0.45 : lr * 0.10) :\n                                  ((h_w[edge.r][edge.c] < h_threshold[edge.r]) ? lr * 0.10 : lr * 0.45);\n                    } else {\n                        prop_lr = (h_n[edge.r][j] < 2) ? lr * 0.45 : lr * 0.35;\n                    }\n                    h_w[edge.r][j] = (1.0 - prop_lr) * h_w[edge.r][j] + prop_lr * h_w[edge.r][edge.c];\n                    h_conf[edge.r][j] = max(0.0, h_conf[edge.r][j] - 0.01);\n                }\n            }\n        } else {\n            int pattern = v_pattern[edge.c];\n            double pat_conf = pattern_confidence[H + edge.c];\n            for (int i = 0; i < H-1; ++i) {\n                if (i != edge.r && v_n[i][edge.c] < 3) {\n                    double prop_lr = 0;\n                    if (pattern == 2 && pat_conf > 0.5) {\n                        prop_lr = (v_w[i][edge.c] < v_threshold[edge.c]) ? \n                                  ((v_w[edge.r][edge.c] < v_threshold[edge.c]) ? lr * 0.45 : lr * 0.10) :\n                                  ((v_w[edge.r][edge.c] < v_threshold[edge.c]) ? lr * 0.10 : lr * 0.45);\n                    } else {\n                        prop_lr = (v_n[i][edge.c] < 2) ? lr * 0.45 : lr * 0.35;\n                    }\n                    v_w[i][edge.c] = (1.0 - prop_lr) * v_w[i][edge.c] + prop_lr * v_w[edge.r][edge.c];\n                    v_conf[i][edge.c] = max(0.0, v_conf[i][edge.c] - 0.01);\n                }\n            }\n        }\n    }\n    \n    // Periodic smoothing (every 150 queries, more conservative)\n    if (query_num > 0 && query_num % 150 == 0) {\n        smooth_weights();\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    init();\n    \n    for (int k = 0; k < 1000; ++k) {\n        int si, sj, ti, tj;\n        cin >> si >> sj >> ti >> tj;\n        \n        string path = dijkstra(si, sj, ti, tj, k);\n        cout << path << \"\\n\" << flush;\n        \n        int observed;\n        cin >> observed;\n        \n        update_weights(path, si, sj, observed, k);\n    }\n    \n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 20;\nconst int MAX_M = 800;\nconst int MAX_LEN = 12;\n\nint M;\nchar grid[N][N];\nchar strings[MAX_M][MAX_LEN];\nuint8_t strLen[MAX_M];\nuint8_t strMatched[MAX_M];\nbool strHasChar[MAX_M][8];\nvector<int> charToStrings[8];\n\ninline bool checkString(int si) {\n    int len = strLen[si];\n    const char* s = strings[si];\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool ok = true;\n            for (int k = 0; k < len; k++) {\n                char c = grid[i][(j + k) % N];\n                if (c != '.' && c != s[k]) { ok = false; break; }\n            }\n            if (ok) return true;\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool ok = true;\n            for (int k = 0; k < len; k++) {\n                char c = grid[(i + k) % N][j];\n                if (c != '.' && c != s[k]) { ok = false; break; }\n            }\n            if (ok) return true;\n        }\n    }\n    \n    return false;\n}\n\nbool tryPlaceString(int si) {\n    int len = strLen[si];\n    const char* s = strings[si];\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool canPlace = true;\n            for (int k = 0; k < len; k++) {\n                char c = grid[i][(j + k) % N];\n                if (c != '.' && c != s[k]) { canPlace = false; break; }\n            }\n            if (canPlace) {\n                for (int k = 0; k < len; k++) grid[i][(j + k) % N] = s[k];\n                return true;\n            }\n            \n            canPlace = true;\n            for (int k = 0; k < len; k++) {\n                char c = grid[(i + k) % N][j];\n                if (c != '.' && c != s[k]) { canPlace = false; break; }\n            }\n            if (canPlace) {\n                for (int k = 0; k < len; k++) grid[(i + k) % N][j] = s[k];\n                return true;\n            }\n        }\n    }\n    return false;\n}\n\nvoid greedyPlace(int* order) {\n    for (int idx = 0; idx < M; idx++) {\n        tryPlaceString(order[idx]);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N_in;\n    cin >> N_in >> M;\n    \n    for (int i = 0; i < M; i++) {\n        string tmp;\n        cin >> tmp;\n        strLen[i] = tmp.length();\n        for (int j = 0; j < strLen[i]; j++) {\n            strings[i][j] = tmp[j];\n            strHasChar[i][tmp[j] - 'A'] = true;\n        }\n        for (int c = 0; c < 8; c++) {\n            if (strHasChar[i][c]) charToStrings[c].push_back(i);\n        }\n    }\n    \n    int bestMatches = 0;\n    char bestGrid[N][N];\n    uint8_t bestStrMatched[MAX_M];\n    \n    int order[MAX_M];\n    for (int pass = 0; pass < 3; pass++) {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                grid[i][j] = '.';\n        \n        mt19937 rng(pass * 12345 + 67890);\n        \n        if (pass == 0) {\n            for (int i = 0; i < M; i++) order[i] = i;\n            sort(order, order + M, [&](int a, int b) { return strLen[a] > strLen[b]; });\n        } else if (pass == 1) {\n            for (int i = 0; i < M; i++) order[i] = i;\n            shuffle(order, order + M, rng);\n        } else {\n            for (int i = 0; i < M; i++) order[i] = i;\n            sort(order, order + M, [&](int a, int b) { return strings[a][0] < strings[b][0]; });\n        }\n        \n        greedyPlace(order);\n        \n        int matches = 0;\n        for (int i = 0; i < M; i++) {\n            strMatched[i] = checkString(i);\n            if (strMatched[i]) matches++;\n        }\n        if (matches > bestMatches) {\n            bestMatches = matches;\n            memcpy(bestGrid, grid, sizeof(grid));\n            memcpy(bestStrMatched, strMatched, M);\n        }\n    }\n    \n    memcpy(grid, bestGrid, sizeof(grid));\n    memcpy(strMatched, bestStrMatched, M);\n    int totalMatches = bestMatches;\n    \n    // Phase 1: General SA - 1200 iterations\n    mt19937 rng(42);\n    int iterations1 = 1200;\n    double temp = 8.0;\n    \n    static bool affected[MAX_M];\n    static int affectedList[MAX_M];\n    static uint8_t savedMatched[MAX_M];\n    \n    for (int iter = 0; iter < iterations1; iter++) {\n        int i = rng() % N;\n        int j = rng() % N;\n        char old = grid[i][j];\n        \n        char newChar = (old == '.') ? ('A' + (rng() % 8)) : ((rng() % 25 == 0) ? '.' : ('A' + (rng() % 8)));\n        \n        if (newChar == old) continue;\n        \n        grid[i][j] = newChar;\n        \n        int oldTotal = totalMatches;\n        int affectedCount = 0;\n        \n        memset(affected, 0, M);\n        \n        if (old != '.') {\n            for (int si : charToStrings[old - 'A']) {\n                if (!affected[si]) { affected[si] = true; affectedList[affectedCount++] = si; }\n            }\n        }\n        if (newChar != '.') {\n            for (int si : charToStrings[newChar - 'A']) {\n                if (!affected[si]) { affected[si] = true; affectedList[affectedCount++] = si; }\n            }\n        }\n        \n        // Save state for potential restore\n        for (int k = 0; k < affectedCount; k++) {\n            savedMatched[k] = strMatched[affectedList[k]];\n        }\n        \n        int delta = 0;\n        for (int k = 0; k < affectedCount; k++) {\n            int si = affectedList[k];\n            bool wasMatched = strMatched[si];\n            bool isMatched = checkString(si);\n            strMatched[si] = isMatched;\n            if (wasMatched && !isMatched) delta--;\n            else if (!wasMatched && isMatched) delta++;\n        }\n        totalMatches += delta;\n        \n        bool accept = (delta >= 0);\n        if (!accept) {\n            accept = (exp(delta / temp) > (double)(rng() % 1000000) / 1000000.0);\n        }\n        \n        if (!accept) {\n            grid[i][j] = old;\n            // Restore only affected strings\n            for (int k = 0; k < affectedCount; k++) {\n                strMatched[affectedList[k]] = savedMatched[k];\n            }\n            totalMatches = oldTotal;\n        }\n        \n        temp *= 0.999;\n    }\n    \n    // Phase 2: Lower temp refinement - 700 iterations\n    if (totalMatches < M) {\n        temp = 2.0;\n        int iterations2 = 700;\n        \n        for (int iter = 0; iter < iterations2; iter++) {\n            int i = rng() % N;\n            int j = rng() % N;\n            char old = grid[i][j];\n            \n            char newChar = (old == '.') ? ('A' + (rng() % 8)) : ((rng() % 20 == 0) ? '.' : ('A' + (rng() % 8)));\n            \n            if (newChar == old) continue;\n            \n            grid[i][j] = newChar;\n            \n            int oldTotal = totalMatches;\n            int affectedCount = 0;\n            \n            memset(affected, 0, M);\n            \n            if (old != '.') {\n                for (int si : charToStrings[old - 'A']) {\n                    if (!affected[si]) { affected[si] = true; affectedList[affectedCount++] = si; }\n                }\n            }\n            if (newChar != '.') {\n                for (int si : charToStrings[newChar - 'A']) {\n                    if (!affected[si]) { affected[si] = true; affectedList[affectedCount++] = si; }\n                }\n            }\n            \n            for (int k = 0; k < affectedCount; k++) {\n                savedMatched[k] = strMatched[affectedList[k]];\n            }\n            \n            int delta = 0;\n            for (int k = 0; k < affectedCount; k++) {\n                int si = affectedList[k];\n                bool wasMatched = strMatched[si];\n                bool isMatched = checkString(si);\n                strMatched[si] = isMatched;\n                if (wasMatched && !isMatched) delta--;\n                else if (!wasMatched && isMatched) delta++;\n            }\n            totalMatches += delta;\n            \n            bool accept = (delta >= 0);\n            if (!accept) {\n                accept = (exp(delta / temp) > (double)(rng() % 1000000) / 1000000.0);\n            }\n            \n            if (!accept) {\n                grid[i][j] = old;\n                for (int k = 0; k < affectedCount; k++) {\n                    strMatched[affectedList[k]] = savedMatched[k];\n                }\n                totalMatches = oldTotal;\n            }\n            \n            temp *= 0.996;\n        }\n    }\n    \n    // Fill remaining '.' if all matched\n    if (totalMatches == M) {\n        for (int i = 0; i < N; i++)\n            for (int j = 0; j < N; j++)\n                if (grid[i][j] == '.') grid[i][j] = 'A' + (rng() % 8);\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cout << grid[i][j];\n        cout << '\\n';\n    }\n    \n    return 0;\n}","ahc005":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <algorithm>\n#include <bitset>\n#include <chrono>\n#include <random>\n#include <cmath>\n#include <map>\n#include <set>\n\nusing namespace std;\n\nconst int MAX_N = 70;\nconst int MAX_SEGMENTS = 5000;\nconst long long INF = 1e18;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Point& other) const {\n        return !(*this == other);\n    }\n    bool operator<(const Point& other) const {\n        if (r != other.r) return r < other.r;\n        return c < other.c;\n    }\n};\n\nint N, si, sj;\nvector<string> grid;\nvector<Point> road_squares;\nint segment_h[MAX_N][MAX_N];\nint segment_v[MAX_N][MAX_N];\nint num_h_segments = 0;\nint num_v_segments = 0;\nint total_road_squares = 0;\nint total_segments = 0;\n\nvector<Point> key_points;\nmap<Point, int> point_to_idx;\nint num_key_points = 0;\nint start_idx = -1;\n\nconst int MAX_KP = 300;\nlong long dist_mat[MAX_KP][MAX_KP];\nbitset<MAX_SEGMENTS> coverage_mat[MAX_KP][MAX_KP];\nvector<Point> path_mat[MAX_KP][MAX_KP];\n\nlong long dist_from_kp[MAX_KP][MAX_N][MAX_N];\n\nint dr[] = {-1, 1, 0, 0};\nint dc[] = {0, 0, -1, 1};\n\nbool is_road(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N && grid[r][c] != '#';\n}\n\nint get_cost(int r, int c) {\n    return grid[r][c] - '0';\n}\n\nvoid identify_segments() {\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            segment_h[i][j] = -1;\n            segment_v[i][j] = -1;\n        }\n    }\n\n    for(int i=0; i<N; ++i) {\n        int j = 0;\n        while(j < N) {\n            if (grid[i][j] == '#') { j++; continue; }\n            int start_j = j;\n            while(j < N && grid[i][j] != '#') j++;\n            for(int k=start_j; k<j; ++k) segment_h[i][k] = num_h_segments;\n            num_h_segments++;\n        }\n    }\n\n    for(int j=0; j<N; ++j) {\n        int i = 0;\n        while(i < N) {\n            if (grid[i][j] == '#') { i++; continue; }\n            int start_i = i;\n            while(i < N && grid[i][j] != '#') i++;\n            for(int k=start_i; k<i; ++k) segment_v[k][j] = num_v_segments;\n            num_v_segments++;\n        }\n    }\n    \n    total_segments = num_h_segments + num_v_segments;\n}\n\nvoid identify_key_points() {\n    set<Point> kp_set;\n    kp_set.insert({si, sj});\n\n    for(const auto& p : road_squares) {\n        int degree = 0;\n        for(int d=0; d<4; ++d) {\n            int nr = p.r + dr[d], nc = p.c + dc[d];\n            if(is_road(nr, nc)) degree++;\n        }\n        if(degree != 2) kp_set.insert(p);\n    }\n    \n    if((int)kp_set.size() > MAX_KP - 10) {\n        vector<Point> sorted_kp(kp_set.begin(), kp_set.end());\n        sort(sorted_kp.begin(), sorted_kp.end(), [&](const Point& a, const Point& b) {\n            return abs(a.r - si) + abs(a.c - sj) < abs(b.r - si) + abs(b.c - sj);\n        });\n        kp_set.clear();\n        for(int i=0; i<MAX_KP - 10 && i<(int)sorted_kp.size(); ++i) kp_set.insert(sorted_kp[i]);\n        kp_set.insert({si, sj});\n    }\n\n    for(const auto& p : kp_set) {\n        if(num_key_points >= MAX_KP) break;\n        point_to_idx[p] = num_key_points;\n        key_points.push_back(p);\n        if(p.r == si && p.c == sj) start_idx = num_key_points;\n        num_key_points++;\n    }\n}\n\nvoid compute_apsp() {\n    for(int i=0; i<num_key_points; ++i) {\n        for(int j=0; j<num_key_points; ++j) {\n            dist_mat[i][j] = INF;\n        }\n    }\n\n    static long long d_grid[MAX_N][MAX_N];\n    static bitset<MAX_SEGMENTS> c_grid[MAX_N][MAX_N];\n    static Point parent_grid[MAX_N][MAX_N];\n    static bool visited[MAX_N][MAX_N];\n\n    for(int src_idx = 0; src_idx < num_key_points; ++src_idx) {\n        Point src = key_points[src_idx];\n        \n        for(int i=0; i<N; ++i) {\n            for(int j=0; j<N; ++j) {\n                d_grid[i][j] = INF;\n                visited[i][j] = false;\n                dist_from_kp[src_idx][i][j] = INF;\n            }\n        }\n\n        priority_queue<pair<long long, Point>, vector<pair<long long, Point>>, greater<pair<long long, Point>>> pq;\n        \n        d_grid[src.r][src.c] = 0;\n        dist_from_kp[src_idx][src.r][src.c] = 0;\n        c_grid[src.r][src.c].reset();\n        if(segment_h[src.r][src.c] >= 0 && segment_h[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_h[src.r][src.c]);\n        if(segment_v[src.r][src.c] >= 0 && segment_v[src.r][src.c] < MAX_SEGMENTS) \n            c_grid[src.r][src.c].set(segment_v[src.r][src.c]);\n        \n        pq.push({0, src});\n        parent_grid[src.r][src.c] = {-1, -1};\n        \n        while(!pq.empty()) {\n            long long cost = pq.top().first;\n            Point u = pq.top().second;\n            pq.pop();\n\n            if(visited[u.r][u.c]) continue;\n            visited[u.r][u.c] = true;\n\n            if(point_to_idx.count(u)) {\n                int v_idx = point_to_idx[u];\n                dist_mat[src_idx][v_idx] = cost;\n                coverage_mat[src_idx][v_idx] = c_grid[u.r][u.c];\n                \n                vector<Point> path;\n                Point curr = u;\n                while(curr.r != -1) {\n                    path.push_back(curr);\n                    if(curr.r == src.r && curr.c == src.c) break;\n                    curr = parent_grid[curr.r][curr.c];\n                }\n                reverse(path.begin(), path.end());\n                path_mat[src_idx][v_idx] = path;\n            }\n\n            for(int d=0; d<4; ++d) {\n                int nr = u.r + dr[d], nc = u.c + dc[d];\n                if(is_road(nr, nc)) {\n                    long long new_cost = cost + get_cost(nr, nc);\n\n                    if(new_cost < d_grid[nr][nc]) {\n                        d_grid[nr][nc] = new_cost;\n                        dist_from_kp[src_idx][nr][nc] = new_cost;\n                        c_grid[nr][nc] = c_grid[u.r][u.c];\n                        if(segment_h[nr][nc] >= 0 && segment_h[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_h[nr][nc]);\n                        if(segment_v[nr][nc] >= 0 && segment_v[nr][nc] < MAX_SEGMENTS) \n                            c_grid[nr][nc].set(segment_v[nr][nc]);\n                        parent_grid[nr][nc] = u;\n                        pq.push({new_cost, {nr, nc}});\n                    }\n                }\n            }\n        }\n    }\n}\n\nvector<int> current_path;\nlong long current_dist = 0;\nbitset<MAX_SEGMENTS> current_cov;\nlong long best_dist = INF;\nvector<int> best_path;\nint best_coverage = 0;\n\nvoid ensure_start_end(vector<int>& path) {\n    if(path.empty()) {\n        path = {start_idx, start_idx};\n        return;\n    }\n    while(!path.empty() && path.front() != start_idx) path.erase(path.begin());\n    while(!path.empty() && path.back() != start_idx) path.pop_back();\n    if(path.empty()) path = {start_idx, start_idx};\n    else if((int)path.size() == 1) path.push_back(start_idx);\n}\n\nlong long calc_path_dist(const vector<int>& path) {\n    long long d = 0;\n    for(size_t i=0; i+1<path.size(); ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            d += dist_mat[path[i]][path[i+1]];\n    }\n    return d;\n}\n\nbitset<MAX_SEGMENTS> calc_path_cov(const vector<int>& path) {\n    bitset<MAX_SEGMENTS> c;\n    for(size_t i=0; i+1<path.size(); ++i) {\n        if(path[i] < num_key_points && path[i+1] < num_key_points)\n            c |= coverage_mat[path[i]][path[i+1]];\n    }\n    return c;\n}\n\nvoid update_state() {\n    current_dist = calc_path_dist(current_path);\n    current_cov = calc_path_cov(current_path);\n    best_coverage = (int)current_cov.count();\n}\n\nlong long energy() {\n    int covered_segs = (int)current_cov.count();\n    long long penalty = (long long)(total_segments - covered_segs) * 10000000LL;\n    return penalty + current_dist;\n}\n\n// Simple nearest-neighbor greedy initial solution\nvoid build_greedy_initial() {\n    vector<int> path = {start_idx};\n    vector<bool> visited(num_key_points, false);\n    if(start_idx >= 0) visited[start_idx] = true;\n    \n    int current = start_idx;\n    while(true) {\n        int best_next = -1;\n        long long best_d = INF;\n        \n        for(int kp = 0; kp < num_key_points; ++kp) {\n            if(visited[kp]) continue;\n            if(dist_mat[current][kp] < best_d) {\n                best_d = dist_mat[current][kp];\n                best_next = kp;\n            }\n        }\n        \n        if(best_next == -1 || best_d >= INF) break;\n        \n        visited[best_next] = true;\n        path.push_back(best_next);\n        current = best_next;\n    }\n    \n    path.push_back(start_idx);\n    current_path = path;\n    update_state();\n    best_path = current_path;\n    best_dist = current_dist;\n    best_coverage = (int)current_cov.count();\n}\n\nvoid solve_sa() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.7;\n\n    int iter = 0;\n    double temp = 50000.0;\n    double cooling = 0.9998;\n\n    while(true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        if(best_coverage >= total_segments && iter > 2000) {\n            if(time_limit - elapsed < 0.15) break;\n        }\n        \n        vector<int> next_path = current_path;\n        int type = rng() % 5;\n        \n        if((int)next_path.size() > 2) {\n            if(type == 0 && (int)next_path.size() > 3) {\n                int i = 1 + rng() % ((int)next_path.size() - 2);\n                int j = i + 1 + rng() % ((int)next_path.size() - 1 - i);\n                if(j >= (int)next_path.size() - 1) j = (int)next_path.size() - 2;\n                reverse(next_path.begin() + i, next_path.begin() + j + 1);\n            } else if(type == 1 && (int)next_path.size() > 3) {\n                int i = 1 + rng() % ((int)next_path.size() - 2);\n                int j = 1 + rng() % ((int)next_path.size() - 2);\n                swap(next_path[i], next_path[j]);\n            } else if(type == 2 || type == 3) {\n                int idx = 1 + rng() % ((int)next_path.size());\n                int kp = rng() % num_key_points;\n                next_path.insert(next_path.begin() + idx, kp);\n            } else {\n                if((int)next_path.size() > 3) {\n                    int idx = 1 + rng() % ((int)next_path.size() - 2);\n                    next_path.erase(next_path.begin() + idx);\n                }\n            }\n        } else {\n            int kp = rng() % num_key_points;\n            next_path.insert(next_path.begin() + 1, kp);\n        }\n\n        ensure_start_end(next_path);\n\n        long long next_dist = calc_path_dist(next_path);\n        if(next_dist >= INF) continue;\n        \n        bitset<MAX_SEGMENTS> next_cov = calc_path_cov(next_path);\n        int next_coverage = (int)next_cov.count();\n\n        long long current_energy = energy();\n        long long next_penalty = (long long)(total_segments - next_coverage) * 10000000LL;\n        long long next_energy = next_penalty + next_dist;\n\n        double delta = (double)(next_energy - current_energy);\n        bool accept = false;\n        if(delta < 0) accept = true;\n        else {\n            double prob = exp(-delta / temp);\n            if((double)rng() / rng.max() < prob) accept = true;\n        }\n\n        if(accept) {\n            current_path = next_path;\n            current_dist = next_dist;\n            current_cov = next_cov;\n        }\n        \n        if(next_coverage >= total_segments) {\n            if(next_dist < best_dist) {\n                best_dist = next_dist;\n                best_path = next_path;\n                best_coverage = next_coverage;\n            }\n        } else if(next_coverage > best_coverage) {\n            best_coverage = next_coverage;\n            best_path = next_path;\n            best_dist = next_dist;\n        }\n\n        temp *= cooling;\n        iter++;\n    }\n}\n\nvoid quick_greedy_fix() {\n    ensure_start_end(best_path);\n    \n    bitset<MAX_SEGMENTS> cov;\n    for(size_t i=0; i+1<best_path.size(); ++i) {\n        if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n            cov |= coverage_mat[best_path[i]][best_path[i+1]];\n    }\n    \n    if((int)cov.count() >= total_segments) return;\n\n    // Single pass, limited iterations\n    for(int fix_iter = 0; fix_iter < 50 && (int)cov.count() < total_segments; ++fix_iter) {\n        int missing_seg = -1;\n        for(int i=0; i<total_segments && i<MAX_SEGMENTS; ++i) {\n            if(!cov.test(i)) {\n                missing_seg = i;\n                break;\n            }\n        }\n        \n        if(missing_seg == -1) break;\n        \n        int best_kp = -1;\n        long long min_insert_cost = INF;\n        int best_pos = -1;\n\n        for(int kp=0; kp<num_key_points; ++kp) {\n            Point p = key_points[kp];\n            bool covers = (segment_h[p.r][p.c] == missing_seg || segment_v[p.r][p.c] == missing_seg);\n            \n            if(covers) {\n                for(size_t i=0; i+1<best_path.size(); ++i) {\n                    int u = best_path[i], v = best_path[i+1];\n                    if(u >= num_key_points || v >= num_key_points) continue;\n                    long long cost = dist_mat[u][kp] + dist_mat[kp][v] - dist_mat[u][v];\n                    if(cost < min_insert_cost) {\n                        min_insert_cost = cost;\n                        best_kp = kp;\n                        best_pos = (int)i + 1;\n                    }\n                }\n            }\n        }\n        \n        if(best_kp != -1 && best_pos != -1) {\n            best_path.insert(best_path.begin() + best_pos, best_kp);\n            ensure_start_end(best_path);\n            cov.reset();\n            for(size_t i=0; i+1<best_path.size(); ++i) {\n                if(best_path[i] < num_key_points && best_path[i+1] < num_key_points)\n                    cov |= coverage_mat[best_path[i]][best_path[i+1]];\n            }\n        } else {\n            break;\n        }\n    }\n}\n\nvoid output_solution() {\n    ensure_start_end(best_path);\n    \n    if(best_path.empty() || best_path.front() != start_idx || best_path.back() != start_idx) {\n        cout << \"\" << endl;\n        return;\n    }\n    \n    string res = \"\";\n    Point curr = {si, sj};\n    for(size_t i=0; i+1<best_path.size(); ++i) {\n        int u = best_path[i], v = best_path[i+1];\n        if(u >= num_key_points || v >= num_key_points) continue;\n        const auto& segment = path_mat[u][v];\n        for(size_t k=1; k<segment.size(); ++k) {\n            Point next = segment[k];\n            if(next.r == curr.r + 1) res += 'D';\n            else if(next.r == curr.r - 1) res += 'U';\n            else if(next.c == curr.c + 1) res += 'R';\n            else if(next.c == curr.c - 1) res += 'L';\n            curr = next;\n        }\n    }\n    cout << res << endl;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if(!(cin >> N >> si >> sj)) return 0;\n    grid.resize(N);\n    for(int i=0; i<N; ++i) cin >> grid[i];\n\n    for(int i=0; i<N; ++i) {\n        for(int j=0; j<N; ++j) {\n            if(grid[i][j] != '#') {\n                road_squares.push_back({i, j});\n                total_road_squares++;\n            }\n        }\n    }\n\n    identify_segments();\n    identify_key_points();\n    compute_apsp();\n\n    build_greedy_initial();\n    solve_sa();\n    quick_greedy_fix();\n    output_solution();\n\n    return 0;\n}","future-contest-2022-qual":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <numeric>\n#include <queue>\n#include <iomanip>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    \n    // Read initial input\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n    \n    // Read task difficulties\n    vector<vector<int>> d(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < K; j++) {\n            cin >> d[i][j];\n        }\n    }\n    \n    // Read dependencies\n    vector<vector<int>> deps(N);\n    vector<vector<int>> rev_deps(N);\n    vector<int> in_degree(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        u--; v--;\n        deps[v].push_back(u);\n        rev_deps[u].push_back(v);\n        in_degree[v]++;\n    }\n    \n    // Skill estimates (start with reasonable guess based on task difficulty distribution)\n    vector<vector<double>> s_est(M, vector<double>(K, 35.0));\n    vector<int> s_obs_count(M, 0);\n    \n    // Task status: -1 = not started, 0 = in progress, 1 = completed\n    vector<int> task_status(N, -1);\n    \n    // Member tracking\n    vector<int> member_task(M, -1);\n    vector<int> member_start_day(M, -1);\n    \n    // Observations for learning: (task_id, observed_days)\n    vector<vector<pair<int, int>>> member_obs(M);\n    \n    // Task priority (estimated remaining tasks in dependency chain)\n    vector<int> task_priority(N, 0);\n    \n    // Calculate task priorities using reverse topological order\n    for (int i = N - 1; i >= 0; i--) {\n        task_priority[i] = 1;\n        for (int next : rev_deps[i]) {\n            task_priority[i] = max(task_priority[i], task_priority[next] + 1);\n        }\n    }\n    \n    int day = 0;\n    int completed_count = 0;\n    \n    // Random number generator for tie-breaking\n    mt19937 rng(42);\n    \n    while (true) {\n        day++;\n        \n        // Read completion information\n        int n_completed;\n        cin >> n_completed;\n        \n        if (n_completed == -1) {\n            break;\n        }\n        \n        vector<int> completed_members(n_completed);\n        for (int i = 0; i < n_completed; i++) {\n            cin >> completed_members[i];\n            completed_members[i]--;\n        }\n        \n        // Process completions and update skill estimates\n        for (int member : completed_members) {\n            if (member_task[member] >= 0) {\n                int task = member_task[member];\n                int days_taken = day - member_start_day[member];\n                \n                task_status[task] = 1;\n                completed_count++;\n                \n                // Record observation\n                member_obs[member].push_back({task, days_taken});\n                s_obs_count[member]++;\n                \n                // Update skill estimate using observed data\n                // w = sum(max(0, d_k - s_k)) \u2248 days_taken (when w > 0)\n                // We try to adjust s_k to reduce the gap\n                if (days_taken > 1 && s_obs_count[member] <= 50) {\n                    // Early learning phase - more aggressive updates\n                    double learning_rate = 0.3 / min(10, s_obs_count[member]);\n                    \n                    for (int k = 0; k < K; k++) {\n                        double deficit = max(0.0, (double)d[task][k] - s_est[member][k]);\n                        // If task took long, increase skill estimate for skills where there was deficit\n                        if (deficit > 0) {\n                            s_est[member][k] += learning_rate * deficit * 0.5;\n                        }\n                        // Cap skill estimates reasonably\n                        s_est[member][k] = min(80.0, max(5.0, s_est[member][k]));\n                    }\n                }\n                \n                member_task[member] = -1;\n                member_start_day[member] = -1;\n            }\n        }\n        \n        // Check if all tasks completed\n        if (completed_count >= N) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Find ready tasks (all dependencies completed, not started)\n        vector<int> ready_tasks;\n        for (int i = 0; i < N; i++) {\n            if (task_status[i] == -1) {\n                bool all_deps_done = true;\n                for (int dep : deps[i]) {\n                    if (task_status[dep] != 1) {\n                        all_deps_done = false;\n                        break;\n                    }\n                }\n                if (all_deps_done) {\n                    ready_tasks.push_back(i);\n                }\n            }\n        }\n        \n        // Find idle members\n        vector<int> idle_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) {\n                idle_members.push_back(j);\n            }\n        }\n        \n        if (idle_members.empty() || ready_tasks.empty()) {\n            cout << 0 << endl;\n            cout.flush();\n            continue;\n        }\n        \n        // Calculate estimated completion time for each (member, task) pair\n        vector<vector<double>> est_time(M, vector<double>(N, 1e9));\n        for (int member : idle_members) {\n            for (int task : ready_tasks) {\n                double w = 0;\n                for (int k = 0; k < K; k++) {\n                    w += max(0.0, (double)d[task][k] - s_est[member][k]);\n                }\n                est_time[member][task] = (w == 0) ? 1.0 : max(1.0, w);\n            }\n        }\n        \n        // Greedy assignment: match tasks to members minimizing estimated time\n        // Prioritize high-priority tasks and good skill matches\n        vector<pair<int, int>> assignments;\n        vector<bool> task_assigned(ready_tasks.size(), false);\n        vector<bool> member_used(idle_members.size(), false);\n        \n        // Create assignment candidates with scores\n        vector<tuple<double, int, int, int>> candidates; // (score, priority, member_idx, task_idx)\n        for (size_t mi = 0; mi < idle_members.size(); mi++) {\n            for (size_t ti = 0; ti < ready_tasks.size(); ti++) {\n                int member = idle_members[mi];\n                int task = ready_tasks[ti];\n                double score = est_time[member][task] - task_priority[task] * 0.1;\n                candidates.push_back({score, task_priority[task], (int)mi, (int)ti});\n            }\n        }\n        \n        // Sort by score (lower is better)\n        sort(candidates.begin(), candidates.end());\n        \n        // Assign greedily\n        for (auto& [score, priority, mi, ti] : candidates) {\n            if (member_used[mi] || task_assigned[ti]) continue;\n            \n            int member = idle_members[mi];\n            int task = ready_tasks[ti];\n            \n            assignments.push_back({member + 1, task + 1});\n            member_used[mi] = true;\n            task_assigned[ti] = true;\n            \n            member_task[member] = task;\n            member_start_day[member] = day;\n            task_status[task] = 0;\n        }\n        \n        // Output assignments\n        cout << assignments.size();\n        for (auto& p : assignments) {\n            cout << \" \" << p.first << \" \" << p.second;\n        }\n        cout << endl;\n        cout.flush();\n        \n        // Output skill predictions for visualization (optional)\n        if (day % 50 == 1) {\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 << endl;\n            }\n            cout.flush();\n        }\n    }\n    \n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\n#include <random>\n#include <chrono>\nusing namespace std;\n\nstruct Order {\n    int id;\n    int ax, ay, cx, cy;\n};\n\nstruct Point {\n    int x, y;\n    int order_id;\n    bool is_pickup;\n};\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nconst int OFFICE_X = 400, OFFICE_Y = 400;\nconst int NUM_ORDERS = 1000;\nconst int SELECT_COUNT = 50;\n\n// Global buffers to avoid reallocation\nstatic vector<bool> g_picked;\nstatic vector<bool> g_pickup_done;\nstatic vector<bool> g_delivery_done;\nstatic vector<pair<double, int>> g_scores;\nstatic vector<tuple<int, int, bool>> g_candidates;\n\nvoid init_buffers() {\n    g_picked.resize(NUM_ORDERS);\n    g_pickup_done.resize(NUM_ORDERS);\n    g_delivery_done.resize(NUM_ORDERS);\n    g_scores.reserve(NUM_ORDERS);\n    g_candidates.reserve(SELECT_COUNT * 2);\n}\n\nlong long calc_distance(const vector<Point>& route) {\n    long long 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\ninline bool is_valid_route(const vector<Point>& route) {\n    fill(g_picked.begin(), g_picked.end(), false);\n    for (const auto& p : route) {\n        if (p.order_id == -1) continue;\n        if (p.is_pickup) {\n            g_picked[p.order_id] = true;\n        } else {\n            if (!g_picked[p.order_id]) return false;\n        }\n    }\n    return true;\n}\n\n// Greedy nearest-neighbor route construction with lookahead\nvector<Point> build_greedy_route(const vector<int>& selected, const vector<Order>& orders, mt19937& rng, double randomness = 0.3) {\n    vector<Point> route;\n    route.reserve(SELECT_COUNT * 2 + 2);\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    fill(g_pickup_done.begin(), g_pickup_done.end(), false);\n    fill(g_delivery_done.begin(), g_delivery_done.end(), false);\n    \n    int remaining = SELECT_COUNT * 2;\n    int cur_x = OFFICE_X, cur_y = OFFICE_Y;\n    \n    while (remaining > 0) {\n        g_candidates.clear();\n        \n        for (int idx : selected) {\n            if (!g_pickup_done[idx] && !g_delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].ax, orders[idx].ay);\n                int lookahead = manhattan(orders[idx].ax, orders[idx].ay, orders[idx].cx, orders[idx].cy);\n                g_candidates.emplace_back(dist + lookahead / 3, idx, true);\n            }\n            if (g_pickup_done[idx] && !g_delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].cx, orders[idx].cy);\n                int lookahead = manhattan(orders[idx].cx, orders[idx].cy, OFFICE_X, OFFICE_Y);\n                g_candidates.emplace_back(dist + lookahead / 4, idx, false);\n            }\n        }\n        \n        if (g_candidates.empty()) break;\n        \n        if (g_candidates.size() > 1) {\n            sort(g_candidates.begin(), g_candidates.end());\n            int k = min((int)g_candidates.size(), 2 + (int)(randomness * 6));\n            int choice = uniform_int_distribution<int>(0, k - 1)(rng);\n            auto [score, order_idx, is_pickup] = g_candidates[choice];\n            \n            if (is_pickup) {\n                route.push_back({orders[order_idx].ax, orders[order_idx].ay, order_idx, true});\n                g_pickup_done[order_idx] = true;\n                cur_x = orders[order_idx].ax;\n                cur_y = orders[order_idx].ay;\n            } else {\n                route.push_back({orders[order_idx].cx, orders[order_idx].cy, order_idx, false});\n                g_delivery_done[order_idx] = true;\n                cur_x = orders[order_idx].cx;\n                cur_y = orders[order_idx].cy;\n            }\n        } else {\n            auto [score, order_idx, is_pickup] = g_candidates[0];\n            if (is_pickup) {\n                route.push_back({orders[order_idx].ax, orders[order_idx].ay, order_idx, true});\n                g_pickup_done[order_idx] = true;\n            } else {\n                route.push_back({orders[order_idx].cx, orders[order_idx].cy, order_idx, false});\n                g_delivery_done[order_idx] = true;\n            }\n        }\n        remaining--;\n    }\n    \n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    return route;\n}\n\n// Pure nearest-neighbor without lookahead (different heuristic)\nvector<Point> build_pure_nn_route(const vector<int>& selected, const vector<Order>& orders, mt19937& rng) {\n    vector<Point> route;\n    route.reserve(SELECT_COUNT * 2 + 2);\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    vector<bool> pickup_done(NUM_ORDERS, false);\n    vector<bool> delivery_done(NUM_ORDERS, false);\n    int remaining = SELECT_COUNT * 2;\n    \n    int cur_x = OFFICE_X, cur_y = OFFICE_Y;\n    \n    while (remaining > 0) {\n        vector<pair<int, int>> candidates;\n        \n        for (int idx : selected) {\n            if (!pickup_done[idx] && !delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].ax, orders[idx].ay);\n                candidates.emplace_back(dist, idx * 2); // pickup\n            }\n            if (pickup_done[idx] && !delivery_done[idx]) {\n                int dist = manhattan(cur_x, cur_y, orders[idx].cx, orders[idx].cy);\n                candidates.emplace_back(dist, idx * 2 + 1); // delivery\n            }\n        }\n        \n        if (candidates.empty()) break;\n        \n        sort(candidates.begin(), candidates.end());\n        int k = min((int)candidates.size(), 2);\n        int choice = uniform_int_distribution<int>(0, k - 1)(rng);\n        int encoded = candidates[choice].second;\n        int idx = encoded / 2;\n        bool is_pickup = (encoded % 2 == 0);\n        \n        if (is_pickup) {\n            route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n            pickup_done[idx] = true;\n            cur_x = orders[idx].ax;\n            cur_y = orders[idx].ay;\n        } else {\n            route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n            delivery_done[idx] = true;\n            cur_x = orders[idx].cx;\n            cur_y = orders[idx].cy;\n        }\n        remaining--;\n    }\n    \n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    return route;\n}\n\n// Angle-based route construction (all pickups before all deliveries)\nvector<Point> build_angle_route(const vector<int>& selected, const vector<Order>& orders) {\n    vector<Point> route;\n    route.reserve(SELECT_COUNT * 2 + 2);\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    vector<pair<double, int>> pickups;\n    pickups.reserve(selected.size());\n    for (int idx : selected) {\n        double angle = atan2(orders[idx].ay - OFFICE_Y, orders[idx].ax - OFFICE_X);\n        pickups.emplace_back(angle, idx);\n    }\n    sort(pickups.begin(), pickups.end());\n    \n    for (auto& p : pickups) {\n        int idx = p.second;\n        route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n    }\n    \n    vector<pair<double, int>> deliveries;\n    deliveries.reserve(selected.size());\n    for (int idx : selected) {\n        double angle = atan2(orders[idx].cy - OFFICE_Y, orders[idx].cx - OFFICE_X);\n        deliveries.emplace_back(angle, idx);\n    }\n    sort(deliveries.begin(), deliveries.end());\n    \n    for (auto& p : deliveries) {\n        int idx = p.second;\n        route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n    }\n    \n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    return route;\n}\n\n// Hybrid route: alternate between greedy and angle-based ordering\nvector<Point> build_hybrid_route(const vector<int>& selected, const vector<Order>& orders, mt19937& rng) {\n    vector<Point> route;\n    route.reserve(SELECT_COUNT * 2 + 2);\n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    \n    vector<bool> pickup_done(NUM_ORDERS, false);\n    vector<bool> delivery_done(NUM_ORDERS, false);\n    int remaining = SELECT_COUNT * 2;\n    \n    int cur_x = OFFICE_X, cur_y = OFFICE_Y;\n    \n    while (remaining > 0) {\n        vector<pair<double, int>> pickups, deliveries;\n        for (int idx : selected) {\n            if (!pickup_done[idx] && !delivery_done[idx]) {\n                double angle = atan2(orders[idx].ay - OFFICE_Y, orders[idx].ax - OFFICE_X);\n                int dist = manhattan(cur_x, cur_y, orders[idx].ax, orders[idx].ay);\n                pickups.emplace_back(dist * 0.5 + angle * 100, idx);\n            }\n            if (pickup_done[idx] && !delivery_done[idx]) {\n                double angle = atan2(orders[idx].cy - OFFICE_Y, orders[idx].cx - OFFICE_X);\n                int dist = manhattan(cur_x, cur_y, orders[idx].cx, orders[idx].cy);\n                deliveries.emplace_back(dist * 0.5 + angle * 100, idx);\n            }\n        }\n        \n        bool do_pickup = false;\n        \n        if (!pickups.empty() && deliveries.empty()) {\n            do_pickup = true;\n        } else if (pickups.empty() && !deliveries.empty()) {\n            do_pickup = false;\n        } else if (!pickups.empty() && !deliveries.empty()) {\n            int pending_pickups = 0;\n            for (int idx : selected) if (pickup_done[idx] && !delivery_done[idx]) pending_pickups++;\n            do_pickup = (pending_pickups < 10);\n        }\n        \n        if (do_pickup && !pickups.empty()) {\n            sort(pickups.begin(), pickups.end());\n            int k = min((int)pickups.size(), 3);\n            int choice = uniform_int_distribution<int>(0, k - 1)(rng);\n            int best_idx = pickups[choice].second;\n            route.push_back({orders[best_idx].ax, orders[best_idx].ay, best_idx, true});\n            pickup_done[best_idx] = true;\n            cur_x = orders[best_idx].ax;\n            cur_y = orders[best_idx].ay;\n        } else if (!deliveries.empty()) {\n            sort(deliveries.begin(), deliveries.end());\n            int k = min((int)deliveries.size(), 3);\n            int choice = uniform_int_distribution<int>(0, k - 1)(rng);\n            int best_idx = deliveries[choice].second;\n            route.push_back({orders[best_idx].cx, orders[best_idx].cy, best_idx, false});\n            delivery_done[best_idx] = true;\n            cur_x = orders[best_idx].cx;\n            cur_y = orders[best_idx].cy;\n        }\n        \n        remaining--;\n    }\n    \n    route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n    return route;\n}\n\nvector<int> select_orders(const vector<Order>& orders, mt19937& rng, bool use_clustering = false, int top_k = 100) {\n    g_scores.clear();\n    \n    for (int i = 0; i < NUM_ORDERS; i++) {\n        int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n        int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n        int return_dist = manhattan(orders[i].cx, orders[i].cy, OFFICE_X, OFFICE_Y);\n        double score = pickup_dist + delivery_dist * 1.5 + return_dist;\n        score += uniform_real_distribution<double>(0, 50)(rng);\n        g_scores.emplace_back(score, i);\n    }\n    \n    sort(g_scores.begin(), g_scores.end());\n    \n    if (!use_clustering) {\n        vector<int> selected;\n        selected.reserve(SELECT_COUNT);\n        for (int i = 0; i < SELECT_COUNT; i++) {\n            selected.push_back(g_scores[i].second);\n        }\n        return selected;\n    }\n    \n    vector<int> selected;\n    selected.reserve(SELECT_COUNT);\n    static vector<bool> used;\n    if (used.size() != NUM_ORDERS) used.resize(NUM_ORDERS);\n    fill(used.begin(), used.end(), false);\n    \n    vector<pair<double, int>> candidates;\n    candidates.reserve(top_k);\n    for (int i = 0; i < min(top_k, NUM_ORDERS); i++) {\n        candidates.push_back(g_scores[i]);\n    }\n    \n    while ((int)selected.size() < SELECT_COUNT && !candidates.empty()) {\n        if (selected.empty()) {\n            selected.push_back(candidates[0].second);\n            used[candidates[0].second] = true;\n            candidates.erase(candidates.begin());\n        } else {\n            int best_idx = 0;\n            double best_score = 1e18;\n            \n            for (int i = 0; i < min(15, (int)candidates.size()); i++) {\n                int order_idx = candidates[i].second;\n                double min_dist = 1e18;\n                \n                for (int sel : selected) {\n                    double d = min({\n                        (double)manhattan(orders[order_idx].ax, orders[order_idx].ay, orders[sel].ax, orders[sel].ay),\n                        (double)manhattan(orders[order_idx].cx, orders[order_idx].cy, orders[sel].cx, orders[sel].cy)\n                    });\n                    min_dist = min(min_dist, d);\n                }\n                \n                double office_dist = manhattan(OFFICE_X, OFFICE_Y, orders[order_idx].ax, orders[order_idx].ay);\n                double combined = min_dist * 0.6 + office_dist * 0.4;\n                \n                if (combined < best_score) {\n                    best_score = combined;\n                    best_idx = i;\n                }\n            }\n            \n            selected.push_back(candidates[best_idx].second);\n            used[candidates[best_idx].second] = true;\n            candidates.erase(candidates.begin() + best_idx);\n        }\n    }\n    \n    while ((int)selected.size() < SELECT_COUNT && !candidates.empty()) {\n        selected.push_back(candidates.back().second);\n        candidates.pop_back();\n    }\n    \n    return selected;\n}\n\nbool try_swap_order(vector<int>& selected, vector<bool>& is_selected, const vector<Order>& orders, \n                    long long& best_dist, vector<Point>& best_route, mt19937& rng) {\n    int remove_idx = uniform_int_distribution<int>(0, SELECT_COUNT - 1)(rng);\n    int remove_order = selected[remove_idx];\n    \n    g_scores.clear();\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        if (!is_selected[i]) {\n            int pickup_dist = manhattan(OFFICE_X, OFFICE_Y, orders[i].ax, orders[i].ay);\n            int delivery_dist = manhattan(orders[i].ax, orders[i].ay, orders[i].cx, orders[i].cy);\n            double score = pickup_dist + delivery_dist * 1.5;\n            g_scores.emplace_back(score, i);\n        }\n    }\n    sort(g_scores.begin(), g_scores.end());\n    \n    for (int try_idx = 0; try_idx < min(15, (int)g_scores.size()); try_idx++) {\n        int add_order = g_scores[try_idx].second;\n        \n        vector<int> new_selected = selected;\n        new_selected[remove_idx] = add_order;\n        \n        is_selected[remove_order] = false;\n        is_selected[add_order] = true;\n        \n        vector<Point> new_route = build_greedy_route(new_selected, orders, rng, 0.2);\n        long long new_dist = calc_distance(new_route);\n        \n        if (new_dist < best_dist) {\n            selected = new_selected;\n            best_dist = new_dist;\n            best_route = new_route;\n            return true;\n        } else {\n            is_selected[remove_order] = true;\n            is_selected[add_order] = false;\n        }\n    }\n    \n    return false;\n}\n\n// Safe simulated annealing with configurable move weights\nvoid optimize_route_safe(vector<Point>& route, long long& best_dist, vector<Point>& best_route, \n                         mt19937& rng, const chrono::steady_clock::time_point& start_time, double end_time,\n                         double w1 = 0.6, double w2 = 0.25, double w3 = 0.15) {\n    double temperature = 12000.0;\n    int iterations = 0;\n    int no_improve_count = 0;\n    \n    vector<double> move_weights = {w1, w2, w3};\n    \n    while (temperature > 0.5) {\n        iterations++;\n        \n        if (iterations % 5000 == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > end_time) break;\n        }\n        \n        double r = uniform_real_distribution<double>(0, 1)(rng);\n        int move_type = 0;\n        double cumsum = 0;\n        for (int i = 0; i < 3; i++) {\n            cumsum += move_weights[i];\n            if (r < cumsum) {\n                move_type = i;\n                break;\n            }\n        }\n        \n        bool improved = false;\n        \n        if (move_type == 0) {\n            int i = uniform_int_distribution<int>(1, (int)route.size() - 3)(rng);\n            int j = uniform_int_distribution<int>(i + 1, (int)route.size() - 2)(rng);\n            \n            vector<Point> new_route = route;\n            reverse(new_route.begin() + i, new_route.begin() + j + 1);\n            \n            if (is_valid_route(new_route)) {\n                long long new_dist = calc_distance(new_route);\n                double delta = new_dist - best_dist;\n                \n                if (delta < 0 || exp(-delta / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                    route = new_route;\n                    if (new_dist < best_dist) {\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                    }\n                }\n            }\n        } else if (move_type == 1) {\n            int i = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            int j = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            \n            if (i != j) {\n                vector<Point> new_route = route;\n                swap(new_route[i], new_route[j]);\n                \n                if (is_valid_route(new_route)) {\n                    long long new_dist = calc_distance(new_route);\n                    if (new_dist < best_dist) {\n                        route = new_route;\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                    } else if (exp(-(new_dist - best_dist) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                        route = new_route;\n                    }\n                }\n            }\n        } else {\n            int pos = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            int new_pos = uniform_int_distribution<int>(1, (int)route.size() - 2)(rng);\n            \n            if (pos != new_pos) {\n                vector<Point> new_route = route;\n                Point p = new_route[pos];\n                new_route.erase(new_route.begin() + pos);\n                int insert_pos = new_pos;\n                if (insert_pos > pos) insert_pos--;\n                new_route.insert(new_route.begin() + insert_pos, p);\n                \n                if (is_valid_route(new_route)) {\n                    long long new_dist = calc_distance(new_route);\n                    if (new_dist < best_dist) {\n                        route = new_route;\n                        best_dist = new_dist;\n                        best_route = route;\n                        improved = true;\n                    } else if (exp(-(new_dist - best_dist) / temperature) > uniform_real_distribution<double>(0, 1)(rng)) {\n                        route = new_route;\n                    }\n                }\n            }\n        }\n        \n        if (improved) {\n            no_improve_count = 0;\n            temperature = min(12000.0, temperature * 1.15);\n        } else {\n            no_improve_count++;\n            if (no_improve_count > 10000) {\n                temperature *= 0.5;\n                no_improve_count = 0;\n            }\n        }\n        \n        temperature *= 0.9998;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    init_buffers();\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.98; // Aggressive - 20ms buffer\n    \n    // Read input\n    vector<Order> orders(NUM_ORDERS);\n    for (int i = 0; i < NUM_ORDERS; i++) {\n        orders[i].id = i + 1;\n        cin >> orders[i].ax >> orders[i].ay >> orders[i].cx >> orders[i].cy;\n    }\n    \n    // 12 strategies with maximum diversity\n    // 5 greedy (standard), 1 pure NN, 2 angle, 2 hybrid, 2 greedy with different params\n    vector<tuple<long long, double, bool, int, int, double, double, double>> strategies = {\n        // seed, randomness, clustering, route_type, top_k, w1, w2, w3\n        // route_type: 0=greedy, 1=pure_nn, 2=angle, 3=hybrid\n        {42, 0.3, false, 0, 100, 0.6, 0.25, 0.15},\n        {123, 0.5, false, 0, 100, 0.6, 0.25, 0.15},\n        {456, 0.2, false, 0, 100, 0.6, 0.25, 0.15},\n        {789, 0.4, true, 0, 100, 0.6, 0.25, 0.15},\n        {1000, 0.3, true, 0, 150, 0.6, 0.25, 0.15}, // Different top_k\n        {2000, 0.0, false, 1, 100, 0.6, 0.25, 0.15}, // Pure NN\n        {3000, 0.0, false, 2, 100, 0.6, 0.25, 0.15},\n        {4000, 0.0, false, 2, 100, 0.6, 0.25, 0.15},\n        {5000, 0.3, false, 3, 100, 0.6, 0.25, 0.15},\n        {6000, 0.4, true, 3, 100, 0.6, 0.25, 0.15},\n        {7000, 0.3, false, 0, 100, 0.7, 0.2, 0.1},  // More 2-opt\n        {8000, 0.3, false, 0, 100, 0.5, 0.3, 0.2}   // More swap/relocate\n    };\n    \n    long long global_best_dist = LLONG_MAX;\n    vector<Point> global_best_route;\n    vector<int> global_best_selected;\n    \n    for (auto& [seed, randomness, use_clustering, route_type, top_k, w1, w2, w3] : strategies) {\n        auto iter_start = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(iter_start - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        mt19937 rng(seed);\n        \n        vector<int> selected = select_orders(orders, rng, use_clustering, top_k);\n        vector<bool> is_selected(NUM_ORDERS, false);\n        for (int idx : selected) is_selected[idx] = true;\n        \n        vector<Point> route;\n        if (route_type == 0) {\n            route = build_greedy_route(selected, orders, rng, randomness);\n        } else if (route_type == 1) {\n            route = build_pure_nn_route(selected, orders, rng);\n        } else if (route_type == 2) {\n            route = build_angle_route(selected, orders);\n        } else {\n            route = build_hybrid_route(selected, orders, rng);\n        }\n        \n        if (!is_valid_route(route)) {\n            continue;\n        }\n        \n        long long cur_dist = calc_distance(route);\n        \n        vector<Point> best_route = route;\n        long long best_dist = cur_dist;\n        \n        // 0.11s per seed (12 strategies need slightly less time each)\n        optimize_route_safe(route, best_dist, best_route, rng, start_time, elapsed + 0.11, w1, w2, w3);\n        \n        // 28 order swap iterations\n        for (int swap_iter = 0; swap_iter < 28; swap_iter++) {\n            auto now = chrono::steady_clock::now();\n            double elapsed2 = chrono::duration<double>(now - start_time).count();\n            if (elapsed2 > TIME_LIMIT) break;\n            \n            if (try_swap_order(selected, is_selected, orders, best_dist, best_route, rng)) {\n                route = best_route;\n                optimize_route_safe(route, best_dist, best_route, rng, start_time, elapsed2 + 0.015, w1, w2, w3);\n            }\n        }\n        \n        if (best_dist < global_best_dist) {\n            global_best_dist = best_dist;\n            global_best_route = best_route;\n            global_best_selected = selected;\n        }\n    }\n    \n    // Final intensive optimization - use ALL remaining time (0.4s minimum)\n    if (!global_best_route.empty()) {\n        mt19937 final_rng(99999);\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = max(0.4, TIME_LIMIT - elapsed);\n        \n        if (remaining > 0.1) {\n            vector<Point> route = global_best_route;\n            long long best_dist = global_best_dist;\n            vector<Point> best_route = global_best_route;\n            \n            optimize_route_safe(route, best_dist, best_route, final_rng, start_time, elapsed + remaining, 0.6, 0.25, 0.15);\n            \n            if (best_dist < global_best_dist) {\n                global_best_dist = best_dist;\n                global_best_route = best_route;\n            }\n        }\n    }\n    \n    // Final validation before output (safety net)\n    if (!is_valid_route(global_best_route)) {\n        vector<Point> valid_route;\n        valid_route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n        for (int idx : global_best_selected) {\n            valid_route.push_back({orders[idx].ax, orders[idx].ay, idx, true});\n        }\n        for (int idx : global_best_selected) {\n            valid_route.push_back({orders[idx].cx, orders[idx].cy, idx, false});\n        }\n        valid_route.push_back({OFFICE_X, OFFICE_Y, -1, false});\n        global_best_route = valid_route;\n    }\n    \n    // Output\n    cout << SELECT_COUNT;\n    for (int idx : global_best_selected) {\n        cout << \" \" << orders[idx].id;\n    }\n    cout << endl;\n    \n    cout << global_best_route.size();\n    for (auto& p : global_best_route) {\n        cout << \" \" << p.x << \" \" << p.y;\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc007":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <numeric>\n#include <algorithm>\n\nusing namespace std;\n\nstruct UnionFind {\n    vector<int> parent;\n    vector<int> size;\n    int components;\n    \n    UnionFind(int n) : parent(n), size(n, 1), components(n) {\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        }\n        return parent[x];\n    }\n    \n    bool unite(int x, int y) {\n        int px = find(x);\n        int py = find(y);\n        if (px == py) return false;\n        \n        if (size[px] < size[py]) swap(px, py);\n        parent[py] = px;\n        size[px] += size[py];\n        components--;\n        return true;\n    }\n    \n    bool same(int x, int y) {\n        return find(x) == find(y);\n    }\n    \n    int componentSize(int x) {\n        return size[find(x)];\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    const int TARGET_EDGES = N - 1;  // 399 edges for MST\n    \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    vector<pair<int, int>> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].first >> edges[i].second;\n    }\n    \n    UnionFind uf(N);\n    int edges_selected = 0;\n    int inter_component_selected = 0;\n    \n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        \n        int u = edges[i].first;\n        int v = edges[i].second;\n        \n        double dx = coords[u].first - coords[v].first;\n        double dy = coords[u].second - coords[v].second;\n        double d = round(sqrt(dx * dx + dy * dy));\n        if (d < 1) d = 1;\n        \n        bool different_components = !uf.same(u, v);\n        bool accept = false;\n        \n        int components_left = uf.components;\n        int edges_left = M - i;\n        int needed = components_left - 1;\n        \n        // Progress through the edge stream (0.0 to 1.0)\n        double progress = (double)i / M;\n        \n        // CRITICAL SAFETY: If we don't have enough edges left to connect, MUST accept\n        if (different_components && needed >= edges_left) {\n            accept = true;\n        }\n        // EMERGENCY MODE 1: Last 200 edges, accept ALL inter-component edges\n        else if (i >= M - 200 && different_components && components_left > 1) {\n            accept = true;\n        }\n        // EMERGENCY MODE 2: Last 350 edges, very lenient (2.9\u00d7d)\n        else if (i >= M - 350 && different_components && components_left > 1) {\n            if (l <= 2.9 * d) {\n                accept = true;\n            }\n        }\n        // EMERGENCY MODE 3: Last 550 edges, lenient (2.75\u00d7d)\n        else if (i >= M - 550 && different_components && components_left > 1) {\n            double threshold = 2.75 * d;\n            if (components_left > 30) threshold = 2.85 * d;\n            if (components_left > 80) threshold = 2.9 * d;\n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Late stage (550-1000 from end): moderately lenient - UNCHANGED\n        else if (i >= M - 1000 && different_components && components_left > 1) {\n            double threshold = 2.4 * d;\n            if (components_left > 50) threshold = 2.6 * d;\n            if (components_left > 100) threshold = 2.7 * d;\n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Mid stage (1000-1500 from end): balanced - UNCHANGED\n        else if (i >= M - 1500 && different_components && components_left > 1) {\n            double threshold = 2.15 * d;\n            if (components_left > 80) threshold = 2.3 * d;\n            if (components_left > 150) threshold = 2.4 * d;\n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Normal mode: inter-component edges - UNCHANGED\n        else if (different_components) {\n            // Start at 2.0d and increase to 2.4d by 70% progress (PROVEN SAFE)\n            double base_threshold = 2.0 + 0.4 * min(1.0, progress / 0.7);\n            double threshold = base_threshold * d;\n            \n            // Adjust based on components remaining (5 tiers for granularity)\n            if (components_left > 250) {\n                threshold = min(threshold, 2.3 * d);\n            } else if (components_left > 150) {\n                threshold = min(threshold, 2.2 * d);\n            } else if (components_left > 80) {\n                threshold = min(threshold, 2.1 * d);\n            } else if (components_left > 40) {\n                threshold = min(threshold, 2.0 * d);\n            }\n            \n            // Adjust based on selection rate (slightly tighter tracking)\n            int target_by_now = (int)(progress * (TARGET_EDGES + 33));\n            \n            if (inter_component_selected < target_by_now - 18) {\n                // Behind: be more lenient\n                threshold = min(threshold, 2.5 * d);\n            } else if (inter_component_selected > target_by_now + 22) {\n                // Ahead: be more selective\n                threshold = max(1.95 * d, threshold - 0.08 * d);\n            }\n            \n            // Prioritize edges connecting larger components (5 tiers - slightly refined)\n            int size_u = uf.componentSize(u);\n            int size_v = uf.componentSize(v);\n            int combined_size = size_u + size_v;\n            \n            if (combined_size > N * 0.65) {\n                // Merging very large components: strongest bonus\n                threshold = min(threshold, 2.25 * d);\n            } else if (combined_size > N * 0.45) {\n                threshold = min(threshold, 2.15 * d);\n            } else if (combined_size > N * 0.25) {\n                threshold = min(threshold, 2.05 * d);\n            } else if (combined_size > N * 0.1) {\n                threshold = min(threshold, 2.0 * d);\n            }\n            \n            // Strong bonus for connecting isolated vertices (size 1)\n            if (size_u == 1 || size_v == 1) {\n                threshold = min(threshold, 2.1 * d);\n            }\n            \n            if (l <= threshold) {\n                accept = true;\n            }\n        }\n        // Intra-component edges: very selective - OPTIMIZED (SAFE)\n        else {\n            // These edges form cycles and add cost without helping connectivity\n            // Can be aggressive here without risking connectivity\n            double intra_threshold = 1.08 * d;\n            \n            // More granular early relaxation (4 stages)\n            if (progress < 0.08) {\n                intra_threshold = 1.18 * d;\n            } else if (progress < 0.15) {\n                intra_threshold = 1.12 * d;\n            } else if (progress < 0.25) {\n                intra_threshold = 1.08 * d;\n            } else if (progress < 0.4) {\n                intra_threshold = 1.05 * d;\n            }\n            \n            if (l <= intra_threshold) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            cout << 1 << \"\\n\";\n            if (uf.unite(u, v)) {\n                inter_component_selected++;\n            }\n            edges_selected++;\n        } else {\n            cout << 0 << \"\\n\";\n        }\n        \n        cout.flush();\n    }\n    \n    return 0;\n}","ahc008":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n#include <cstring>\n\nusing namespace std;\n\n// Structure to represent a position\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\n// Global variables\nint N, M;\nvector<Pos> pets;\nvector<int> pet_types;\nvector<Pos> humans;\nbool walls[32][32]; // Global wall state\nint pet_sum[32][32]; // Prefix sum of pet positions\n\n// Target zone\nint target_r1, target_r2, target_c1, target_c2;\nbool zone_locked = false; // If true, don't search for new zone for a while\nint turns_since_rezone = 0;\n\n// Check bounds\nbool in_grid(int r, int c) {\n    return r >= 0 && r < 30 && c >= 0 && c < 30;\n}\n\n// Update prefix sum of pet positions\nvoid update_pet_sum() {\n    int grid[32][32] = {0};\n    for(const auto& p : pets) {\n        if (in_grid(p.r, p.c)) {\n            grid[p.r][p.c]++;\n        }\n    }\n    // Compute 2D prefix sum\n    memset(pet_sum, 0, sizeof(pet_sum));\n    for(int i=0; i<30; ++i) {\n        for(int j=0; j<30; ++j) {\n            pet_sum[i+1][j+1] = grid[i][j] + pet_sum[i][j+1] + pet_sum[i+1][j] - pet_sum[i][j];\n        }\n    }\n}\n\n// Count pets in rectangle [r1, r2] x [c1, c2] (0-based inclusive)\nint count_pets(int r1, int c1, int r2, int c2) {\n    if (r1 > r2 || c1 > c2) return 0;\n    r1 = max(0, r1); c1 = max(0, c1);\n    r2 = min(29, r2); c2 = min(29, c2);\n    return pet_sum[r2+1][c2+1] - pet_sum[r1][c2+1] - pet_sum[r2+1][c1] + pet_sum[r1][c1];\n}\n\n// Evaluate a zone\nint evaluate_zone(int r1, int r2, int c1, int c2) {\n    if (r1 > r2 || c1 > c2) return -2000000;\n    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n    \n    // Critical: No pets inside\n    if (count_pets(r1, c1, r2, c2) > 0) {\n        return -1000000; \n    }\n    \n    // Penalty for pets adjacent to perimeter\n    int pets_adjacent = 0;\n    for(const auto& p : pets) {\n        int closest_r = max(r1, min(r2, p.r));\n        int closest_c = max(c1, min(c2, p.c));\n        int dist = abs(p.r - closest_r) + abs(p.c - closest_c);\n        if (dist == 1) {\n            pets_adjacent++;\n        }\n    }\n    \n    return area - pets_adjacent * 10;\n}\n\nvoid find_best_zone() {\n    int best_score = -2000000;\n    int best_r1 = 5, best_r2 = 24, best_c1 = 5, best_c2 = 24;\n    \n    for (int r1 = 0; r1 < 30; ++r1) {\n        for (int r2 = r1; r2 < 30; ++r2) {\n            for (int c1 = 0; c1 < 30; ++c1) {\n                for (int c2 = c1; c2 < 30; ++c2) {\n                    int score = evaluate_zone(r1, r2, c1, c2);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1;\n                        best_r2 = r2;\n                        best_c1 = c1;\n                        best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n    \n    target_r1 = best_r1;\n    target_r2 = best_r2;\n    target_c1 = best_c1;\n    target_c2 = best_c2;\n    \n    if (best_score > -500000) {\n        zone_locked = true;\n        turns_since_rezone = 0;\n    } else {\n        zone_locked = false;\n    }\n}\n\n// Get perimeter cells of the target zone\nvector<Pos> get_perimeter() {\n    vector<Pos> cells;\n    for (int c = target_c1; c <= target_c2; ++c) {\n        cells.push_back({target_r1, c});\n        if (target_r2 != target_r1) cells.push_back({target_r2, c});\n    }\n    for (int r = target_r1 + 1; r < target_r2; ++r) {\n        cells.push_back({r, target_c1});\n        if (target_c2 != target_c1) cells.push_back({r, target_c2});\n    }\n    return cells;\n}\n\n// Check if building at (r, c) is safe\nbool can_build(int r, int c, const vector<Pos>& current_humans) {\n    if (!in_grid(r, c)) return false;\n    if (walls[r][c]) return false; // Already a wall\n    \n    // Check if any human is at this position\n    for (const auto& h : current_humans) {\n        if (h.r == r && h.c == c) {\n            return false;\n        }\n    }\n    \n    // Check if any pet is at this position\n    for (const auto& p : pets) {\n        if (p.r == r && p.c == c) {\n            return false;\n        }\n    }\n    \n    // Check adjacency to pets (cannot build adjacent to pets)\n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    for (const auto& p : pets) {\n        for (int k = 0; k < 4; ++k) {\n            if (p.r + dr[k] == r && p.c + dc[k] == c) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// BFS for human movement avoiding walls\nPos get_next_move(Pos start, Pos target, const bool grid[32][32]) {\n    if (start == target) return start;\n    \n    queue<Pos> q;\n    q.push(start);\n    int dist[32][32];\n    Pos parent[32][32];\n    for(int i=0; i<32; ++i) for(int j=0; j<32; ++j) {\n        dist[i][j] = -1;\n        parent[i][j] = {-1, -1};\n    }\n    \n    dist[start.r][start.c] = 0;\n    \n    int dr[] = {-1, 1, 0, 0};\n    int dc[] = {0, 0, -1, 1};\n    \n    while(!q.empty()){\n        Pos cur = q.front(); q.pop();\n        if (cur == target) break;\n        \n        for(int k=0; k<4; ++k){\n            int nr = cur.r + dr[k];\n            int nc = cur.c + dc[k];\n            if(in_grid(nr, nc) && !grid[nr][nc] && dist[nr][nc] == -1){\n                dist[nr][nc] = dist[cur.r][cur.c] + 1;\n                parent[nr][nc] = cur;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    if (dist[target.r][target.c] == -1) return start;\n    \n    Pos curr = target;\n    while(parent[curr.r][curr.c] != start){\n        curr = parent[curr.r][curr.c];\n        if (curr.r == -1) return start;\n    }\n    return curr;\n}\n\nchar get_action_char(Pos from, Pos to) {\n    if (from == to) return '.';\n    if (to.r < from.r) return 'U';\n    if (to.r > from.r) return 'D';\n    if (to.c < from.c) return 'L';\n    if (to.c > from.c) return 'R';\n    return '.';\n}\n\nchar get_build_char(Pos from, Pos wall_pos) {\n    if (wall_pos.r < from.r) return 'u';\n    if (wall_pos.r > from.r) return 'd';\n    if (wall_pos.c < from.c) return 'l';\n    if (wall_pos.c > from.c) return 'r';\n    return '.';\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N)) return 0;\n    pets.resize(N);\n    pet_types.resize(N);\n    for(int i=0; i<N; ++i){\n        cin >> pets[i].r >> pets[i].c >> pet_types[i];\n        pets[i].r--; pets[i].c--;\n    }\n    cin >> M;\n    humans.resize(M);\n    for(int i=0; i<M; ++i){\n        cin >> humans[i].r >> humans[i].c;\n        humans[i].r--; humans[i].c--;\n    }\n    \n    memset(walls, 0, sizeof(walls));\n    \n    update_pet_sum();\n    find_best_zone();\n    \n    vector<Pos> perimeter = get_perimeter();\n    \n    for(int turn=0; turn<300; ++turn){\n        if (turn > 0) {\n            for(int i=0; i<N; ++i){\n                string s;\n                cin >> s;\n                if (s == \".\") continue;\n                for(char c : s){\n                    if (c == 'U') pets[i].r--;\n                    else if (c == 'D') pets[i].r++;\n                    else if (c == 'L') pets[i].c--;\n                    else if (c == 'R') pets[i].c++;\n                }\n            }\n            update_pet_sum();\n        }\n        \n        bool need_rezone = false;\n        if (!zone_locked) {\n            turns_since_rezone++;\n            if (turns_since_rezone >= 50) need_rezone = true;\n        }\n        \n        if (count_pets(target_r1, target_c1, target_r2, target_c2) > 0) {\n            need_rezone = true;\n            zone_locked = false;\n        }\n        \n        if (need_rezone) {\n            find_best_zone();\n            perimeter = get_perimeter();\n            turns_since_rezone = 0;\n        }\n        \n        bool temp_walls[32][32];\n        memcpy(temp_walls, walls, sizeof(walls));\n        \n        vector<char> human_actions(M, '.');\n        vector<Pos> next_human_pos(M);\n        vector<Pos> old_humans = humans;\n        \n        // Identify buildable segments (check against current human positions)\n        vector<int> buildable_indices;\n        for(size_t i=0; i<perimeter.size(); ++i){\n            if (!walls[perimeter[i].r][perimeter[i].c]) {\n                if (can_build(perimeter[i].r, perimeter[i].c, humans)) {\n                    buildable_indices.push_back(i);\n                }\n            }\n        }\n        \n        vector<bool> segment_taken(perimeter.size(), false);\n        vector<bool> human_assigned_build(M, false);\n        \n        for(int i=0; i<M; ++i){\n            int best_seg = -1;\n            int min_dist = 10000;\n            \n            for(int idx : buildable_indices){\n                if (segment_taken[idx]) continue;\n                int d = abs(humans[i].r - perimeter[idx].r) + abs(humans[i].c - perimeter[idx].c);\n                if (d < min_dist) {\n                    min_dist = d;\n                    best_seg = idx;\n                }\n            }\n            \n            Pos target;\n            if (best_seg != -1) {\n                segment_taken[best_seg] = true;\n                human_assigned_build[i] = true;\n                target = perimeter[best_seg];\n                \n                int dist = abs(humans[i].r - target.r) + abs(humans[i].c - target.c);\n                if (dist == 1) {\n                    // Re-check can_build with temp_walls and updated human positions\n                    // (other humans might move to this position this turn)\n                    bool can_build_now = true;\n                    if (temp_walls[target.r][target.c]) can_build_now = false;\n                    \n                    // Check if any OTHER human will be at this position\n                    for(int j=0; j<M; ++j){\n                        if (i == j) continue;\n                        // Check if human j is already there or will move there\n                        if (humans[j].r == target.r && humans[j].c == target.c) {\n                            can_build_now = false;\n                            break;\n                        }\n                    }\n                    \n                    // Check pet adjacency again\n                    if (can_build_now) {\n                        int dr[] = {-1, 1, 0, 0};\n                        int dc[] = {0, 0, -1, 1};\n                        for (const auto& p : pets) {\n                            for (int k = 0; k < 4; ++k) {\n                                if (p.r + dr[k] == target.r && p.c + dc[k] == target.c) {\n                                    can_build_now = false;\n                                    break;\n                                }\n                            }\n                            if (!can_build_now) break;\n                        }\n                    }\n                    \n                    if (can_build_now) {\n                        human_actions[i] = get_build_char(humans[i], target);\n                        temp_walls[target.r][target.c] = true;\n                        next_human_pos[i] = humans[i]; // Stay\n                    } else {\n                        // Cannot build, move closer or wait\n                        Pos next = get_next_move(humans[i], target, temp_walls);\n                        human_actions[i] = get_action_char(humans[i], next);\n                        next_human_pos[i] = next;\n                    }\n                } else {\n                    Pos next = get_next_move(humans[i], target, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                }\n            } else {\n                // No buildable segments available\n                bool all_built = true;\n                for(const auto& p : perimeter) {\n                    if (!walls[p.r][p.c]) {\n                        all_built = false;\n                        break;\n                    }\n                }\n                \n                if (all_built) {\n                    Pos center = {(target_r1 + target_r2)/2, (target_c1 + target_c2)/2};\n                    Pos next = get_next_move(humans[i], center, temp_walls);\n                    human_actions[i] = get_action_char(humans[i], next);\n                    next_human_pos[i] = next;\n                } else {\n                    // Wait for buildable segments to become available\n                    human_actions[i] = '.';\n                    next_human_pos[i] = humans[i];\n                }\n            }\n        }\n        \n        // Output\n        string out = \"\";\n        for(int i=0; i<M; ++i) out += human_actions[i];\n        cout << out << endl;\n        \n        // Update state\n        for(int i=0; i<M; ++i){\n            humans[i] = next_human_pos[i];\n            char act = human_actions[i];\n            if (act == 'u') walls[old_humans[i].r - 1][old_humans[i].c] = true;\n            else if (act == 'd') walls[old_humans[i].r + 1][old_humans[i].c] = true;\n            else if (act == 'l') walls[old_humans[i].r][old_humans[i].c - 1] = true;\n            else if (act == 'r') walls[old_humans[i].r][old_humans[i].c + 1] = true;\n        }\n    }\n    \n    return 0;\n}","ahc009":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <cmath>\n#include <chrono>\n#include <random>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nint SI, SJ, TI, TJ;\ndouble P;\nchar H[20][20];\nchar V[20][20];\n\nconst int DI[4] = {-1, 1, 0, 0};\nconst int DJ[4] = {0, 0, -1, 1};\nconst char DIRS[4] = {'U', 'D', 'L', 'R'};\n\ninline int get_idx(int r, int c) { return r * 20 + c; }\n\ninline bool is_wall(int r, int c, int dir) {\n    int nr = r + DI[dir];\n    int nc = c + DJ[dir];\n    if (nr < 0 || nr >= 20 || nc < 0 || nc >= 20) return true;\n    if (dir == 0) return V[r-1][c] == '1';\n    if (dir == 1) return V[r][c] == '1';\n    if (dir == 2) return H[r][c-1] == '1';\n    if (dir == 3) return H[r][c] == '1';\n    return true;\n}\n\nconst int L = 200;\nint TARGET_IDX;\n\ndouble dp[201][400];\nint active_count[201];\nint active_list[201][400];\ndouble D[201];\nchar S[201];\n\ndouble work_dp[400];\nint work_active[400];\nint work_token[400];\nint work_token_val = 0;\n\ndouble next_work_dp[400];\nint next_work_active[400];\nint next_work_token[400];\nint next_work_token_val = 0;\n\ndouble compute_dp_from(int k, const char* current_S, double* out_D_suffix) {\n    work_token_val++;\n    next_work_token_val++;\n    \n    int w_count = 0;\n    int* ak = active_list[k];\n    int ack = active_count[k];\n    double* dpk = dp[k];\n    \n    for (int i = 0; i < ack; ++i) {\n        int idx = ak[i];\n        double val = dpk[idx];\n        if (val > 1e-10) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = D[k];\n    double score_suffix = 0.0;\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = current_S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        int nw_count = 0;\n        int di = DI[dir_idx], dj = DJ[dir_idx];\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = idx / 20, c = idx % 20;\n            \n            int nr = r + di, nc = c + dj;\n            bool wall = (nr < 0 || nr >= 20 || nc < 0 || nc >= 20);\n            if (!wall) {\n                if (dir_idx == 0 && (r == 0 || V[r-1][c] == '1')) wall = true;\n                else if (dir_idx == 1 && (r == 19 || V[r][c] == '1')) wall = true;\n                else if (dir_idx == 2 && (c == 0 || H[r][c-1] == '1')) wall = true;\n                else if (dir_idx == 3 && (c == 19 || H[r][c] == '1')) wall = true;\n            }\n            \n            if (wall) {\n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob;\n            } else {\n                int nidx = nr * 20 + nc;\n                \n                if (next_work_token[idx] != next_work_token_val) {\n                    next_work_token[idx] = next_work_token_val;\n                    next_work_dp[idx] = 0.0;\n                    next_work_active[nw_count++] = idx;\n                }\n                next_work_dp[idx] += prob * P;\n                \n                if (nidx == TARGET_IDX) {\n                    sim_D += prob * (1.0 - P);\n                } else {\n                    if (next_work_token[nidx] != next_work_token_val) {\n                        next_work_token[nidx] = next_work_token_val;\n                        next_work_dp[nidx] = 0.0;\n                        next_work_active[nw_count++] = nidx;\n                    }\n                    next_work_dp[nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        double D_next = sim_D;\n        score_suffix += (t + 1 < L) ? D_next : (201.0 * D_next);\n        \n        w_count = nw_count;\n        double total_mass = 0.0;\n        for(int i = 0; i < w_count; ++i) {\n            int idx = next_work_active[i];\n            work_dp[idx] = next_work_dp[idx];\n            work_active[i] = idx;\n            work_token[idx] = work_token_val;\n            total_mass += work_dp[idx];\n        }\n        \n        if (total_mass < 1e-10 && D_next > 0.999) {\n            for (int rem = t + 2; rem < L; ++rem) score_suffix += D_next;\n            break;\n        }\n    }\n    \n    *out_D_suffix = score_suffix;\n    return sim_D;\n}\n\nvoid update_cache_from(int k) {\n    work_token_val++;\n    \n    int w_count = 0;\n    int* ak = active_list[k];\n    int ack = active_count[k];\n    double* dpk = dp[k];\n    \n    for (int i = 0; i < ack; ++i) {\n        int idx = ak[i];\n        double val = dpk[idx];\n        if (val > 1e-10) {\n            work_dp[idx] = val;\n            if (work_token[idx] != work_token_val) {\n                work_token[idx] = work_token_val;\n                work_active[w_count++] = idx;\n            }\n        }\n    }\n    \n    double sim_D = D[k];\n    static int global_next_token[400];\n    static int global_next_token_val = 0;\n    \n    for (int t = k; t < L; ++t) {\n        int dir_idx = 0;\n        char c = S[t];\n        if (c == 'U') dir_idx = 0;\n        else if (c == 'D') dir_idx = 1;\n        else if (c == 'L') dir_idx = 2;\n        else if (c == 'R') dir_idx = 3;\n        \n        global_next_token_val++;\n        active_count[t+1] = 0;\n        double next_D = sim_D;\n        int di = DI[dir_idx], dj = DJ[dir_idx];\n        \n        for (int i = 0; i < w_count; ++i) {\n            int idx = work_active[i];\n            double prob = work_dp[idx];\n            int r = idx / 20, c = idx % 20;\n            \n            int nr = r + di, nc = c + dj;\n            bool wall = (nr < 0 || nr >= 20 || nc < 0 || nc >= 20);\n            if (!wall) {\n                if (dir_idx == 0 && (r == 0 || V[r-1][c] == '1')) wall = true;\n                else if (dir_idx == 1 && (r == 19 || V[r][c] == '1')) wall = true;\n                else if (dir_idx == 2 && (c == 0 || H[r][c-1] == '1')) wall = true;\n                else if (dir_idx == 3 && (c == 19 || H[r][c] == '1')) wall = true;\n            }\n            \n            if (wall) {\n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active_list[t+1][active_count[t+1]++] = idx;\n                }\n                dp[t+1][idx] += prob;\n            } else {\n                int nidx = nr * 20 + nc;\n                \n                if (global_next_token[idx] != global_next_token_val) {\n                    global_next_token[idx] = global_next_token_val;\n                    dp[t+1][idx] = 0.0;\n                    active_list[t+1][active_count[t+1]++] = idx;\n                }\n                dp[t+1][idx] += prob * P;\n                \n                if (nidx == TARGET_IDX) {\n                    next_D += prob * (1.0 - P);\n                } else {\n                    if (global_next_token[nidx] != global_next_token_val) {\n                        global_next_token[nidx] = global_next_token_val;\n                        dp[t+1][nidx] = 0.0;\n                        active_list[t+1][active_count[t+1]++] = nidx;\n                    }\n                    dp[t+1][nidx] += prob * (1.0 - P);\n                }\n            }\n        }\n        \n        sim_D = next_D;\n        D[t+1] = sim_D;\n        \n        w_count = 0;\n        int* ac = active_list[t+1];\n        int acc = active_count[t+1];\n        double* dpt = dp[t+1];\n        for (int i = 0; i < acc; ++i) {\n            int idx = ac[i];\n            work_dp[idx] = dpt[idx];\n            work_active[w_count++] = idx;\n            work_token[idx] = work_token_val;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> SI >> SJ >> TI >> TJ >> P)) return 0;\n    \n    for (int i = 0; i < 20; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < 19; ++j) H[i][j] = row[j];\n    }\n    for (int i = 0; i < 19; ++i) {\n        string row; cin >> row;\n        for (int j = 0; j < 20; ++j) V[i][j] = row[j];\n    }\n    \n    TARGET_IDX = get_idx(TI, TJ);\n    int start_idx = get_idx(SI, SJ);\n    \n    // Single BFS for shortest path\n    int dist[400], parent[400], parent_dir[400];\n    memset(dist, -1, sizeof(dist));\n    queue<int> q;\n    dist[start_idx] = 0;\n    q.push(start_idx);\n    \n    while(!q.empty()){\n        int idx = q.front(); q.pop();\n        if(idx == TARGET_IDX) break;\n        int r = idx / 20, c = idx % 20;\n        for(int d = 0; d < 4; ++d){\n            if (!is_wall(r, c, d)) {\n                int nr = r + DI[d], nc = c + DJ[d];\n                int nidx = nr * 20 + nc;\n                if(dist[nidx] == -1){\n                    dist[nidx] = dist[idx] + 1;\n                    parent[nidx] = idx;\n                    parent_dir[nidx] = d;\n                    q.push(nidx);\n                }\n            }\n        }\n    }\n    \n    // Construct initial path\n    string path = \"D\";\n    if(dist[TARGET_IDX] != -1){\n        path = \"\";\n        int curr = TARGET_IDX;\n        while(curr != start_idx){\n            path += DIRS[parent_dir[curr]];\n            curr = parent[curr];\n        }\n        reverse(path.begin(), path.end());\n    }\n    \n    // Fill S with repeated path\n    int path_len = path.length();\n    for(int i = 0; i < L; ++i) S[i] = path[i % path_len];\n    S[L] = '\\0';\n    \n    // Initial DP Compute\n    memset(dp, 0, sizeof(dp));\n    memset(active_count, 0, sizeof(active_count));\n    memset(D, 0, sizeof(D));\n    work_token_val = 0;\n    next_work_token_val = 0;\n    \n    dp[0][start_idx] = 1.0;\n    active_list[0][0] = start_idx;\n    active_count[0] = 1;\n    \n    update_cache_from(0);\n    \n    double current_score = 0.0;\n    for(int t=1; t<L; ++t) current_score += D[t];\n    current_score += 201.0 * D[L];\n    \n    double best_score = current_score;\n    string best_S_str(S, S + L);\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.8;\n    \n    double temp = 30.0;\n    int accepted = 0, total = 0;\n    \n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if(elapsed > time_limit) break;\n        \n        if(total > 0 && total % 500 == 0){\n            double rate = (double)accepted / total;\n            if(rate > 0.4) temp *= 0.85;\n            else if(rate < 0.15) temp *= 1.15;\n            accepted = 0;\n            total = 0;\n        }\n        \n        int k = uniform_int_distribution<int>(0, L-1)(rng);\n        char old_char = S[k];\n        \n        int old_dir = (old_char == 'U') ? 0 : (old_char == 'D') ? 1 : (old_char == 'L') ? 2 : 3;\n        \n        int new_dir = uniform_int_distribution<int>(0, 3)(rng);\n        while(new_dir == old_dir) {\n            new_dir = (new_dir + 1) % 4;\n        }\n        \n        S[k] = DIRS[new_dir];\n        \n        double new_suffix_score;\n        compute_dp_from(k, S, &new_suffix_score);\n        \n        double prefix_score = 0.0;\n        for(int t=1; t<=k; ++t) prefix_score += D[t];\n        \n        double new_total_score = prefix_score + new_suffix_score;\n        double delta = new_total_score - current_score;\n        \n        if(delta > 0 || exp(delta / temp) > uniform_real_distribution<double>(0, 1)(rng)){\n            current_score = new_total_score;\n            update_cache_from(k);\n            accepted++;\n            \n            if(current_score > best_score){\n                best_score = current_score;\n                best_S_str = string(S, S + L);\n            }\n        } else {\n            S[k] = old_char;\n        }\n        \n        total++;\n        temp *= 0.99992;\n    }\n    \n    cout << best_S_str << endl;\n    \n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int N = 30;\nconst int MAX_STATES = N * N * 4 + 10;\n\n// Connection table: to[tile_type][entry_direction] = exit_direction\nconst int to_table[8][4] = {\n    {1, 0, -1, -1}, {3, -1, -1, 0}, {-1, -1, 3, 2}, {-1, 2, 1, -1},\n    {1, 0, 3, 2}, {3, 2, 1, 0}, {2, -1, 0, -1}, {-1, 3, -1, 1},\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nint tiles[N][N];\nint rotation[N][N];\nint best_rotation[N][N];\n\ninline int get_tile(int i, int j) {\n    return (tiles[i][j] + rotation[i][j]) % 8;\n}\n\n// Find all loops and return two longest lengths\npair<int, int> find_two_longest_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    \n    int max1 = 0, max2 = 0;\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                if (!visited[i][j][d]) {\n                    int si = i, sj = j, sd = d;\n                    int ci = i, cj = j, cd = d;\n                    int length = 0;\n                    bool valid = true;\n                    \n                    do {\n                        int tile = get_tile(ci, cj);\n                        int d2 = to_table[tile][cd];\n                        \n                        if (d2 == -1) { valid = false; break; }\n                        ci += di[d2]; cj += dj[d2];\n                        if (ci < 0 || ci >= N || cj < 0 || cj >= N) { valid = false; break; }\n                        cd = (d2 + 2) % 4;\n                        length++;\n                        if (length > MAX_STATES) { valid = false; break; }\n                    } while (!(ci == si && cj == sj && cd == sd));\n                    \n                    if (valid && length > 0) {\n                        ci = si; cj = sj; cd = sd;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2]; cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == si && cj == sj && cd == sd));\n                        \n                        if (length > max1) { max2 = max1; max1 = length; }\n                        else if (length > max2) { max2 = length; }\n                    }\n                }\n            }\n        }\n    }\n    \n    return {max1, max2};\n}\n\nlong long calculate_score() {\n    auto [l1, l2] = find_two_longest_loops();\n    return (long long)l1 * l2;\n}\n\nint count_loops() {\n    static bool visited[N][N][4];\n    memset(visited, 0, sizeof(visited));\n    int count = 0;\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                if (!visited[i][j][d]) {\n                    int si = i, sj = j, sd = d;\n                    int ci = i, cj = j, cd = d;\n                    int length = 0;\n                    bool valid = true;\n                    \n                    do {\n                        int tile = get_tile(ci, cj);\n                        int d2 = to_table[tile][cd];\n                        if (d2 == -1) { valid = false; break; }\n                        ci += di[d2]; cj += dj[d2];\n                        if (ci < 0 || ci >= N || cj < 0 || cj >= N) { valid = false; break; }\n                        cd = (d2 + 2) % 4;\n                        length++;\n                        if (length > MAX_STATES) { valid = false; break; }\n                    } while (!(ci == si && cj == sj && cd == sd));\n                    \n                    if (valid && length > 0) {\n                        count++;\n                        ci = si; cj = sj; cd = sd;\n                        do {\n                            visited[ci][cj][cd] = true;\n                            int tile = get_tile(ci, cj);\n                            int d2 = to_table[tile][cd];\n                            ci += di[d2]; cj += dj[d2];\n                            cd = (d2 + 2) % 4;\n                        } while (!(ci == si && cj == sj && cd == sd));\n                    }\n                }\n            }\n        }\n    }\n    \n    return count;\n}\n\nvoid initialize_random(mt19937_64& rng) {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            rotation[i][j] = uniform_int_distribution<>(0, 3)(rng);\n        }\n    }\n}\n\nlong long run_sa(mt19937_64& rng, double time_budget) {\n    initialize_random(rng);\n    \n    // Ensure at least 2 loops\n    int attempts = 0;\n    while (count_loops() < 2 && attempts < 15) {\n        initialize_random(rng);\n        attempts++;\n    }\n    \n    long long current_score = calculate_score();\n    long long best_score = current_score;\n    \n    if (current_score > 0) {\n        memcpy(best_rotation, rotation, sizeof(rotation));\n    }\n    \n    double temperature = 2500.0;\n    int no_improve = 0;\n    int total_moves = 0;\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        \n        if (elapsed > time_budget) break;\n        \n        double remaining = time_budget - elapsed;\n        temperature = max(0.1, 500.0 * (remaining / time_budget));\n        \n        // Pick random tile\n        int i = uniform_int_distribution<>(0, N-1)(rng);\n        int j = uniform_int_distribution<>(0, N-1)(rng);\n        \n        int old_rot = rotation[i][j];\n        int new_rot = (old_rot + uniform_int_distribution<>(1, 3)(rng)) % 4;\n        rotation[i][j] = new_rot;\n        \n        long long new_score = calculate_score();\n        \n        if (new_score == 0) {\n            rotation[i][j] = old_rot;\n            continue;\n        }\n        \n        double delta = (double)(new_score - current_score);\n        bool accept = false;\n        \n        if (delta > 0) {\n            accept = true;\n        } else if (temperature > 0.1) {\n            double prob = exp(delta / temperature);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (new_score > best_score) {\n                best_score = new_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n                no_improve = 0;\n            } else {\n                no_improve++;\n            }\n        } else {\n            rotation[i][j] = old_rot;\n        }\n        \n        total_moves++;\n        \n        // Restart if stuck\n        if (no_improve > 8000 && temperature < 10.0) {\n            temperature = 400.0;\n            no_improve = 0;\n            // Randomize larger region\n            int ri = uniform_int_distribution<>(0, N-12)(rng);\n            int rj = uniform_int_distribution<>(0, N-12)(rng);\n            for (int x = ri; x < ri + 12 && x < N; x++) {\n                for (int y = rj; y < rj + 12 && y < N; y++) {\n                    rotation[x][y] = uniform_int_distribution<>(0, 3)(rng);\n                }\n            }\n            current_score = calculate_score();\n            if (current_score > best_score && current_score > 0) {\n                best_score = current_score;\n                memcpy(best_rotation, rotation, sizeof(rotation));\n            }\n        }\n    }\n    \n    return best_score;\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        string s;\n        cin >> s;\n        for (int j = 0; j < N; j++) {\n            tiles[i][j] = s[j] - '0';\n            rotation[i][j] = 0;\n        }\n    }\n    \n    long long global_best = 0;\n    auto start_time = chrono::steady_clock::now();\n    const double total_time = 1.92;\n    \n    // More runs with moderate length\n    int num_runs = 8;\n    double time_per_run = (total_time - 0.2) / num_runs;  // Reserve 0.2s for final refinement\n    \n    for (int run = 0; run < num_runs; run++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > total_time - 0.25) break;\n        \n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count() + run * 2345678);\n        long long score = run_sa(rng, time_per_run);\n        \n        if (score > global_best && score > 0) {\n            global_best = score;\n        }\n    }\n    \n    // Final intensive refinement on best solution\n    if (global_best > 0) {\n        memcpy(rotation, best_rotation, sizeof(rotation));\n        long long current_score = global_best;\n        \n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count() + 888888);\n        \n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = total_time - elapsed - 0.03;\n        \n        if (remaining > 0.05) {\n            double temperature = 100.0;\n            int refine_iter = 0;\n            auto refine_start = chrono::steady_clock::now();\n            \n            while (true) {\n                auto now2 = chrono::steady_clock::now();\n                double refine_elapsed = chrono::duration<double>(now2 - refine_start).count();\n                if (refine_elapsed > remaining) break;\n                \n                // Try all 3 other rotations for random tile\n                int i = uniform_int_distribution<>(0, N-1)(rng);\n                int j = uniform_int_distribution<>(0, N-1)(rng);\n                \n                int old_rot = rotation[i][j];\n                bool improved = false;\n                \n                for (int try_rot = 0; try_rot < 4; try_rot++) {\n                    if (try_rot == old_rot) continue;\n                    rotation[i][j] = try_rot;\n                    long long new_score = calculate_score();\n                    \n                    if (new_score > current_score) {\n                        current_score = new_score;\n                        improved = true;\n                        if (new_score > global_best) {\n                            global_best = new_score;\n                            memcpy(best_rotation, rotation, sizeof(rotation));\n                        }\n                        old_rot = try_rot;\n                    }\n                }\n                \n                if (!improved) {\n                    rotation[i][j] = old_rot;\n                }\n                \n                temperature *= 0.9999;\n                refine_iter++;\n                \n                if (refine_iter > 500000) break;\n            }\n        }\n    }\n    \n    // Ensure valid output\n    if (global_best == 0) {\n        mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n        initialize_random(rng);\n        int attempts = 0;\n        while (calculate_score() == 0 && attempts < 50) {\n            initialize_random(rng);\n            attempts++;\n        }\n        memcpy(best_rotation, rotation, sizeof(rotation));\n    }\n    \n    // Output exactly 900 characters\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << best_rotation[i][j];\n        }\n    }\n    cout << '\\n';\n    \n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nvector<string> board;\nint empty_r, empty_c;\nstring moves = \"\";\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\nconst int opp_dir[] = {1, 0, 3, 2};\n\nint hex_to_int(char c) {\n    if (c >= '0' && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nint get_tile(int r, int c) {\n    if (r < 0 || r >= N || c < 0 || c >= N) return -1;\n    if (board[r][c] == '0') return 0;\n    return hex_to_int(board[r][c]);\n}\n\nbool has_connection(int tile_val, int d) {\n    if (tile_val == 0) return false;\n    const int mask[] = {2, 8, 1, 4};\n    return (tile_val & mask[d]) != 0;\n}\n\nbool tiles_connect(int r1, int c1, int r2, int c2) {\n    int t1 = get_tile(r1, c1);\n    int t2 = get_tile(r2, c2);\n    if (t1 == 0 || t2 == 0) return false;\n    \n    if (r2 == r1 + 1) return has_connection(t1, 1) && has_connection(t2, 0);\n    if (r2 == r1 - 1) return has_connection(t1, 0) && has_connection(t2, 1);\n    if (c2 == c1 + 1) return has_connection(t1, 3) && has_connection(t2, 2);\n    if (c2 == c1 - 1) return has_connection(t1, 2) && has_connection(t2, 3);\n    return false;\n}\n\nvoid make_move(int d) {\n    int nr = empty_r + dr[d];\n    int nc = empty_c + dc[d];\n    \n    if (nr < 0 || nr >= N || nc < 0 || nc >= N) return;\n    if ((int)moves.size() >= T - 2) return;\n    \n    swap(board[empty_r][empty_c], board[nr][nc]);\n    empty_r = nr;\n    empty_c = nc;\n    moves += dir_char[d];\n}\n\nvector<int> bfs_path(int sr, int sc, int tr, int tc) {\n    if (sr == tr && sc == tc) return {};\n    \n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> par(N, vector<pair<int,int>>(N, {-1,-1}));\n    vector<vector<int>> par_d(N, vector<int>(N, -1));\n    \n    queue<pair<int,int>> q;\n    q.push({sr, sc});\n    vis[sr][sc] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (nr >= 0 && nr < N && nc >= 0 && nc < N && !vis[nr][nc]) {\n                vis[nr][nc] = true;\n                par[nr][nc] = {r, c};\n                par_d[nr][nc] = d;\n                q.push({nr, nc});\n                if (nr == tr && nc == tc) {\n                    vector<int> path;\n                    int cr = nr, cc = nc;\n                    while (cr != sr || cc != sc) {\n                        path.push_back(par_d[cr][cc]);\n                        tie(cr, cc) = par[cr][cc];\n                    }\n                    reverse(path.begin(), path.end());\n                    return path;\n                }\n            }\n        }\n    }\n    return {};\n}\n\nvoid move_empty_to(int tr, int tc) {\n    while (empty_r != tr || empty_c != tc) {\n        if ((int)moves.size() >= T - 10) break;\n        auto path = bfs_path(empty_r, empty_c, tr, tc);\n        if (path.empty()) break;\n        for (int d : path) {\n            if ((int)moves.size() >= T - 5) break;\n            make_move(d);\n        }\n    }\n}\n\nvoid move_tile_to(int& tile_r, int& tile_c, int tr, int tc) {\n    while (tile_r != tr || tile_c != tc) {\n        if ((int)moves.size() >= T - 20) break;\n        \n        int empty_tr, empty_tc, move_d;\n        if (tile_r < tr) { empty_tr = tile_r + 1; empty_tc = tile_c; move_d = 0; }\n        else if (tile_r > tr) { empty_tr = tile_r - 1; empty_tc = tile_c; move_d = 1; }\n        else if (tile_c < tc) { empty_tr = tile_r; empty_tc = tile_c + 1; move_d = 2; }\n        else { empty_tr = tile_r; empty_tc = tile_c - 1; move_d = 3; }\n        \n        if (empty_tr < 0 || empty_tr >= N || empty_tc < 0 || empty_tc >= N) break;\n        \n        move_empty_to(empty_tr, empty_tc);\n        if (empty_r == empty_tr && empty_c == empty_tc) {\n            make_move(move_d);\n            if (move_d == 0) tile_r++;\n            else if (move_d == 1) tile_r--;\n            else if (move_d == 2) tile_c++;\n            else if (move_d == 3) tile_c--;\n        } else break;\n    }\n}\n\nstruct Tile {\n    int value, r, c, id;\n};\n\nstruct Placement {\n    vector<int> assignment;\n    int score;\n};\n\n// Build placement with connection-aware scoring\nPlacement build_placement(const vector<Tile>& tiles, int total, int start_tile, int start_pos) {\n    Placement result;\n    result.assignment.assign(total, -1);\n    result.score = 0;\n    \n    vector<bool> used(total, false);\n    vector<vector<bool>> placed(N, vector<bool>(N, false));\n    \n    // Target positions in snake pattern\n    vector<pair<int,int>> targets;\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)) targets.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (!(i == N-1 && j == N-1)) targets.push_back({i, j});\n            }\n        }\n    }\n    \n    // Place starting tile\n    result.assignment[start_pos] = start_tile;\n    used[start_tile] = true;\n    placed[targets[start_pos].first][targets[start_pos].second] = true;\n    result.score += __builtin_popcount(tiles[start_tile].value) * 10;\n    \n    // Grow by adding compatible tiles\n    for (int ti = 0; ti < total; ti++) {\n        if (ti == start_pos) continue;\n        \n        int tr = targets[ti].first, tc = targets[ti].second;\n        int best_tile = -1, best_score = -1e9;\n        \n        for (int tidx = 0; tidx < total; tidx++) {\n            if (used[tidx]) continue;\n            \n            int score = 0;\n            \n            // Check connections with placed neighbors (high weight)\n            for (int d = 0; d < 4; d++) {\n                int pr = tr + dr[d], pc = tc + dc[d];\n                if (pr >= 0 && pr < N && pc >= 0 && pc < N && !(pr == N-1 && pc == N-1)) {\n                    if (placed[pr][pc]) {\n                        for (int nt = 0; nt < total; nt++) {\n                            if (result.assignment[nt] >= 0 && targets[nt] == make_pair(pr, pc)) {\n                                int neighbor = result.assignment[nt];\n                                int opp = opp_dir[d];\n                                if (has_connection(tiles[tidx].value, d) && \n                                    has_connection(tiles[neighbor].value, opp)) {\n                                    score += 50;\n                                }\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n            \n            // Distance penalty (low)\n            int dist = abs(tiles[tidx].r - tr) + abs(tiles[tidx].c - tc);\n            score -= dist;\n            \n            // Connection potential\n            score += __builtin_popcount(tiles[tidx].value) * 5;\n            \n            if (score > best_score) {\n                best_score = score;\n                best_tile = tidx;\n            }\n        }\n        \n        if (best_tile >= 0) {\n            result.assignment[ti] = best_tile;\n            used[best_tile] = true;\n            placed[tr][tc] = true;\n            result.score += best_score;\n        }\n    }\n    \n    return result;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> T;\n    board.resize(N);\n    \n    vector<Tile> tiles;\n    int tile_id = 0;\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; empty_c = j;\n            } else {\n                tiles.push_back({hex_to_int(board[i][j]), i, j, tile_id++});\n            }\n        }\n    }\n    \n    int total = N * N - 1;\n    \n    // Target positions in snake pattern\n    vector<pair<int,int>> targets;\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)) targets.push_back({i, j});\n            }\n        } else {\n            for (int j = N-1; j >= 0; j--) {\n                if (!(i == N-1 && j == N-1)) targets.push_back({i, j});\n            }\n        }\n    }\n    \n    // Try multiple starting configurations\n    Placement best_placement;\n    best_placement.score = -1e9;\n    \n    // Sort tiles by connection count\n    vector<pair<int,int>> by_conn;\n    for (int i = 0; i < total; i++) {\n        by_conn.push_back({__builtin_popcount(tiles[i].value), i});\n    }\n    sort(by_conn.rbegin(), by_conn.rend());\n    \n    // Try diverse starting tiles for better coverage\n    vector<int> priority_tiles;\n    // High connection tiles (tree centers) - most important\n    for (int i = 0; i < min(3, total); i++) priority_tiles.push_back(by_conn[i].second);\n    // Low connection tiles (tree leaves) - also important\n    for (int i = total-1; i >= max(0, total-3); i--) priority_tiles.push_back(by_conn[i].second);\n    // Fill remaining\n    for (int i = 0; i < total; i++) {\n        if (find(priority_tiles.begin(), priority_tiles.end(), i) == priority_tiles.end()) {\n            priority_tiles.push_back(i);\n        }\n    }\n    \n    // Proven starting positions\n    vector<int> start_positions = {0, 1, 2, total/2, total-1};\n    \n    int attempts = 0;\n    int max_attempts = 25;\n    \n    for (int st : priority_tiles) {\n        for (int sp : start_positions) {\n            if (attempts >= max_attempts) break;\n            \n            Placement p = build_placement(tiles, total, st, sp);\n            \n            // Score-based selection (proven to work best)\n            if (p.score > best_placement.score) {\n                best_placement = p;\n            }\n            attempts++;\n        }\n        if (attempts >= max_attempts) break;\n    }\n    \n    // Execute best placement - ensure all tiles placed\n    for (int ti = 0; ti < total; ti++) {\n        if ((int)moves.size() >= T - 50) break;\n        if (best_placement.assignment[ti] < 0) continue;\n        \n        int tidx = best_placement.assignment[ti];\n        int tr = targets[ti].first, tc = targets[ti].second;\n        int tile_val = tiles[tidx].value;\n        \n        // Find current position\n        int cur_r = -1, cur_c = -1;\n        for (int i = 0; i < N && cur_r < 0; i++) {\n            for (int j = 0; j < N && cur_r < 0; j++) {\n                if (get_tile(i, j) == tile_val) {\n                    cur_r = i; cur_c = j;\n                }\n            }\n        }\n        if (cur_r < 0) continue;\n        \n        move_tile_to(cur_r, cur_c, tr, tc);\n    }\n    \n    move_empty_to(N-1, N-1);\n    \n    cout << moves << endl;\n    \n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\nstruct Strawberry {\n    int id;\n    long long x, y;\n};\n\nint N, K;\nvector<int> a(11);\nvector<Strawberry> strawberries;\nvector<Line> lines;\n\nconst long long COORD_MIN = -1000000000LL;\nconst long long COORD_MAX = 1000000000LL;\n\nlong long clampCoord(long long v) {\n    if (v < COORD_MIN) return COORD_MIN;\n    if (v > COORD_MAX) return COORD_MAX;\n    return v;\n}\n\nint sideOfLine(const Line& l, long long x, long long y) {\n    __int128 dx1 = (__int128)l.qx - l.px;\n    __int128 dy1 = (__int128)l.qy - l.py;\n    __int128 dx2 = (__int128)x - l.px;\n    __int128 dy2 = (__int128)y - l.py;\n    __int128 cross = dx1 * dy2 - dy1 * dx2;\n    if (cross > 0) return 1;\n    if (cross < 0) return -1;\n    return 0;\n}\n\nbool isCut(int idx) {\n    for (const auto& l : lines) {\n        if (sideOfLine(l, strawberries[idx].x, strawberries[idx].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\nvector<string> getRegions() {\n    vector<string> region(N);\n    for (int i = 0; i < N; i++) {\n        if (isCut(i)) {\n            region[i] = \"CUT\";\n            continue;\n        }\n        string sig = \"\";\n        for (size_t j = 0; j < lines.size() && j < 60; j++) {\n            int s = sideOfLine(lines[j], strawberries[i].x, strawberries[i].y);\n            sig += (s == 1 ? \"L\" : (s == -1 ? \"R\" : \"0\"));\n        }\n        region[i] = sig;\n    }\n    return region;\n}\n\nint calculateScore() {\n    auto regions = getRegions();\n    map<string, int> pieceCount;\n    for (int i = 0; i < N; i++) {\n        if (regions[i] != \"CUT\") {\n            pieceCount[regions[i]]++;\n        }\n    }\n    \n    int score = 0;\n    for (int d = 1; d <= 10; d++) {\n        int b_d = 0;\n        for (auto& kv : pieceCount) {\n            if (kv.second == d) b_d++;\n        }\n        score += min(a[d], b_d);\n    }\n    return score;\n}\n\nlong long distSq(long long x1, long long y1, long long x2, long long y2) {\n    __int128 dx = (__int128)x1 - x2;\n    __int128 dy = (__int128)y1 - y2;\n    __int128 result = dx * dx + dy * dy;\n    if (result > (__int128)4e18) return 4000000000000000000LL;\n    return (long long)result;\n}\n\nLine createLineFromPoints(long long x1, long long y1, long long x2, long long y2) {\n    long long px = clampCoord(x1);\n    long long py = clampCoord(y1);\n    long long qx = clampCoord(x2);\n    long long qy = clampCoord(y2);\n    \n    if (px == qx && py == qy) {\n        qx = clampCoord(qx + 1);\n    }\n    \n    return Line{px, py, qx, qy};\n}\n\nLine createSeparatingLine(const vector<int>& group1, const vector<int>& group2) {\n    if (group1.empty() || group2.empty()) {\n        return createLineFromPoints(0, 0, 1, 0);\n    }\n    \n    long long cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0;\n    for (int idx : group1) {\n        cx1 += strawberries[idx].x;\n        cy1 += strawberries[idx].y;\n    }\n    for (int idx : group2) {\n        cx2 += strawberries[idx].x;\n        cy2 += strawberries[idx].y;\n    }\n    cx1 /= (long long)group1.size();\n    cy1 /= (long long)group1.size();\n    cx2 /= (long long)group2.size();\n    cy2 /= (long long)group2.size();\n    \n    long long mx = (cx1 + cx2) / 2;\n    long long my = (cy1 + cy2) / 2;\n    long long dx = cx2 - cx1;\n    long long dy = cy2 - cy1;\n    \n    if (dx == 0 && dy == 0) {\n        dx = 1;\n        dy = 0;\n    }\n    \n    long long scale = 500000;\n    long long px = mx - dy;\n    long long py = my + dx;\n    long long qx = mx + dy;\n    long long qy = my - dx;\n    \n    // Extend line to cake boundary\n    long long len = max(abs(qx - px), abs(qy - py));\n    if (len > 0) {\n        px = mx - dy * scale / len;\n        py = my + dx * scale / len;\n        qx = mx + dy * scale / len;\n        qy = my - dx * scale / len;\n    }\n    \n    return createLineFromPoints(px, py, qx, qy);\n}\n\n// Check if line cuts any strawberry\nbool lineCutsStrawberry(const Line& l) {\n    for (int k = 0; k < N; k++) {\n        if (sideOfLine(l, strawberries[k].x, strawberries[k].y) == 0) {\n            return true;\n        }\n    }\n    return false;\n}\n\n// Check if two groups are already separated by existing lines\nbool groupsSeparated(const vector<int>& g1, const vector<int>& g2) {\n    if (g1.empty() || g2.empty()) return true;\n    \n    for (int idx1 : g1) {\n        for (int idx2 : g2) {\n            bool same = true;\n            for (const auto& l : lines) {\n                int s1 = sideOfLine(l, strawberries[idx1].x, strawberries[idx1].y);\n                int s2 = sideOfLine(l, strawberries[idx2].x, strawberries[idx2].y);\n                if (s1 != 0 && s2 != 0 && s1 != s2) {\n                    same = false;\n                    break;\n                }\n            }\n            if (same) return false;\n        }\n    }\n    return true;\n}\n\n// Distance-based clustering\nvector<vector<int>> clusterByDistance() {\n    vector<vector<int>> clusters;\n    vector<bool> used(N, false);\n    \n    // Create weighted demand list (prioritize higher demands)\n    vector<pair<int, int>> demands; // (size, priority)\n    for (int d = 1; d <= 10; d++) {\n        for (int i = 0; i < a[d]; i++) {\n            demands.push_back({d, a[d]});\n        }\n    }\n    sort(demands.rbegin(), demands.rend());\n    \n    // Find unassigned strawberry nearest to origin as seed\n    auto findSeed = [&]() -> int {\n        int best = -1;\n        long long bestDist = -1;\n        for (int i = 0; i < N; i++) {\n            if (used[i]) continue;\n            long long d = distSq(strawberries[i].x, strawberries[i].y, 0, 0);\n            if (best == -1 || d < bestDist) {\n                bestDist = d;\n                best = i;\n            }\n        }\n        return best;\n    };\n    \n    for (auto& demand : demands) {\n        if ((int)clusters.size() > K + 10) break;\n        \n        int seed = findSeed();\n        if (seed == -1) break;\n        \n        // Find nearest unassigned strawberries\n        vector<pair<long long, int>> candidates;\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) {\n                long long d = distSq(strawberries[seed].x, strawberries[seed].y,\n                                    strawberries[i].x, strawberries[i].y);\n                candidates.push_back({d, i});\n            }\n        }\n        sort(candidates.begin(), candidates.end());\n        \n        vector<int> cluster;\n        for (auto& cand : candidates) {\n            if ((int)cluster.size() >= demand.first) break;\n            cluster.push_back(cand.second);\n            used[cand.second] = true;\n        }\n        \n        if (!cluster.empty()) {\n            clusters.push_back(cluster);\n        }\n    }\n    \n    // Assign remaining\n    for (int i = 0; i < N; i++) {\n        if (!used[i]) {\n            if (!clusters.empty() && (int)clusters.back().size() < 10) {\n                clusters.back().push_back(i);\n            } else {\n                clusters.push_back({i});\n            }\n            used[i] = true;\n        }\n    }\n    \n    return clusters;\n}\n\nvoid generateLinesFromClusters(const vector<vector<int>>& clusters) {\n    lines.clear();\n    \n    for (size_t i = 0; i < clusters.size() && (int)lines.size() < K; i++) {\n        for (size_t j = i + 1; j < clusters.size() && (int)lines.size() < K; j++) {\n            if (groupsSeparated(clusters[i], clusters[j])) continue;\n            \n            Line l = createSeparatingLine(clusters[i], clusters[j]);\n            \n            if (!lineCutsStrawberry(l)) {\n                lines.push_back(l);\n            }\n        }\n    }\n}\n\n// Try adding a random line\nbool tryAddRandomLine() {\n    if ((int)lines.size() >= K) return false;\n    \n    int i1 = rand() % N;\n    int i2 = rand() % N;\n    while (i1 == i2) i2 = rand() % N;\n    \n    Line newLine = createSeparatingLine({i1}, {i2});\n    \n    if (!lineCutsStrawberry(newLine)) {\n        lines.push_back(newLine);\n        return true;\n    }\n    return false;\n}\n\n// Perturb an existing line\nvoid perturbLine(int idx) {\n    if (idx >= (int)lines.size()) return;\n    \n    Line& l = lines[idx];\n    long long dx = (rand() % 2001) - 1000;\n    long long dy = (rand() % 2001) - 1000;\n    \n    Line newLine = createLineFromPoints(l.px + dx, l.py + dy, l.qx + dx, l.qy + dy);\n    \n    if (!lineCutsStrawberry(newLine)) {\n        lines[idx] = newLine;\n    }\n}\n\n// Optimize using local search\nvoid optimize() {\n    int baseScore = calculateScore();\n    int noImprovement = 0;\n    \n    for (int iter = 0; iter < 500 && noImprovement < 100; iter++) {\n        int choice = rand() % 3;\n        \n        if (choice == 0 && (int)lines.size() < K) {\n            // Try adding a line\n            lines.push_back(createLineFromPoints(0, 0, 1, 0));\n            int newScore = calculateScore();\n            if (newScore >= baseScore) {\n                baseScore = newScore;\n                noImprovement = 0;\n            } else {\n                lines.pop_back();\n                noImprovement++;\n            }\n        } else if (choice == 1 && !lines.empty()) {\n            // Try perturbing a line\n            int idx = rand() % lines.size();\n            Line oldLine = lines[idx];\n            perturbLine(idx);\n            int newScore = calculateScore();\n            if (newScore >= baseScore) {\n                baseScore = newScore;\n                noImprovement = 0;\n            } else {\n                lines[idx] = oldLine;\n                noImprovement++;\n            }\n        } else {\n            // Try adding random line\n            if (tryAddRandomLine()) {\n                int newScore = calculateScore();\n                if (newScore >= baseScore) {\n                    baseScore = newScore;\n                    noImprovement = 0;\n                } else {\n                    lines.pop_back();\n                    noImprovement++;\n                }\n            } else {\n                noImprovement++;\n            }\n        }\n    }\n    \n    // Final cleanup: remove lines that don't help\n    for (int i = (int)lines.size() - 1; i >= 0; i--) {\n        Line removed = lines[i];\n        lines.erase(lines.begin() + i);\n        int newScore = calculateScore();\n        if (newScore < baseScore) {\n            lines.insert(lines.begin() + i, removed);\n        }\n        baseScore = calculateScore();\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    srand(42);\n    \n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> a[d];\n    }\n    \n    strawberries.resize(N);\n    for (int i = 0; i < N; i++) {\n        strawberries[i].id = i;\n        cin >> strawberries[i].x >> strawberries[i].y;\n    }\n    \n    // Cluster strawberries\n    auto clusters = clusterByDistance();\n    \n    // Generate separating lines\n    generateLinesFromClusters(clusters);\n    \n    // Optimize with local search\n    optimize();\n    \n    // Output\n    cout << lines.size() << \"\\n\";\n    for (const auto& l : lines) {\n        cout << l.px << \" \" << l.py << \" \" << l.qx << \" \" << l.qy << \"\\n\";\n    }\n    \n    return 0;\n}","ahc014":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& other) const {\n        return x == other.x && y == other.y;\n    }\n};\n\nstruct Rect {\n    Point p[4];\n    long long weight;\n    int perimeter_len;\n    \n    bool operator<(const Rect& other) const {\n        if (weight != other.weight) return weight > other.weight;\n        return perimeter_len < other.perimeter_len;\n    }\n};\n\nint N, M;\nvector<Point> initial_dots;\nvector<vector<bool>> has_dot;\nvector<vector<bool>> used_h;  // horizontal edge from (x,y) to (x+1,y)\nvector<vector<bool>> used_v;  // vertical edge from (x,y) to (x,y+1)\nvector<vector<bool>> used_d1; // diagonal from (x,y) to (x+1,y+1)\nvector<vector<bool>> used_d2; // diagonal from (x,y) to (x+1,y-1)\n\nlong long total_weight_S = 0;\nvector<vector<long long>> weights;\ndouble center_c;\n\nvoid init_weights() {\n    center_c = (N - 1) / 2.0;\n    weights.assign(N, vector<long long>(N));\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long w = (long long)round(pow(x - center_c, 2) + pow(y - center_c, 2) + 1);\n            weights[x][y] = w;\n            total_weight_S += w;\n        }\n    }\n}\n\nlong long get_weight(int x, int y) {\n    return weights[x][y];\n}\n\nbool is_inside(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y < N;\n}\n\n// Check if there are dots on the line segment (excluding endpoints)\nbool has_dot_on_segment(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    int steps = max(abs(dx), abs(dy));\n    if (steps <= 1) return false;\n    \n    int sx = (dx > 0) - (dx < 0);\n    int sy = (dy > 0) - (dy < 0);\n    \n    for (int i = 1; i < steps; ++i) {\n        int cx = x1 + i * sx;\n        int cy = y1 + i * sy;\n        if (has_dot[cx][cy]) return true;\n    }\n    return false;\n}\n\n// Check if rectangle perimeter has dots (excluding the 4 corners)\nbool check_rect_perimeter_dots(const Rect& r) {\n    for (int i = 0; i < 4; ++i) {\n        if (has_dot_on_segment(r.p[i].x, r.p[i].y, r.p[(i+1)%4].x, r.p[(i+1)%4].y)) {\n            return false;\n        }\n    }\n    return true;\n}\n\n// Mark/check edges of rectangle. Returns false if any edge is already used.\nbool process_rect_edges(const Rect& r, bool mark) {\n    for (int i = 0; i < 4; ++i) {\n        int x1 = r.p[i].x, y1 = r.p[i].y;\n        int x2 = r.p[(i+1)%4].x, y2 = r.p[(i+1)%4].y;\n        \n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        int steps = max(abs(dx), abs(dy));\n        \n        if (steps == 0) return false;\n        \n        int sx = (dx > 0) - (dx < 0);\n        int sy = (dy > 0) - (dy < 0);\n        \n        // Validate edge direction\n        bool valid_dir = false;\n        if (sx == 1 && sy == 0) valid_dir = true;      // right\n        else if (sx == -1 && sy == 0) valid_dir = true; // left\n        else if (sx == 0 && sy == 1) valid_dir = true;  // up\n        else if (sx == 0 && sy == -1) valid_dir = true; // down\n        else if (sx == 1 && sy == 1) valid_dir = true;  // up-right\n        else if (sx == -1 && sy == -1) valid_dir = true;// down-left\n        else if (sx == 1 && sy == -1) valid_dir = true; // down-right\n        else if (sx == -1 && sy == 1) valid_dir = true; // up-left\n        else return false;\n        \n        for (int j = 0; j < steps; ++j) {\n            int cx = x1 + j * sx;\n            int cy = y1 + j * sy;\n            \n            bool used = false;\n            \n            if (sx == 1 && sy == 0) {\n                // Horizontal right: edge from (cx,cy) to (cx+1,cy)\n                if (cx < N-1 && cy >= 0 && cy < N) {\n                    if (used_h[cx][cy]) used = true;\n                    else if (mark) used_h[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == 0) {\n                // Horizontal left: edge from (cx-1,cy) to (cx,cy)\n                if (cx > 0 && cy >= 0 && cy < N) {\n                    if (used_h[cx-1][cy]) used = true;\n                    else if (mark) used_h[cx-1][cy] = true;\n                }\n            } else if (sx == 0 && sy == 1) {\n                // Vertical up: edge from (cx,cy) to (cx,cy+1)\n                if (cx >= 0 && cx < N && cy < N-1) {\n                    if (used_v[cx][cy]) used = true;\n                    else if (mark) used_v[cx][cy] = true;\n                }\n            } else if (sx == 0 && sy == -1) {\n                // Vertical down: edge from (cx,cy-1) to (cx,cy)\n                if (cx >= 0 && cx < N && cy > 0) {\n                    if (used_v[cx][cy-1]) used = true;\n                    else if (mark) used_v[cx][cy-1] = true;\n                }\n            } else if (sx == 1 && sy == 1) {\n                // Diagonal up-right: edge from (cx,cy) to (cx+1,cy+1)\n                if (cx < N-1 && cy < N-1) {\n                    if (used_d1[cx][cy]) used = true;\n                    else if (mark) used_d1[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == -1) {\n                // Diagonal down-left: edge from (cx-1,cy-1) to (cx,cy)\n                if (cx > 0 && cy > 0) {\n                    if (used_d1[cx-1][cy-1]) used = true;\n                    else if (mark) used_d1[cx-1][cy-1] = true;\n                }\n            } else if (sx == 1 && sy == -1) {\n                // Diagonal down-right: edge from (cx,cy) to (cx+1,cy-1)\n                if (cx < N-1 && cy > 0) {\n                    if (used_d2[cx][cy]) used = true;\n                    else if (mark) used_d2[cx][cy] = true;\n                }\n            } else if (sx == -1 && sy == 1) {\n                // Diagonal up-left: edge from (cx-1,cy+1) to (cx,cy)\n                if (cx > 0 && cy < N-1) {\n                    if (used_d2[cx-1][cy+1]) used = true;\n                    else if (mark) used_d2[cx-1][cy+1] = true;\n                }\n            }\n            \n            if (used) return false;\n        }\n    }\n    return true;\n}\n\n// Check if 4 points form a valid rectangle (axis-aligned or 45-degree)\nbool is_valid_rectangle(const Point& p1, const Point& p2, const Point& p3, const Point& p4) {\n    // Check all 4 edges have same direction type (all axis or all 45-deg)\n    auto get_edge_type = [](const Point& a, const Point& b) -> int {\n        int dx = b.x - a.x;\n        int dy = b.y - a.y;\n        if (dx == 0 || dy == 0) return 1; // axis-aligned\n        if (abs(dx) == abs(dy)) return 2; // 45-degree\n        return 0; // invalid\n    };\n    \n    int t1 = get_edge_type(p1, p2);\n    int t2 = get_edge_type(p2, p3);\n    int t3 = get_edge_type(p3, p4);\n    int t4 = get_edge_type(p4, p1);\n    \n    if (t1 == 0 || t2 == 0 || t3 == 0 || t4 == 0) return false;\n    if (t1 != t2 || t2 != t3 || t3 != t4) return false;\n    \n    // Check it's actually a rectangle (opposite sides equal, adjacent sides perpendicular)\n    long long dx1 = p2.x - p1.x, dy1 = p2.y - p1.y;\n    long long dx2 = p3.x - p2.x, dy2 = p3.y - p2.y;\n    long long dx3 = p4.x - p3.x, dy3 = p4.y - p3.y;\n    long long dx4 = p1.x - p4.x, dy4 = p1.y - p4.y;\n    \n    // Adjacent edges should be perpendicular\n    if (dx1 * dx2 + dy1 * dy2 != 0) return false;\n    if (dx2 * dx3 + dy2 * dy3 != 0) return false;\n    if (dx3 * dx4 + dy3 * dy4 != 0) return false;\n    if (dx4 * dx1 + dy4 * dy1 != 0) return false;\n    \n    return true;\n}\n\nvector<Rect> generate_candidates(const vector<Point>& active_dots) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    \n    for (int i = 0; i < S; ++i) {\n        for (int j = i + 1; j < S; ++j) {\n            Point A = active_dots[i];\n            Point B = active_dots[j];\n            \n            // Case 1: A, B are diagonal of axis-aligned rectangle\n            if (A.x != B.x && A.y != B.y) {\n                Point C1 = {A.x, B.y};\n                Point C2 = {B.x, A.y};\n                \n                // Target C1, sources: C2, B, A (in order around rectangle)\n                if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && \n                    is_inside(C2.x, C2.y) && has_dot[C2.x][C2.y]) {\n                    Rect r;\n                    r.p[0] = C1; r.p[1] = C2; r.p[2] = B; r.p[3] = A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                \n                // Target C2, sources: C1, A, B\n                if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && \n                    is_inside(C1.x, C1.y) && has_dot[C1.x][C1.y]) {\n                    Rect r;\n                    r.p[0] = C2; r.p[1] = C1; r.p[2] = A; r.p[3] = B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 2: A, B vertical side of 45-degree rectangle\n            if (A.x == B.x && (A.y + B.y) % 2 == 0) {\n                int my = (A.y + B.y) / 2;\n                int dist = abs(A.y - B.y) / 2;\n                Point C = {A.x - dist, my};\n                Point D = {A.x + dist, my};\n                \n                if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                    is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                    is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 3: A, B horizontal side of 45-degree rectangle\n            if (A.y == B.y && (A.x + B.x) % 2 == 0) {\n                int mx = (A.x + B.x) / 2;\n                int dist = abs(A.x - B.x) / 2;\n                Point C = {mx, A.y - dist};\n                Point D = {mx, A.y + dist};\n                \n                if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                    is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                    is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            }\n            \n            // Case 4: Three corners form right angle, find 4th\n            for (int k = 0; k < S; ++k) {\n                if (k == i || k == j) continue;\n                Point C = active_dots[k];\n                \n                auto try_corner = [&](Point P1, Point P2, Point corner) {\n                    long long dx1 = P1.x - corner.x, dy1 = P1.y - corner.y;\n                    long long dx2 = P2.x - corner.x, dy2 = P2.y - corner.y;\n                    \n                    if (dx1*dx2 + dy1*dy2 != 0) return;\n                    \n                    bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                    bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                    if (!(axis || deg45)) return;\n                    \n                    Point D = {P1.x + P2.x - corner.x, P1.y + P2.y - corner.y};\n                    if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                        Rect r; r.p[0]=D; r.p[1]=corner; r.p[2]=P1; r.p[3]=P2;\n                        if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                            cands.push_back(r);\n                    }\n                };\n                \n                try_corner(A, B, A);\n                try_corner(A, B, B);\n                try_corner(A, B, C);\n            }\n        }\n    }\n    return cands;\n}\n\nvector<Rect> generate_candidates_with_new(const vector<Point>& active_dots, Point new_dot) {\n    vector<Rect> cands;\n    int S = active_dots.size();\n    \n    for (int i = 0; i < S; ++i) {\n        Point A = active_dots[i];\n        Point B = new_dot;\n        \n        // Diagonal cases\n        if (A.x != B.x && A.y != B.y) {\n            Point C1 = {A.x, B.y};\n            Point C2 = {B.x, A.y};\n            \n            if (is_inside(C1.x, C1.y) && !has_dot[C1.x][C1.y] && \n                is_inside(C2.x, C2.y) && has_dot[C2.x][C2.y]) {\n                Rect r; r.p[0]=C1; r.p[1]=C2; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(C2.x, C2.y) && !has_dot[C2.x][C2.y] && \n                is_inside(C1.x, C1.y) && has_dot[C1.x][C1.y]) {\n                Rect r; r.p[0]=C2; r.p[1]=C1; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        if (A.x == B.x && (A.y + B.y) % 2 == 0) {\n            int my = (A.y + B.y) / 2;\n            int dist = abs(A.y - B.y) / 2;\n            Point C = {A.x - dist, my};\n            Point D = {A.x + dist, my};\n            \n            if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        if (A.y == B.y && (A.x + B.x) % 2 == 0) {\n            int mx = (A.x + B.x) / 2;\n            int dist = abs(A.x - B.x) / 2;\n            Point C = {mx, A.y - dist};\n            Point D = {mx, A.y + dist};\n            \n            if (is_inside(C.x, C.y) && !has_dot[C.x][C.y] && \n                is_inside(D.x, D.y) && has_dot[D.x][D.y]) {\n                Rect r; r.p[0]=C; r.p[1]=D; r.p[2]=B; r.p[3]=A;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n            if (is_inside(D.x, D.y) && !has_dot[D.x][D.y] && \n                is_inside(C.x, C.y) && has_dot[C.x][C.y]) {\n                Rect r; r.p[0]=D; r.p[1]=C; r.p[2]=A; r.p[3]=B;\n                if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                    cands.push_back(r);\n            }\n        }\n        \n        // Three-corner cases\n        for (int k = 0; k < S; ++k) {\n            if (k == i) continue;\n            Point C = active_dots[k];\n            \n            auto try_corner = [&](Point P1, Point P2, Point corner) {\n                long long dx1 = P1.x - corner.x, dy1 = P1.y - corner.y;\n                long long dx2 = P2.x - corner.x, dy2 = P2.y - corner.y;\n                \n                if (dx1*dx2 + dy1*dy2 != 0) return;\n                \n                bool axis = (dx1==0 || dy1==0) && (dx2==0 || dy2==0);\n                bool deg45 = (abs(dx1)==abs(dy1)) && (abs(dx2)==abs(dy2));\n                if (!(axis || deg45)) return;\n                \n                Point D = {P1.x + P2.x - corner.x, P1.y + P2.y - corner.y};\n                if (is_inside(D.x, D.y) && !has_dot[D.x][D.y]) {\n                    Rect r; r.p[0]=D; r.p[1]=corner; r.p[2]=P1; r.p[3]=P2;\n                    if (is_valid_rectangle(r.p[0], r.p[1], r.p[2], r.p[3]))\n                        cands.push_back(r);\n                }\n            };\n            \n            try_corner(A, B, A);\n            try_corner(A, B, B);\n            try_corner(A, B, C);\n        }\n    }\n    return cands;\n}\n\nstruct Solution {\n    vector<Rect> ops;\n    long long score;\n};\n\nSolution solve_one(mt19937& rng) {\n    has_dot.assign(N, vector<bool>(N, false));\n    used_h.assign(N, vector<bool>(N, false));\n    used_v.assign(N, vector<bool>(N, false));\n    used_d1.assign(N, vector<bool>(N, false));\n    used_d2.assign(N, vector<bool>(N, false));\n    \n    vector<Point> active_dots = initial_dots;\n    for (auto& p : active_dots) has_dot[p.x][p.y] = true;\n    \n    vector<Rect> ops;\n    vector<Rect> candidates = generate_candidates(active_dots);\n    \n    while (true) {\n        vector<Rect> valid_cands;\n        valid_cands.reserve(candidates.size());\n        \n        for (auto& r : candidates) {\n            // Check target is empty\n            if (has_dot[r.p[0].x][r.p[0].y]) continue;\n            \n            // Check sources have dots\n            if (!has_dot[r.p[1].x][r.p[1].y]) continue;\n            if (!has_dot[r.p[2].x][r.p[2].y]) continue;\n            if (!has_dot[r.p[3].x][r.p[3].y]) continue;\n            \n            // Check no dots on perimeter\n            if (!check_rect_perimeter_dots(r)) continue;\n            \n            // Check edges not used\n            if (!process_rect_edges(r, false)) continue;\n            \n            r.weight = get_weight(r.p[0].x, r.p[0].y);\n            int len = 0;\n            for(int i=0; i<4; ++i) {\n                len += max(abs(r.p[i].x - r.p[(i+1)%4].x), \n                           abs(r.p[i].y - r.p[(i+1)%4].y));\n            }\n            r.perimeter_len = len;\n            valid_cands.push_back(r);\n        }\n        \n        if (valid_cands.empty()) break;\n        \n        // Add randomness\n        for(auto& r : valid_cands) {\n            r.weight += (rng() % 100);\n        }\n        sort(valid_cands.begin(), valid_cands.end());\n        \n        Rect best = valid_cands[0];\n        ops.push_back(best);\n        has_dot[best.p[0].x][best.p[0].y] = true;\n        active_dots.push_back(best.p[0]);\n        process_rect_edges(best, true);\n        \n        vector<Rect> new_cands = generate_candidates_with_new(active_dots, best.p[0]);\n        candidates.insert(candidates.end(), new_cands.begin(), new_cands.end());\n    }\n    \n    Solution sol;\n    sol.ops = ops;\n    long long current_weight_sum = 0;\n    for(int x=0; x<N; ++x) \n        for(int y=0; y<N; ++y) \n            if(has_dot[x][y]) current_weight_sum += weights[x][y];\n    \n    double score_d = 1e6 * (double)N * N / M * (double)current_weight_sum / total_weight_S;\n    sol.score = (long long)round(score_d);\n    \n    return sol;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    initial_dots.resize(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> initial_dots[i].x >> initial_dots[i].y;\n    }\n    \n    init_weights();\n    \n    Solution best_sol;\n    best_sol.score = -1;\n    \n    auto start = chrono::steady_clock::now();\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 4.8) break;\n        \n        Solution sol = solve_one(rng);\n        if (sol.score > best_sol.score) {\n            best_sol = sol;\n        }\n    }\n    \n    cout << best_sol.ops.size() << \"\\n\";\n    for (const auto& op : best_sol.ops) {\n        cout << op.p[0].x << \" \" << op.p[0].y << \" \"\n             << op.p[1].x << \" \" << op.p[1].y << \" \"\n             << op.p[2].x << \" \" << op.p[2].y << \" \"\n             << op.p[3].x << \" \" << op.p[3].y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc015":"#include <iostream>\n#include <vector>\n#include <array>\n#include <utility>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nusing Grid = array<array<int, 10>, 10>;\n\n// Calculate sum of squares of connected component sizes\nlong long calculate_component_score(const Grid& g) {\n    long long score = 0;\n    bool visited[10][10];\n    memset(visited, 0, sizeof(visited));\n    int dr[4] = {0, 0, 1, -1};\n    int dc[4] = {1, -1, 0, 0};\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                pair<int, int> q[100];\n                int head = 0, tail = 0;\n                q[tail++] = {r, c};\n                visited[r][c] = true;\n                size++;\n                \n                while(head < tail){\n                    int cr = q[head].first;\n                    int cc = q[head].second;\n                    head++;\n                    for(int i=0; i<4; ++i){\n                        int nr = cr + dr[i];\n                        int nc = cc + dc[i];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                            if(!visited[nr][nc] && g[nr][nc] == flavor){\n                                visited[nr][nc] = true;\n                                size++;\n                                q[tail++] = {nr, nc};\n                            }\n                        }\n                    }\n                }\n                score += (long long)size * size;\n            }\n        }\n    }\n    return score;\n}\n\n// Count adjacent pairs with phase-aware weighting\nlong long calculate_adjacency_bonus(const Grid& g, int empty_cells) {\n    long long score = 0;\n    long long same_bonus, diff_penalty;\n    \n    if (empty_cells <= 15) {\n        same_bonus = 20;\n        diff_penalty = 10;\n    } else if (empty_cells <= 30) {\n        same_bonus = 12;\n        diff_penalty = 6;\n    } else if (empty_cells <= 50) {\n        same_bonus = 8;\n        diff_penalty = 4;\n    } else {\n        same_bonus = 6;\n        diff_penalty = 2;\n    }\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0) {\n                // Check right neighbor\n                if (c + 1 < 10 && g[r][c+1] != 0) {\n                    if (g[r][c+1] == g[r][c]) score += same_bonus;\n                    else score -= diff_penalty;\n                }\n                // Check down neighbor\n                if (r + 1 < 10 && g[r+1][c] != 0) {\n                    if (g[r+1][c] == g[r][c]) score += same_bonus;\n                    else score -= diff_penalty;\n                }\n            }\n        }\n    }\n    return score;\n}\n\nint count_empty_cells(const Grid& g) {\n    int count = 0;\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] == 0) count++;\n        }\n    }\n    return count;\n}\n\nlong long calculate_total_score(const Grid& g, int empty_cells) {\n    long long component_weight;\n    if (empty_cells <= 15) {\n        component_weight = 300;\n    } else if (empty_cells <= 30) {\n        component_weight = 150;\n    } else if (empty_cells <= 50) {\n        component_weight = 120;\n    } else {\n        component_weight = 100;\n    }\n    \n    return calculate_component_score(g) * component_weight + calculate_adjacency_bonus(g, empty_cells);\n}\n\nlong long calculate_secondary_score(const Grid& g) {\n    long long score = 0;\n    bool visited[10][10];\n    memset(visited, 0, sizeof(visited));\n    int dr[4] = {0, 0, 1, -1};\n    int dc[4] = {1, -1, 0, 0};\n    int max_size = 0;\n    int num_components = 0;\n\n    for (int r = 0; r < 10; ++r) {\n        for (int c = 0; c < 10; ++c) {\n            if (g[r][c] != 0 && !visited[r][c]) {\n                int flavor = g[r][c];\n                int size = 0;\n                pair<int, int> q[100];\n                int head = 0, tail = 0;\n                q[tail++] = {r, c};\n                visited[r][c] = true;\n                size++;\n                \n                while(head < tail){\n                    int cr = q[head].first;\n                    int cc = q[head].second;\n                    head++;\n                    for(int i=0; i<4; ++i){\n                        int nr = cr + dr[i];\n                        int nc = cc + dc[i];\n                        if(nr >= 0 && nr < 10 && nc >= 0 && nc < 10){\n                            if(!visited[nr][nc] && g[nr][nc] == flavor){\n                                visited[nr][nc] = true;\n                                size++;\n                                q[tail++] = {nr, nc};\n                            }\n                        }\n                    }\n                }\n                max_size = max(max_size, size);\n                num_components++;\n            }\n        }\n    }\n    \n    return max_size * 200 - num_components * 20;\n}\n\n// Fixed tilt function with proper direction handling\nGrid apply_tilt(const Grid& g, char dir) {\n    Grid ng;\n    for(auto& row : ng) row.fill(0);\n\n    if (dir == 'L' || dir == 'R') {\n        for (int r = 0; r < 10; ++r) {\n            // Collect non-zero values in the row\n            vector<int> vals;\n            vals.reserve(10);\n            if (dir == 'L') {\n                for (int c = 0; c < 10; ++c) {\n                    if (g[r][c] != 0) vals.push_back(g[r][c]);\n                }\n                // Write from left\n                for (int i = 0; i < (int)vals.size(); ++i) {\n                    ng[r][i] = vals[i];\n                }\n            } else { // dir == 'R'\n                for (int c = 0; c < 10; ++c) {\n                    if (g[r][c] != 0) vals.push_back(g[r][c]);\n                }\n                // Write from right\n                for (int i = 0; i < (int)vals.size(); ++i) {\n                    ng[r][9 - i] = vals[(int)vals.size() - 1 - i];\n                }\n            }\n        }\n    } else { // dir == 'F' || dir == 'B'\n        for (int c = 0; c < 10; ++c) {\n            // Collect non-zero values in the column\n            vector<int> vals;\n            vals.reserve(10);\n            if (dir == 'F') {\n                for (int r = 0; r < 10; ++r) {\n                    if (g[r][c] != 0) vals.push_back(g[r][c]);\n                }\n                // Write from top\n                for (int i = 0; i < (int)vals.size(); ++i) {\n                    ng[i][c] = vals[i];\n                }\n            } else { // dir == 'B'\n                for (int r = 0; r < 10; ++r) {\n                    if (g[r][c] != 0) vals.push_back(g[r][c]);\n                }\n                // Write from bottom\n                for (int i = 0; i < (int)vals.size(); ++i) {\n                    ng[9 - i][c] = vals[(int)vals.size() - 1 - i];\n                }\n            }\n        }\n    }\n    return ng;\n}\n\nstruct MoveSequence {\n    string moves;\n    Grid final_grid;\n    long long score;\n    long long secondary_score;\n};\n\nvector<MoveSequence> beam_search(const Grid& g, int depth, int beam_width, int empty_cells) {\n    vector<MoveSequence> current_beam;\n    current_beam.reserve(beam_width * 4);\n    char dirs[4] = {'F', 'B', 'L', 'R'};\n    \n    for (char d : dirs) {\n        Grid ng = apply_tilt(g, d);\n        int ng_empty = count_empty_cells(ng);\n        long long sc = calculate_total_score(ng, ng_empty);\n        long long sc2 = calculate_secondary_score(ng);\n        current_beam.push_back({string(1, d), ng, sc, sc2});\n    }\n    \n    sort(current_beam.begin(), current_beam.end(), \n         [](const MoveSequence& a, const MoveSequence& b) {\n             if (a.score != b.score) return a.score > b.score;\n             return a.secondary_score > b.secondary_score;\n         });\n    \n    if ((int)current_beam.size() > beam_width) {\n        current_beam.resize(beam_width);\n    }\n    \n    for (int d = 1; d < depth; ++d) {\n        vector<MoveSequence> next_beam;\n        next_beam.reserve(current_beam.size() * 3);\n        \n        for (const auto& seq : current_beam) {\n            for (char dir : dirs) {\n                char last = seq.moves.back();\n                if ((last == 'F' && dir == 'B') || (last == 'B' && dir == 'F') ||\n                    (last == 'L' && dir == 'R') || (last == 'R' && dir == 'L')) {\n                    continue;\n                }\n                \n                int same_count = 0;\n                for (int i = (int)seq.moves.size() - 1; i >= 0 && seq.moves[i] == dir; --i) {\n                    same_count++;\n                }\n                if (same_count >= 3) continue;\n                \n                Grid ng = apply_tilt(seq.final_grid, dir);\n                int ng_empty = count_empty_cells(ng);\n                long long sc = calculate_total_score(ng, ng_empty);\n                long long sc2 = calculate_secondary_score(ng);\n                next_beam.push_back({seq.moves + dir, ng, sc, sc2});\n            }\n        }\n        \n        sort(next_beam.begin(), next_beam.end(), \n             [](const MoveSequence& a, const MoveSequence& b) {\n                 if (a.score != b.score) return a.score > b.score;\n                 return a.secondary_score > b.secondary_score;\n             });\n        \n        if ((int)next_beam.size() > beam_width) {\n            next_beam.resize(beam_width);\n        }\n        \n        current_beam = move(next_beam);\n    }\n    \n    return current_beam;\n}\n\nint main() {\n    cin.tie(NULL);\n    ios_base::sync_with_stdio(false);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; ++i) {\n        cin >> f[i];\n    }\n\n    Grid grid;\n    for(auto& row : grid) row.fill(0);\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        \n        int count = 0;\n        bool placed = false;\n        for (int r = 0; r < 10; ++r) {\n            for (int c = 0; c < 10; ++c) {\n                if (grid[r][c] == 0) {\n                    count++;\n                    if (count == p) {\n                        grid[r][c] = f[t];\n                        placed = true;\n                        break;\n                    }\n                }\n            }\n            if (placed) break;\n        }\n\n        if (t == 99) {\n            cout << \"F\" << endl;\n            break;\n        }\n\n        int empty_cells = count_empty_cells(grid);\n        int depth, beam_width;\n        \n        // Conservative, proven parameters\n        if (empty_cells > 80) {\n            depth = 5;\n            beam_width = 20;\n        } else if (empty_cells > 60) {\n            depth = 4;\n            beam_width = 16;\n        } else if (empty_cells > 40) {\n            depth = 3;\n            beam_width = 12;\n        } else if (empty_cells > 20) {\n            depth = 2;\n            beam_width = 10;\n        } else {\n            depth = 2;\n            beam_width = 8;\n        }\n        \n        vector<MoveSequence> results = beam_search(grid, depth, beam_width, empty_cells);\n        \n        char best_dir = results[0].moves[0];\n        \n        cout << best_dir << endl;\n        grid = apply_tilt(grid, best_dir);\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\n\nusing namespace std;\n\nint M;\ndouble epsilon;\nint N;\nvector<string> graphs;\n\n// Parse graph string to adjacency matrix\nvector<vector<int>> parseGraph(const string& s, int n) {\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    int idx = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            adj[i][j] = adj[j][i] = s[idx++] - '0';\n        }\n    }\n    return adj;\n}\n\n// Convert adjacency matrix to graph string\nstring toGraphString(const vector<vector<int>>& adj, int n) {\n    string s;\n    s.reserve(n * (n - 1) / 2);\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            s += (adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\n// Count edges\nint countEdges(const string& s) {\n    return count(s.begin(), s.end(), '1');\n}\n\n// Compute degree sequence (sorted)\nvector<int> degreeSequence(const vector<vector<int>>& adj, int n) {\n    vector<int> deg(n, 0);\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            deg[i] += adj[i][j];\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Compute degree sum of squares (more stable than full sequence)\nlong long degreeSumSquares(const vector<int>& deg) {\n    long long sum = 0;\n    for (int d : deg) {\n        sum += 1LL * d * d;\n    }\n    return sum;\n}\n\n// Count paths of length 2 (related to degree sum of squares)\nint countPaths2(const vector<vector<int>>& adj, int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        int deg = 0;\n        for (int j = 0; j < n; j++) {\n            deg += adj[i][j];\n        }\n        count += deg * (deg - 1) / 2;\n    }\n    return count;\n}\n\n// Compute optimal N - much more aggressive minimization\nint computeOptimalN(int m, double eps) {\n    // For each candidate N, check if we can separate M graphs\n    for (int n = 4; n <= 100; n++) {\n        int total_edges = n * (n - 1) / 2;\n        \n        // Expected noise: each edge flips with probability eps\n        double noise_std = sqrt(total_edges * eps * (1 - eps));\n        \n        // Need separation of at least 2-3 standard deviations between graphs\n        double min_sep = max(1.0, 2.5 * noise_std);\n        \n        // Can we fit M graphs in the edge count range?\n        // Use 80% of range to allow margin\n        double available = total_edges * 0.8;\n        double needed = (m - 1) * min_sep;\n        \n        if (needed <= available) {\n            // Additional constraint: prefer smaller N for easier cases\n            if (m <= 30 && eps <= 0.15 && n > 25) continue;\n            if (m <= 50 && eps <= 0.2 && n > 35) continue;\n            if (m <= 70 && eps <= 0.25 && n > 50) continue;\n            return n;\n        }\n    }\n    \n    return 100;\n}\n\n// Generate graph with specific properties\nstring generateGraph(int n, int target_edges, int seed, int type) {\n    mt19937 rng(seed);\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    \n    vector<pair<int, int>> edges;\n    edges.reserve(n * (n - 1) / 2);\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    }\n    \n    // Different construction strategies for variety\n    if (type == 0) {\n        // Random\n        shuffle(edges.begin(), edges.end(), rng);\n    } else if (type == 1) {\n        // Prefer edges with small index sum (creates dense region)\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return a.first + a.second < b.first + b.second;\n        });\n    } else if (type == 2) {\n        // Prefer edges that create degree variation\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return max(a.first, a.second) < max(b.first, b.second);\n        });\n    } else if (type == 3) {\n        // Prefer edges with small index difference (creates local clusters)\n        sort(edges.begin(), edges.end(), [](const pair<int,int>& a, const pair<int,int>& b) {\n            return abs(a.first - a.second) < abs(b.first - b.second);\n        });\n    }\n    \n    int added = 0;\n    for (auto& [u, v] : edges) {\n        if (added >= target_edges) break;\n        adj[u][v] = adj[v][u] = 1;\n        added++;\n    }\n    \n    return toGraphString(adj, n);\n}\n\n// Generate M well-separated graphs\nvector<string> generateGraphs(int m, int n, double eps) {\n    vector<string> result;\n    result.reserve(m);\n    \n    int total_edges = n * (n - 1) / 2;\n    double noise_std = sqrt(total_edges * eps * (1 - eps));\n    int min_sep = max(1, (int)(3.0 * noise_std));\n    \n    // Edge count range\n    int min_edges = max(0, (int)(total_edges * 0.1));\n    int max_edges = min(total_edges, (int)(total_edges * 0.9));\n    int range = max_edges - min_edges;\n    \n    // Calculate step size\n    int step = max(min_sep, range / max(1, m - 1));\n    \n    for (int k = 0; k < m; k++) {\n        int edges = min_edges + k * step;\n        edges = max(min_edges, min(max_edges, edges));\n        \n        // Vary structure type\n        int type = k % 4;\n        string g = generateGraph(n, edges, k * 1234 + n, type);\n        result.push_back(g);\n    }\n    \n    return result;\n}\n\n// Graph signature\nstruct GraphSignature {\n    int edge_count;\n    long long degree_sum_sq;\n    int paths2;\n    vector<int> degree_seq;\n    int min_deg, max_deg;\n    \n    GraphSignature() {}\n    \n    GraphSignature(const string& s, int n) {\n        edge_count = countEdges(s);\n        auto adj = parseGraph(s, n);\n        degree_seq = degreeSequence(adj, n);\n        degree_sum_sq = degreeSumSquares(degree_seq);\n        paths2 = countPaths2(adj, n);\n        min_deg = degree_seq[0];\n        max_deg = degree_seq[n-1];\n    }\n};\n\n// Compute distance with noise-adaptive weighting\ndouble signatureDistance(const GraphSignature& s1, const GraphSignature& s2, double eps) {\n    double dist = 0;\n    \n    // Edge count - most important, weight increases with noise\n    double edge_weight = 5.0 + 20.0 * eps;\n    dist += abs(s1.edge_count - s2.edge_count) * edge_weight;\n    \n    // Degree sum of squares - stable under permutation\n    double dss_weight = 0.01 + 0.05 * eps;\n    dist += abs(s1.degree_sum_sq - s2.degree_sum_sq) * dss_weight;\n    \n    // Paths of length 2\n    double p2_weight = 0.02 + 0.03 * eps;\n    dist += abs(s1.paths2 - s2.paths2) * p2_weight;\n    \n    // Degree range\n    dist += abs(s1.min_deg - s2.min_deg) * 2.0;\n    dist += abs(s1.max_deg - s2.max_deg) * 2.0;\n    \n    // Full degree sequence (less weight under high noise)\n    double deg_seq_weight = max(0.1, 1.0 - eps);\n    for (size_t i = 0; i < s1.degree_seq.size(); i++) {\n        dist += abs(s1.degree_seq[i] - s2.degree_seq[i]) * deg_seq_weight;\n    }\n    \n    return dist;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> M >> epsilon;\n    \n    // Compute optimal N\n    N = computeOptimalN(M, epsilon);\n    \n    // Generate graphs\n    graphs = generateGraphs(M, N, epsilon);\n    \n    // Precompute signatures\n    vector<GraphSignature> signatures(M);\n    for (int i = 0; i < M; i++) {\n        signatures[i] = GraphSignature(graphs[i], N);\n    }\n    \n    // Output\n    cout << N << \"\\n\";\n    for (int i = 0; i < M; i++) {\n        cout << graphs[i] << \"\\n\";\n    }\n    cout.flush();\n    \n    // Process queries\n    for (int q = 0; q < 100; q++) {\n        string h;\n        cin >> h;\n        \n        GraphSignature h_sig(h, N);\n        \n        int best_idx = 0;\n        double best_dist = 1e18;\n        double second_best = 1e18;\n        \n        for (int i = 0; i < M; i++) {\n            double dist = signatureDistance(h_sig, signatures[i], epsilon);\n            if (dist < best_dist) {\n                second_best = best_dist;\n                best_dist = dist;\n                best_idx = i;\n            } else if (dist < second_best) {\n                second_best = dist;\n            }\n        }\n        \n        // Confidence check - if best is much better, trust it\n        // Otherwise, could add more sophisticated logic\n        cout << best_idx << \"\\n\";\n        cout.flush();\n    }\n    \n    return 0;\n}","ahc017":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Edge {\n    int u, v, w, id;\n};\n\nconst long long INF = 1e18;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, D, K;\n    if (!(cin >> N >> M >> D >> K)) return 0;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int, int>>> adj(N + 1);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\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    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    auto total_start = chrono::steady_clock::now();\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    // Conflict matrix W - simple co-occurrence only\n    vector<int> W(M * M, 0);\n    vector<int> edge_usage(M, 0);\n\n    // Path sampling\n    int num_samples = 20000;\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 1);\n    shuffle(vertices.begin(), vertices.end(), rng);\n\n    auto w_start = chrono::steady_clock::now();\n    \n    for (int iter = 0; iter < num_samples; ++iter) {\n        if (iter % 1000 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration_cast<chrono::milliseconds>(now - w_start).count() > 1000) break;\n        }\n        \n        int s = vertices[iter % N];\n        int t = vertices[(iter * 17 + 5) % N];\n        if (s == t) {\n            t = vertices[(iter + 1) % N];\n        }\n        \n        vector<long long> dist(N + 1, INF);\n        vector<int> par_edge(N + 1, -1);\n        vector<int> par_node(N + 1, -1);\n        dist[s] = 0;\n        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d > dist[u]) continue;\n            for (auto [v, eid] : adj[u]) {\n                if (dist[u] + edges[eid].w < dist[v]) {\n                    dist[v] = dist[u] + edges[eid].w;\n                    par_node[v] = u;\n                    par_edge[v] = eid;\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        if (dist[t] == INF) continue;\n\n        vector<int> path_edges;\n        int curr = t;\n        while (curr != s && par_edge[curr] != -1) {\n            path_edges.push_back(par_edge[curr]);\n            curr = par_node[curr];\n        }\n\n        for (int eid : path_edges) {\n            edge_usage[eid]++;\n        }\n        int L = path_edges.size();\n        for (int i = 0; i < L; ++i) {\n            for (int j = i + 1; j < L; ++j) {\n                int u = path_edges[i];\n                int v = path_edges[j];\n                // Simple co-occurrence - no weight factor\n                W[u * M + v]++;\n                W[v * M + u]++;\n            }\n        }\n    }\n\n    // Edge importance\n    vector<long long> edge_importance(M, 0);\n    for (int i = 0; i < M; ++i) {\n        edge_importance[i] = (long long)edge_usage[i] * 100;\n        for (int j = 0; j < M; ++j) {\n            edge_importance[i] += W[i * M + j];\n        }\n    }\n\n    // Solve function - simplified\n    auto solve = [&](int seed_offset, int time_limit_ms) -> pair<vector<int>, long long> {\n        mt19937_64 local_rng(rng() + seed_offset);\n        \n        // Initial assignment - simple single strategy\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return edge_importance[a] > edge_importance[b];\n        });\n        \n        for (int i = M - 1; i > 0; --i) {\n            int j = uniform_int_distribution<>(0, i)(local_rng);\n            swap(order[i], order[j]);\n        }\n\n        vector<int> assignment(M, -1);\n        vector<int> day_size(D, 0);\n        vector<vector<int>> day_edges(D);\n        \n        for (int e : order) {\n            int best_day = -1;\n            long long min_cost = -1;\n            \n            vector<int> day_order(D);\n            iota(day_order.begin(), day_order.end(), 0);\n            shuffle(day_order.begin(), day_order.end(), local_rng);\n            \n            for (int k : day_order) {\n                if (day_size[k] < K) {\n                    long long cost = 0;\n                    for (int other : day_edges[k]) {\n                        cost += W[e * M + other];\n                    }\n                    if (best_day == -1 || cost < min_cost) {\n                        min_cost = cost;\n                        best_day = k;\n                    }\n                }\n            }\n            \n            if (best_day != -1) {\n                assignment[e] = best_day;\n                day_edges[best_day].push_back(e);\n                day_size[best_day]++;\n            }\n        }\n\n        // Precompute C[k][e]\n        vector<long long> C(D * M, 0);\n        for (int k = 0; k < D; ++k) {\n            for (int e : day_edges[k]) {\n                for (int other = 0; other < M; ++other) {\n                    C[k * M + other] += W[e * M + other];\n                }\n            }\n        }\n        \n        long long current_cost = 0;\n        for (int k = 0; k < D; ++k) {\n            for (int i : day_edges[k]) {\n                for (int j : day_edges[k]) {\n                    if (i < j) current_cost += W[i * M + j];\n                }\n            }\n        }\n        \n        long long best_cost = current_cost;\n        vector<int> best_assignment = assignment;\n        vector<int> best_day_size = day_size;\n\n        // Simulated Annealing\n        auto ls_start = chrono::steady_clock::now();\n        double temperature = 500.0;\n        int moves = 0;\n        int no_improve_count = 0;\n        int stagnation_count = 0;\n        \n        while (true) {\n            auto now = chrono::steady_clock::now();\n            auto elapsed = chrono::duration_cast<chrono::milliseconds>(now - ls_start).count();\n            if (elapsed > time_limit_ms) break;\n            \n            auto total_elapsed = chrono::duration_cast<chrono::milliseconds>(now - total_start).count();\n            if (total_elapsed > 5900) break;\n            \n            if (moves % 10000 == 0 && moves > 0) {\n                if (no_improve_count > 40000) {\n                    stagnation_count++;\n                    if (stagnation_count < 3) {\n                        temperature *= 10;\n                        no_improve_count = 0;\n                    }\n                }\n            }\n            \n            temperature *= 0.9998;\n            \n            int e = uniform_int_distribution<>(0, M - 1)(local_rng);\n            int k_old = assignment[e];\n            if (k_old < 0) { moves++; continue; }\n            \n            int k_new = uniform_int_distribution<>(0, D - 1)(local_rng);\n            if (k_new == k_old) { moves++; continue; }\n            if (day_size[k_new] >= K) { moves++; continue; }\n            \n            long long delta = C[k_new * M + e] - C[k_old * M + e];\n            \n            bool accept = (delta < 0) || (temperature > 0.1 && exp(-delta / temperature) > uniform_real_distribution<>(0, 1)(local_rng));\n            \n            if (accept) {\n                assignment[e] = k_new;\n                day_size[k_old]--;\n                day_size[k_new]++;\n                \n                for (int other = 0; other < M; ++other) {\n                    long long w_val = W[e * M + other];\n                    C[k_old * M + other] -= w_val;\n                    C[k_new * M + other] += w_val;\n                }\n                \n                current_cost += delta;\n                if (current_cost < best_cost) {\n                    best_cost = current_cost;\n                    best_assignment = assignment;\n                    best_day_size = day_size;\n                    no_improve_count = 0;\n                } else {\n                    no_improve_count++;\n                }\n            } else {\n                no_improve_count++;\n            }\n            \n            moves++;\n        }\n        \n        // Greedy final pass\n        bool improved = true;\n        int greedy_iter = 0;\n        \n        assignment = best_assignment;\n        day_size = best_day_size;\n        \n        fill(C.begin(), C.end(), 0);\n        for (int k = 0; k < D; ++k) {\n            for (int e = 0; e < M; ++e) {\n                if (assignment[e] == k) {\n                    for (int other = 0; other < M; ++other) {\n                        C[k * M + other] += W[e * M + other];\n                    }\n                }\n            }\n        }\n        \n        current_cost = best_cost;\n        \n        while (improved && greedy_iter < 30) {\n            improved = false;\n            greedy_iter++;\n            \n            for (int e = 0; e < M; ++e) {\n                int k_old = assignment[e];\n                if (k_old < 0) continue;\n                \n                long long best_delta = 0;\n                int best_k = -1;\n                \n                for (int k = 0; k < D; ++k) {\n                    if (k == k_old) continue;\n                    if (day_size[k] >= K) continue;\n                    \n                    long long delta = C[k * M + e] - C[k_old * M + e];\n                    \n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_k = k;\n                    }\n                }\n                \n                if (best_k >= 0 && best_delta < 0) {\n                    assignment[e] = best_k;\n                    day_size[k_old]--;\n                    day_size[best_k]++;\n                    \n                    for (int other = 0; other < M; ++other) {\n                        long long w_val = W[e * M + other];\n                        C[k_old * M + other] -= w_val;\n                        C[best_k * M + other] += w_val;\n                    }\n                    \n                    current_cost += best_delta;\n                    if (current_cost < best_cost) {\n                        best_cost = current_cost;\n                        best_assignment = assignment;\n                        best_day_size = day_size;\n                    }\n                    improved = true;\n                }\n            }\n        }\n        \n        return {best_assignment, best_cost};\n    };\n\n    // 6 restarts with 800ms each - back to working configuration\n    vector<int> best_assignment;\n    long long best_cost = -1;\n    \n    int num_restarts = 6;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        int time_per_restart = 800;\n        \n        auto [assignment, cost] = solve(restart * 1000000, time_per_restart);\n        \n        if (best_cost < 0 || cost < best_cost) {\n            best_cost = cost;\n            best_assignment = assignment;\n        }\n        \n        auto now = chrono::steady_clock::now();\n        if (chrono::duration_cast<chrono::milliseconds>(now - total_start).count() > 5900) break;\n    }\n\n    // Output\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;\n\nint D;\nvector<string> f1, r1, f2, r2;\nvector<vector<vector<bool>>> valid1, valid2;\nvector<vector<vector<int>>> b1, b2;\n\nstruct Block {\n    vector<tuple<int,int,int>> cells;\n    int id;\n    bool usedIn1 = false;\n    bool usedIn2 = false;\n    \n    void normalize() {\n        if (cells.empty()) return;\n        int minX = 100, minY = 100, minZ = 100;\n        for (auto& cell : cells) {\n            minX = min(minX, get<0>(cell));\n            minY = min(minY, get<1>(cell));\n            minZ = min(minZ, get<2>(cell));\n        }\n        for (auto& cell : cells) {\n            get<0>(cell) -= minX;\n            get<1>(cell) -= minY;\n            get<2>(cell) -= minZ;\n        }\n        sort(cells.begin(), cells.end());\n    }\n};\n\nvector<Block> blocks;\n\n// 24 rotation matrices\nint rotations_24[24][3][3] = {\n    {{1,0,0},{0,1,0},{0,0,1}}, {{0,-1,0},{1,0,0},{0,0,1}}, {{-1,0,0},{0,-1,0},{0,0,1}}, {{0,1,0},{-1,0,0},{0,0,1}},\n    {{1,0,0},{0,0,-1},{0,1,0}}, {{0,0,1},{1,0,0},{0,1,0}}, {{-1,0,0},{0,0,1},{0,1,0}}, {{0,0,-1},{-1,0,0},{0,1,0}},\n    {{1,0,0},{0,0,1},{0,-1,0}}, {{0,0,-1},{1,0,0},{0,-1,0}}, {{-1,0,0},{0,0,-1},{0,-1,0}}, {{0,0,1},{-1,0,0},{0,-1,0}},\n    {{0,1,0},{0,0,1},{1,0,0}}, {{0,0,-1},{0,1,0},{1,0,0}}, {{0,-1,0},{0,0,-1},{1,0,0}}, {{0,0,1},{0,-1,0},{1,0,0}},\n    {{0,1,0},{0,0,-1},{-1,0,0}}, {{0,0,1},{0,1,0},{-1,0,0}}, {{0,-1,0},{0,0,1},{-1,0,0}}, {{0,0,-1},{0,-1,0},{-1,0,0}},\n    {{0,-1,0},{1,0,0},{0,0,1}}, {{1,0,0},{0,0,1},{0,1,0}}, {{0,1,0},{-1,0,0},{0,0,1}}, {{-1,0,0},{0,0,-1},{0,1,0}}\n};\n\nvector<tuple<int,int,int>> getNeighbors(int x, int y, int z) {\n    vector<tuple<int,int,int>> neighbors;\n    int dx[] = {1, -1, 0, 0, 0, 0};\n    int dy[] = {0, 0, 1, -1, 0, 0};\n    int dz[] = {0, 0, 0, 0, 1, -1};\n    \n    for (int d = 0; d < 6; d++) {\n        int nx = x + dx[d], ny = y + dy[d], nz = z + dz[d];\n        if (nx >= 0 && nx < D && ny >= 0 && ny < D && nz >= 0 && nz < D) {\n            neighbors.emplace_back(nx, ny, nz);\n        }\n    }\n    return neighbors;\n}\n\ntuple<int,int,int> rotateCell(int x, int y, int z, int rot) {\n    int nx = rotations_24[rot][0][0]*x + rotations_24[rot][0][1]*y + rotations_24[rot][0][2]*z;\n    int ny = rotations_24[rot][1][0]*x + rotations_24[rot][1][1]*y + rotations_24[rot][1][2]*z;\n    int nz = rotations_24[rot][2][0]*x + rotations_24[rot][2][1]*y + rotations_24[rot][2][2]*z;\n    return make_tuple(nx, ny, nz);\n}\n\nbool canPlace(const vector<tuple<int,int,int>>& shape, int bx, int by, int bz, int rot,\n              const vector<vector<vector<bool>>>& valid,\n              const vector<vector<vector<bool>>>& placed) {\n    int x0 = get<0>(shape[0]), y0 = get<1>(shape[0]), z0 = get<2>(shape[0]);\n    for (const auto& cell : shape) {\n        int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n        auto rotated = rotateCell(x - x0, y - y0, z - z0, rot);\n        int px = bx + get<0>(rotated), py = by + get<1>(rotated), pz = bz + get<2>(rotated);\n        if (px < 0 || px >= D || py < 0 || py >= D || pz < 0 || pz >= D) return false;\n        if (placed[px][py][pz]) return false;\n        if (!valid[px][py][pz]) return false;\n    }\n    return true;\n}\n\nvoid placeBlock(const vector<tuple<int,int,int>>& shape, int bx, int by, int bz, int rot,\n                int blockId,\n                vector<vector<vector<bool>>>& placed,\n                vector<vector<vector<int>>>& b) {\n    int x0 = get<0>(shape[0]), y0 = get<1>(shape[0]), z0 = get<2>(shape[0]);\n    for (const auto& cell : shape) {\n        int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n        auto rotated = rotateCell(x - x0, y - y0, z - z0, rot);\n        int px = bx + get<0>(rotated), py = by + get<1>(rotated), pz = bz + get<2>(rotated);\n        placed[px][py][pz] = true;\n        b[px][py][pz] = blockId;\n    }\n}\n\nvector<tuple<int,int,int>> growRegion(int sx, int sy, int sz, int maxSize,\n                                       const vector<vector<vector<bool>>>& valid,\n                                       const vector<vector<vector<bool>>>& placed) {\n    vector<tuple<int,int,int>> region;\n    queue<tuple<int,int,int>> q;\n    set<tuple<int,int,int>> visited;\n    \n    q.emplace(sx, sy, sz);\n    visited.emplace(sx, sy, sz);\n    \n    while (!q.empty() && (int)region.size() < maxSize) {\n        auto cur = q.front();\n        q.pop();\n        region.emplace_back(cur);\n        \n        for (auto neighbor : getNeighbors(get<0>(cur), get<1>(cur), get<2>(cur))) {\n            if (visited.count(neighbor)) continue;\n            int nx = get<0>(neighbor), ny = get<1>(neighbor), nz = get<2>(neighbor);\n            if (!valid[nx][ny][nz]) continue;\n            if (placed[nx][ny][nz]) continue;\n            \n            visited.emplace(neighbor);\n            q.emplace(neighbor);\n        }\n    }\n    \n    return region;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> D;\n    \n    f1.resize(D); r1.resize(D);\n    f2.resize(D); r2.resize(D);\n    \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    valid1.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    valid2.assign(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    b1.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    b2.assign(D, vector<vector<int>>(D, vector<int>(D, 0)));\n    \n    for (int z = 0; z < D; z++) {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (f1[z][x] == '1' && r1[z][y] == '1') valid1[x][y][z] = true;\n                if (f2[z][x] == '1' && r2[z][y] == '1') valid2[x][y][z] = true;\n            }\n        }\n    }\n    \n    vector<vector<vector<bool>>> placed1(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    vector<vector<vector<bool>>> placed2(D, vector<vector<bool>>(D, vector<bool>(D, false)));\n    \n    int blockId = 0;\n    \n    // Phase 1: Create shared blocks from common positions\n    vector<tuple<int,int,int>> common;\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++)\n                if (valid1[x][y][z] && valid2[x][y][z])\n                    common.emplace_back(x, y, z);\n    \n    sort(common.begin(), common.end(), [&](const auto& a, const auto& b) {\n        int x1 = get<0>(a), y1 = get<1>(a), z1 = get<2>(a);\n        int x2 = get<0>(b), y2 = get<1>(b), z2 = get<2>(b);\n        int c1 = 0, c2 = 0;\n        for (auto n : getNeighbors(x1, y1, z1)) {\n            int nx = get<0>(n), ny = get<1>(n), nz = get<2>(n);\n            if (valid1[nx][ny][nz] && valid2[nx][ny][nz]) c1++;\n        }\n        for (auto n : getNeighbors(x2, y2, z2)) {\n            int nx = get<0>(n), ny = get<1>(n), nz = get<2>(n);\n            if (valid1[nx][ny][nz] && valid2[nx][ny][nz]) c2++;\n        }\n        return c1 > c2;\n    });\n    \n    for (const auto& seed : common) {\n        int sx = get<0>(seed), sy = get<1>(seed), sz = get<2>(seed);\n        if (placed1[sx][sy][sz] || placed2[sx][sy][sz]) continue;\n        \n        int targetSize = min(8, max(3, (int)common.size() / 10 + 3));\n        auto region = growRegion(sx, sy, sz, targetSize, valid1, placed1);\n        \n        bool canPlace2 = true;\n        for (const auto& cell : region) {\n            int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n            if (!valid2[x][y][z] || placed2[x][y][z]) {\n                canPlace2 = false;\n                break;\n            }\n        }\n        \n        if (!canPlace2 || (int)region.size() < 2) {\n            region = growRegion(sx, sy, sz, min(4, targetSize/2), valid1, placed1);\n            canPlace2 = true;\n            for (const auto& cell : region) {\n                int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n                if (!valid2[x][y][z] || placed2[x][y][z]) {\n                    canPlace2 = false;\n                    break;\n                }\n            }\n        }\n        \n        if (region.empty()) continue;\n        \n        blockId++;\n        Block block;\n        block.id = blockId;\n        block.cells = region;\n        block.normalize();\n        block.usedIn1 = true;\n        block.usedIn2 = canPlace2;\n        \n        for (const auto& cell : region) {\n            int x = get<0>(cell), y = get<1>(cell), z = get<2>(cell);\n            placed1[x][y][z] = true;\n            b1[x][y][z] = blockId;\n            if (canPlace2) {\n                placed2[x][y][z] = true;\n                b2[x][y][z] = blockId;\n            }\n        }\n        \n        blocks.push_back(block);\n    }\n    \n    // Phase 2: Try to match remaining positions between solutions\n    vector<tuple<int,int,int>> remaining1, remaining2;\n    for (int x = 0; x < D; x++)\n        for (int y = 0; y < D; y++)\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && !placed1[x][y][z]) remaining1.emplace_back(x, y, z);\n                if (valid2[x][y][z] && !placed2[x][y][z]) remaining2.emplace_back(x, y, z);\n            }\n    \n    for (const auto& seed : remaining1) {\n        int sx = get<0>(seed), sy = get<1>(seed), sz = get<2>(seed);\n        if (placed1[sx][sy][sz]) continue;\n        \n        for (int size = 3; size >= 2; size--) {\n            auto region = growRegion(sx, sy, sz, size, valid1, placed1);\n            if ((int)region.size() < size) continue;\n            \n            bool found = false;\n            int bestX = -1, bestY = -1, bestZ = -1, bestRot = 0;\n            \n            for (const auto& target : remaining2) {\n                int tx = get<0>(target), ty = get<1>(target), tz = get<2>(target);\n                if (placed2[tx][ty][tz]) continue;\n                for (int rot = 0; rot < 24 && !found; rot++) {\n                    if (canPlace(region, tx, ty, tz, rot, valid2, placed2)) {\n                        bestX = tx; bestY = ty; bestZ = tz; bestRot = rot;\n                        found = true;\n                    }\n                }\n                if (found) break;\n            }\n            \n            if (found) {\n                blockId++;\n                Block block;\n                block.id = blockId;\n                block.cells = region;\n                block.normalize();\n                block.usedIn1 = true;\n                block.usedIn2 = true;\n                \n                placeBlock(region, sx, sy, sz, 0, blockId, placed1, b1);\n                placeBlock(region, bestX, bestY, bestZ, bestRot, blockId, placed2, b2);\n                \n                blocks.push_back(block);\n                break;\n            }\n        }\n    }\n    \n    // Phase 3: Fill remaining positions with 1x1x1 blocks\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (valid1[x][y][z] && !placed1[x][y][z]) {\n                    blockId++;\n                    Block block;\n                    block.id = blockId;\n                    block.cells.emplace_back(x, y, z);\n                    block.usedIn1 = true;\n                    block.usedIn2 = false;\n                    placed1[x][y][z] = true;\n                    b1[x][y][z] = blockId;\n                    blocks.push_back(block);\n                }\n                if (valid2[x][y][z] && !placed2[x][y][z]) {\n                    blockId++;\n                    Block block;\n                    block.id = blockId;\n                    block.cells.emplace_back(x, y, z);\n                    block.usedIn1 = false;\n                    block.usedIn2 = true;\n                    placed2[x][y][z] = true;\n                    b2[x][y][z] = blockId;\n                    blocks.push_back(block);\n                }\n            }\n        }\n    }\n    \n    // Output\n    cout << blockId << \"\\n\";\n    \n    bool first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b1[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    first = true;\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (!first) cout << \" \";\n                cout << b2[x][y][z];\n                first = false;\n            }\n        }\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc020":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <random>\n#include <cstring>\n\nusing namespace std;\n\nint N, M, K;\nint vx[105], vy[105];\nint eu[305], ev[305], ew[305];\nint ax[5005], ay[5005];\nint adj[105][10];\nint adjCnt[105];\n\nint P[105];\nint B[305];\n\nbool reachable[105];\nbool covered[5005];\n\ninline int dist2(int x1, int y1, int x2, int y2) {\n    int dx = x1 - x2;\n    int dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nvoid updateReachable() {\n    memset(reachable, 0, sizeof(reachable));\n    int q[105];\n    int head = 0, tail = 0;\n    q[tail++] = 0;\n    reachable[0] = true;\n    \n    while (head < tail) {\n        int u = q[head++];\n        for (int i = 0; i < adjCnt[u]; i++) {\n            int ej = adj[u][i];\n            if (B[ej]) {\n                int v = (eu[ej] == u) ? ev[ej] : eu[ej];\n                if (!reachable[v]) {\n                    reachable[v] = true;\n                    q[tail++] = v;\n                }\n            }\n        }\n    }\n}\n\nint countCovered() {\n    int count = 0;\n    memset(covered, 0, sizeof(bool) * K);\n    \n    for (int i = 0; i < N; i++) {\n        if (!reachable[i] || P[i] == 0) continue;\n        int p2 = P[i] * P[i];\n        for (int k = 0; k < K; k++) {\n            if (!covered[k]) {\n                int d2 = dist2(vx[i], vy[i], ax[k], ay[k]);\n                if (d2 <= p2) {\n                    covered[k] = true;\n                    count++;\n                }\n            }\n        }\n    }\n    return count;\n}\n\nlong long calculateCost() {\n    long long cost = 0;\n    for (int i = 0; i < N; i++) cost += 1LL * P[i] * P[i];\n    for (int j = 0; j < M; j++) if (B[j]) cost += ew[j];\n    return cost;\n}\n\nvoid buildInitialTree() {\n    memset(B, 0, sizeof(B));\n    memset(P, 0, sizeof(P));\n    \n    bool visited[105] = {false};\n    int q[105];\n    int head = 0, tail = 0;\n    q[tail++] = 0;\n    visited[0] = true;\n    \n    int parentEdge[105];\n    memset(parentEdge, -1, sizeof(parentEdge));\n    \n    while (head < tail) {\n        int u = q[head++];\n        for (int i = 0; i < adjCnt[u]; i++) {\n            int ej = adj[u][i];\n            int v = (eu[ej] == u) ? ev[ej] : eu[ej];\n            if (!visited[v]) {\n                visited[v] = true;\n                parentEdge[v] = ej;\n                q[tail++] = v;\n            }\n        }\n    }\n    \n    for (int i = 1; i < N; i++) {\n        if (parentEdge[i] >= 0) B[parentEdge[i]] = 1;\n    }\n}\n\nvoid setPForCoverage() {\n    updateReachable();\n    for (int i = 0; i < N; i++) if (!reachable[i]) P[i] = 0;\n    \n    memset(covered, 0, sizeof(bool) * K);\n    \n    for (int k = 0; k < K; k++) {\n        if (covered[k]) continue;\n        \n        int bestI = -1, bestD2 = 1e9;\n        for (int i = 0; i < N; i++) {\n            if (!reachable[i]) continue;\n            int d2 = dist2(vx[i], vy[i], ax[k], ay[k]);\n            if (d2 < bestD2) {\n                bestD2 = d2;\n                bestI = i;\n            }\n        }\n        \n        if (bestI >= 0 && bestD2 <= 25000000) {\n            int needed = (int)ceil(sqrt(bestD2));\n            if (needed > P[bestI]) P[bestI] = needed;\n            covered[k] = true;\n        }\n    }\n}\n\nvoid reducePValues() {\n    updateReachable();\n    \n    // Single-pass reduction: try 10% reduction\n    for (int i = 0; i < N; i++) {\n        if (!reachable[i] || P[i] == 0) continue;\n        \n        int oldP = P[i];\n        int newP = oldP * 90 / 100;\n        \n        if (newP < oldP) {\n            P[i] = newP;\n            int c = countCovered();\n            if (c < K) {\n                P[i] = oldP;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    for (int i = 0; i < N; i++) cin >> vx[i] >> vy[i];\n    \n    memset(adjCnt, 0, sizeof(adjCnt));\n    for (int j = 0; j < M; j++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        u--; v--;\n        eu[j] = u; ev[j] = v; ew[j] = w;\n        adj[u][adjCnt[u]++] = j;\n        adj[v][adjCnt[v]++] = j;\n    }\n    \n    for (int k = 0; k < K; k++) cin >> ax[k] >> ay[k];\n    \n    buildInitialTree();\n    setPForCoverage();\n    \n    int bestCovered = countCovered();\n    long long bestCost = calculateCost();\n    \n    int bestP[105], bestB[305];\n    memcpy(bestP, P, sizeof(P));\n    memcpy(bestB, B, sizeof(B));\n    \n    mt19937 rng(42);\n    \n    // 140 iterations - 17% more than 120\n    int maxIter = 140;\n    int noImprove = 0;\n    \n    for (int iter = 0; iter < maxIter; iter++) {\n        double progress = (double)iter / maxIter;\n        double temp = 1.0 - progress;\n        \n        // 70% edge flip, 30% edge swap\n        int moveType = rng() % 10;\n        \n        if (moveType < 7) {\n            // Edge flip\n            int edgeIdx = rng() % M;\n            int oldB = B[edgeIdx];\n            B[edgeIdx] = 1 - oldB;\n            \n            updateReachable();\n            int covered = countCovered();\n            long long cost = calculateCost();\n            \n            bool accept = false;\n            if (covered > bestCovered) {\n                accept = true;\n            } else if (covered == bestCovered) {\n                if (cost < bestCost) {\n                    accept = true;\n                } else if (bestCovered == K && temp > 0.2) {\n                    double delta = (double)(cost - bestCost);\n                    double prob = exp(-delta / (2500.0 * (temp + 0.01)));\n                    if ((double)(rng() % 10000) / 10000.0 < prob) {\n                        accept = true;\n                    }\n                }\n            }\n            \n            if (accept) {\n                if (covered > bestCovered || (covered == bestCovered && cost < bestCost)) {\n                    bestCovered = covered;\n                    bestCost = cost;\n                    memcpy(bestP, P, sizeof(P));\n                    memcpy(bestB, B, sizeof(B));\n                    noImprove = 0;\n                }\n            } else {\n                B[edgeIdx] = oldB;\n                noImprove++;\n            }\n        } else {\n            // Edge swap: turn off one edge, turn on another\n            int onEdge = -1, offEdge = -1;\n            for (int i = 0; i < M && (onEdge < 0 || offEdge < 0); i++) {\n                int idx = rng() % M;\n                if (B[idx] && onEdge < 0) onEdge = idx;\n                if (!B[idx] && offEdge < 0) offEdge = idx;\n            }\n            \n            if (onEdge >= 0 && offEdge >= 0) {\n                int oldOn = B[onEdge];\n                int oldOff = B[offEdge];\n                B[onEdge] = 0;\n                B[offEdge] = 1;\n                \n                updateReachable();\n                int covered = countCovered();\n                long long cost = calculateCost();\n                \n                bool accept = false;\n                if (covered > bestCovered) {\n                    accept = true;\n                } else if (covered == bestCovered && cost < bestCost) {\n                    accept = true;\n                }\n                \n                if (accept) {\n                    if (covered > bestCovered || (covered == bestCovered && cost < bestCost)) {\n                        bestCovered = covered;\n                        bestCost = cost;\n                        memcpy(bestP, P, sizeof(P));\n                        memcpy(bestB, B, sizeof(B));\n                        noImprove = 0;\n                    }\n                } else {\n                    B[onEdge] = oldOn;\n                    B[offEdge] = oldOff;\n                    noImprove++;\n                }\n            }\n        }\n        \n        // Early termination\n        if (noImprove > 50 && bestCovered == K) break;\n    }\n    \n    // Restore best solution\n    memcpy(P, bestP, sizeof(P));\n    memcpy(B, bestB, sizeof(B));\n    \n    // Final P optimization - 5 passes for better reduction\n    if (bestCovered == K) {\n        reducePValues();\n        reducePValues();\n        reducePValues();\n        reducePValues();\n        reducePValues();\n    } else {\n        setPForCoverage();\n    }\n    \n    for (int i = 0; i < N; i++) {\n        cout << P[i] << (i == N - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    for (int j = 0; j < M; j++) {\n        cout << B[j] << (j == M - 1 ? \"\" : \" \");\n    }\n    cout << \"\\n\";\n    \n    return 0;\n}","ahc021":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\n#include <tuple>\n\nusing namespace std;\n\nconst int N = 30;\nconst int TOTAL_BALLS = N * (N + 1) / 2;\n\nstruct Coord {\n    int x, y;\n    bool operator==(const Coord& other) const {\n        return x == other.x && y == other.y;\n    }\n    bool operator!=(const Coord& other) const {\n        return !(*this == other);\n    }\n};\n\nint grid[N][N];\nCoord pos[TOTAL_BALLS];\n\n// 6 adjacent directions\nconst int DX[6] = {-1, -1, 0, 0, 1, 1};\nconst int DY[6] = {-1, 0, -1, 1, 0, 1};\n\nbool isValid(int x, int y) {\n    return x >= 0 && x < N && y >= 0 && y <= x;\n}\n\nbool areAdjacent(Coord c1, Coord c2) {\n    int dx = abs(c1.x - c2.x);\n    int dy = abs(c1.y - c2.y);\n    if (dx > 1) return false;\n    if (dx == 0) return dy == 1;\n    return dy == 0 || dy == 1;\n}\n\n// Calculate target tier based on value\nint getTargetTier(int value) {\n    int cumulative = 0;\n    for (int t = 0; t < N; t++) {\n        cumulative += (t + 1);\n        if (value < cumulative) {\n            return t;\n        }\n    }\n    return N - 1;\n}\n\nvector<tuple<int,int,int,int>> operations;\n\nvoid swapBalls(Coord c1, Coord c2) {\n    if (c1 == c2 || !areAdjacent(c1, c2)) return;\n    if (operations.size() >= 10000) return;\n    \n    operations.push_back({c1.x, c1.y, c2.x, c2.y});\n    \n    int val1 = grid[c1.x][c1.y];\n    int val2 = grid[c2.x][c2.y];\n    \n    grid[c1.x][c1.y] = val2;\n    grid[c2.x][c2.y] = val1;\n    \n    pos[val1] = c2;\n    pos[val2] = c1;\n}\n\n// BFS for pathfinding\nvector<Coord> findPath(Coord start, Coord end) {\n    if (start == end) return {start};\n    \n    queue<Coord> q;\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<Coord>> parent(N, vector<Coord>(N, {-1, -1}));\n    \n    dist[start.x][start.y] = 0;\n    q.push(start);\n    \n    while (!q.empty()) {\n        Coord curr = q.front();\n        q.pop();\n        \n        if (curr == end) {\n            vector<Coord> path;\n            Coord c = end;\n            while (c != start) {\n                path.push_back(c);\n                c = parent[c.x][c.y];\n            }\n            path.push_back(start);\n            reverse(path.begin(), path.end());\n            return path;\n        }\n        \n        for (int i = 0; i < 6; i++) {\n            int nx = curr.x + DX[i];\n            int ny = curr.y + DY[i];\n            if (isValid(nx, ny) && dist[nx][ny] == -1) {\n                dist[nx][ny] = dist[curr.x][curr.y] + 1;\n                parent[nx][ny] = curr;\n                q.push({nx, ny});\n            }\n        }\n    }\n    \n    return {};\n}\n\nvoid moveBall(int value, Coord target) {\n    Coord current = pos[value];\n    \n    if (current == target) return;\n    \n    int maxSteps = 35;\n    while (current != target && operations.size() < 5000 && maxSteps > 0) {\n        auto path = findPath(current, target);\n        if (path.size() < 2) break;\n        \n        Coord next = path[1];\n        swapBalls(current, next);\n        current = pos[value];\n        maxSteps--;\n    }\n}\n\nint countViolations() {\n    int E = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            if (grid[x][y] > grid[x + 1][y]) E++;\n            if (grid[x][y] > grid[x + 1][y + 1]) E++;\n        }\n    }\n    return E;\n}\n\n// Find worst violation (largest difference)\ntuple<int, int, int, int> findWorstViolation() {\n    int maxDiff = -1;\n    int bestX = -1, bestY = -1, bestChild = -1;\n    \n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            int curr = grid[x][y];\n            int left = grid[x + 1][y];\n            int right = grid[x + 1][y + 1];\n            \n            if (curr > left) {\n                int diff = curr - left;\n                if (diff > maxDiff) {\n                    maxDiff = diff;\n                    bestX = x;\n                    bestY = y;\n                    bestChild = 0;\n                }\n            }\n            if (curr > right) {\n                int diff = curr - right;\n                if (diff > maxDiff) {\n                    maxDiff = diff;\n                    bestX = x;\n                    bestY = y;\n                    bestChild = 1;\n                }\n            }\n        }\n    }\n    \n    return {bestX, bestY, bestChild, maxDiff};\n}\n\n// Fix violations prioritizing worst ones\nvoid fixViolations() {\n    for (int pass = 0; pass < 25 && operations.size() < 9500; pass++) {\n        int E = countViolations();\n        if (E == 0) break;\n        \n        // Find and fix worst violation\n        auto [x, y, child, diff] = findWorstViolation();\n        \n        if (x >= 0 && diff > 0) {\n            if (child == 0 && areAdjacent({x, y}, {x + 1, y})) {\n                swapBalls({x, y}, {x + 1, y});\n            } else if (child == 1 && areAdjacent({x, y}, {x + 1, y + 1})) {\n                swapBalls({x, y}, {x + 1, y + 1});\n            }\n        } else {\n            // Fallback: standard pass\n            bool changed = false;\n            for (int x = 0; x < N - 1 && operations.size() < 9500; x++) {\n                for (int y = 0; y <= x && operations.size() < 9500; y++) {\n                    int curr = grid[x][y];\n                    int left = grid[x + 1][y];\n                    int right = grid[x + 1][y + 1];\n                    \n                    if (curr > left && curr > right) {\n                        if (left <= right && areAdjacent({x, y}, {x + 1, y})) {\n                            swapBalls({x, y}, {x + 1, y});\n                            changed = true;\n                        } else if (areAdjacent({x, y}, {x + 1, y + 1})) {\n                            swapBalls({x, y}, {x + 1, y + 1});\n                            changed = true;\n                        }\n                    } else if (curr > left && areAdjacent({x, y}, {x + 1, y})) {\n                        swapBalls({x, y}, {x + 1, y});\n                        changed = true;\n                    } else if (curr > right && areAdjacent({x, y}, {x + 1, y + 1})) {\n                        swapBalls({x, y}, {x + 1, y + 1});\n                        changed = true;\n                    }\n                }\n            }\n            if (!changed) break;\n        }\n    }\n}\n\n// Bottom-up heapify\nvoid heapify() {\n    for (int x = N - 2; x >= 0 && operations.size() < 9800; x--) {\n        for (int y = 0; y <= x && operations.size() < 9800; y++) {\n            int curr = grid[x][y];\n            int left = grid[x + 1][y];\n            int right = grid[x + 1][y + 1];\n            \n            if (curr > left || curr > right) {\n                if (left < right && areAdjacent({x, y}, {x + 1, y})) {\n                    swapBalls({x, y}, {x + 1, y});\n                } else if (areAdjacent({x, y}, {x + 1, y + 1})) {\n                    swapBalls({x, y}, {x + 1, y + 1});\n                }\n            }\n        }\n    }\n}\n\n// Final cleanup\nvoid finalCleanup() {\n    for (int iter = 0; iter < 30 && operations.size() < 9950; iter++) {\n        int E = countViolations();\n        if (E == 0) break;\n        \n        bool changed = false;\n        for (int x = 0; x < N - 1 && operations.size() < 9950; x++) {\n            for (int y = 0; y <= x && operations.size() < 9950; y++) {\n                if (grid[x][y] > grid[x + 1][y] && areAdjacent({x, y}, {x + 1, y})) {\n                    swapBalls({x, y}, {x + 1, y});\n                    changed = true;\n                }\n                if (grid[x][y] > grid[x + 1][y + 1] && areAdjacent({x, y}, {x + 1, y + 1})) {\n                    swapBalls({x, y}, {x + 1, y + 1});\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    // Read input\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> grid[x][y];\n            pos[grid[x][y]] = {x, y};\n        }\n    }\n    \n    // Group balls by target tier\n    vector<vector<int>> tierBalls(N);\n    for (int v = 0; v < TOTAL_BALLS; v++) {\n        int tier = getTargetTier(v);\n        tierBalls[tier].push_back(v);\n    }\n    \n    // Sort each tier's balls for consistent ordering\n    for (int t = 0; t < N; t++) {\n        sort(tierBalls[t].begin(), tierBalls[t].end());\n    }\n    \n    // Track which positions in each tier are \"claimed\"\n    vector<vector<bool>> tierPositions(N);\n    for (int t = 0; t < N; t++) {\n        tierPositions[t].resize(t + 1, false);\n    }\n    \n    // Move balls to their target tiers with smarter position selection\n    for (int tier = 0; tier < N && operations.size() < 5000; tier++) {\n        for (int value : tierBalls[tier]) {\n            if (operations.size() >= 5000) break;\n            \n            Coord current = pos[value];\n            \n            // Skip if already in correct tier\n            if (current.x == tier) continue;\n            \n            // Find best available position in target tier\n            int bestY = 0;\n            int minDist = 1e9;\n            for (int y = 0; y <= tier; y++) {\n                if (!tierPositions[tier][y]) {\n                    int dist = abs(current.x - tier) + abs(current.y - y);\n                    if (dist < minDist) {\n                        minDist = dist;\n                        bestY = y;\n                    }\n                }\n            }\n            \n            Coord target = {tier, bestY};\n            moveBall(value, target);\n            \n            // Mark position as claimed (approximate - actual position may differ)\n            if (pos[value].x == tier) {\n                tierPositions[tier][pos[value].y] = true;\n            }\n        }\n        \n        // Early termination check after each tier\n        if (countViolations() == 0 && tier >= N / 2) {\n            break;\n        }\n    }\n    \n    // Apply heapify from bottom up\n    heapify();\n    \n    // Check E=0 before more fixing\n    if (countViolations() == 0) {\n        cout << operations.size() << \"\\n\";\n        for (auto& op : operations) {\n            cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n                 << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n        }\n        return 0;\n    }\n    \n    // Fix violations with priority on worst ones\n    fixViolations();\n    \n    // Check E=0 again\n    if (countViolations() == 0) {\n        cout << operations.size() << \"\\n\";\n        for (auto& op : operations) {\n            cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n                 << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n        }\n        return 0;\n    }\n    \n    // Final cleanup to ensure E=0\n    finalCleanup();\n    \n    // Output\n    cout << operations.size() << \"\\n\";\n    for (auto& op : operations) {\n        cout << get<0>(op) << \" \" << get<1>(op) << \" \"\n             << get<2>(op) << \" \" << get<3>(op) << \"\\n\";\n    }\n    \n    return 0;\n}","toyota2023summer-final":"#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nconst int D = 9;\nconst int ENTRANCE_R = 0;\nconst int ENTRANCE_C = 4;\n\nstruct Container {\n    int id;\n    int r, c;\n};\n\nint grid[D][D];  // -1: empty, -2: obstacle, >=0: container id\nint dist_from_entrance[D][D];\nvector<pair<int, int>> empty_squares;\nvector<Container> containers;\n\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\n\nbool isValid(int r, int c) {\n    return r >= 0 && r < D && c >= 0 && c < D && grid[r][c] != -2;\n}\n\n// BFS to find all reachable empty squares from entrance\nvector<vector<bool>> computeReachable() {\n    vector<vector<bool>> reachable(D, vector<bool>(D, false));\n    queue<pair<int, int>> q;\n    \n    q.push({ENTRANCE_R, ENTRANCE_C});\n    reachable[ENTRANCE_R][ENTRANCE_C] = true;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && grid[nr][nc] == -1 && !reachable[nr][nc]) {\n                reachable[nr][nc] = true;\n                q.push({nr, nc});\n            }\n        }\n    }\n    \n    return reachable;\n}\n\n// Check if container at (r, c) is reachable (adjacent to reachable empty square)\nbool isContainerReachable(int r, int c) {\n    for (int i = 0; i < 4; i++) {\n        int nr = r + dr[i];\n        int nc = c + dc[i];\n        \n        if (isValid(nr, nc) && grid[nr][nc] == -1) {\n            auto reachable = computeReachable();\n            if (reachable[nr][nc]) return true;\n        }\n    }\n    return false;\n}\n\n// Check if placing container maintains connectivity for all existing containers\nbool canPlace(int r, int c) {\n    if (!isValid(r, c) || grid[r][c] != -1) return false;\n    \n    grid[r][c] = -3;  // Temporarily occupied\n    \n    bool ok = true;\n    for (const auto& cont : containers) {\n        if (!isContainerReachable(cont.r, cont.c)) {\n            ok = false;\n            break;\n        }\n    }\n    \n    grid[r][c] = -1;\n    return ok;\n}\n\nvoid computeDistances() {\n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            dist_from_entrance[i][j] = 1e9;\n        }\n    }\n    \n    queue<pair<int, int>> q;\n    q.push({ENTRANCE_R, ENTRANCE_C});\n    dist_from_entrance[ENTRANCE_R][ENTRANCE_C] = 0;\n    \n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        \n        for (int i = 0; i < 4; i++) {\n            int nr = r + dr[i];\n            int nc = c + dc[i];\n            \n            if (isValid(nr, nc) && dist_from_entrance[nr][nc] > dist_from_entrance[r][c] + 1) {\n                dist_from_entrance[nr][nc] = dist_from_entrance[r][c] + 1;\n                q.push({nr, nc});\n            }\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    cin >> D >> N;\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            grid[i][j] = -1;\n        }\n    }\n    \n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        grid[r][c] = -2;\n    }\n    \n    computeDistances();\n    \n    for (int i = 0; i < D; i++) {\n        for (int j = 0; j < D; j++) {\n            if (grid[i][j] == -1 && !(i == ENTRANCE_R && j == ENTRANCE_C)) {\n                empty_squares.push_back({i, j});\n            }\n        }\n    }\n    \n    sort(empty_squares.begin(), empty_squares.end(), [](const pair<int, int>& a, const pair<int, int>& b) {\n        return dist_from_entrance[a.first][a.second] < dist_from_entrance[b.first][b.second];\n    });\n    \n    int total_containers = D * D - 1 - N;\n    \n    for (int d = 0; d < total_containers; d++) {\n        int container_id;\n        cin >> container_id;\n        \n        int best_r = -1, best_c = -1;\n        int best_score = 1e9;\n        \n        for (const auto& [r, c] : empty_squares) {\n            if (grid[r][c] == -1 && canPlace(r, c)) {\n                int score = dist_from_entrance[r][c] * 100;\n                if (container_id < total_containers / 2) {\n                    score -= 50;  // Prefer closer for smaller IDs\n                }\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_r = r;\n                    best_c = c;\n                }\n            }\n        }\n        \n        grid[best_r][best_c] = container_id;\n        containers.push_back({container_id, best_r, best_c});\n        \n        cout << best_r << \" \" << best_c << endl;\n    }\n    \n    // Retrieval: output in order 0, 1, 2, ...\n    vector<bool> retrieved(total_containers, false);\n    vector<pair<int, int>> output_order;\n    \n    for (int target_id = 0; target_id < total_containers; target_id++) {\n        for (auto& cont : containers) {\n            if (cont.id == target_id && !retrieved[target_id]) {\n                if (isContainerReachable(cont.r, cont.c)) {\n                    output_order.push_back({cont.r, cont.c});\n                    retrieved[target_id] = true;\n                    grid[cont.r][cont.c] = -1;  // Remove container\n                    break;\n                }\n            }\n        }\n    }\n    \n    // Output any remaining\n    for (auto& cont : containers) {\n        if (!retrieved[cont.id]) {\n            output_order.push_back({cont.r, cont.c});\n        }\n    }\n    \n    for (const auto& [r, c] : output_order) {\n        cout << r << \" \" << c << endl;\n    }\n    \n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\n#include <atcoder/all>\nusing namespace std;\nusing namespace atcoder;\n\nconst int N = 50;\nconst int M = 100;\n\nint n, m;\nint grid[N][N];\nint adj[M + 1][M + 1];  // adjacency matrix\nint color_count[M + 1]; // count of each color\n\n// Check if a color region is connected using BFS\nbool check_connectivity(int c) {\n    vector<pair<int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == c) {\n                cells.push_back({i, j});\n            }\n        }\n    }\n    if (cells.empty()) return c == 0; // color 0 can be empty (connects through outside)\n    \n    // BFS from first cell\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    queue<pair<int, int>> q;\n    q.push(cells[0]);\n    visited[cells[0].first][cells[0].second] = true;\n    int count = 1;\n    \n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\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                !visited[ni][nj] && grid[ni][nj] == c) {\n                visited[ni][nj] = true;\n                count++;\n                q.push({ni, nj});\n            }\n        }\n    }\n    return count == (int)cells.size();\n}\n\n// Check if all color regions are connected\nbool check_all_connectivity() {\n    for (int c = 1; c <= m; c++) {\n        if (!check_connectivity(c)) return false;\n    }\n    // Color 0 connectivity through outside is automatic if other colors are connected\n    return true;\n}\n\n// Build adjacency matrix from current grid\nvoid build_adjacency() {\n    memset(adj, 0, sizeof(adj));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    // Boundary touches color 0\n                    adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Get current adjacency from grid\nvoid get_current_adjacency(int cur_adj[M + 1][M + 1]) {\n    memset(cur_adj, 0, sizeof(int) * (M + 1) * (M + 1));\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    int c1 = grid[i][j];\n                    int c2 = grid[ni][nj];\n                    if (c1 != c2) {\n                        cur_adj[min(c1, c2)][max(c1, c2)] = 1;\n                    }\n                } else {\n                    cur_adj[0][grid[i][j]] = 1;\n                }\n            }\n        }\n    }\n}\n\n// Check if adjacency is preserved\nbool check_adjacency_preserved() {\n    int cur_adj[M + 1][M + 1];\n    get_current_adjacency(cur_adj);\n    \n    for (int c1 = 0; c1 <= m; c1++) {\n        for (int c2 = c1 + 1; c2 <= m; c2++) {\n            if (adj[c1][c2] != cur_adj[c1][c2]) {\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\n// Count color 0 squares\nint count_zeros() {\n    int cnt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] == 0) cnt++;\n        }\n    }\n    return cnt;\n}\n\n// Try to fill a 0 cell with a color\nbool try_fill_zero(int i, int j, int c) {\n    if (grid[i][j] != 0) return false;\n    \n    int old = grid[i][j];\n    grid[i][j] = c;\n    \n    // Check connectivity\n    if (!check_connectivity(c)) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    // Check adjacency preservation\n    if (!check_adjacency_preserved()) {\n        grid[i][j] = old;\n        return false;\n    }\n    \n    return true;\n}\n\n// Get colors adjacent to position (i, j)\nvector<int> get_adjacent_colors(int i, int j) {\n    vector<int> colors;\n    vector<bool> seen(M + 1, false);\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\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            int c = grid[ni][nj];\n            if (c != 0 && !seen[c]) {\n                seen[c] = true;\n                colors.push_back(c);\n            }\n        } else {\n            if (!seen[0]) {\n                seen[0] = true;\n                colors.push_back(0);\n            }\n        }\n    }\n    return colors;\n}\n\n// Check if filling (i,j) with color c would create unwanted adjacency\nbool would_create_bad_adjacency(int i, int j, int c) {\n    int di[] = {0, 0, 1, -1};\n    int dj[] = {1, -1, 0, 0};\n    \n    for (int d = 0; d < 4; d++) {\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        int neighbor_c;\n        if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n            neighbor_c = grid[ni][nj];\n        } else {\n            neighbor_c = 0;\n        }\n        \n        if (neighbor_c != c && neighbor_c != 0) {\n            // Check if c and neighbor_c should be adjacent\n            if (!adj[min(c, neighbor_c)][max(c, neighbor_c)]) {\n                return true; // Would create unwanted adjacency\n            }\n        }\n    }\n    return false;\n}\n\n// Check if filling (i,j) with color c would miss required adjacency\nbool would_miss_adjacency(int i, int j, int c) {\n    // This is harder to check locally, skip for now\n    return false;\n}\n\n// Greedy fill zeros\nvoid greedy_fill() {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        vector<tuple<int, int, int>> candidates;\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    vector<int> adj_colors = get_adjacent_colors(i, j);\n                    for (int c : adj_colors) {\n                        if (c == 0) continue;\n                        if (!would_create_bad_adjacency(i, j, c)) {\n                            candidates.push_back({i, j, c});\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Try candidates in random order\n        shuffle(candidates.begin(), candidates.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count()));\n        \n        for (auto [i, j, c] : candidates) {\n            if (grid[i][j] == 0 && try_fill_zero(i, j, c)) {\n                changed = true;\n                break; // Restart to be safe\n            }\n        }\n    }\n}\n\n// Simulated annealing style local search\nvoid local_search() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 5000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find a 0 cell\n        vector<pair<int, int>> zeros;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] == 0) {\n                    zeros.push_back({i, j});\n                }\n            }\n        }\n        \n        if (zeros.empty()) break;\n        \n        auto [i, j] = zeros[rng() % zeros.size()];\n        vector<int> adj_colors = get_adjacent_colors(i, j);\n        \n        if (adj_colors.empty()) continue;\n        \n        int c = adj_colors[rng() % adj_colors.size()];\n        if (c == 0) continue;\n        \n        if (try_fill_zero(i, j, c)) {\n            // Success, continue\n        }\n    }\n}\n\n// Compact regions by moving boundary cells\nvoid compact_regions() {\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    int iterations = 3000;\n    for (int iter = 0; iter < iterations; iter++) {\n        // Find boundary cells (colored cells adjacent to 0)\n        vector<tuple<int, int, int>> boundaries; // i, j, color\n        \n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (grid[i][j] != 0) {\n                    int di[] = {0, 0, 1, -1};\n                    int dj[] = {1, -1, 0, 0};\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 && grid[ni][nj] == 0) {\n                            boundaries.push_back({i, j, grid[i][j]});\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (boundaries.empty()) break;\n        \n        auto [i, j, c] = boundaries[rng() % boundaries.size()];\n        \n        // Try to expand into adjacent 0\n        int di[] = {0, 0, 1, -1};\n        int dj[] = {1, -1, 0, 0};\n        \n        vector<pair<int, int>> adjacent_zeros;\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 && grid[ni][nj] == 0) {\n                adjacent_zeros.push_back({ni, nj});\n            }\n        }\n        \n        if (adjacent_zeros.empty()) continue;\n        \n        auto [ni, nj] = adjacent_zeros[rng() % adjacent_zeros.size()];\n        \n        if (!would_create_bad_adjacency(ni, nj, c)) {\n            int old = grid[ni][nj];\n            grid[ni][nj] = c;\n            \n            if (check_connectivity(c) && check_adjacency_preserved()) {\n                // Keep the change\n            } else {\n                grid[ni][nj] = old;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n >> m;\n    \n    int zeros = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> grid[i][j];\n            if (grid[i][j] == 0) zeros++;\n            color_count[grid[i][j]]++;\n        }\n    }\n    \n    // Build target adjacency from input\n    build_adjacency();\n    \n    // Phase 1: Greedy fill\n    greedy_fill();\n    \n    // Phase 2: Local search\n    local_search();\n    \n    // Phase 3: Compact regions\n    compact_regions();\n    \n    // Phase 4: Final greedy pass\n    greedy_fill();\n    \n    // Output\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cout << grid[i][j] << (j == n - 1 ? \"\" : \" \");\n        }\n        cout << \"\\n\";\n    }\n    \n    return 0;\n}","ahc025":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <random>\n#include <cmath>\n#include <chrono>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    // Estimate weights through comparisons\n    // Use a reference-based approach: compare each item against a reference set\n    vector<double> estimated_weight(N, 1.0);\n    vector<int> win_count(N, 0);\n    vector<int> lose_count(N, 0);\n    \n    // Phase 1: Pairwise comparisons to build relative ranking\n    // Use tournament-style comparisons\n    int queries_used = 0;\n    \n    // First, do pairwise comparisons between items\n    // Compare item i vs item j by putting them on opposite sides\n    for (int i = 0; i < N && queries_used < Q; i++) {\n        for (int j = i + 1; j < N && queries_used < Q; j++) {\n            // Compare single items\n            cout << \"1 1 \" << i << \" \" << j << endl;\n            queries_used++;\n            \n            string result;\n            cin >> result;\n            \n            if (result == \">\") {\n                win_count[i]++;\n                lose_count[j]++;\n            } else if (result == \"<\") {\n                lose_count[i]++;\n                win_count[j]++;\n            }\n            // \"=\" means equal, no change\n        }\n    }\n    \n    // Calculate estimated weights based on win/loss ratio\n    for (int i = 0; i < N; i++) {\n        int total = win_count[i] + lose_count[i];\n        if (total > 0) {\n            estimated_weight[i] = 1.0 + (double)win_count[i] / total;\n        }\n    }\n    \n    // If we have remaining queries, do more refined comparisons\n    // Compare items against groups to get better estimates\n    while (queries_used < Q) {\n        // Pick two random items to compare\n        static mt19937 rng(42);\n        int i = rng() % N;\n        int j = rng() % N;\n        if (i == j) continue;\n        \n        cout << \"1 1 \" << i << \" \" << j << endl;\n        queries_used++;\n        \n        string result;\n        cin >> result;\n        \n        if (result == \">\") {\n            estimated_weight[i] += 0.1;\n            estimated_weight[j] -= 0.05;\n        } else if (result == \"<\") {\n            estimated_weight[i] -= 0.05;\n            estimated_weight[j] += 0.1;\n        }\n    }\n    \n    // Phase 2: Partition items into D sets\n    // Use greedy approach: sort by estimated weight, assign to lightest bin\n    \n    // Create indices sorted by estimated weight (descending)\n    vector<int> indices(N);\n    iota(indices.begin(), indices.end(), 0);\n    sort(indices.begin(), indices.end(), [&](int a, int b) {\n        return estimated_weight[a] > estimated_weight[b];\n    });\n    \n    // Initialize D bins\n    vector<vector<int>> bins(D);\n    vector<double> bin_weight(D, 0.0);\n    \n    // Greedy assignment: assign heaviest items first to lightest bin\n    for (int idx : indices) {\n        // Find bin with minimum current weight\n        int min_bin = 0;\n        for (int d = 1; d < D; d++) {\n            if (bin_weight[d] < bin_weight[min_bin]) {\n                min_bin = d;\n            }\n        }\n        bins[min_bin].push_back(idx);\n        bin_weight[min_bin] += estimated_weight[idx];\n    }\n    \n    // Phase 3: Local optimization to reduce variance\n    // Try swapping items between bins to reduce variance\n    auto calc_variance = [&]() -> double {\n        double mean = 0.0;\n        for (double w : bin_weight) mean += w;\n        mean /= D;\n        double var = 0.0;\n        for (double w : bin_weight) {\n            double diff = w - mean;\n            var += diff * diff;\n        }\n        return var / D;\n    };\n    \n    // Local search optimization\n    bool improved = true;\n    int max_iterations = 1000;\n    int iteration = 0;\n    \n    while (improved && iteration < max_iterations) {\n        improved = false;\n        iteration++;\n        \n        double current_var = calc_variance();\n        \n        // Try swapping pairs of items between different bins\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = d1 + 1; d2 < D && !improved; d2++) {\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    for (int j = 0; j < (int)bins[d2].size() && !improved; j++) {\n                        int item1 = bins[d1][i];\n                        int item2 = bins[d2][j];\n                        \n                        // Calculate new weights if we swap\n                        double new_w1 = bin_weight[d1] - estimated_weight[item1] + estimated_weight[item2];\n                        double new_w2 = bin_weight[d2] - estimated_weight[item2] + estimated_weight[item1];\n                        \n                        // Check if this reduces variance\n                        double mean = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            if (d == d1) mean += new_w1;\n                            else if (d == d2) mean += new_w2;\n                            else mean += bin_weight[d];\n                        }\n                        mean /= D;\n                        \n                        double new_var = 0.0;\n                        for (int d = 0; d < D; d++) {\n                            double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                            double diff = w - mean;\n                            new_var += diff * diff;\n                        }\n                        new_var /= D;\n                        \n                        if (new_var < current_var - 1e-9) {\n                            // Perform swap\n                            swap(bins[d1][i], bins[d2][j]);\n                            bin_weight[d1] = new_w1;\n                            bin_weight[d2] = new_w2;\n                            improved = true;\n                            current_var = new_var;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Also try moving single items\n        for (int d1 = 0; d1 < D && !improved; d1++) {\n            for (int d2 = 0; d2 < D && !improved; d2++) {\n                if (d1 == d2) continue;\n                for (int i = 0; i < (int)bins[d1].size() && !improved; i++) {\n                    int item = bins[d1][i];\n                    \n                    double new_w1 = bin_weight[d1] - estimated_weight[item];\n                    double new_w2 = bin_weight[d2] + estimated_weight[item];\n                    \n                    double mean = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        if (d == d1) mean += new_w1;\n                        else if (d == d2) mean += new_w2;\n                        else mean += bin_weight[d];\n                    }\n                    mean /= D;\n                    \n                    double new_var = 0.0;\n                    for (int d = 0; d < D; d++) {\n                        double w = (d == d1) ? new_w1 : (d == d2) ? new_w2 : bin_weight[d];\n                        double diff = w - mean;\n                        new_var += diff * diff;\n                    }\n                    new_var /= D;\n                    \n                    if (new_var < current_var - 1e-9) {\n                        bins[d1].erase(bins[d1].begin() + i);\n                        bins[d2].push_back(item);\n                        bin_weight[d1] = new_w1;\n                        bin_weight[d2] = new_w2;\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Create output assignment\n    vector<int> assignment(N);\n    for (int d = 0; d < D; d++) {\n        for (int item : bins[d]) {\n            assignment[item] = d;\n        }\n    }\n    \n    // Output final assignment\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    cin >> n >> m;\n    \n    int boxes_per_stack = n / m;\n    \n    vector<vector<int>> stacks(m);\n    vector<pair<int, int>> pos(n + 1);\n    vector<int> move_count(n + 1, 0);\n    \n    for (int i = 0; i < m; i++) {\n        stacks[i].resize(boxes_per_stack);\n        for (int j = 0; j < boxes_per_stack; j++) {\n            cin >> stacks[i][j];\n            pos[stacks[i][j]] = {i, j};\n        }\n    }\n    \n    vector<pair<int, int>> operations;\n    \n    auto update_positions = [&](int stack_idx) {\n        for (int h = 0; h < (int)stacks[stack_idx].size(); h++) {\n            pos[stacks[stack_idx][h]] = {stack_idx, h};\n        }\n    };\n    \n    auto get_urgency = [&](int box, int current_v) -> int {\n        if (box < current_v) return 10000;\n        return box - current_v;\n    };\n    \n    auto find_best_stack = [&](int source_idx, int box_to_move, int current_v) -> int {\n        int best_stack = -1;\n        double best_score = 1e18;\n        \n        int urgency = get_urgency(box_to_move, current_v);\n        int boxes_remaining = n - current_v + 1;\n        \n        // Endgame at 45 boxes (slightly earlier for more consolidation time)\n        bool endgame = (boxes_remaining <= 45);\n        \n        // Adaptive thresholds\n        int tier1_threshold = endgame ? 7 : max(3, min(6, boxes_remaining / 25));\n        int tier2_threshold = endgame ? 22 : max(10, min(20, boxes_remaining / 8));\n        \n        for (int s = 0; s < m; s++) {\n            if (s == source_idx) continue;\n            \n            double score = 0;\n            int stack_size = stacks[s].size();\n            \n            // Tier 1: Very urgent (1-7)\n            if (urgency <= tier1_threshold) {\n                score += stack_size * 11.0;\n                if (stack_size > 0) score += 32.0;\n                if (stack_size == 0) score -= 22.0;\n                if (endgame && stack_size == 0) score -= 18.0;\n                if (endgame && stack_size <= 3) score -= 12.0;\n            }\n            // Tier 2: Soon (8-22)\n            else if (urgency <= tier2_threshold) {\n                score += stack_size * 5.5;\n                if (stack_size > 12) score += 22.0;\n                if (endgame && stack_size <= 5) score -= 10.0;\n            }\n            // Tier 3: Later (23+)\n            else {\n                score += stack_size * 2.2;\n                int late_boxes = 0;\n                for (int h = 0; h < stack_size; h++) {\n                    if (get_urgency(stacks[s][h], current_v) > tier2_threshold) {\n                        late_boxes++;\n                    }\n                }\n                score -= late_boxes * 1.8;\n                if (endgame && late_boxes >= 3) score -= 14.0;\n            }\n            \n            // Analyze destination contents\n            int very_urgent = 0, urgent = 0;\n            double chain_bonus = 0;\n            int sequence_count = 0;\n            int long_chain = 0;\n            \n            for (int h = 0; h < stack_size; h++) {\n                int box_in_dest = stacks[s][h];\n                int dest_urgency = get_urgency(box_in_dest, current_v);\n                \n                if (dest_urgency <= tier1_threshold) very_urgent++;\n                else if (dest_urgency <= tier2_threshold) urgent++;\n                \n                // Penalty for burying urgent boxes\n                if (dest_urgency <= tier2_threshold && urgency > dest_urgency) {\n                    score += (tier2_threshold - dest_urgency) * 4.5;\n                }\n                \n                // Bonus for grouping similar urgency\n                if (urgency <= tier2_threshold && dest_urgency <= tier2_threshold) {\n                    if (abs(urgency - dest_urgency) <= 4) {\n                        score -= 6.5;\n                    }\n                    if (abs(urgency - dest_urgency) <= 2) {\n                        score -= 3.0;\n                    }\n                }\n                \n                // Chain bonus for consecutive boxes (enhanced)\n                if (abs(box_to_move - box_in_dest) == 1) {\n                    chain_bonus += 10.0;\n                    sequence_count++;\n                }\n                if (abs(box_to_move - box_in_dest) == 2) {\n                    chain_bonus += 6.0;\n                    if (sequence_count >= 1) long_chain++;\n                }\n                if (abs(box_to_move - box_in_dest) == 3) {\n                    chain_bonus += 4.0;\n                    if (sequence_count >= 1) long_chain++;\n                }\n                if (abs(box_to_move - box_in_dest) == 4) {\n                    chain_bonus += 2.0;\n                }\n            }\n            \n            score -= chain_bonus;\n            \n            // Strong sequence bonus\n            if (sequence_count >= 2) {\n                score -= 20.0;\n            }\n            if (long_chain >= 2) {\n                score -= 15.0; // Long chains (v, v+2, v+3) are valuable\n            }\n            \n            // Check for existing sequences\n            int existing_sequences = 0;\n            for (int h = 0; h < stack_size - 1 && h < 18; h++) {\n                if (abs(stacks[s][h] - stacks[s][h+1]) == 1) {\n                    existing_sequences++;\n                }\n            }\n            if (urgency <= 12 && existing_sequences >= 1) {\n                score -= existing_sequences * 5.0;\n            }\n            \n            // Move count consideration (more aggressive penalties)\n            if (move_count[box_to_move] >= 1) {\n                if (urgency > tier2_threshold) {\n                    score -= 8.0; // Even 1 move is costly for late boxes\n                } else {\n                    score += 5.0;\n                }\n            }\n            if (move_count[box_to_move] >= 2) {\n                if (urgency > tier2_threshold) {\n                    score -= 12.0;\n                } else {\n                    score += 8.0;\n                }\n            }\n            if (move_count[box_to_move] >= 3) {\n                score += 18.0; // Heavy penalty for 3+ moves\n            }\n            \n            // Urgent box grouping\n            if (urgency <= tier2_threshold) {\n                if (urgent > 0 || very_urgent > 0) {\n                    score -= (urgent + very_urgent) * 3.5;\n                }\n            } else {\n                if (very_urgent > 0) {\n                    score += very_urgent * 5.5;\n                }\n                if (urgent >= 2) {\n                    score += 10.0;\n                }\n            }\n            \n            // Stack height balancing (slightly tighter)\n            if (stack_size > 33) {\n                score += (stack_size - 33) * 7.0;\n            }\n            if (stack_size > 38) {\n                score += (stack_size - 38) * 14.0;\n            }\n            \n            // Block detection (more sensitive)\n            int soon_needed_in_stack = 0;\n            for (int h = 0; h < stack_size && h < 20; h++) {\n                if (get_urgency(stacks[s][h], current_v) <= 10) {\n                    soon_needed_in_stack++;\n                }\n            }\n            if (urgency > 10 && soon_needed_in_stack >= 2) {\n                score += 9.0;\n            }\n            if (urgency > 15 && soon_needed_in_stack >= 3) {\n                score += 14.0;\n            }\n            \n            // Endgame optimization\n            if (endgame) {\n                // Prefer consolidating\n                int non_empty = 0;\n                for (int ss = 0; ss < m; ss++) {\n                    if (ss != source_idx && stacks[ss].size() > 0) {\n                        non_empty++;\n                    }\n                }\n                if (non_empty >= 7 && stack_size == 0) {\n                    score -= 22.0;\n                }\n                if (non_empty >= 6 && stack_size <= 2) {\n                    score -= 15.0;\n                }\n                \n                // Avoid re-moving\n                int will_need_move = 0;\n                for (int h = 0; h < stack_size; h++) {\n                    int box = stacks[s][h];\n                    int box_urgency = get_urgency(box, current_v);\n                    if (box_urgency > 0 && box_urgency < urgency && box_urgency <= 20) {\n                        will_need_move++;\n                    }\n                }\n                score += will_need_move * 3.0;\n                \n                // Prefer stacks that will be cleared soon\n                int soon_cleared = 0;\n                for (int h = 0; h < stack_size; h++) {\n                    int box = stacks[s][h];\n                    int box_urgency = get_urgency(box, current_v);\n                    if (box_urgency > 0 && box_urgency <= 12) {\n                        soon_cleared++;\n                    }\n                }\n                if (soon_cleared >= 2 && urgency > 15) {\n                    score += 10.0;\n                }\n            }\n            \n            // Accessibility score: estimate how deep this box will be when needed\n            if (urgency <= 20) {\n                int estimated_depth = stack_size;\n                // Count boxes that will be removed before this one\n                for (int h = 0; h < stack_size; h++) {\n                    int box = stacks[s][h];\n                    int box_urgency = get_urgency(box, current_v);\n                    if (box_urgency > 0 && box_urgency < urgency) {\n                        estimated_depth--;\n                    }\n                }\n                if (estimated_depth > 5) {\n                    score += (estimated_depth - 5) * 2.0;\n                }\n            }\n            \n            // Small tiebreaker\n            score += (s * 0.0001);\n            \n            if (score < best_score) {\n                best_score = score;\n                best_stack = s;\n            }\n        }\n        \n        if (best_stack == -1) {\n            for (int s = 0; s < m; s++) {\n                if (s != source_idx) {\n                    best_stack = s;\n                    break;\n                }\n            }\n        }\n        \n        return best_stack;\n    };\n    \n    for (int v = 1; v <= n; v++) {\n        auto [stack_idx, height_idx] = pos[v];\n        \n        if (height_idx == (int)stacks[stack_idx].size() - 1) {\n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        } else {\n            while ((int)stacks[stack_idx].size() - 1 > height_idx) {\n                int top_box = stacks[stack_idx].back();\n                int dest_stack = find_best_stack(stack_idx, top_box, v);\n                \n                operations.push_back({top_box, dest_stack + 1});\n                stacks[stack_idx].pop_back();\n                stacks[dest_stack].push_back(top_box);\n                move_count[top_box]++;\n                \n                update_positions(stack_idx);\n                update_positions(dest_stack);\n            }\n            \n            operations.push_back({v, 0});\n            stacks[stack_idx].pop_back();\n            pos[v] = {-1, -1};\n        }\n    }\n    \n    for (const auto& op : operations) {\n        cout << op.first << \" \" << op.second << \"\\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 DI[4] = {0, 1, 0, -1};\nconst int DJ[4] = {1, 0, -1, 0};\nconst char DIR_CHAR[4] = {'R', 'D', 'L', 'U'};\n\nchrono::steady_clock::time_point startTime;\nconst int TIME_LIMIT_MS = 1550;\n\nbool timeLimitReached() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration_cast<chrono::milliseconds>(now - startTime).count() > TIME_LIMIT_MS;\n}\n\nbool canMove(int i, int j, int dir) {\n    int ni = i + DI[dir];\n    int nj = j + DJ[dir];\n    if (ni < 0 || ni >= N || nj < 0 || nj >= N) return false;\n    \n    if (dir == 0) return v[i][j] == '0';\n    else if (dir == 1) return h[i][j] == '0';\n    else if (dir == 2) return v[i][nj] == '0';\n    else return h[ni][j] == '0';\n}\n\nvector<int> bfsPath(int si, int sj, int ti, int tj) {\n    if (si == ti && sj == tj) return {};\n    \n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    vector<vector<int>> parentDir(N, vector<int>(N, -1));\n    \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();\n        q.pop();\n        \n        if (i == ti && j == tj) break;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    parent[ni][nj] = {i, j};\n                    parentDir[ni][nj] = dir;\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    if (dist[ti][tj] == -1) return {};\n    \n    vector<int> path;\n    int ci = ti, cj = tj;\n    while (ci != si || cj != sj) {\n        path.push_back(parentDir[ci][cj]);\n        auto [pi, pj] = parent[ci][cj];\n        ci = pi;\n        cj = pj;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstring buildBFSTour() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    vector<vector<pair<int,int>>> parent(N, vector<pair<int,int>>(N, {-1, -1}));\n    \n    queue<pair<int,int>> q;\n    q.push({0, 0});\n    visited[0][0] = true;\n    \n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    visited[ni][nj] = true;\n                    parent[ni][nj] = {i, j};\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n    \n    vector<vector<vector<pair<int,int>>>> children(N, vector<vector<pair<int,int>>>(N));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (parent[i][j].first != -1) {\n                int pi = parent[i][j].first;\n                int pj = parent[i][j].second;\n                children[pi][pj].push_back({i, j});\n            }\n        }\n    }\n    \n    string tour;\n    function<void(int, int)> dfsTour = [&](int i, int j) {\n        for (auto& child : children[i][j]) {\n            int ni = child.first;\n            int nj = child.second;\n            int dir = -1;\n            for (int d = 0; d < 4; d++) {\n                if (i + DI[d] == ni && j + DJ[d] == nj) {\n                    dir = d;\n                    break;\n                }\n            }\n            if (dir != -1) {\n                tour += DIR_CHAR[dir];\n                dfsTour(ni, nj);\n                tour += DIR_CHAR[(dir + 2) % 4];\n            }\n        }\n    };\n    \n    dfsTour(0, 0);\n    return tour;\n}\n\nstring buildDFSTour() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    string tour;\n    \n    function<void(int, int)> dfs = [&](int i, int j) {\n        visited[i][j] = true;\n        \n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(i, j, dir)) {\n                int ni = i + DI[dir];\n                int nj = j + DJ[dir];\n                if (!visited[ni][nj]) {\n                    tour += DIR_CHAR[dir];\n                    dfs(ni, nj);\n                    tour += DIR_CHAR[(dir + 2) % 4];\n                }\n            }\n        }\n    };\n    \n    dfs(0, 0);\n    return tour;\n}\n\n// Greedy nearest unvisited neighbor tour\nstring buildGreedyTour() {\n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    string tour;\n    int ci = 0, cj = 0;\n    visited[0][0] = true;\n    int visitedCount = 1;\n    \n    while (visitedCount < N * N && !timeLimitReached()) {\n        int bestNi = -1, bestNj = -1, bestDir = -1;\n        \n        // First try adjacent unvisited\n        for (int dir = 0; dir < 4; dir++) {\n            if (canMove(ci, cj, dir)) {\n                int ni = ci + DI[dir];\n                int nj = cj + DJ[dir];\n                if (!visited[ni][nj]) {\n                    bestNi = ni;\n                    bestNj = nj;\n                    bestDir = dir;\n                    break;\n                }\n            }\n        }\n        \n        // If no adjacent unvisited, find nearest unvisited\n        if (bestNi == -1) {\n            int minDist = 1e9;\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    if (!visited[i][j]) {\n                        int dist = 0;\n                        vector<vector<int>> d(N, vector<int>(N, -1));\n                        queue<pair<int,int>> q;\n                        q.push({ci, cj});\n                        d[ci][cj] = 0;\n                        \n                        while (!q.empty() && d[i][j] == -1) {\n                            auto [x, y] = q.front();\n                            q.pop();\n                            if (x == i && y == j) {\n                                dist = d[x][y];\n                                break;\n                            }\n                            for (int dir = 0; dir < 4; dir++) {\n                                if (canMove(x, y, dir)) {\n                                    int nx = x + DI[dir];\n                                    int ny = y + DJ[dir];\n                                    if (d[nx][ny] == -1) {\n                                        d[nx][ny] = d[x][y] + 1;\n                                        q.push({nx, ny});\n                                    }\n                                }\n                            }\n                        }\n                        \n                        if (d[i][j] != -1 && d[i][j] < minDist) {\n                            minDist = d[i][j];\n                            // Get first step\n                            vector<int> path = bfsPath(ci, cj, i, j);\n                            if (!path.empty()) {\n                                bestDir = path[0];\n                                bestNi = ci + DI[bestDir];\n                                bestNj = cj + DJ[bestDir];\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (bestDir != -1) {\n            tour += DIR_CHAR[bestDir];\n            ci = bestNi;\n            cj = bestNj;\n            if (!visited[ci][cj]) {\n                visited[ci][cj] = true;\n                visitedCount++;\n            }\n        } else {\n            break;\n        }\n    }\n    \n    // Return to start\n    vector<int> pathHome = bfsPath(ci, cj, 0, 0);\n    for (int dir : pathHome) {\n        tour += DIR_CHAR[dir];\n    }\n    \n    return tour;\n}\n\nbool checkCoverage(const string& route) {\n    if (route.empty()) return false;\n    \n    vector<vector<bool>> visited(N, vector<bool>(N, false));\n    int ci = 0, cj = 0;\n    visited[0][0] = true;\n    \n    for (char c : route) {\n        int dir;\n        if (c == 'R') dir = 0;\n        else if (c == 'D') dir = 1;\n        else if (c == 'L') dir = 2;\n        else dir = 3;\n        ci += DI[dir];\n        cj += DJ[dir];\n        \n        if (ci < 0 || ci >= N || cj < 0 || cj >= N) return false;\n        visited[ci][cj] = true;\n    }\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (!visited[i][j]) return false;\n        }\n    }\n    return true;\n}\n\npair<int,int> getFinalPos(const string& route) {\n    int ci = 0, cj = 0;\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n    }\n    return {ci, cj};\n}\n\nvector<vector<int>> getVisitCount(const string& route) {\n    vector<vector<int>> count(N, vector<int>(N, 0));\n    int ci = 0, cj = 0;\n    count[0][0] = 1;\n    for (char c : route) {\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n        count[ci][cj]++;\n    }\n    return count;\n}\n\nvector<pair<int,int>> getSampledPositions(const string& route, int sampleRate) {\n    vector<pair<int,int>> positions;\n    int ci = 0, cj = 0;\n    positions.push_back({ci, cj});\n    \n    int step = 0;\n    for (char c : route) {\n        step++;\n        if (c == 'R') cj++;\n        else if (c == 'D') ci++;\n        else if (c == 'L') cj--;\n        else ci--;\n        \n        if (step % sampleRate == 0) {\n            positions.push_back({ci, cj});\n        }\n    }\n    if (step % sampleRate != 0) {\n        positions.push_back({ci, cj});\n    }\n    return positions;\n}\n\n// Two-pass local search: remove immediate backtracking\nstring removeBacktracking(string route) {\n    for (int pass = 0; pass < 2 && !timeLimitReached(); pass++) {\n        bool changed = false;\n        string newRoute;\n        newRoute.reserve(route.size());\n        \n        for (int i = 0; i < (int)route.size(); i++) {\n            if (i + 1 < (int)route.size()) {\n                char c1 = route[i];\n                char c2 = route[i + 1];\n                \n                bool isBacktrack = false;\n                if (c1 == 'L' && c2 == 'R') isBacktrack = true;\n                if (c1 == 'R' && c2 == 'L') isBacktrack = true;\n                if (c1 == 'U' && c2 == 'D') isBacktrack = true;\n                if (c1 == 'D' && c2 == 'U') isBacktrack = true;\n                \n                if (isBacktrack) {\n                    i++;\n                    changed = true;\n                    continue;\n                }\n            }\n            newRoute += route[i];\n        }\n        \n        if (changed && checkCoverage(newRoute)) {\n            route = newRoute;\n        } else {\n            break;\n        }\n    }\n    \n    return route;\n}\n\n// Safe optimization with insertions\nstring optimizeRoute(string baseRoute, int maxLen) {\n    if ((int)baseRoute.size() >= maxLen - 5000) return baseRoute;\n    if (timeLimitReached()) return baseRoute;\n    \n    vector<vector<int>> visitCount = getVisitCount(baseRoute);\n    vector<pair<int,int>> sampledPositions = getSampledPositions(baseRoute, 30);\n    \n    // Calculate priority\n    vector<tuple<double, int, int>> priorities;\n    long long totalDirt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            totalDirt += d[i][j];\n        }\n    }\n    \n    double avgDirt = (double)totalDirt / (N * N);\n    int L = baseRoute.size();\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            double interval = (visitCount[i][j] > 0) ? (double)L / visitCount[i][j] : 1e9;\n            double priority = d[i][j] * pow(interval, 0.6);\n            if (d[i][j] > avgDirt * 1.0) {\n                priorities.push_back({priority, i, j});\n            }\n        }\n    }\n    \n    sort(priorities.begin(), priorities.end(), greater<tuple<double,int,int>>());\n    \n    // Collect all insertions first\n    vector<pair<int, string>> insertions;\n    int budget = maxLen - (int)baseRoute.size() - 500;\n    int maxOptimizations = min((int)priorities.size(), 100);\n    \n    int optCount = 0;\n    for (auto& [pri, ti, tj] : priorities) {\n        if (budget <= 50) break;\n        if (optCount >= maxOptimizations) break;\n        if (timeLimitReached()) break;\n        \n        // Find nearest sampled position\n        int bestIdx = -1;\n        int bestDist = 1e9;\n        for (int idx = 0; idx < (int)sampledPositions.size(); idx++) {\n            int dist = abs(sampledPositions[idx].first - ti) + abs(sampledPositions[idx].second - tj);\n            if (dist < bestDist) {\n                bestDist = dist;\n                bestIdx = idx;\n            }\n        }\n        \n        if (bestIdx == -1) continue;\n        \n        int approxPos = bestIdx * 30;\n        if (approxPos >= (int)baseRoute.size()) approxPos = baseRoute.size() - 1;\n        if (approxPos < 0) approxPos = 0;\n        \n        // Get actual position at approxPos\n        int pi = 0, pj = 0;\n        for (int k = 0; k < approxPos && k < (int)baseRoute.size(); k++) {\n            char c = baseRoute[k];\n            if (c == 'R') pj++;\n            else if (c == 'D') pi++;\n            else if (c == 'L') pj--;\n            else pi--;\n        }\n        \n        vector<int> pathTo = bfsPath(pi, pj, ti, tj);\n        if (pathTo.empty()) continue;\n        \n        vector<int> pathBack = bfsPath(ti, tj, pi, pj);\n        if (pathBack.empty()) continue;\n        \n        int pathLen = pathTo.size() + pathBack.size();\n        if (pathLen > budget) continue;\n        \n        string insert;\n        for (int dir : pathTo) insert += DIR_CHAR[dir];\n        for (int dir : pathBack) insert += DIR_CHAR[dir];\n        \n        insertions.push_back({approxPos, insert});\n        budget -= pathLen;\n        optCount++;\n    }\n    \n    // Sort by position descending\n    sort(insertions.begin(), insertions.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n    \n    // Apply all insertions\n    string result = baseRoute;\n    result.reserve(maxLen);\n    for (auto& [pos, content] : insertions) {\n        if (pos >= 0 && pos <= (int)result.size()) {\n            result.insert(pos, content);\n        }\n    }\n    \n    return result;\n}\n\n// Create frequency-based route with round trips appended\nstring buildFrequencyRoute(int maxLen) {\n    if (timeLimitReached()) return \"\";\n    \n    vector<tuple<int, int, int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cells.push_back({d[i][j], i, j});\n        }\n    }\n    sort(cells.begin(), cells.end(), greater<tuple<int,int,int>>());\n    \n    long long totalDirt = 0;\n    for (auto& [dirt, i, j] : cells) {\n        totalDirt += dirt;\n    }\n    \n    string baseTour = buildBFSTour();\n    \n    if ((int)baseTour.size() > maxLen - 5000) {\n        return baseTour;\n    }\n    \n    string result = baseTour;\n    result.reserve(maxLen);\n    int budget = maxLen - (int)result.size() - 500;\n    \n    int ci = 0, cj = 0;\n    \n    int maxPasses = 4;\n    int pass = 0;\n    while (budget > 50 && pass < maxPasses) {\n        if (timeLimitReached()) break;\n        \n        for (auto& [dirt, ti, tj] : cells) {\n            if (budget <= 50) break;\n            if (dirt < totalDirt / (N * N)) break;\n            \n            vector<int> pathTo = bfsPath(ci, cj, ti, tj);\n            if (pathTo.empty()) continue;\n            \n            vector<int> pathBack = bfsPath(ti, tj, ci, cj);\n            if (pathBack.empty()) continue;\n            \n            int pathLen = pathTo.size() + pathBack.size();\n            if (pathLen > budget) continue;\n            \n            for (int dir : pathTo) result += DIR_CHAR[dir];\n            for (int dir : pathBack) result += DIR_CHAR[dir];\n            \n            budget -= pathLen;\n        }\n        pass++;\n    }\n    \n    return result;\n}\n\nstring ensureValidRoute(string route, int maxLen) {\n    if (route.empty()) {\n        return buildBFSTour();\n    }\n    \n    // Remove backtracking\n    route = removeBacktracking(route);\n    \n    if (!checkCoverage(route)) {\n        return buildBFSTour();\n    }\n    \n    pair<int,int> finalPos = getFinalPos(route);\n    if (finalPos.first != 0 || finalPos.second != 0) {\n        vector<int> pathHome = bfsPath(finalPos.first, finalPos.second, 0, 0);\n        if (!pathHome.empty()) {\n            for (int dir : pathHome) {\n                route += DIR_CHAR[dir];\n            }\n        } else {\n            return buildBFSTour();\n        }\n    }\n    \n    if ((int)route.size() > maxLen) {\n        return buildBFSTour();\n    }\n    \n    if (!checkCoverage(route)) {\n        return buildBFSTour();\n    }\n    \n    return route;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    startTime = chrono::steady_clock::now();\n    \n    cin >> N;\n    \n    h.resize(N - 1);\n    for (int i = 0; i < N - 1; i++) {\n        cin >> h[i];\n    }\n    \n    v.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> v[i];\n    }\n    \n    d.resize(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    }\n    \n    int maxLen = 100000;\n    \n    vector<string> candidates;\n    \n    // Strategy 1: BFS tree tour + optimization\n    string route1 = buildBFSTour();\n    if (!timeLimitReached()) {\n        route1 = optimizeRoute(route1, maxLen);\n    }\n    route1 = ensureValidRoute(route1, maxLen);\n    candidates.push_back(route1);\n    \n    // Strategy 2: DFS tree tour + optimization\n    if (!timeLimitReached()) {\n        string route2 = buildDFSTour();\n        if (checkCoverage(route2)) {\n            route2 = optimizeRoute(route2, maxLen);\n            route2 = ensureValidRoute(route2, maxLen);\n            candidates.push_back(route2);\n        }\n    }\n    \n    // Strategy 3: Greedy nearest neighbor tour\n    if (!timeLimitReached()) {\n        string route3 = buildGreedyTour();\n        if (checkCoverage(route3)) {\n            route3 = optimizeRoute(route3, maxLen);\n            route3 = ensureValidRoute(route3, maxLen);\n            candidates.push_back(route3);\n        }\n    }\n    \n    // Strategy 4: Frequency-based route\n    if (!timeLimitReached()) {\n        string route4 = buildFrequencyRoute(maxLen);\n        route4 = ensureValidRoute(route4, maxLen);\n        candidates.push_back(route4);\n    }\n    \n    // Select best valid route (prefer shorter)\n    string bestRoute;\n    int bestLen = 1e9;\n    \n    for (const auto& route : candidates) {\n        if (!route.empty() && checkCoverage(route) && (int)route.size() <= maxLen) {\n            if ((int)route.size() < bestLen) {\n                bestLen = route.size();\n                bestRoute = route;\n            }\n        }\n    }\n    \n    // Final fallback\n    if (bestRoute.empty() || !checkCoverage(bestRoute)) {\n        bestRoute = buildBFSTour();\n        bestRoute = ensureValidRoute(bestRoute, maxLen);\n    }\n    \n    cout << bestRoute << endl;\n    \n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, si, sj;\nvector<string> A;\nvector<string> t;\nvector<vector<pair<int,int>>> charPos(26);\nint overlap[200][200];\nmt19937 rng;\n\n// Precomputed costs\nint minCostFromPos[15][15][26];\npair<int,int> bestPosFromPos[15][15][26];\n\nvoid precomputeAll() {\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            for (int ch = 0; ch < 26; ch++) {\n                int minD = 1e9;\n                pair<int,int> bestP = {r, c};\n                for (auto [nr, nc] : charPos[ch]) {\n                    int d = abs(r - nr) + abs(c - nc) + 1;\n                    if (d < minD) {\n                        minD = d;\n                        bestP = {nr, nc};\n                    }\n                }\n                minCostFromPos[r][c][ch] = minD;\n                bestPosFromPos[r][c][ch] = bestP;\n            }\n        }\n    }\n}\n\n// Fast cost calculation using precomputed positions\ninline long long calcCost(const vector<int>& order) {\n    if (order.empty()) return 0;\n    \n    long long cost = 0;\n    int curR = si, curC = sj;\n    \n    for (size_t w = 0; w < order.size(); w++) {\n        int prevOverlap = (w == 0) ? 0 : overlap[order[w-1]][order[w]];\n        for (int i = prevOverlap; i < 5; i++) {\n            int ch = t[order[w]][i] - 'A';\n            cost += minCostFromPos[curR][curC][ch];\n            auto [nr, nc] = bestPosFromPos[curR][curC][ch];\n            curR = nr;\n            curC = nc;\n        }\n    }\n    \n    return cost;\n}\n\n// Optimized position selection\nvector<pair<int,int>> optimizePositions(const string& s) {\n    int L = s.size();\n    if (L == 0) return {};\n    \n    vector<pair<int,int>> path(L);\n    int curI = si, curJ = sj;\n    \n    for (int i = 0; i < L; i++) {\n        int idx = s[i] - 'A';\n        auto [bestI, bestJ] = bestPosFromPos[curI][curJ][idx];\n        path[i] = {bestI, bestJ};\n        curI = bestI;\n        curJ = bestJ;\n    }\n    \n    for (int pass = 0; pass < 8; pass++) {\n        bool changed = false;\n        for (int i = 0; i < L; i++) {\n            int idx = s[i] - 'A';\n            int bestI = path[i].first;\n            int bestJ = path[i].second;\n            \n            int prevI = (i == 0) ? si : path[i-1].first;\n            int prevJ = (i == 0) ? sj : path[i-1].second;\n            int nextI = (i == L-1) ? -1 : path[i+1].first;\n            int nextJ = (i == L-1) ? -1 : path[i+1].second;\n            \n            int currentCost = abs(bestI - prevI) + abs(bestJ - prevJ) + 1;\n            if (nextI != -1) currentCost += abs(nextI - bestI) + abs(nextJ - bestJ) + 1;\n            \n            for (auto [ni, nj] : charPos[idx]) {\n                int newCost = abs(ni - prevI) + abs(nj - prevJ) + 1;\n                if (nextI != -1) newCost += abs(nextI - ni) + abs(nextJ - nj) + 1;\n                \n                if (newCost < currentCost) {\n                    currentCost = newCost;\n                    bestI = ni;\n                    bestJ = nj;\n                    changed = true;\n                }\n            }\n            path[i] = {bestI, bestJ};\n        }\n        if (!changed) break;\n    }\n    \n    return path;\n}\n\nstring buildString(const vector<int>& order) {\n    if (order.empty()) return \"\";\n    string s;\n    s.reserve(M * 5);\n    s = t[order[0]];\n    for (size_t i = 1; i < order.size(); i++) {\n        int ov = overlap[order[i-1]][order[i]];\n        s.append(t[order[i]].substr(ov));\n    }\n    return s;\n}\n\nvector<int> greedyInit(int startWord) {\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    \n    order.push_back(startWord);\n    used[startWord] = true;\n    \n    for (int i = 1; i < M; i++) {\n        int bestNext = -1;\n        int bestScore = -1e9;\n        int lastW = order.back();\n        \n        for (int j = 0; j < M; j++) {\n            if (!used[j]) {\n                int ov = overlap[lastW][j];\n                int score = ov * 100 - (5 - ov) * 10;\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestNext = j;\n                }\n            }\n        }\n        \n        if (bestNext != -1) {\n            used[bestNext] = true;\n            order.push_back(bestNext);\n        }\n    }\n    return order;\n}\n\nvector<int> greedyPositionAware(int startWord) {\n    vector<bool> used(M, false);\n    vector<int> order;\n    order.reserve(M);\n    \n    order.push_back(startWord);\n    used[startWord] = true;\n    \n    int curR = si, curC = sj;\n    \n    for (int i = 1; i < M; i++) {\n        int bestNext = -1;\n        double bestScore = -1e18;\n        int lastW = order.back();\n        \n        for (int j = 0; j < M; j++) {\n            if (!used[j]) {\n                int ov = overlap[lastW][j];\n                int addedLen = 5 - ov;\n                \n                long long moveCost = 0;\n                int estR = curR, estC = curC;\n                for (int k = ov; k < 5; k++) {\n                    int ch = t[j][k] - 'A';\n                    moveCost += minCostFromPos[estR][estC][ch];\n                    auto [nr, nc] = bestPosFromPos[estR][estC][ch];\n                    estR = nr;\n                    estC = nc;\n                }\n                \n                double score = ov * 150.0 - addedLen * 20.0 - moveCost * 0.05;\n                \n                if (score > bestScore) {\n                    bestScore = score;\n                    bestNext = j;\n                }\n            }\n        }\n        \n        if (bestNext != -1) {\n            used[bestNext] = true;\n            order.push_back(bestNext);\n            \n            int ov = overlap[order[order.size()-2]][bestNext];\n            for (int k = ov; k < 5; k++) {\n                int ch = t[bestNext][k] - 'A';\n                auto [nr, nc] = bestPosFromPos[curR][curC][ch];\n                curR = nr;\n                curC = nc;\n            }\n        }\n    }\n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto startTime = chrono::steady_clock::now();\n    \n    cin >> N >> M;\n    cin >> si >> sj;\n    \n    A.resize(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n    \n    t.resize(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            charPos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n    \n    precomputeAll();\n    \n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i == j) continue;\n            int maxOv = 0;\n            for (int ov = 1; ov < 5; ov++) {\n                bool match = true;\n                for (int k = 0; k < ov; k++) {\n                    if (t[i][5 - ov + k] != t[j][k]) {\n                        match = false;\n                        break;\n                    }\n                }\n                if (match) maxOv = ov;\n            }\n            overlap[i][j] = maxOv;\n        }\n    }\n    \n    rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> bestOrder;\n    long long bestCost = 1e18;\n    \n    // Conservative time limit for safety\n    double timeLimit = 1.88;\n    \n    // Phase 1: Greedy initialization (limited)\n    int numGreedy = min(M, 15);\n    for (int i = 0; i < numGreedy; i++) {\n        vector<int> order = greedyInit(i);\n        long long cost = calcCost(order);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOrder = order;\n        }\n        \n        if (i % 5 == 0) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - startTime).count() > timeLimit * 0.1) break;\n        }\n    }\n    \n    // Position-aware greedy (limited)\n    for (int i = 0; i < min(M, 5); i++) {\n        vector<int> order = greedyPositionAware(i);\n        long long cost = calcCost(order);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestOrder = order;\n        }\n        \n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - startTime).count() > timeLimit * 0.15) break;\n    }\n    \n    // Phase 2: Single Simulated Annealing run\n    vector<int> currentOrder = bestOrder;\n    long long currentCost = bestCost;\n    \n    double temp = 2500.0;\n    double cooling = 0.99986;\n    long long iterations = 0;\n    int accepted = 0;\n    int checkInterval = 1000;\n    \n    while (true) {\n        if (iterations % checkInterval == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > timeLimit) break;\n            \n            double acceptRate = (double)accepted / checkInterval;\n            if (acceptRate < 0.04 && temp > 10) {\n                temp *= 1.4;\n            }\n            accepted = 0;\n        }\n        \n        vector<int> neighbor = currentOrder;\n        int move = rng() % 4;\n        \n        if (move == 0) {\n            int i = rng() % M;\n            int j = rng() % M;\n            swap(neighbor[i], neighbor[j]);\n        } else if (move == 1) {\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i != j) {\n                int val = neighbor[i];\n                neighbor.erase(neighbor.begin() + i);\n                neighbor.insert(neighbor.begin() + j, val);\n            }\n        } else if (move == 2) {\n            int i = rng() % M;\n            int j = rng() % M;\n            if (i > j) swap(i, j);\n            if (j - i > 1) {\n                reverse(neighbor.begin() + i, neighbor.begin() + j + 1);\n            }\n        } else {\n            int i = rng() % (M - 1);\n            swap(neighbor[i], neighbor[i + 1]);\n        }\n        \n        long long neighborCost = calcCost(neighbor);\n        double delta = (double)(neighborCost - currentCost);\n        \n        if (delta < 0 || (temp > 0.1 && exp(-delta / temp) > (double)rng() / rng.max())) {\n            currentOrder = neighbor;\n            currentCost = neighborCost;\n            accepted++;\n            if (currentCost < bestCost) {\n                bestCost = currentCost;\n                bestOrder = currentOrder;\n            }\n        }\n        \n        temp *= cooling;\n        iterations++;\n    }\n    \n    // Final construction with optimized positions\n    string finalStr = buildString(bestOrder);\n    vector<pair<int,int>> path = optimizePositions(finalStr);\n    \n    if ((int)path.size() > 5000) path.resize(5000);\n    \n    for (auto [i, j] : path) {\n        cout << i << \" \" << j << \"\\n\";\n    }\n    \n    return 0;\n}","ahc030":"#include <iostream>\n#include <vector>\n#include <cmath>\n#include <algorithm>\n#include <chrono>\n#include <iomanip>\n\nusing namespace std;\n\nconst double EPS = 1e-10;\nconst double INF = 1e100;\n\nstruct Field {\n    int id;\n    vector<pair<int, int>> shape;\n    int h, w;\n    vector<pair<int, int>> valid_positions;\n};\n\nint N, M;\ndouble epsilon;\nvector<Field> fields;\nvector<double> probs;\nvector<vector<int>> drill_results;\nvector<double> row_obs;\nvector<double> col_obs;\n\ninline int idx(int k, int r, int c) {\n    return k * N * N + r * N + c;\n}\n\n// Precompute which positions cover which cells\nvector<vector<vector<vector<pair<int, int>>>>> cover_map;\n\nvoid build_cover_map() {\n    cover_map.assign(M, vector<vector<vector<pair<int, int>>>>(N, vector<vector<pair<int, int>>>(N)));\n    for (int k = 0; k < M; ++k) {\n        for (auto [r, c] : fields[k].valid_positions) {\n            for (auto [si, sj] : fields[k].shape) {\n                int i = r + si;\n                int j = c + sj;\n                if (i >= 0 && i < N && j >= 0 && j < N) {\n                    cover_map[k][i][j].push_back({r, c});\n                }\n            }\n        }\n    }\n}\n\nvoid init_probs() {\n    probs.assign(M * N * N, 0.0);\n    for (int k = 0; k < M; ++k) {\n        double count = (double)fields[k].valid_positions.size();\n        if (count < EPS) count = 1.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] = 1.0 / count;\n        }\n    }\n}\n\ndouble get_marginal(int k, int i, int j) {\n    double p = 0.0;\n    for (auto [r, c] : cover_map[k][i][j]) {\n        p += probs[idx(k, r, c)];\n    }\n    return min(1.0, max(0.0, p));\n}\n\n// Update based on drill result at (i, j) with value V\nvoid update_drill(int i, int j, int V) {\n    vector<double> q(M);\n    for (int k = 0; k < M; ++k) {\n        q[k] = get_marginal(k, i, j);\n    }\n    \n    // Compute P(S=V) and P(S=V | X_k=1), P(S=V | X_k=0) using DP\n    // First compute full distribution\n    vector<double> dp(M + 1, 0.0);\n    dp[0] = 1.0;\n    \n    for (int k = 0; k < M; ++k) {\n        for (int s = k + 1; s >= 1; --s) {\n            dp[s] = dp[s] * (1.0 - q[k]) + dp[s-1] * q[k];\n        }\n        dp[0] = dp[0] * (1.0 - q[k]);\n    }\n    \n    double prob_S_V = (V <= M) ? dp[V] : 0.0;\n    if (prob_S_V < EPS) prob_S_V = EPS;\n    \n    // Update each field\n    for (int k = 0; k < M; ++k) {\n        // Compute distribution without field k\n        vector<double> dp_without(M, 0.0);\n        dp_without[0] = 1.0;\n        \n        for (int other = 0; other < M; ++other) {\n            if (other == k) continue;\n            double p = q[other];\n            for (int s = other; s >= 1; --s) {\n                dp_without[s] = dp_without[s] * (1.0 - p) + dp_without[s-1] * p;\n            }\n            dp_without[0] = dp_without[0] * (1.0 - p);\n        }\n        \n        double prob_S_V_given_1 = (V > 0 && V - 1 < M) ? dp_without[V - 1] : 0.0;\n        double prob_S_V_given_0 = (V < M) ? dp_without[V] : 0.0;\n        \n        double num_1 = prob_S_V_given_1 * q[k];\n        double num_0 = prob_S_V_given_0 * (1.0 - q[k]);\n        double denom = num_1 + num_0;\n        \n        double new_q;\n        if (denom < EPS) {\n            new_q = q[k];\n        } else {\n            new_q = num_1 / denom;\n        }\n        new_q = min(1.0, max(0.0, new_q));\n        \n        // Update probs for field k\n        double old_q = q[k];\n        if (abs(old_q - new_q) < EPS) continue;\n        \n        double f1 = (old_q > EPS) ? (new_q / old_q) : 1.0;\n        double f0 = (old_q < 1.0 - EPS) ? ((1.0 - new_q) / (1.0 - old_q)) : 1.0;\n        \n        f1 = min(INF, max(1.0/INF, f1));\n        f0 = min(INF, max(1.0/INF, f0));\n        \n        double sum_p = 0.0;\n        for (auto [r, c] : fields[k].valid_positions) {\n            bool covers = false;\n            for (auto [si, sj] : fields[k].shape) {\n                if (r + si == i && c + sj == j) {\n                    covers = true;\n                    break;\n                }\n            }\n            \n            if (covers) {\n                probs[idx(k, r, c)] *= f1;\n            } else {\n                probs[idx(k, r, c)] *= f0;\n            }\n            probs[idx(k, r, c)] = min(INF, max(EPS, probs[idx(k, r, c)]));\n            sum_p += probs[idx(k, r, c)];\n        }\n        \n        if (sum_p < EPS) sum_p = EPS;\n        for (auto [r, c] : fields[k].valid_positions) {\n            probs[idx(k, r, c)] /= sum_p;\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> epsilon)) return 1;\n    \n    fields.resize(M);\n    for (int k = 0; k < M; ++k) {\n        fields[k].id = k;\n        int d;\n        cin >> d;\n        fields[k].shape.resize(d);\n        int max_i = -1, max_j = -1;\n        for (int i = 0; i < d; ++i) {\n            cin >> fields[k].shape[i].first >> fields[k].shape[i].second;\n            max_i = max(max_i, fields[k].shape[i].first);\n            max_j = max(max_j, fields[k].shape[i].second);\n        }\n        fields[k].h = max_i + 1;\n        fields[k].w = max_j + 1;\n        for (int r = 0; r <= N - fields[k].h; ++r) {\n            for (int c = 0; c <= N - fields[k].w; ++c) {\n                fields[k].valid_positions.push_back({r, c});\n            }\n        }\n    }\n    \n    build_cover_map();\n    init_probs();\n    \n    drill_results.assign(N, vector<int>(N, -1));\n    row_obs.assign(N, 0.0);\n    col_obs.assign(N, 0.0);\n    \n    auto start_time = chrono::steady_clock::now();\n    \n    // 1. Query all rows\n    for (int i = 0; i < N; ++i) {\n        cout << \"q \" << N;\n        for (int j = 0; j < N; ++j) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << \"\\n\" << flush;\n        cin >> row_obs[i];\n    }\n    \n    // 2. Query all columns\n    for (int j = 0; j < N; ++j) {\n        cout << \"q \" << N;\n        for (int i = 0; i < N; ++i) {\n            cout << \" \" << i << \" \" << j;\n        }\n        cout << \"\\n\" << flush;\n        cin >> col_obs[j];\n    }\n    \n    // 3. Simple belief update from row/col observations\n    // For each cell, estimate probability based on row/col sums\n    vector<vector<double>> cell_prob(N, vector<double>(N, 0.5));\n    \n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            // Simple heuristic: average contribution from row and col\n            double row_avg = row_obs[i] / N;\n            double col_avg = col_obs[j] / N;\n            cell_prob[i][j] = min(1.0, max(0.0, (row_avg + col_avg) / 2.0));\n        }\n    }\n    \n    // 4. Iterative drilling with entropy-based selection\n    int ops_count = 2 * N;\n    int max_ops = 2 * N * N;\n    \n    while (ops_count < max_ops) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.8) break;\n        \n        int best_i = -1, best_j = -1;\n        double max_entropy = -1.0;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (drill_results[i][j] != -1) continue;\n                \n                // Use cell_prob as estimate\n                double p = cell_prob[i][j];\n                // Refine with marginal probabilities\n                double p_marginal = 0.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal(k, i, j);\n                    p_marginal = 1.0 - (1.0 - p_marginal) * (1.0 - q);\n                }\n                p = (p + p_marginal) / 2.0;\n                \n                if (p < EPS) p = EPS;\n                if (p > 1.0 - EPS) p = 1.0 - EPS;\n                \n                double H = -p * log2(p) - (1.0 - p) * log2(1.0 - p);\n                if (H > max_entropy) {\n                    max_entropy = H;\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1 || max_entropy < 0.1) break;\n        \n        cout << \"q 1 \" << best_i << \" \" << best_j << \"\\n\" << flush;\n        int val;\n        cin >> val;\n        drill_results[best_i][best_j] = val;\n        ops_count++;\n        \n        // Update cell probabilities based on drill\n        if (val > 0) {\n            cell_prob[best_i][best_j] = 1.0;\n            // Boost nearby cells\n            for (int di = -2; di <= 2; ++di) {\n                for (int dj = -2; dj <= 2; ++dj) {\n                    int ni = best_i + di;\n                    int nj = best_j + dj;\n                    if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                        if (drill_results[ni][nj] == -1) {\n                            cell_prob[ni][nj] = min(1.0, cell_prob[ni][nj] + 0.1);\n                        }\n                    }\n                }\n            }\n        } else {\n            cell_prob[best_i][best_j] = 0.0;\n        }\n        \n        // Update belief state\n        update_drill(best_i, best_j, val);\n    }\n    \n    // 5. Construct answer\n    vector<pair<int, int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            bool has_oil = false;\n            if (drill_results[i][j] != -1) {\n                has_oil = (drill_results[i][j] > 0);\n            } else {\n                double p_empty = 1.0;\n                for (int k = 0; k < M; ++k) {\n                    double q = get_marginal(k, i, j);\n                    p_empty *= (1.0 - q);\n                }\n                double p_marginal = 1.0 - p_empty;\n                double p_combined = (p_marginal + cell_prob[i][j]) / 2.0;\n                has_oil = (p_combined > 0.5);\n            }\n            \n            if (has_oil) {\n                ans.push_back({i, j});\n            }\n        }\n    }\n    \n    // 6. Submit answer\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) {\n        cout << \" \" << i << \" \" << j;\n    }\n    cout << \"\\n\" << flush;\n    \n    int resp;\n    cin >> resp;\n    \n    // If wrong, we could try again but for now just exit\n    (void)resp;\n    \n    return 0;\n}","ahc031":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n#include <random>\n#include <chrono>\n\nusing namespace std;\n\nconst int W = 1000;\nconst double TIME_LIMIT = 2.8;\n\nstruct Rect {\n    int r0, c0, r1, c1;\n    long long area() const { return (long long)(r1 - r0) * (c1 - c0); }\n};\n\nstruct Node {\n    int id;\n    bool is_leaf;\n    int left = -1, right = -1;\n    int res_id = -1;\n    long long target_area = 0;\n    \n    int r0, c0, r1, c1;\n    int cut_pos = 0;\n    int cut_type = 0;\n    \n    int prev_cut_pos = 0;\n    int prev_cut_type = 0;\n};\n\nstruct Solver {\n    int D, N;\n    vector<vector<int>> A;\n    vector<Node> tree;\n    vector<Rect> prev_day_rects;\n    mt19937 rng;\n    chrono::steady_clock::time_point start_time;\n    \n    // Mutation statistics for adaptive selection\n    vector<double> mutation_weight;\n    vector<int> mutation_count;\n    \n    Solver() {\n        rng.seed(chrono::steady_clock::now().time_since_epoch().count());\n        mutation_weight.resize(6, 1.0);\n        mutation_count.resize(6, 1);\n    }\n    \n    void run() {\n        start_time = chrono::steady_clock::now();\n        \n        int W_in;\n        if (!(cin >> W_in >> D >> N)) return;\n        \n        A.resize(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        prev_day_rects.resize(N);\n        \n        // Build tree\n        tree.resize(2 * N - 1);\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].id = i;\n            if (i >= N - 1) {\n                tree[i].is_leaf = true;\n                tree[i].res_id = i - (N - 1);\n            } else {\n                tree[i].is_leaf = false;\n                tree[i].left = 2 * i + 1;\n                tree[i].right = 2 * i + 2;\n                tree[i].cut_type = (i % 2);\n            }\n        }\n        \n        // Day 0\n        assign_reservations(0);\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n        output_day(0);\n        \n        // Subsequent days\n        for (int d = 1; d < D; ++d) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n            \n            // Calculate area change from previous day\n            double area_change = 0;\n            for (int k = 0; k < N; ++k) {\n                area_change += abs(A[d][k] - A[d-1][k]);\n            }\n            \n            if (elapsed < TIME_LIMIT * 0.85) {\n                solve_day(d, area_change);\n            } else {\n                assign_reservations(d);\n                layout(0, 0, 0, W, W);\n                update_prev_info();\n            }\n            \n            output_day(d);\n            \n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT * 0.95) {\n                for (int d2 = d + 1; d2 < D; ++d2) {\n                    assign_reservations(d2);\n                    layout(0, 0, 0, W, W);\n                    update_prev_info();\n                    output_day(d2);\n                }\n                break;\n            }\n        }\n    }\n    \n    void assign_reservations(int d) {\n        vector<pair<int, int>> requests;\n        for (int k = 0; k < N; ++k) {\n            requests.push_back({A[d][k], k});\n        }\n        sort(requests.begin(), requests.end());\n        \n        vector<pair<long long, int>> leaf_areas;\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            long long area = (long long)(tree[leaf_idx].r1 - tree[leaf_idx].r0) * \n                            (tree[leaf_idx].c1 - tree[leaf_idx].c0);\n            leaf_areas.push_back({area, leaf_idx});\n        }\n        sort(leaf_areas.begin(), leaf_areas.end());\n        \n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = leaf_areas[i].second;\n            int k = requests[i].second;\n            tree[leaf_idx].res_id = k;\n            tree[leaf_idx].target_area = A[d][k];\n        }\n    }\n    \n    int select_mutation() {\n        double total = accumulate(mutation_weight.begin(), mutation_weight.end(), 0.0);\n        double r = uniform_real_distribution<>(0.0, total)(rng);\n        double cumsum = 0;\n        for (int i = 0; i < 6; ++i) {\n            cumsum += mutation_weight[i];\n            if (r <= cumsum) return i;\n        }\n        return uniform_int_distribution<>(0, 5)(rng);\n    }\n    \n    void solve_day(int d, double area_change) {\n        assign_reservations(d);\n        layout(0, 0, 0, W, W);\n        \n        double best_cost = calc_total_cost();\n        vector<Node> best_tree = tree;\n        \n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n        double remaining = TIME_LIMIT - elapsed;\n        double time_per_day = TIME_LIMIT / D;\n        \n        // Adaptive iterations based on time and area change\n        int max_iterations = 30000;\n        if (remaining < time_per_day * 0.3) max_iterations = 5000;\n        else if (remaining < time_per_day * 0.6) max_iterations = 15000;\n        else if (remaining > time_per_day * 1.5) max_iterations = 50000;\n        \n        // More iterations for large area changes\n        if (area_change > 40000) max_iterations = min(max_iterations + 15000, 70000);\n        \n        // Multiple restarts\n        int num_restarts = 1;\n        if (remaining > time_per_day * 1.5) num_restarts = 2;\n        if (area_change > 60000 && remaining > time_per_day * 2) num_restarts = 3;\n        \n        double initial_temp = 10000.0;\n        double final_temp = 0.01;\n        \n        for (int restart = 0; restart < num_restarts; ++restart) {\n            if (chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT * 0.9) break;\n            \n            // Reset to best tree for restart\n            if (restart > 0) {\n                tree = best_tree;\n                layout(0, 0, 0, W, W);\n            }\n            \n            double cooling_rate = pow(final_temp / initial_temp, 1.0 / (max_iterations / num_restarts));\n            double temperature = initial_temp * (1.0 - 0.15 * restart);\n            \n            int iter_per_restart = max_iterations / num_restarts;\n            int no_improve = 0;\n            \n            for (int iter = 0; iter < iter_per_restart; ++iter) {\n                if (iter % 500 == 0 && chrono::duration<double>(chrono::steady_clock::now() - start_time).count() > TIME_LIMIT * 0.9) {\n                    break;\n                }\n                \n                int mutation_type = select_mutation();\n                \n                int node_idx = -1, node_idx2 = -1;\n                int leaf1 = -1, leaf2 = -1;\n                int saved_left = -1, saved_right = -1, saved_cut_type = -1;\n                int saved_res1 = -1, saved_res2 = -1;\n                long long saved_area1 = 0, saved_area2 = 0;\n                bool valid_mutation = true;\n                \n                if (mutation_type == 0) {\n                    // Swap children (weight will be updated)\n                    node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n                    saved_left = tree[node_idx].left;\n                    saved_right = tree[node_idx].right;\n                    swap(tree[node_idx].left, tree[node_idx].right);\n                } else if (mutation_type == 1) {\n                    // Flip cut type\n                    node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n                    saved_cut_type = tree[node_idx].cut_type;\n                    tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n                } else if (mutation_type == 2) {\n                    // Swap leaf assignments\n                    leaf1 = uniform_int_distribution<>(N - 1, 2 * N - 2)(rng);\n                    leaf2 = uniform_int_distribution<>(N - 1, 2 * N - 2)(rng);\n                    if (leaf1 != leaf2) {\n                        saved_res1 = tree[leaf1].res_id;\n                        saved_res2 = tree[leaf2].res_id;\n                        saved_area1 = tree[leaf1].target_area;\n                        saved_area2 = tree[leaf2].target_area;\n                        swap(tree[leaf1].res_id, tree[leaf2].res_id);\n                        swap(tree[leaf1].target_area, tree[leaf2].target_area);\n                    } else {\n                        valid_mutation = false;\n                    }\n                } else if (mutation_type == 3) {\n                    // Swap children + flip cut type\n                    node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n                    saved_left = tree[node_idx].left;\n                    saved_right = tree[node_idx].right;\n                    saved_cut_type = tree[node_idx].cut_type;\n                    swap(tree[node_idx].left, tree[node_idx].right);\n                    tree[node_idx].cut_type = 1 - tree[node_idx].cut_type;\n                } else if (mutation_type == 4) {\n                    // Random cut type\n                    node_idx = uniform_int_distribution<>(0, N - 2)(rng);\n                    saved_cut_type = tree[node_idx].cut_type;\n                    tree[node_idx].cut_type = uniform_int_distribution<>(0, 1)(rng);\n                } else {\n                    // Subtree swap (swap two subtrees at same level)\n                    int level = uniform_int_distribution<>(0, (int)log2(N) - 1)(rng);\n                    int start = (1 << level) - 1;\n                    int end = min((1 << (level + 1)) - 2, N - 2);\n                    if (start < end) {\n                        node_idx = uniform_int_distribution<>(start, end)(rng);\n                        node_idx2 = uniform_int_distribution<>(start, end)(rng);\n                        if (node_idx != node_idx2) {\n                            swap(tree[node_idx].left, tree[node_idx2].left);\n                            swap(tree[node_idx].right, tree[node_idx2].right);\n                            swap(tree[node_idx].cut_type, tree[node_idx2].cut_type);\n                            saved_left = tree[node_idx].left;\n                            saved_right = tree[node_idx].right;\n                            saved_cut_type = tree[node_idx].cut_type;\n                            // Also need to save node_idx2's values\n                        } else {\n                            valid_mutation = false;\n                        }\n                    } else {\n                        valid_mutation = false;\n                    }\n                }\n                \n                if (!valid_mutation) {\n                    temperature *= cooling_rate;\n                    continue;\n                }\n                \n                layout(0, 0, 0, W, W);\n                double new_cost = calc_total_cost();\n                \n                double delta = new_cost - best_cost;\n                bool accept = false;\n                if (delta < -1e-9) {\n                    accept = true;\n                    no_improve = 0;\n                    // Update mutation weight\n                    mutation_weight[mutation_type] += 0.5;\n                } else if (delta < 1e-9) {\n                    accept = true;\n                } else {\n                    double prob = exp(-delta / temperature);\n                    if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                        accept = true;\n                    }\n                }\n                mutation_count[mutation_type]++;\n                \n                if (accept) {\n                    if (new_cost < best_cost - 1e-9) {\n                        best_cost = new_cost;\n                        best_tree = tree;\n                    }\n                } else {\n                    // Revert\n                    if (mutation_type == 0) {\n                        tree[node_idx].left = saved_left;\n                        tree[node_idx].right = saved_right;\n                    } else if (mutation_type == 1) {\n                        tree[node_idx].cut_type = saved_cut_type;\n                    } else if (mutation_type == 2 && leaf1 >= 0) {\n                        tree[leaf1].res_id = saved_res1;\n                        tree[leaf2].res_id = saved_res2;\n                        tree[leaf1].target_area = saved_area1;\n                        tree[leaf2].target_area = saved_area2;\n                    } else if (mutation_type == 3) {\n                        tree[node_idx].left = saved_left;\n                        tree[node_idx].right = saved_right;\n                        tree[node_idx].cut_type = saved_cut_type;\n                    } else if (mutation_type == 4) {\n                        tree[node_idx].cut_type = saved_cut_type;\n                    } else if (mutation_type == 5) {\n                        // Revert subtree swap\n                        swap(tree[node_idx].left, tree[node_idx2].left);\n                        swap(tree[node_idx].right, tree[node_idx2].right);\n                        swap(tree[node_idx].cut_type, tree[node_idx2].cut_type);\n                    }\n                }\n                \n                temperature *= cooling_rate;\n                no_improve++;\n                \n                // Decay mutation weights slightly\n                if (iter % 1000 == 0) {\n                    for (int i = 0; i < 6; ++i) {\n                        mutation_weight[i] *= 0.95;\n                        if (mutation_weight[i] < 0.1) mutation_weight[i] = 0.1;\n                    }\n                }\n            }\n        }\n        \n        tree = best_tree;\n        layout(0, 0, 0, W, W);\n        update_prev_info();\n    }\n    \n    void layout(int u, int r0, int c0, int r1, int c1) {\n        tree[u].r0 = r0;\n        tree[u].c0 = c0;\n        tree[u].r1 = r1;\n        tree[u].c1 = c1;\n        \n        if (tree[u].is_leaf) return;\n        \n        int left = tree[u].left;\n        int right = tree[u].right;\n        long long area_l = get_subtree_area(left);\n        long long area_r = get_subtree_area(right);\n        long long total = area_l + area_r;\n        \n        int width = c1 - c0;\n        int height = r1 - r0;\n        \n        int actual_cut_type = tree[u].cut_type;\n        if (width <= 1) {\n            actual_cut_type = 1;\n        } else if (height <= 1) {\n            actual_cut_type = 0;\n        }\n        \n        if (actual_cut_type == 0) {\n            int min_cut = c0 + 1;\n            int max_cut = c1 - 1;\n            \n            if (min_cut > max_cut) {\n                tree[u].cut_pos = c0 + 1;\n            } else {\n                if (total == 0) {\n                    tree[u].cut_pos = (min_cut + max_cut) / 2;\n                } else {\n                    long long w_l = (width * area_l + total / 2) / total;\n                    if (w_l < 1) w_l = 1;\n                    if (w_l > width - 1) w_l = width - 1;\n                    tree[u].cut_pos = c0 + w_l;\n                    if (tree[u].cut_pos < min_cut) tree[u].cut_pos = min_cut;\n                    if (tree[u].cut_pos > max_cut) tree[u].cut_pos = max_cut;\n                }\n            }\n            \n            layout(left, r0, c0, r1, tree[u].cut_pos);\n            layout(right, r0, tree[u].cut_pos, r1, c1);\n        } else {\n            int min_cut = r0 + 1;\n            int max_cut = r1 - 1;\n            \n            if (min_cut > max_cut) {\n                tree[u].cut_pos = r0 + 1;\n            } else {\n                if (total == 0) {\n                    tree[u].cut_pos = (min_cut + max_cut) / 2;\n                } else {\n                    long long h_l = (height * area_l + total / 2) / total;\n                    if (h_l < 1) h_l = 1;\n                    if (h_l > height - 1) h_l = height - 1;\n                    tree[u].cut_pos = r0 + h_l;\n                    if (tree[u].cut_pos < min_cut) tree[u].cut_pos = min_cut;\n                    if (tree[u].cut_pos > max_cut) tree[u].cut_pos = max_cut;\n                }\n            }\n            \n            layout(left, r0, c0, tree[u].cut_pos, c1);\n            layout(right, tree[u].cut_pos, c0, r1, c1);\n        }\n    }\n    \n    long long get_subtree_area(int u) {\n        if (tree[u].is_leaf) return tree[u].target_area;\n        return get_subtree_area(tree[u].left) + get_subtree_area(tree[u].right);\n    }\n    \n    double calc_total_cost() {\n        double cost = 0;\n        \n        for (int i = N - 1; i < 2 * N - 1; ++i) {\n            long long actual_area = (long long)(tree[i].r1 - tree[i].r0) * (tree[i].c1 - tree[i].c0);\n            if (actual_area < tree[i].target_area) {\n                cost += 100.0 * (tree[i].target_area - actual_area);\n            }\n        }\n        \n        for (int i = 0; i < N - 1; ++i) {\n            if (tree[i].cut_type != tree[i].prev_cut_type) {\n                int span_old = (tree[i].prev_cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                int span_new = (tree[i].cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                cost += span_old + span_new;\n            } else {\n                int pos_diff = abs(tree[i].cut_pos - tree[i].prev_cut_pos);\n                int span = (tree[i].cut_type == 0) ? \n                    max(1, tree[i].r1 - tree[i].r0) : max(1, tree[i].c1 - tree[i].c0);\n                cost += 2.0 * pos_diff * span;\n            }\n        }\n        \n        return cost;\n    }\n    \n    void update_prev_info() {\n        for (int i = 0; i < 2 * N - 1; ++i) {\n            tree[i].prev_cut_pos = tree[i].cut_pos;\n            tree[i].prev_cut_type = tree[i].cut_type;\n        }\n        \n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            prev_day_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, \n                                tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n    }\n    \n    void output_day(int) {\n        vector<Rect> current_rects(N);\n        for (int i = 0; i < N; ++i) {\n            int leaf_idx = N - 1 + i;\n            int k = tree[leaf_idx].res_id;\n            current_rects[k] = {tree[leaf_idx].r0, tree[leaf_idx].c0, \n                               tree[leaf_idx].r1, tree[leaf_idx].c1};\n        }\n        \n        for (int k = 0; k < N; ++k) {\n            cout << current_rects[k].r0 << \" \" << current_rects[k].c0 << \" \" \n                 << current_rects[k].r1 << \" \" << current_rects[k].c1 << \"\\n\";\n        }\n    }\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    Solver solver;\n    solver.run();\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long MOD = 998244353;\n\nstruct Operation {\n    int m, p, q;\n    \n    bool operator==(const Operation& other) const {\n        return m == other.m && p == other.p && q == other.q;\n    }\n    \n    bool operator!=(const Operation& other) const {\n        return !(*this == other);\n    }\n    \n    bool operator<(const Operation& other) const {\n        if (m != other.m) return m < other.m;\n        if (p != other.p) return p < other.p;\n        return q < other.q;\n    }\n};\n\nint N, M, K;\nvector<vector<long long>> a;\nvector<vector<vector<long long>>> s;\n\n// Safe modulo that handles negative numbers\ninline long long safeMod(long long x) {\n    long long r = x % MOD;\n    return r < 0 ? r + MOD : r;\n}\n\n// Current board state (cumulative additions from operations)\nvector<vector<long long>> board;\n\n// Current modulo values for each cell\nvector<vector<long long>> mod_vals;\n\n// Current total score\nlong long current_score;\n\n// Current operations\nvector<Operation> ops;\n\n// Initialize board state from operations\nvoid resetBoard() {\n    board.assign(N, vector<long long>(N, 0));\n    mod_vals.resize(N, vector<long long>(N));\n    \n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            mod_vals[i][j] = safeMod(a[i][j]);\n        }\n    }\n    \n    current_score = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            current_score += mod_vals[i][j];\n        }\n    }\n    \n    // Apply all operations\n    for (const auto& op : ops) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                int r = op.p + i;\n                int c = op.q + j;\n                long long old_mod = mod_vals[r][c];\n                board[r][c] += s[op.m][i][j];\n                mod_vals[r][c] = safeMod(board[r][c] + a[r][c]);\n                current_score += mod_vals[r][c] - old_mod;\n            }\n        }\n    }\n}\n\n// Calculate delta if we change operation at index idx to new_op\nlong long calculateDelta(int idx, const Operation& new_op) {\n    const auto& old_op = ops[idx];\n    long long delta = 0;\n    \n    bool visited[9][9] = {};\n    vector<pair<int, int>> affected;\n    affected.reserve(18);\n    \n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = old_op.p + i;\n            int c = old_op.q + j;\n            if (!visited[r][c]) {\n                visited[r][c] = true;\n                affected.emplace_back(r, c);\n            }\n        }\n    }\n    \n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = new_op.p + i;\n            int c = new_op.q + j;\n            if (!visited[r][c]) {\n                visited[r][c] = true;\n                affected.emplace_back(r, c);\n            }\n        }\n    }\n    \n    for (const auto& [r, c] : affected) {\n        long long old_mod = mod_vals[r][c];\n        long long new_val = board[r][c] + a[r][c];\n        \n        if (r >= old_op.p && r < old_op.p + 3 && c >= old_op.q && c < old_op.q + 3) {\n            new_val -= s[old_op.m][r - old_op.p][c - old_op.q];\n        }\n        if (r >= new_op.p && r < new_op.p + 3 && c >= new_op.q && c < new_op.q + 3) {\n            new_val += s[new_op.m][r - new_op.p][c - new_op.q];\n        }\n        \n        long long new_mod = safeMod(new_val);\n        delta += new_mod - old_mod;\n    }\n    \n    return delta;\n}\n\n// Actually change operation at index idx\nvoid changeOp(int idx, const Operation& new_op) {\n    const auto& old_op = ops[idx];\n    \n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = old_op.p + i;\n            int c = old_op.q + j;\n            long long old_mod = mod_vals[r][c];\n            board[r][c] -= s[old_op.m][i][j];\n            mod_vals[r][c] = safeMod(board[r][c] + a[r][c]);\n            current_score += mod_vals[r][c] - old_mod;\n        }\n    }\n    \n    ops[idx] = new_op;\n    \n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            int r = new_op.p + i;\n            int c = new_op.q + j;\n            long long old_mod = mod_vals[r][c];\n            board[r][c] += s[new_op.m][i][j];\n            mod_vals[r][c] = safeMod(board[r][c] + a[r][c]);\n            current_score += mod_vals[r][c] - old_mod;\n        }\n    }\n}\n\n// Greedy initialization with optional slight randomization\nvector<Operation> greedyInit(mt19937& rng, double randomization = 0.0) {\n    vector<Operation> result;\n    result.reserve(K);\n    \n    vector<vector<long long>> cur_board = a;\n    vector<vector<long long>> cur_mod(N, vector<long long>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cur_mod[i][j] = safeMod(cur_board[i][j]);\n        }\n    }\n    \n    for (int op = 0; op < K; op++) {\n        vector<tuple<long long, int, int, int>> candidates;\n        candidates.reserve(M * (N - 2) * (N - 2));\n        \n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p <= N - 3; p++) {\n                for (int q = 0; q <= N - 3; q++) {\n                    long long delta = 0;\n                    for (int i = 0; i < 3; i++) {\n                        for (int j = 0; j < 3; j++) {\n                            long long old_mod = cur_mod[p + i][q + j];\n                            long long new_mod = safeMod(cur_board[p + i][q + j] + s[m][i][j]);\n                            delta += new_mod - old_mod;\n                        }\n                    }\n                    candidates.emplace_back(delta, m, p, q);\n                }\n            }\n        }\n        \n        sort(candidates.begin(), candidates.end(), greater<>());\n        \n        int pick = 0;\n        if (randomization > 0.0) {\n            int top_k = max(1, (int)(candidates.size() * (1.0 - randomization)));\n            uniform_int_distribution<int> dist_top(0, top_k - 1);\n            pick = dist_top(rng);\n        }\n        \n        auto& [best_delta, best_m, best_p, best_q] = candidates[pick];\n        \n        result.push_back({best_m, best_p, best_q});\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cur_board[best_p + i][best_q + j] += s[best_m][i][j];\n                cur_mod[best_p + i][best_q + j] = safeMod(cur_board[best_p + i][best_q + j]);\n            }\n        }\n    }\n    \n    return result;\n}\n\n// Local search with tabu list\nvoid localSearch(int iterations, mt19937& rng) {\n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    \n    queue<pair<int, Operation>> tabu;\n    unordered_set<long long> tabu_set;\n    int tabu_size = 25;\n    \n    auto makeTabuHash = [](int idx, const Operation& op) -> long long {\n        return ((long long)idx << 20) ^ (op.m << 10) ^ (op.p << 5) ^ op.q;\n    };\n    \n    int no_improve = 0;\n    for (int iter = 0; iter < iterations && no_improve < iterations / 8; iter++) {\n        bool improved = false;\n        \n        for (int trial = 0; trial < 200; trial++) {\n            int idx = dist_op(rng);\n            Operation new_op = {dist_m(rng), dist_p(rng), dist_q(rng)};\n            \n            long long hash_val = makeTabuHash(idx, ops[idx]);\n            if (tabu_set.count(hash_val)) continue;\n            \n            long long delta = calculateDelta(idx, new_op);\n            if (delta > 0) {\n                if ((int)tabu.size() >= tabu_size) {\n                    auto old = tabu.front();\n                    tabu.pop();\n                    tabu_set.erase(makeTabuHash(old.first, old.second));\n                }\n                tabu.push({idx, ops[idx]});\n                tabu_set.insert(hash_val);\n                \n                changeOp(idx, new_op);\n                improved = true;\n                no_improve = 0;\n            }\n        }\n        \n        for (int trial = 0; trial < 100; trial++) {\n            int idx1 = dist_op(rng);\n            int idx2 = dist_op(rng);\n            if (idx1 == idx2) continue;\n            \n            long long score_before = current_score;\n            \n            Operation op1 = ops[idx1];\n            Operation op2 = ops[idx2];\n            \n            changeOp(idx1, op2);\n            changeOp(idx2, op1);\n            \n            if (current_score > score_before) {\n                improved = true;\n                no_improve = 0;\n            } else {\n                changeOp(idx2, op2);\n                changeOp(idx1, op1);\n            }\n        }\n        \n        if (!improved) no_improve++;\n    }\n}\n\n// Simulated annealing\nvoid simulatedAnnealing(double time_limit, mt19937& rng) {\n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_score = current_score;\n    vector<Operation> best_ops = ops;\n    \n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    uniform_int_distribution<int> dist_p(0, N - 3);\n    uniform_int_distribution<int> dist_q(0, N - 3);\n    uniform_real_distribution<double> dist_real(0.0, 1.0);\n    \n    double temperature = 100000.0;\n    double cooling_rate = 0.9998;\n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        int idx = dist_op(rng);\n        Operation old_op = ops[idx];\n        Operation new_op = old_op;\n        \n        int change_type = dist_op(rng) % 4;\n        if (change_type == 0 || change_type == 1) {\n            new_op.m = dist_m(rng);\n        } else if (change_type == 2) {\n            new_op.p = dist_p(rng);\n        } else {\n            new_op.q = dist_q(rng);\n        }\n        \n        long long delta = calculateDelta(idx, new_op);\n        double accept_prob = exp((double)delta / temperature);\n        \n        if (delta > 0 || dist_real(rng) < accept_prob) {\n            changeOp(idx, new_op);\n            \n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ops = ops;\n            }\n        }\n        \n        temperature *= cooling_rate;\n        iterations++;\n        \n        if (iterations % 30000 == 0 && temperature < 0.001) break;\n    }\n    \n    if (best_score > current_score) {\n        ops = best_ops;\n        resetBoard();\n    }\n}\n\n// Final intensification on best solution\nvoid intensify(double time_limit, mt19937& rng) {\n    auto start_time = chrono::steady_clock::now();\n    \n    long long best_score = current_score;\n    vector<Operation> best_ops = ops;\n    \n    uniform_int_distribution<int> dist_op(0, K - 1);\n    uniform_int_distribution<int> dist_m(0, M - 1);\n    \n    int iterations = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        int idx = dist_op(rng);\n        int p = ops[idx].p;\n        int q = ops[idx].q;\n        \n        long long local_best_delta = 0;\n        int local_best_m = ops[idx].m;\n        \n        for (int m = 0; m < M; m++) {\n            if (m == ops[idx].m) continue;\n            Operation new_op = {m, p, q};\n            long long delta = calculateDelta(idx, new_op);\n            if (delta > local_best_delta) {\n                local_best_delta = delta;\n                local_best_m = m;\n            }\n        }\n        \n        if (local_best_delta > 0) {\n            changeOp(idx, {local_best_m, p, q});\n            if (current_score > best_score) {\n                best_score = current_score;\n                best_ops = ops;\n            }\n        }\n        \n        iterations++;\n        if (iterations > 15000) break;\n    }\n    \n    if (best_score > current_score) {\n        ops = best_ops;\n        resetBoard();\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> N >> M >> K;\n    \n    a.assign(N, vector<long long>(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    s.assign(M, vector<vector<long long>>(3, vector<long long>(3)));\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> s[m][i][j];\n            }\n        }\n    }\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_budget = 1.97;\n    \n    vector<pair<long long, vector<Operation>>> top_solutions;\n    \n    // 20 restarts: 17 deterministic + 3 with slight randomization for diversity\n    int num_restarts = 20;\n    for (int restart = 0; restart < num_restarts; restart++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_budget * 0.82) break;\n        \n        double remaining = time_budget - elapsed;\n        double time_per_restart = remaining / max(1, num_restarts - restart);\n        \n        // More diverse seeds using prime multipliers\n        unsigned seed = restart * 31337 + (unsigned)chrono::steady_clock::now().time_since_epoch().count();\n        mt19937 rng(seed);\n        \n        // Mostly deterministic, but 3 restarts with slight randomization for hard cases\n        double randomization = 0.0;\n        if (restart == 17) randomization = 0.03;\n        else if (restart == 18) randomization = 0.05;\n        else if (restart == 19) randomization = 0.08;\n        \n        ops = greedyInit(rng, randomization);\n        resetBoard();\n        \n        // Local search with tabu\n        localSearch(3500, rng);\n        \n        // Simulated annealing\n        double sa_time = min(0.23, time_per_restart * 0.65);\n        simulatedAnnealing(sa_time, rng);\n        \n        top_solutions.emplace_back(current_score, ops);\n    }\n    \n    // Sort by score\n    sort(top_solutions.begin(), top_solutions.end(), greater<>());\n    \n    // Final intensification on best solution (0.4s instead of 0.35s)\n    if (!top_solutions.empty()) {\n        ops = top_solutions[0].second;\n        resetBoard();\n        \n        mt19937 rng(99999);\n        intensify(0.40, rng);\n        \n        long long best_final = current_score;\n        vector<Operation> final_ops = ops;\n        \n        // Try 2nd best if time permits\n        if (top_solutions.size() >= 2) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed < time_budget * 0.97) {\n                ops = top_solutions[1].second;\n                resetBoard();\n                intensify(0.12, rng);\n                \n                if (current_score > best_final) {\n                    best_final = current_score;\n                    final_ops = ops;\n                }\n            }\n        }\n        \n        ops = final_ops;\n        resetBoard();\n    }\n    \n    cout << ops.size() << \"\\n\";\n    for (const auto& op : ops) {\n        cout << op.m << \" \" << op.p << \" \" << op.q << \"\\n\";\n    }\n    \n    return 0;\n}","ahc033":"#include <iostream>\n#include <vector>\n#include <string>\n\nusing namespace std;\n\nconst int N = 5;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\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    vector<vector<int>> grid(N, vector<int>(N, -1));\n    vector<int> crane_r(N), crane_c(N, 0);\n    vector<int> crane_hold(N, -1);\n    vector<int> recv_idx(N, 0);\n    vector<int> gate_empty_turn(N, 0); // last turn gate was verified empty\n    \n    for (int i = 0; i < N; i++) crane_r[i] = i;\n    \n    vector<string> ans(N, \"\");\n    int dispatched = 0;\n    int turn = 0;\n    \n    // Turn 0: Clear column 0\n    for (int c = 0; c < N; c++) {\n        ans[c] += 'R';\n        crane_c[c] = 1;\n    }\n    turn++;\n    \n    // Containers arrive\n    for (int i = 0; i < N; i++) {\n        if (recv_idx[i] < N) {\n            grid[i][0] = A[i][recv_idx[i]];\n            recv_idx[i]++;\n        }\n    }\n    \n    while (turn < 6000 && dispatched < N * N) {\n        vector<char> act(N, '.');\n        vector<int> next_r = crane_r, next_c = crane_c;\n        vector<bool> ok(N, true);\n        \n        // Update gate empty tracking\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N-1] == -1) {\n                gate_empty_turn[i] = turn;\n            }\n        }\n        \n        // Plan actions\n        for (int c = 0; c < N; c++) {\n            int r = crane_r[c];\n            int col = crane_c[c];\n            int hold = crane_hold[c];\n            bool is_large = (c == 0);\n            \n            if (hold == -1) {\n                if (grid[r][col] != -1) {\n                    int container = grid[r][col];\n                    int target_gate = container / N;\n                    if (is_large || c == target_gate) {\n                        act[c] = 'P';\n                    } else if (col > 0) {\n                        act[c] = 'L'; next_c[c] = col - 1;\n                    }\n                } else {\n                    if (is_large) {\n                        if (r < N - 1) { act[c] = 'D'; next_r[c] = r + 1; }\n                        else if (col > 0) { act[c] = 'L'; next_c[c] = col - 1; }\n                        else { act[c] = 'U'; next_r[c] = 0; }\n                    } else if (col > 0) {\n                        act[c] = 'L'; next_c[c] = col - 1;\n                    }\n                }\n            } else {\n                int target_r = hold / N;\n                int target_c = N - 1;\n                \n                if (r == target_r && col == target_c) {\n                    // At gate - only Q if gate empty for 3+ turns\n                    if (turn - gate_empty_turn[target_r] >= 3) {\n                        act[c] = 'Q';\n                    } else {\n                        act[c] = '.';\n                    }\n                } else {\n                    if (is_large) {\n                        if (r < target_r) { act[c] = 'D'; next_r[c] = r + 1; }\n                        else if (r > target_r) { act[c] = 'U'; next_r[c] = r - 1; }\n                        else if (col < target_c) { act[c] = 'R'; next_c[c] = col + 1; }\n                        else if (col > target_c) { act[c] = 'L'; next_c[c] = col - 1; }\n                    } else {\n                        if (col < target_c) { act[c] = 'R'; next_c[c] = col + 1; }\n                        else if (col > target_c) { act[c] = 'L'; next_c[c] = col - 1; }\n                        else if (r < target_r) { act[c] = 'D'; next_r[c] = r + 1; }\n                        else if (r > target_r) { act[c] = 'U'; next_r[c] = r - 1; }\n                    }\n                }\n            }\n        }\n        \n        // Minimal collision check\n        for (int c = 0; c < N; c++) {\n            if (act[c] == '.' || act[c] == 'P' || act[c] == 'Q') continue;\n            if (next_r[c] < 0 || next_r[c] >= N || next_c[c] < 0 || next_c[c] >= N) {\n                ok[c] = false; act[c] = '.'; next_r[c] = crane_r[c]; next_c[c] = crane_c[c];\n                continue;\n            }\n            if (c > 0 && crane_hold[c] != -1 && grid[next_r[c]][next_c[c]] != -1) {\n                ok[c] = false; act[c] = '.'; next_r[c] = crane_r[c]; next_c[c] = crane_c[c];\n                continue;\n            }\n            for (int c2 = 0; c2 < N; c2++) {\n                if (c2 == c || !ok[c]) continue;\n                if (next_r[c] == next_r[c2] && next_c[c] == next_c[c2]) {\n                    ok[c] = false; act[c] = '.'; next_r[c] = crane_r[c]; next_c[c] = crane_c[c];\n                    break;\n                }\n                if (next_r[c] == crane_r[c2] && next_c[c] == crane_c[c2] &&\n                    next_r[c2] == crane_r[c] && next_c[c2] == crane_c[c]) {\n                    ok[c] = false; act[c] = '.'; next_r[c] = crane_r[c]; next_c[c] = crane_c[c];\n                    break;\n                }\n                if ((act[c2] == '.' || act[c2] == 'P' || act[c2] == 'Q') &&\n                    next_r[c] == crane_r[c2] && next_c[c] == crane_c[c2]) {\n                    ok[c] = false; act[c] = '.'; next_r[c] = crane_r[c]; next_c[c] = crane_c[c];\n                    break;\n                }\n            }\n        }\n        \n        // Final P/Q check\n        for (int c = 0; c < N; c++) {\n            if (!ok[c]) continue;\n            int r = crane_r[c], col = crane_c[c];\n            if (act[c] == 'P' && (crane_hold[c] != -1 || grid[r][col] == -1)) act[c] = '.';\n            if (act[c] == 'Q' && (crane_hold[c] == -1 || grid[r][col] != -1)) act[c] = '.';\n        }\n        \n        // One Q per gate\n        vector<bool> gate_used(N, false);\n        for (int c = 0; c < N; c++) {\n            if (ok[c] && act[c] == 'Q') {\n                int g = crane_hold[c] / N;\n                if (gate_used[g]) act[c] = '.';\n                else gate_used[g] = true;\n            }\n        }\n        \n        // Execute\n        for (int c = 0; c < N; c++) {\n            ans[c] += act[c];\n            int r = crane_r[c], col = crane_c[c];\n            if (act[c] == 'P' && crane_hold[c] == -1 && grid[r][col] != -1) {\n                crane_hold[c] = grid[r][col];\n                grid[r][col] = -1;\n            } else if (act[c] == 'Q' && crane_hold[c] != -1 && grid[r][col] == -1) {\n                grid[r][col] = crane_hold[c];\n                crane_hold[c] = -1;\n            }\n            if (ok[c] && act[c] != '.' && act[c] != 'P' && act[c] != 'Q') {\n                crane_r[c] = next_r[c];\n                crane_c[c] = next_c[c];\n            }\n        }\n        \n        // Dispatch\n        for (int i = 0; i < N; i++) {\n            if (grid[i][N-1] != -1) {\n                bool here = false;\n                for (int c = 0; c < N; c++) {\n                    if (crane_r[c] == i && crane_c[c] == N-1) { here = true; break; }\n                }\n                if (!here) {\n                    grid[i][N-1] = -1;\n                    dispatched++;\n                    gate_empty_turn[i] = turn;\n                }\n            }\n        }\n        \n        // Receive\n        for (int i = 0; i < N; i++) {\n            if (recv_idx[i] < N && grid[i][0] == -1) {\n                bool blocked = false;\n                for (int c = 0; c < N; c++) {\n                    if (crane_r[c] == i && crane_c[c] == 0 && crane_hold[c] != -1) {\n                        blocked = true; break;\n                    }\n                }\n                if (!blocked) {\n                    grid[i][0] = A[i][recv_idx[i]];\n                    recv_idx[i]++;\n                }\n            }\n        }\n        \n        turn++;\n    }\n    \n    size_t maxlen = 0;\n    for (int i = 0; i < N; i++) maxlen = max(maxlen, ans[i].size());\n    for (int i = 0; i < N; i++) {\n        while (ans[i].size() < maxlen) ans[i] += '.';\n    }\n    \n    for (int i = 0; i < N; i++) cout << ans[i] << \"\\n\";\n    \n    return 0;\n}","ahc034":"#include <iostream>\n#include <vector>\n#include <string>\n#include <cmath>\n#include <algorithm>\n#include <numeric>\n\nusing namespace std;\n\nstruct Cell {\n    int r, c;\n    int h;\n    int id;\n};\n\nint N;\nvector<vector<int>> H;\nvector<string> ops;\nint curr_r, curr_c;\nlong long current_load;\n\nvoid add_op(const string& s) {\n    ops.push_back(s);\n}\n\nvoid move_to(int tr, int tc) {\n    while (curr_r < tr) {\n        add_op(\"D\");\n        curr_r++;\n    }\n    while (curr_r > tr) {\n        add_op(\"U\");\n        curr_r--;\n    }\n    while (curr_c < tc) {\n        add_op(\"R\");\n        curr_c++;\n    }\n    while (curr_c > tc) {\n        add_op(\"L\");\n        curr_c--;\n    }\n}\n\nint dist(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N)) return 0;\n\n    H.assign(N, vector<int>(N));\n    vector<Cell> sources;\n    vector<Cell> sinks;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> H[i][j];\n            if (H[i][j] > 0) {\n                sources.push_back({i, j, H[i][j], i * N + j});\n            } else if (H[i][j] < 0) {\n                sinks.push_back({i, j, H[i][j], i * N + j});\n            }\n        }\n    }\n\n    curr_r = 0;\n    curr_c = 0;\n    current_load = 0;\n\n    while (!sources.empty() || current_load > 0) {\n        if (current_load == 0 && !sources.empty()) {\n            // Select source with best estimated total cost - O(S * M)\n            // Use single nearest sink (proven most effective)\n            int best_idx = -1;\n            long long best_score = -1;\n            int best_h = -1; // For tie-breaking\n\n            for (int i = 0; i < (int)sources.size(); ++i) {\n                int d1 = dist(curr_r, curr_c, sources[i].r, sources[i].c);\n                \n                // Find nearest sink distance - O(M)\n                int min_d_sink = 1e9;\n                for (const auto& s : sinks) {\n                    int d = dist(sources[i].r, sources[i].c, s.r, s.c);\n                    if (d < min_d_sink) min_d_sink = d;\n                }\n                \n                // Score: empty travel + loaded travel to nearest sink\n                long long score = 100LL * d1 + (100LL + sources[i].h) * min_d_sink;\n                \n                // Select best score, tie-break with larger source (amortizes fixed costs)\n                if (best_idx == -1 || score < best_score || \n                    (score == best_score && sources[i].h > best_h)) {\n                    best_score = score;\n                    best_idx = i;\n                    best_h = sources[i].h;\n                }\n            }\n\n            Cell u = sources[best_idx];\n            sources[best_idx] = sources.back();\n            sources.pop_back();\n\n            move_to(u.r, u.c);\n            long long amount = u.h;\n            add_op(\"+\" + to_string(amount));\n            current_load += amount;\n            H[u.r][u.c] = 0;\n        }\n\n        if (current_load > 0 && !sinks.empty()) {\n            // Select nearest sink - O(M)\n            // Tie-break with higher capacity (reduces number of visits)\n            int best_idx = -1;\n            int min_d = 1e9;\n            long long max_demand = -1;\n\n            for (int i = 0; i < (int)sinks.size(); ++i) {\n                int d = dist(curr_r, curr_c, sinks[i].r, sinks[i].c);\n                long long demand = -H[sinks[i].r][sinks[i].c];\n                if (demand <= 0) continue;\n                \n                if (d < min_d || (d == min_d && demand > max_demand)) {\n                    min_d = d;\n                    best_idx = i;\n                    max_demand = demand;\n                }\n            }\n\n            if (best_idx == -1) break;\n\n            Cell v = sinks[best_idx];\n            move_to(v.r, v.c);\n            \n            // Always unload maximum at this sink\n            long long demand = -H[v.r][v.c];\n            long long amount = min(current_load, demand);\n            \n            add_op(\"-\" + to_string(amount));\n            current_load -= amount;\n            H[v.r][v.c] += amount;\n            \n            // If sink is satisfied, remove from list\n            if (H[v.r][v.c] == 0) {\n                sinks[best_idx] = sinks.back();\n                sinks.pop_back();\n            }\n        }\n    }\n\n    for (const auto& op : ops) {\n        cout << op << \"\\n\";\n    }\n\n    return 0;\n}","ahc035":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <numeric>\n#include <cmath>\n\nusing namespace std;\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n    \n    int seed_count = 2 * N * (N - 1);\n    vector<vector<int>> X(seed_count, vector<int>(M));\n    vector<int> values(seed_count, 0);\n    \n    // Read initial seeds\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            cin >> X[i][j];\n            values[i] += X[i][j];\n        }\n    }\n    \n    // Track maximum value for each criterion\n    vector<int> max_per_criterion(M, 0);\n    for (int i = 0; i < seed_count; i++) {\n        for (int j = 0; j < M; j++) {\n            max_per_criterion[j] = max(max_per_criterion[j], X[i][j]);\n        }\n    }\n    \n    // Calculate criterion weights\n    vector<double> criterion_weight(M, 0);\n    double total_max = 0;\n    for (int j = 0; j < M; j++) {\n        total_max += max_per_criterion[j];\n    }\n    if (total_max > 0) {\n        for (int j = 0; j < M; j++) {\n            criterion_weight[j] = max_per_criterion[j] / total_max;\n        }\n    } else {\n        for (int j = 0; j < M; j++) {\n            criterion_weight[j] = 1.0 / M;\n        }\n    }\n    \n    // Neighbor count for each position\n    vector<vector<int>> neighbor_count(N, vector<int>(N, 0));\n    int di[] = {-1, 1, 0, 0};\n    int dj[] = {0, 0, -1, 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 ni = i + di[d];\n                int nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N) {\n                    neighbor_count[i][j]++;\n                }\n            }\n        }\n    }\n    \n    // Position priority: center first (most neighbors)\n    vector<pair<int, int>> positions;\n    positions.reserve(N * N);\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    sort(positions.begin(), positions.end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n        if (neighbor_count[a.first][a.second] != neighbor_count[b.first][b.second]) {\n            return neighbor_count[a.first][a.second] > neighbor_count[b.first][b.second];\n        }\n        int dist_a = abs(a.first - (N-1)/2) + abs(a.second - (N-1)/2);\n        int dist_b = abs(b.first - (N-1)/2) + abs(b.second - (N-1)/2);\n        return dist_a < dist_b;\n    });\n    \n    for (int t = 0; t < T; t++) {\n        // Smooth continuous decay for exploration\n        // Start at 0.5, decay to 0.0 by turn T\n        double progress = (double)t / T;\n        double exploration_weight = max(0.0, 0.5 * (1.0 - progress * progress)); // Quadratic decay\n        double exploitation_weight = 1.0 - exploration_weight;\n        \n        // Calculate seed scores\n        vector<double> seed_score(seed_count, 0);\n        \n        for (int i = 0; i < seed_count; i++) {\n            // Value score\n            double value_score = values[i] / 1500.0 * 1000;\n            \n            // Criterion coverage score\n            double coverage_score = 0;\n            int elite_count = 0;      // >= 95% of max\n            int near_elite_count = 0; // >= 85% of max\n            int max_count = 0;        // == max\n            double min_ratio = 1.0;   // Track worst criterion\n            \n            for (int j = 0; j < M; j++) {\n                if (max_per_criterion[j] > 0) {\n                    double ratio = (double)X[i][j] / max_per_criterion[j];\n                    coverage_score += ratio * criterion_weight[j] * 1000;\n                    min_ratio = min(min_ratio, ratio);\n                    \n                    if (ratio >= 0.95) elite_count++;\n                    if (ratio >= 0.85) near_elite_count++;\n                    if (X[i][j] == max_per_criterion[j]) max_count++;\n                }\n            }\n            \n            // Combined score\n            seed_score[i] = value_score * exploitation_weight + \n                           coverage_score * exploration_weight +\n                           elite_count * 150 +\n                           near_elite_count * 30 +\n                           max_count * 400;\n            \n            // Synergy bonus for multiple max criteria\n            if (max_count >= 2) {\n                seed_score[i] += (max_count - 1) * 150;\n            }\n            \n            // Consistency bonus (penalize seeds with very weak criteria)\n            seed_score[i] += min_ratio * 100;\n        }\n        \n        // Sort seeds by score (deterministic)\n        vector<int> indices(seed_count);\n        iota(indices.begin(), indices.end(), 0);\n        \n        sort(indices.begin(), indices.end(), [&](int a, int b) {\n            if (seed_score[a] > seed_score[b] + 0.5) return true;\n            if (seed_score[b] > seed_score[a] + 0.5) return false;\n            if (values[a] != values[b]) return values[a] > values[b];\n            return a < b;\n        });\n        \n        // Simple greedy placement - top seeds to top positions\n        vector<vector<int>> A(N, vector<int>(N, 0));\n        vector<bool> seed_used(seed_count, false);\n        \n        int seed_idx = 0;\n        for (int p = 0; p < N * N && seed_idx < seed_count; p++) {\n            int i = positions[p].first;\n            int j = positions[p].second;\n            \n            while (seed_idx < seed_count && seed_used[indices[seed_idx]]) {\n                seed_idx++;\n            }\n            \n            if (seed_idx < seed_count) {\n                A[i][j] = indices[seed_idx];\n                seed_used[indices[seed_idx]] = true;\n                seed_idx++;\n            }\n        }\n        \n        // Output the placement - exactly N lines\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j > 0) cout << \" \";\n                cout << A[i][j];\n            }\n            cout << \"\\n\";\n        }\n        cout.flush();\n        \n        // Read new seeds\n        for (int i = 0; i < seed_count; i++) {\n            values[i] = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n                values[i] += X[i][j];\n            }\n        }\n        \n        // Update max per criterion\n        for (int j = 0; j < M; j++) {\n            max_per_criterion[j] = 0;\n            for (int i = 0; i < seed_count; i++) {\n                max_per_criterion[j] = max(max_per_criterion[j], X[i][j]);\n            }\n        }\n        \n        // Recalculate criterion weights\n        total_max = 0;\n        for (int j = 0; j < M; j++) {\n            total_max += max_per_criterion[j];\n        }\n        if (total_max > 0) {\n            for (int j = 0; j < M; j++) {\n                criterion_weight[j] = max_per_criterion[j] / total_max;\n            }\n        } else {\n            for (int j = 0; j < M; j++) {\n                criterion_weight[j] = 1.0 / M;\n            }\n        }\n    }\n    \n    return 0;\n}","ahc038":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <cmath>\n\nusing namespace std;\n\nstruct Point {\n    int r, c;\n    bool operator==(const Point& other) const {\n        return r == other.r && c == other.c;\n    }\n};\n\nint dist(Point p1, Point p2) {\n    return abs(p1.r - p2.r) + abs(p1.c - p2.c);\n}\n\nPoint getFingerPos(int root_r, int root_c, int dir, int length = 1) {\n    int dr[] = {0, -1, 0, 1};\n    int dc[] = {1, 0, -1, 0};\n    return {root_r + dr[dir] * length, root_c + dc[dir] * length};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M_in, V;\n    if (!(cin >> N >> M_in >> V)) return 0;\n\n    vector<string> S_grid(N), T_grid(N);\n    vector<Point> starts, targets;\n\n    for (int i = 0; i < N; ++i) cin >> S_grid[i];\n    for (int i = 0; i < N; ++i) cin >> T_grid[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (S_grid[i][j] == '1') starts.push_back({i, j});\n            if (T_grid[i][j] == '1') targets.push_back({i, j});\n        }\n    }\n\n    // Output Arm Design: Star Graph\n    int V_prime = V;\n    cout << V_prime << \"\\n\";\n    for (int i = 1; i < V_prime; ++i) {\n        cout << 0 << \" \" << 1 << \"\\n\";\n    }\n    cout << 0 << \" \" << 0 << \"\\n\";\n\n    // Track grid state\n    vector<vector<int>> has_takoyaki(N, vector<int>(N, 0));\n    vector<vector<int>> is_target(N, vector<int>(N, 0));\n    \n    for (auto& p : starts) has_takoyaki[p.r][p.c] = 1;\n    for (auto& p : targets) is_target[p.r][p.c] = 1;\n\n    int already_correct = 0;\n    for (auto& p : starts) {\n        if (is_target[p.r][p.c]) already_correct++;\n    }\n\n    int need_to_move = starts.size() - already_correct;\n    if (need_to_move == 0) return 0;\n\n    // Precompute target positions for faster lookup\n    vector<Point> empty_targets;\n    for (int tr = 0; tr < N; ++tr) {\n        for (int tc = 0; tc < N; ++tc) {\n            if (is_target[tr][tc]) empty_targets.push_back({tr, tc});\n        }\n    }\n\n    // Simulation State\n    int cur_r = 0, cur_c = 0;\n    int holding_finger = -1;\n    vector<int> finger_dir(V_prime, 0);\n\n    int total_turns = 0;\n    const int MAX_TURNS = 99000;\n    int takoyaki_moved = 0;\n\n    int dr[] = {0, -1, 0, 1};\n    int dc[] = {1, 0, -1, 0};\n\n    while (takoyaki_moved < need_to_move && total_turns < MAX_TURNS - 300) {\n        // Refresh empty targets list\n        empty_targets.clear();\n        for (int tr = 0; tr < N; ++tr) {\n            for (int tc = 0; tc < N; ++tc) {\n                if (is_target[tr][tc] && !has_takoyaki[tr][tc]) {\n                    empty_targets.push_back({tr, tc});\n                }\n            }\n        }\n        \n        if (empty_targets.empty()) break;\n\n        // Find best (pickup, drop) pair - simplified scoring\n        Point pickup_pos = {-1, -1};\n        Point drop_pos = {-1, -1};\n        int best_score = 1e9;\n        \n        int region_size = 5;\n        int cur_region = (cur_r / region_size) * 10 + (cur_c / region_size);\n        \n        // Limit search to first few candidates for speed\n        int candidates_checked = 0;\n        const int MAX_CANDIDATES = 500;\n        \n        for (int r = 0; r < N && candidates_checked < MAX_CANDIDATES; ++r) {\n            for (int c = 0; c < N && candidates_checked < MAX_CANDIDATES; ++c) {\n                if (has_takoyaki[r][c] && !is_target[r][c]) {\n                    Point s = {r, c};\n                    candidates_checked++;\n                    \n                    int pickup_region = (s.r / region_size) * 10 + (s.c / region_size);\n                    int region_penalty = abs(cur_region - pickup_region) * 5;\n                    int d_to_pickup = dist({cur_r, cur_c}, s);\n                    \n                    // Find nearest empty target\n                    Point best_t = {-1, -1};\n                    int best_t_dist = 1e9;\n                    for (const auto& t : empty_targets) {\n                        int d = dist(s, t);\n                        if (d < best_t_dist) {\n                            best_t_dist = d;\n                            best_t = t;\n                        }\n                    }\n                    \n                    if (best_t.r == -1) continue;\n                    \n                    // Simple scoring: distance to pickup + task distance + region penalty\n                    int score = d_to_pickup * 2 + best_t_dist + region_penalty;\n                    \n                    if (score < best_score) {\n                        best_score = score;\n                        pickup_pos = s;\n                        drop_pos = best_t;\n                    }\n                }\n            }\n        }\n        \n        if (pickup_pos.r == -1) break;\n        if (drop_pos.r == -1) break;\n\n        // Use finger 1\n        int finger = 1;\n        if (holding_finger >= 0) continue;\n\n        // === PICKUP PHASE ===\n        int target_dir = -1;\n        for (int d = 0; d < 4; ++d) {\n            Point fp = getFingerPos(cur_r, cur_c, d, 1);\n            if (fp.r == pickup_pos.r && fp.c == pickup_pos.c) {\n                target_dir = d;\n                break;\n            }\n        }\n\n        if (target_dir == -1) {\n            int best_nr = -1, best_nc = -1, min_d = 1e9;\n            for (int d = 0; d < 4; ++d) {\n                int nr = pickup_pos.r - dr[d];\n                int nc = pickup_pos.c - dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int dm = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (dm < min_d) {\n                        min_d = dm;\n                        best_nr = nr;\n                        best_nc = nc;\n                        target_dir = d;\n                    }\n                }\n            }\n            \n            if (best_nr == -1) break;\n\n            while ((cur_r != best_nr || cur_c != best_nc) && total_turns < MAX_TURNS - 200) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                cout << cmd << \"\\n\";\n                total_turns++;\n            }\n        }\n\n        // Rotate finger (minimum rotation)\n        while (finger_dir[finger] != target_dir && total_turns < MAX_TURNS - 200) {\n            string rot_cmd(2 * V_prime, '.');\n            int diff = (target_dir - finger_dir[finger] + 4) % 4;\n            if (diff == 1) { rot_cmd[finger] = 'L'; finger_dir[finger] = (finger_dir[finger] + 1) % 4; }\n            else if (diff == 2) { rot_cmd[finger] = 'L'; finger_dir[finger] = (finger_dir[finger] + 1) % 4; }\n            else if (diff == 3) { rot_cmd[finger] = 'R'; finger_dir[finger] = (finger_dir[finger] + 3) % 4; }\n            cout << rot_cmd << \"\\n\";\n            total_turns++;\n        }\n\n        // Verify and pickup\n        Point finger_pos = getFingerPos(cur_r, cur_c, finger_dir[finger], 1);\n        bool pickup_success = false;\n        if (finger_pos.r >= 0 && finger_pos.r < N && finger_pos.c >= 0 && finger_pos.c < N) {\n            if (finger_pos.r == pickup_pos.r && finger_pos.c == pickup_pos.c) {\n                if (has_takoyaki[finger_pos.r][finger_pos.c]) {\n                    string grab_cmd(2 * V_prime, '.');\n                    grab_cmd[V_prime + finger] = 'P';\n                    cout << grab_cmd << \"\\n\";\n                    total_turns++;\n                    holding_finger = finger;\n                    has_takoyaki[finger_pos.r][finger_pos.c] = 0;\n                    pickup_success = true;\n                }\n            }\n        }\n\n        if (!pickup_success) continue;\n\n        // === DROP PHASE ===\n        target_dir = -1;\n        for (int d = 0; d < 4; ++d) {\n            Point fp = getFingerPos(cur_r, cur_c, d, 1);\n            if (fp.r == drop_pos.r && fp.c == drop_pos.c) {\n                target_dir = d;\n                break;\n            }\n        }\n\n        if (target_dir == -1) {\n            int best_nr = -1, best_nc = -1, min_d = 1e9;\n            for (int d = 0; d < 4; ++d) {\n                int nr = drop_pos.r - dr[d];\n                int nc = drop_pos.c - dc[d];\n                if (nr >= 0 && nr < N && nc >= 0 && nc < N) {\n                    int dm = abs(nr - cur_r) + abs(nc - cur_c);\n                    if (dm < min_d) {\n                        min_d = dm;\n                        best_nr = nr;\n                        best_nc = nc;\n                        target_dir = d;\n                    }\n                }\n            }\n            \n            if (best_nr == -1) {\n                holding_finger = -1;\n                continue;\n            }\n\n            while ((cur_r != best_nr || cur_c != best_nc) && total_turns < MAX_TURNS - 200) {\n                string cmd(2 * V_prime, '.');\n                if (cur_r < best_nr) { cur_r++; cmd[0] = 'D'; }\n                else if (cur_r > best_nr) { cur_r--; cmd[0] = 'U'; }\n                else if (cur_c < best_nc) { cur_c++; cmd[0] = 'R'; }\n                else if (cur_c > best_nc) { cur_c--; cmd[0] = 'L'; }\n                cout << cmd << \"\\n\";\n                total_turns++;\n            }\n        }\n\n        // Rotate to drop direction\n        while (finger_dir[finger] != target_dir && total_turns < MAX_TURNS - 200) {\n            string rot_cmd(2 * V_prime, '.');\n            int diff = (target_dir - finger_dir[finger] + 4) % 4;\n            if (diff == 1) { rot_cmd[finger] = 'L'; finger_dir[finger] = (finger_dir[finger] + 1) % 4; }\n            else if (diff == 2) { rot_cmd[finger] = 'L'; finger_dir[finger] = (finger_dir[finger] + 1) % 4; }\n            else if (diff == 3) { rot_cmd[finger] = 'R'; finger_dir[finger] = (finger_dir[finger] + 3) % 4; }\n            cout << rot_cmd << \"\\n\";\n            total_turns++;\n        }\n\n        // Verify and drop\n        finger_pos = getFingerPos(cur_r, cur_c, finger_dir[finger], 1);\n        bool drop_success = false;\n        if (finger_pos.r >= 0 && finger_pos.r < N && finger_pos.c >= 0 && finger_pos.c < N) {\n            if (finger_pos.r == drop_pos.r && finger_pos.c == drop_pos.c) {\n                if (!has_takoyaki[drop_pos.r][drop_pos.c] && is_target[drop_pos.r][drop_pos.c]) {\n                    string drop_cmd(2 * V_prime, '.');\n                    drop_cmd[V_prime + finger] = 'P';\n                    cout << drop_cmd << \"\\n\";\n                    total_turns++;\n                    holding_finger = -1;\n                    has_takoyaki[drop_pos.r][drop_pos.c] = 1;\n                    drop_success = true;\n                    takoyaki_moved++;\n                }\n            }\n        }\n\n        if (!drop_success) {\n            holding_finger = -1;\n        }\n    }\n\n    return 0;\n}","ahc039":"#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <queue>\n#include <map>\n#include <chrono>\n#include <set>\n#include <random>\n\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    bool operator==(const Point& o) const { return x == o.x && y == o.y; }\n    bool operator!=(const Point& o) const { return !(*this == o); }\n};\n\nstruct Fish {\n    int x, y;\n    int type;\n};\n\nstruct Cluster {\n    vector<int> fish_indices;\n    int min_x, min_y, max_x, max_y;\n    int score;\n};\n\nint N;\nvector<Fish> fish;\n\nint G_SIZE;\nint CELL_SIZE;\nvector<vector<int>> grid_score;\nvector<vector<bool>> selected;\nvector<vector<vector<int>>> grid_fish;\n\nconst int dx[4] = {0, 1, 0, -1};\nconst int dy[4] = {1, 0, -1, 0};\n\nauto start_time = chrono::steady_clock::now();\nconst int TIME_LIMIT_MS = 1950;\n\nbool time_ok() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration_cast<chrono::milliseconds>(now - start_time).count() < TIME_LIMIT_MS;\n}\n\nvoid read_input() {\n    cin >> N;\n    fish.resize(2 * N);\n    for (int i = 0; i < 2 * N; ++i) {\n        cin >> fish[i].x >> fish[i].y;\n        fish[i].type = (i < N) ? 0 : 1;\n    }\n}\n\nvoid build_grid(int G) {\n    G_SIZE = G;\n    CELL_SIZE = 100000 / G;\n    grid_score.assign(G, vector<int>(G, 0));\n    selected.assign(G, vector<bool>(G, false));\n    grid_fish.assign(G, vector<vector<int>>(G));\n\n    for (int i = 0; i < 2 * N; ++i) {\n        int gx = min(fish[i].x / CELL_SIZE, G - 1);\n        int gy = min(fish[i].y / CELL_SIZE, G - 1);\n        grid_fish[gx][gy].push_back(i);\n        if (fish[i].type == 0) grid_score[gx][gy]++;\n        else grid_score[gx][gy]--;\n    }\n}\n\nvoid fill_holes() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    queue<pair<int, int>> q;\n\n    for (int i = 0; i < G_SIZE; ++i) {\n        if (!selected[i][0]) { q.push({i, 0}); visited[i][0] = true; }\n        if (!selected[i][G_SIZE - 1]) { q.push({i, G_SIZE - 1}); visited[i][G_SIZE - 1] = true; }\n        if (!selected[0][i]) { q.push({0, i}); visited[0][i] = true; }\n        if (!selected[G_SIZE - 1][i]) { q.push({G_SIZE - 1, i}); visited[G_SIZE - 1][i] = true; }\n    }\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n            if (nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE) {\n                if (!visited[nx][ny] && !selected[nx][ny]) {\n                    visited[nx][ny] = true;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (!selected[i][j] && !visited[i][j]) {\n                selected[i][j] = true;\n            }\n        }\n    }\n}\n\nvector<vector<pair<int, int>>> get_components() {\n    vector<vector<bool>> visited(G_SIZE, vector<bool>(G_SIZE, false));\n    vector<vector<pair<int, int>>> components;\n    \n    for (int i = 0; i < G_SIZE && time_ok(); ++i) {\n        for (int j = 0; j < G_SIZE && time_ok(); ++j) {\n            if (selected[i][j] && !visited[i][j]) {\n                vector<pair<int, int>> comp;\n                queue<pair<int, int>> q;\n                q.push({i, j});\n                visited[i][j] = true;\n                comp.push_back({i, j});\n                \n                while(!q.empty() && time_ok()){\n                    auto [cx, cy] = q.front(); q.pop();\n                    for(int d=0; d<4; ++d){\n                        int nx = cx + dx[d];\n                        int ny = cy + dy[d];\n                        if(nx >= 0 && nx < G_SIZE && ny >= 0 && ny < G_SIZE){\n                            if(!visited[nx][ny] && selected[nx][ny]){\n                                visited[nx][ny] = true;\n                                q.push({nx, ny});\n                                comp.push_back({nx, ny});\n                            }\n                        }\n                    }\n                }\n                components.push_back(comp);\n            }\n        }\n    }\n    return components;\n}\n\nvoid ensure_connected_topk() {\n    auto components = get_components();\n    if (components.empty()) return;\n    \n    vector<pair<long long, size_t>> comp_scores;\n    for (size_t i = 0; i < components.size(); ++i) {\n        long long s = 0;\n        for (auto [x, y] : components[i]) s += grid_score[x][y];\n        comp_scores.push_back({s, i});\n    }\n    \n    sort(comp_scores.rbegin(), comp_scores.rend());\n    \n    size_t best_idx = comp_scores[0].second;\n    \n    selected.assign(G_SIZE, vector<bool>(G_SIZE, false));\n    for (auto [x, y] : components[best_idx]) {\n        selected[x][y] = true;\n    }\n}\n\nvoid select_positive_cells(int expand_threshold) {\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (grid_score[i][j] > 0) {\n                selected[i][j] = true;\n            }\n        }\n    }\n    \n    for (int iter = 0; iter < 2 && time_ok(); ++iter) {\n        vector<vector<bool>> to_add(G_SIZE, vector<bool>(G_SIZE, false));\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (selected[i][j]) {\n                    for (int d = 0; d < 4; ++d) {\n                        int ni = i + dx[d];\n                        int nj = j + dy[d];\n                        if (ni >= 0 && ni < G_SIZE && nj >= 0 && nj < G_SIZE) {\n                            if (!selected[ni][nj] && grid_score[ni][nj] >= expand_threshold) {\n                                to_add[ni][nj] = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        bool changed = false;\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (to_add[i][j]) {\n                    selected[i][j] = true;\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n    }\n    \n    fill_holes();\n    ensure_connected_topk();\n}\n\nvector<Point> extract_polygon() {\n    map<pair<int, int>, vector<pair<int, int>>> adj;\n    \n    auto add_edge = [&](pair<int, int> p1, pair<int, int> p2) {\n        adj[p1].push_back(p2);\n        adj[p2].push_back(p1);\n    };\n    \n    for (int i = 0; i <= G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            bool left = (i > 0 && selected[i-1][j]);\n            bool right = (i < G_SIZE && selected[i][j]);\n            if (left != right) {\n                int x = i * CELL_SIZE;\n                int y1 = j * CELL_SIZE;\n                int y2 = (j + 1) * CELL_SIZE;\n                add_edge({x, y1}, {x, y2});\n            }\n        }\n    }\n    \n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j <= G_SIZE; ++j) {\n            bool down = (j > 0 && selected[i][j-1]);\n            bool up = (j < G_SIZE && selected[i][j]);\n            if (down != up) {\n                int y = j * CELL_SIZE;\n                int x1 = i * CELL_SIZE;\n                int x2 = (i + 1) * CELL_SIZE;\n                add_edge({x1, y}, {x2, y});\n            }\n        }\n    }\n    \n    if (adj.empty()) return {};\n    \n    pair<int, int> start = {200000, 200000};\n    for (auto& kv : adj) {\n        if (kv.first.second < start.second || (kv.first.second == start.second && kv.first.first < start.first)) {\n            start = kv.first;\n        }\n    }\n    \n    vector<Point> poly;\n    pair<int, int> curr = start;\n    pair<int, int> prev = {-1000000, start.second};\n    \n    while (true) {\n        poly.push_back({curr.first, curr.second});\n        \n        auto& neighbors = adj[curr];\n        if (neighbors.size() != 2) return {};\n        \n        pair<int, int> next = (neighbors[0] == prev) ? neighbors[1] : neighbors[0];\n        \n        if (next == start) break;\n        \n        prev = curr;\n        curr = next;\n        \n        if (poly.size() > 2000) return {};\n    }\n    \n    if (poly.size() <= 4) return poly;\n    \n    vector<Point> simplified;\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        Point p3 = poly[(i + 2) % poly.size()];\n        \n        bool collinear = (p1.x == p2.x && p2.x == p3.x) || (p1.y == p2.y && p2.y == p3.y);\n        \n        if (!collinear || i == 0) {\n            simplified.push_back(p2);\n        }\n    }\n    \n    if (simplified.size() < 4) return poly;\n    return simplified;\n}\n\nlong long grid_score_estimate() {\n    long long total = 0;\n    for (int i = 0; i < G_SIZE; ++i) {\n        for (int j = 0; j < G_SIZE; ++j) {\n            if (selected[i][j]) {\n                total += grid_score[i][j];\n            }\n        }\n    }\n    return total;\n}\n\nbool is_inside(const vector<Point>& poly, int px, int py) {\n    for (size_t i = 0; i < poly.size(); ++i) {\n        Point p1 = poly[i];\n        Point p2 = poly[(i + 1) % poly.size()];\n        if (p1.x == p2.x) {\n            if (px == p1.x && py >= min(p1.y, p2.y) && py <= max(p1.y, p2.y)) return true;\n        } else {\n            if (py == p1.y && px >= min(p1.x, p2.x) && px <= max(p1.x, p2.x)) return true;\n        }\n    }\n    \n    bool inside = false;\n    for (size_t i = 0, j = poly.size() - 1; i < poly.size(); j = i++) {\n        if ((poly[i].y > py) != (poly[j].y > py)) {\n            long long val = (long long)(poly[j].x - poly[i].x) * (long long)(py - poly[i].y);\n            long long denom = (long long)(poly[j].y - poly[i].y);\n            long long rhs = (long long)poly[i].x * denom + val;\n            if (denom > 0) {\n                if ((long long)px * denom < rhs) inside = !inside;\n            } else {\n                if ((long long)px * denom > rhs) inside = !inside;\n            }\n        }\n    }\n    return inside;\n}\n\nlong long calculate_score(const vector<Point>& poly) {\n    long long a = 0, b = 0;\n    for (int i = 0; i < G_SIZE && time_ok(); ++i) {\n        for (int j = 0; j < G_SIZE && time_ok(); ++j) {\n            if (grid_fish[i][j].empty()) continue;\n            \n            int cx = i * CELL_SIZE + CELL_SIZE / 2;\n            int cy = j * CELL_SIZE + CELL_SIZE / 2;\n            \n            if (is_inside(poly, cx, cy)) {\n                for (int fidx : grid_fish[i][j]) {\n                    if (is_inside(poly, fish[fidx].x, fish[fidx].y)) {\n                        if (fish[fidx].type == 0) a++;\n                        else b++;\n                    }\n                }\n            }\n        }\n    }\n    return a - b;\n}\n\nvector<Point> make_rectangle(int x1, int y1, int x2, int y2) {\n    if (x2 <= x1 || y2 <= y1) return {};\n    if (x2 - x1 + y2 - y1 > 400000) return {};\n    return {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n}\n\n// Find best rectangle around a center point with sardine avoidance\nvector<Point> find_best_rectangle_around(int cx, int cy, int max_size) {\n    vector<Point> best_poly;\n    long long best_score = -1e18;\n    \n    for (int w = 1; w <= max_size; w += 2) {\n        for (int h = 1; h <= max_size; h += 2) {\n            for (int ox = -w; ox <= 0; ox += w/2+1) {\n                for (int oy = -h; oy <= 0; oy += h/2+1) {\n                    int x1 = max(0, cx + ox);\n                    int y1 = max(0, cy + oy);\n                    int x2 = min(100000, cx + ox + w * 500);\n                    int y2 = min(100000, cy + oy + h * 500);\n                    \n                    vector<Point> poly = make_rectangle(x1, y1, x2, y2);\n                    if (poly.size() < 4) continue;\n                    \n                    long long score = calculate_score(poly);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_poly = poly;\n                    }\n                }\n            }\n        }\n    }\n    \n    return best_poly;\n}\n\n// Cluster fish by proximity\nvector<Cluster> cluster_fish(int max_dist) {\n    vector<Cluster> clusters;\n    vector<bool> assigned(N, false);\n    \n    for (int i = 0; i < N && time_ok(); ++i) {\n        if (assigned[i]) continue;\n        \n        Cluster c;\n        c.fish_indices.push_back(i);\n        c.min_x = c.max_x = fish[i].x;\n        c.min_y = c.max_y = fish[i].y;\n        assigned[i] = true;\n        \n        for (int j = i + 1; j < N && time_ok(); ++j) {\n            if (assigned[j]) continue;\n            \n            int dist = abs(fish[i].x - fish[j].x) + abs(fish[i].y - fish[j].y);\n            if (dist <= max_dist) {\n                c.fish_indices.push_back(j);\n                c.min_x = min(c.min_x, fish[j].x);\n                c.max_x = max(c.max_x, fish[j].x);\n                c.min_y = min(c.min_y, fish[j].y);\n                c.max_y = max(c.max_y, fish[j].y);\n                assigned[j] = true;\n            }\n        }\n        \n        c.score = c.fish_indices.size();\n        if (c.fish_indices.size() >= 1) {\n            clusters.push_back(c);\n        }\n    }\n    \n    sort(clusters.rbegin(), clusters.rend(), [](const Cluster& a, const Cluster& b) {\n        return a.score > b.score;\n    });\n    \n    return clusters;\n}\n\nvector<Point> build_cluster_polygon(const Cluster& c, int margin) {\n    if (c.fish_indices.empty()) return {};\n    \n    int min_x = max(0, c.min_x - margin);\n    int min_y = max(0, c.min_y - margin);\n    int max_x = min(100000, c.max_x + margin);\n    int max_y = min(100000, c.max_y + margin);\n    \n    if (max_x - min_x + max_y - min_y > 400000) return {};\n    \n    int sardine_count = 0;\n    for (int i = N; i < 2 * N && time_ok(); ++i) {\n        if (fish[i].x >= min_x && fish[i].x <= max_x &&\n            fish[i].y >= min_y && fish[i].y <= max_y) {\n            sardine_count++;\n        }\n    }\n    \n    if ((int)c.fish_indices.size() <= sardine_count) return {};\n    \n    return make_rectangle(min_x, min_y, max_x, max_y);\n}\n\n// Aggressive local search with random restarts\nvector<Point> aggressive_local_search(vector<Point> initial_poly, int iterations) {\n    if (initial_poly.size() < 4) return initial_poly;\n    \n    vector<Point> best_poly = initial_poly;\n    long long best_score = calculate_score(initial_poly);\n    \n    mt19937 rng(42);\n    \n    for (int restart = 0; restart < 5 && time_ok(); ++restart) {\n        vector<Point> poly = initial_poly;\n        long long current_score = best_score;\n        \n        for (int iter = 0; iter < iterations / 5 && time_ok(); ++iter) {\n            vector<Point> new_poly = poly;\n            \n            // Modify 1-2 vertices\n            int num_changes = 1 + (rng() % 2);\n            for (int c = 0; c < num_changes; ++c) {\n                int idx = rng() % poly.size();\n                int delta = 500 + rng() % 2000;\n                int dx = (rng() % 2 == 0) ? delta : -delta;\n                int dy = (rng() % 2 == 0) ? delta : -delta;\n                \n                if (rng() % 2 == 0) {\n                    new_poly[idx].x = max(0, min(100000, new_poly[idx].x + dx));\n                } else {\n                    new_poly[idx].y = max(0, min(100000, new_poly[idx].y + dy));\n                }\n            }\n            \n            // Validate\n            long long perim = 0;\n            bool valid = true;\n            for (size_t i = 0; i < new_poly.size(); ++i) {\n                Point p1 = new_poly[i];\n                Point p2 = new_poly[(i + 1) % new_poly.size()];\n                perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n                if (p1.x == p2.x && p1.y == p2.y) { valid = false; break; }\n            }\n            if (!valid || perim > 400000) continue;\n            \n            long long score = calculate_score(new_poly);\n            if (score >= current_score) {\n                poly = new_poly;\n                current_score = score;\n                if (score > best_score) {\n                    best_score = score;\n                    best_poly = new_poly;\n                }\n            }\n        }\n    }\n    \n    return best_poly;\n}\n\npair<double, double> analyze_distribution() {\n    double mackerel_variance = 0, mackerel_mean_x = 0, mackerel_mean_y = 0;\n    \n    for (int i = 0; i < N; ++i) {\n        mackerel_mean_x += fish[i].x;\n        mackerel_mean_y += fish[i].y;\n    }\n    mackerel_mean_x /= N;\n    mackerel_mean_y /= N;\n    \n    for (int i = 0; i < N; ++i) {\n        mackerel_variance += (fish[i].x - mackerel_mean_x) * (fish[i].x - mackerel_mean_x);\n        mackerel_variance += (fish[i].y - mackerel_mean_y) * (fish[i].y - mackerel_mean_y);\n    }\n    mackerel_variance /= N;\n    \n    return {mackerel_variance, mackerel_mean_x};\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    read_input();\n    \n    auto [variance, mean_x] = analyze_distribution();\n    \n    vector<Point> best_poly;\n    long long best_score = -1e18;\n    long long best_estimate = -1e18;\n    \n    // Grid-based approach\n    vector<int> grids = {10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100, 120, 150, 180, 200, 250, 300};\n    vector<int> thresholds = {-2, -1, 0};\n    \n    for (int G : grids) {\n        if (!time_ok()) break;\n        \n        build_grid(G);\n        \n        for (int thresh : thresholds) {\n            if (!time_ok()) break;\n            \n            select_positive_cells(thresh);\n            \n            vector<Point> poly = extract_polygon();\n            if (poly.empty() || poly.size() < 4 || poly.size() > 1000) continue;\n            \n            long long perim = 0;\n            for (size_t i = 0; i < poly.size(); ++i) {\n                Point p1 = poly[i];\n                Point p2 = poly[(i + 1) % poly.size()];\n                perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n            }\n            if (perim > 400000) continue;\n            \n            long long estimate = grid_score_estimate();\n            \n            if (estimate > best_estimate - 100) {\n                long long score = calculate_score(poly);\n                if (score > best_score) {\n                    best_score = score;\n                    best_estimate = estimate;\n                    best_poly = poly;\n                }\n            }\n        }\n    }\n    \n    // Rectangle search\n    if (time_ok()) {\n        for (int G : {150, 200, 250, 300}) {\n            if (!time_ok()) break;\n            build_grid(G);\n            int CELL = 100000 / G;\n            \n            vector<pair<int, pair<int, int>>> cell_scores;\n            for (int i = 0; i < G_SIZE; ++i) {\n                for (int j = 0; j < G_SIZE; ++j) {\n                    if (grid_score[i][j] > 0) {\n                        cell_scores.push_back({grid_score[i][j], {i, j}});\n                    }\n                }\n            }\n            sort(cell_scores.rbegin(), cell_scores.rend());\n            \n            int max_cells = min(60, (int)cell_scores.size());\n            for (int k = 0; k < max_cells && time_ok(); ++k) {\n                auto [score, pos] = cell_scores[k];\n                auto [gi, gj] = pos;\n                \n                vector<pair<int,int>> sizes = {\n                    {1,1}, {1,2}, {2,1}, {1,3}, {3,1}, {2,2}, {2,3}, {3,2}, {3,3},\n                    {1,4}, {4,1}, {2,4}, {4,2}, {3,4}, {4,3}, {4,4},\n                    {1,5}, {5,1}, {2,5}, {5,2}, {3,5}, {5,3}, {4,5}, {5,4}, {5,5},\n                    {1,6}, {6,1}, {2,6}, {6,2}, {3,6}, {6,3}, {4,6}, {6,4}\n                };\n                \n                for (auto [w, h] : sizes) {\n                    vector<Point> rect = make_rectangle(\n                        gi * CELL, gj * CELL,\n                        min(100000, (gi + w) * CELL), min(100000, (gj + h) * CELL)\n                    );\n                    if (rect.size() < 4) continue;\n                    \n                    long long perim = 0;\n                    for (size_t i = 0; i < rect.size(); ++i) {\n                        Point p1 = rect[i];\n                        Point p2 = rect[(i + 1) % rect.size()];\n                        perim += abs(p1.x - p2.x) + abs(p1.y - p2.y);\n                    }\n                    if (perim > 400000) continue;\n                    \n                    long long rect_score = calculate_score(rect);\n                    if (rect_score > best_score) {\n                        best_score = rect_score;\n                        best_poly = rect;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Fish clustering for scattered distributions\n    if (time_ok()) {\n        for (int max_dist : {3000, 5000, 8000, 10000, 15000}) {\n            if (!time_ok()) break;\n            \n            auto clusters = cluster_fish(max_dist);\n            if (clusters.empty()) continue;\n            \n            for (int k = 0; k < min(15, (int)clusters.size()) && time_ok(); ++k) {\n                for (int margin : {0, 300, 500, 800, 1000, 1500, 2000, 3000, 5000}) {\n                    vector<Point> poly = build_cluster_polygon(clusters[k], margin);\n                    if (poly.size() < 4) continue;\n                    \n                    long long score = calculate_score(poly);\n                    if (score > best_score) {\n                        best_score = score;\n                        best_poly = poly;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Direct fish targeting for very scattered cases\n    if (time_ok() && best_score < 500) {\n        // Target individual high-value mackerel positions\n        vector<pair<int, int>> mackerel_positions;\n        for (int i = 0; i < N && time_ok(); ++i) {\n            // Count nearby sardines\n            int nearby_sardines = 0;\n            for (int j = N; j < 2 * N; ++j) {\n                int dist = abs(fish[i].x - fish[j].x) + abs(fish[i].y - fish[j].y);\n                if (dist < 2000) nearby_sardines++;\n            }\n            \n            if (nearby_sardines <= 2) {\n                mackerel_positions.push_back({fish[i].x, fish[i].y});\n            }\n        }\n        \n        for (auto [mx, my] : mackerel_positions) {\n            for (int size : {500, 1000, 1500, 2000, 3000}) {\n                vector<Point> poly = make_rectangle(\n                    max(0, mx - size/2), max(0, my - size/2),\n                    min(100000, mx + size/2), min(100000, my + size/2)\n                );\n                if (poly.size() < 4) continue;\n                \n                long long score = calculate_score(poly);\n                if (score > best_score) {\n                    best_score = score;\n                    best_poly = poly;\n                }\n            }\n        }\n    }\n    \n    // Aggressive local search for low-scoring cases\n    if (time_ok() && best_poly.size() >= 4 && best_score < 1000) {\n        int iterations = (best_score < 300) ? 200 : 100;\n        vector<Point> optimized = aggressive_local_search(best_poly, iterations);\n        long long new_score = calculate_score(optimized);\n        if (new_score > best_score) {\n            best_score = new_score;\n            best_poly = optimized;\n        }\n    }\n    \n    // Final fallback\n    if (best_poly.empty() || best_poly.size() < 4) {\n        build_grid(100);\n        int best_i = 0, best_j = 0;\n        int best_cell_score = -1e9;\n        for (int i = 0; i < G_SIZE; ++i) {\n            for (int j = 0; j < G_SIZE; ++j) {\n                if (grid_score[i][j] > best_cell_score) {\n                    best_cell_score = grid_score[i][j];\n                    best_i = i;\n                    best_j = j;\n                }\n            }\n        }\n        \n        selected.assign(G_SIZE, vector<bool>(G_SIZE, false));\n        selected[best_i][best_j] = true;\n        fill_holes();\n        best_poly = extract_polygon();\n        if (best_poly.size() < 4) {\n            best_poly = {{0, 0}, {10, 0}, {10, 10}, {0, 10}};\n        }\n    }\n    \n    cout << best_poly.size() << \"\\n\";\n    for (const auto& p : best_poly) {\n        cout << p.x << \" \" << p.y << \"\\n\";\n    }\n    \n    return 0;\n}","ahc040":"#include <iostream>\n#include <vector>\n#include <string>\n#include <random>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n\nusing namespace std;\n\nstruct Rectangle {\n    int id;\n    int w_obs, h_obs;\n};\n\nstruct Placement {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Solution {\n    vector<Placement> placements;\n    int score;\n};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, T;\n    double sigma;\n    cin >> N >> T >> sigma;\n    \n    vector<Rectangle> rects(N);\n    for (int i = 0; i < N; i++) {\n        rects[i].id = i;\n        cin >> rects[i].w_obs >> rects[i].h_obs;\n    }\n    \n    mt19937 rng(42);\n    \n    int best_score = 2000000000;\n    vector<Placement> best_placements;\n    \n    vector<Solution> top_solutions;\n    const int TOP_K = 6;\n    \n    // Calculate properties\n    vector<double> aspect(N);\n    vector<int> area(N);\n    int total_area = 0;\n    for (int i = 0; i < N; i++) {\n        aspect[i] = (double)max(rects[i].w_obs, rects[i].h_obs) / \n                    min(rects[i].w_obs, rects[i].h_obs);\n        area[i] = rects[i].w_obs * rects[i].h_obs;\n        total_area += area[i];\n    }\n    \n    // Sort indices by area for reference (but placement indices stay sequential)\n    vector<int> sorted_by_area(N);\n    iota(sorted_by_area.begin(), sorted_by_area.end(), 0);\n    sort(sorted_by_area.begin(), sorted_by_area.end(), [&](int a, int b) {\n        return area[a] > area[b];\n    });\n    \n    // Rank of each rectangle by area\n    vector<int> area_rank(N);\n    for (int i = 0; i < N; i++) {\n        area_rank[sorted_by_area[i]] = i;\n    }\n    \n    for (int turn = 0; turn < T; turn++) {\n        vector<Placement> placements;\n        placements.reserve(N);\n        \n        double progress = (double)turn / T;\n        double temp = 1.0 - progress;\n        \n        // Strategy selection with clear phases\n        int strategy;\n        if (progress > 0.85) {\n            // Very late: 90% exploit best\n            if (rng() % 10 < 9 && !top_solutions.empty()) {\n                strategy = 100 + (rng() % min((int)top_solutions.size(), 3));\n            } else {\n                strategy = rng() % 15;\n            }\n        } else if (progress > 0.6) {\n            // Late: 70% exploit\n            if (rng() % 10 < 7 && !top_solutions.empty()) {\n                strategy = 100 + (rng() % min((int)top_solutions.size(), 5));\n            } else {\n                strategy = 15 + (rng() % 25);\n            }\n        } else if (progress > 0.3) {\n            // Mid: 40% exploit\n            if (rng() % 5 < 2 && !top_solutions.empty()) {\n                strategy = 100 + (rng() % min((int)top_solutions.size(), 6));\n            } else {\n                strategy = 40 + (rng() % 30);\n            }\n        } else {\n            // Early: 15% exploit\n            if (rng() % 20 < 3 && !top_solutions.empty()) {\n                strategy = 100 + (rng() % min((int)top_solutions.size(), 6));\n            } else {\n                strategy = 70 + (rng() % 30);\n            }\n        }\n        \n        // Generate placement - IMPORTANT: indices must be 0,1,2,...,N-1 in order\n        if (strategy >= 100) {\n            // Exploit: mutate from top solutions\n            int sol_idx = strategy - 100;\n            if (sol_idx < (int)top_solutions.size()) {\n                placements = top_solutions[sol_idx].placements;\n                \n                // Adaptive mutation size\n                int mutations;\n                if (progress > 0.85) {\n                    mutations = max(1, N / 20);\n                } else if (progress > 0.6) {\n                    mutations = max(1, N / 10);\n                } else {\n                    mutations = max(1, N / 5);\n                }\n                mutations = max(1, (int)(mutations * temp));\n                \n                for (int m = 0; m < mutations; m++) {\n                    int idx = rng() % N;\n                    int change = rng() % 4;\n                    \n                    if (change == 0) {\n                        placements[idx].r = 1 - placements[idx].r;\n                    } else if (change == 1) {\n                        placements[idx].d = (placements[idx].d == 'U') ? 'L' : 'U';\n                    } else if (change == 2 && idx > 0) {\n                        placements[idx].b = (placements[idx].b == -1) ? idx - 1 : -1;\n                    } else if (change == 3 && idx > 0) {\n                        swap(placements[idx].r, placements[idx - 1].r);\n                    }\n                }\n            } else {\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, 'U', -1});\n                }\n            }\n        } else if (strategy < 15) {\n            // Basic stacks\n            if (strategy < 2) {\n                char dir = (strategy == 0) ? 'U' : 'L';\n                for (int i = 0; i < N; i++) {\n                    placements.push_back({i, 0, dir, -1});\n                }\n            } else if (strategy < 4) {\n                char dir = (strategy < 3) ? 'U' : 'L';\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    placements.push_back({i, rot, dir, -1});\n                }\n            } else if (strategy < 6) {\n                char dir = (strategy < 5) ? 'U' : 'L';\n                for (int i = 0; i < N; i++) {\n                    int rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                    placements.push_back({i, rot, dir, -1});\n                }\n            } else if (strategy < 8) {\n                for (int i = 0; i < N; i++) {\n                    char dir = (i % 2 == 0) ? 'U' : 'L';\n                    placements.push_back({i, 0, dir, -1});\n                }\n            } else if (strategy < 10) {\n                for (int i = 0; i < N; i++) {\n                    char dir = (i % 2 == 0) ? 'U' : 'L';\n                    int rot = i % 2;\n                    placements.push_back({i, rot, dir, -1});\n                }\n            } else {\n                for (int i = 0; i < N; i++) {\n                    int rot = rng() % 2;\n                    char dir = (rng() % 5 < 4) ? 'U' : 'L';\n                    int ref = -1;\n                    if (i > 0 && rng() % 3 == 0) ref = i - 1;\n                    placements.push_back({i, rot, dir, ref});\n                }\n            }\n        } else if (strategy < 40) {\n            // Shelf packing - main focus\n            int shelf_idx = strategy - 15;\n            int shelf = 2 + shelf_idx % 11;\n            int rot_mode = shelf_idx / 11;\n            \n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                if (rot_mode == 1) {\n                    rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                } else if (rot_mode == 2) {\n                    rot = (rects[i].w_obs > rects[i].h_obs) ? 1 : 0;\n                } else if (rot_mode == 3) {\n                    rot = i % 2;\n                } else if (rot_mode == 4) {\n                    rot = (aspect[i] > 1.5) ? 1 : 0;\n                }\n                \n                char dir = 'U';\n                int ref = -1;\n                if (i > 0 && i % shelf == 0) {\n                    dir = 'L';\n                    ref = i - 1;\n                } else if (i > 0) {\n                    ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy < 55) {\n            // Variable shelf patterns\n            int pat = strategy - 40;\n            \n            for (int i = 0; i < N; i++) {\n                int shelf = 3 + (i / 8) % 5;\n                if (pat >= 5) shelf = 4 + (i / 10) % 4;\n                if (pat >= 10) shelf = 5 + (i / 12) % 3;\n                \n                int rot = 0;\n                if (pat % 5 == 1) rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                else if (pat % 5 == 2) rot = i % 2;\n                else if (pat % 5 == 3) rot = (i / 3) % 2;\n                else if (pat % 5 == 4) rot = (aspect[i] > 1.5) ? 1 : 0;\n                \n                char dir = 'U';\n                int ref = -1;\n                if (i > 0 && i % shelf == 0) {\n                    dir = 'L';\n                    ref = i - 1;\n                } else if (i > 0) {\n                    ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});\n            }\n        } else if (strategy < 70) {\n            // Area-rank based patterns (FIXED: indices still sequential)\n            int pat = strategy - 55;\n            \n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                if (pat % 5 == 1) rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                else if (pat % 5 == 2) rot = (area_rank[i] < N / 2) ? 0 : 1;\n                else if (pat % 5 == 3) rot = (area[i] > total_area / N) ? 1 : 0;\n                else if (pat % 5 == 4) rot = area_rank[i] % 2;\n                \n                int shelf = 4 + pat / 5;\n                char dir = 'U';\n                int ref = -1;\n                if (i > 0 && i % shelf == 0) {\n                    dir = 'L';\n                    ref = i - 1;\n                } else if (i > 0) {\n                    ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});  // FIXED: using i, not sorted_idx\n            }\n        } else {\n            // Compact 2D patterns\n            int pat = strategy - 70;\n            \n            for (int i = 0; i < N; i++) {\n                int rot = 0;\n                char dir = 'U';\n                int ref = -1;\n                \n                if (pat < 5) {\n                    int shelf = 2 + pat;\n                    rot = (i % 3 == 0) ? 1 : 0;\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat < 10) {\n                    int row = i / 5;\n                    int shelf = 5;\n                    rot = (row % 2 == 0) ? 0 : 1;\n                    if (i > 0 && i % shelf == 0) {\n                        dir = (row % 2 == 0) ? 'L' : 'U';\n                        ref = i - 1;\n                    } else if (i > 0) ref = i - 1;\n                } else if (pat < 15) {\n                    int block = i / 6;\n                    dir = (block % 2 == 0) ? 'U' : 'L';\n                    rot = (i % 4 == 0) ? 1 : 0;\n                    if (i > 0 && i % 6 == 0 && dir == 'L') ref = i - 1;\n                    else if (i > 0) ref = i - 1;\n                } else if (pat < 20) {\n                    int layer = i / 8;\n                    int shelf = 4 + layer % 3;\n                    rot = (layer % 2 == 0) ? 0 : 1;\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else if (pat < 25) {\n                    int shelf = (i < N / 2) ? 3 : 6;\n                    rot = (rects[i].h_obs > rects[i].w_obs) ? 1 : 0;\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                } else {\n                    int shelf = 3 + rng() % 5;\n                    rot = rng() % 2;\n                    dir = (rng() % 4 < 3) ? 'U' : 'L';\n                    if (i > 0 && i % shelf == 0) { dir = 'L'; ref = i - 1; }\n                    else if (i > 0) ref = i - 1;\n                }\n                placements.push_back({i, rot, dir, ref});  // Always sequential indices\n            }\n        }\n        \n        // Output\n        cout << N << \"\\n\";\n        for (const auto& p : placements) {\n            cout << p.p << \" \" << p.r << \" \" << p.d << \" \" << p.b << \"\\n\";\n        }\n        cout << flush;\n        \n        // Read result\n        int W_prime, H_prime;\n        cin >> W_prime >> H_prime;\n        \n        int score = W_prime + H_prime;\n        \n        // Update best\n        if (score < best_score) {\n            best_score = score;\n            best_placements = placements;\n        }\n        \n        // Update top-K\n        Solution sol{placements, score};\n        top_solutions.push_back(sol);\n        sort(top_solutions.begin(), top_solutions.end(), \n             [](const Solution& a, const Solution& b) { return a.score < b.score; });\n        if ((int)top_solutions.size() > TOP_K) {\n            top_solutions.resize(TOP_K);\n        }\n    }\n    \n    return 0;\n}","ahc041":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <random>\n#include <chrono>\n#include <cmath>\n#include <algorithm>\n#include <queue>\n\nusing namespace std;\n\n// Global variables\nint N, M, H;\nvector<int> A;\nvector<vector<int>> adj;\nvector<int> L;\nvector<int> support_count;\nint violations = 0;\nlong long current_score = 0;\n\n// Check if v is supported\nbool is_supported(int v) {\n    if (L[v] == 0) return true;\n    return support_count[v] > 0;\n}\n\n// Count violations\nint count_violations() {\n    int cnt = 0;\n    for (int v = 0; v < N; ++v) {\n        if (!is_supported(v)) cnt++;\n    }\n    return cnt;\n}\n\n// Calculate score\nlong long calculate_score() {\n    long long score = 0;\n    for (int v = 0; v < N; ++v) {\n        score += (long long)(L[v] + 1) * A[v];\n    }\n    return score;\n}\n\n// Initialize with BFS from selected roots\nvoid initialize_bfs(mt19937& rng, double root_fraction = 0.1, int strategy = 0) {\n    L.assign(N, -1);\n    support_count.assign(N, 0);\n    \n    vector<pair<double, int>> candidates;\n    for (int v = 0; v < N; ++v) {\n        double score;\n        if (strategy == 0) {\n            score = (double)A[v] * adj[v].size() * (0.5 + uniform_real_distribution<double>(0, 1)(rng));\n        } else if (strategy == 1) {\n            score = (double)A[v] * (0.3 + 0.7 * uniform_real_distribution<double>(0, 1)(rng));\n        } else {\n            score = (double)adj[v].size() * (0.3 + 0.7 * uniform_real_distribution<double>(0, 1)(rng));\n        }\n        candidates.push_back({score, v});\n    }\n    sort(candidates.rbegin(), candidates.rend());\n    \n    int num_roots = max(1, (int)(N * root_fraction));\n    vector<int> roots;\n    for (int i = 0; i < num_roots && i < (int)candidates.size(); ++i) {\n        roots.push_back(candidates[i].second);\n    }\n    \n    queue<int> q;\n    for (int r : roots) {\n        L[r] = 0;\n        q.push(r);\n    }\n    \n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        \n        vector<int> neighbors = adj[v];\n        shuffle(neighbors.begin(), neighbors.end(), rng);\n        \n        for (int u : neighbors) {\n            if (L[u] == -1 && L[v] < H) {\n                L[u] = L[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n    \n    for (int v = 0; v < N; ++v) {\n        if (L[v] == -1) L[v] = 0;\n    }\n    \n    for (int v = 0; v < N; ++v) {\n        if (L[v] > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == L[v] - 1) {\n                    support_count[v]++;\n                }\n            }\n        }\n    }\n    \n    violations = count_violations();\n    current_score = calculate_score();\n}\n\n// Fix violations by reducing levels\nvoid fix_violations(mt19937& rng) {\n    int max_iter = N * 20;\n    for (int iter = 0; iter < max_iter && violations > 0; ++iter) {\n        vector<int> violated;\n        for (int v = 0; v < N; ++v) {\n            if (!is_supported(v)) {\n                violated.push_back(v);\n            }\n        }\n        if (violated.empty()) break;\n        \n        int v = violated[uniform_int_distribution<int>(0, violated.size() - 1)(rng)];\n        \n        if (L[v] > 0) {\n            int old_L = L[v];\n            int new_L = L[v] - 1;\n            \n            for (int u : adj[v]) {\n                if (L[u] == old_L + 1) {\n                    support_count[u]--;\n                }\n                if (L[u] == new_L + 1) {\n                    support_count[u]++;\n                }\n            }\n            \n            support_count[v] = 0;\n            if (new_L > 0) {\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) support_count[v]++;\n                }\n            }\n            \n            L[v] = new_L;\n            current_score -= A[v];\n        }\n    }\n    \n    violations = count_violations();\n}\n\n// Perturbation to escape local optima\nvoid perturb(mt19937& rng, int num_changes = 20) {\n    for (int i = 0; i < num_changes; ++i) {\n        int v = uniform_int_distribution<int>(0, N - 1)(rng);\n        \n        if (L[v] > 0 && L[v] < H) {\n            int delta = uniform_int_distribution<int>(0, 1)(rng) ? 1 : -1;\n            int new_L = L[v] + delta;\n            \n            if (new_L >= 0 && new_L <= H) {\n                int new_support = 0;\n                if (new_L > 0) {\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L - 1) new_support++;\n                    }\n                }\n                \n                if (new_L == 0 || new_support > 0) {\n                    bool can_move = true;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L + 1 && support_count[u] == 1) {\n                            can_move = false;\n                            break;\n                        }\n                    }\n                    \n                    if (can_move) {\n                        int old_L = L[v];\n                        \n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                support_count[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                support_count[u]++;\n                            }\n                        }\n                        \n                        support_count[v] = (new_L > 0) ? new_support : 0;\n                        L[v] = new_L;\n                        current_score += (long long)(new_L - old_L) * A[v];\n                    }\n                }\n            }\n        }\n    }\n    \n    violations = count_violations();\n}\n\n// Aggressive greedy improvement with multiple strategies\nvoid greedy_improve(mt19937& rng, int passes = 45) {\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    \n    bool improved = true;\n    int pass_count = 0;\n    while (improved && pass_count < passes) {\n        improved = false;\n        pass_count++;\n        \n        if (pass_count % 3 == 0) {\n            shuffle(order.begin(), order.end(), rng);\n        } else if (pass_count % 3 == 1) {\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return A[a] > A[b];\n            });\n        } else {\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return A[a] < A[b];\n            });\n        }\n        \n        for (int v : order) {\n            if (L[v] < H) {\n                int new_L = L[v] + 1;\n                \n                int new_support = 0;\n                for (int u : adj[v]) {\n                    if (L[u] == new_L - 1) new_support++;\n                }\n                \n                if (new_support > 0) {\n                    bool can_move = true;\n                    for (int u : adj[v]) {\n                        if (L[u] == new_L + 1 && support_count[u] == 1) {\n                            can_move = false;\n                            break;\n                        }\n                    }\n                    \n                    if (can_move) {\n                        int old_L = L[v];\n                        \n                        for (int u : adj[v]) {\n                            if (L[u] == old_L + 1) {\n                                support_count[u]--;\n                            }\n                            if (L[u] == new_L + 1) {\n                                support_count[u]++;\n                            }\n                        }\n                        \n                        support_count[v] = new_support;\n                        L[v] = new_L;\n                        current_score += A[v];\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\n// Simulated Annealing with penalty-based approach\nvoid simulated_annealing(mt19937& rng, double time_limit) {\n    auto start_time = chrono::steady_clock::now();\n    \n    const long long PENALTY = 1000000000LL;\n    double temp = 135000.0;\n    double initial_temp = 135000.0;\n    int accepted = 0;\n    int total = 0;\n    \n    long long best_valid_score = (violations == 0) ? current_score : -1;\n    vector<int> best_L = (violations == 0) ? L : vector<int>();\n    vector<int> best_support = (violations == 0) ? support_count : vector<int>();\n    \n    int iterations = 0;\n    \n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        double remaining = time_limit - elapsed;\n        \n        if (remaining < 0.03) break;\n        \n        temp = initial_temp * pow(0.9999, iterations);\n        \n        if (total > 200) {\n            double acceptance_rate = (double)accepted / total;\n            if (acceptance_rate > 0.5) {\n                temp *= 0.9997;\n            } else if (acceptance_rate < 0.1) {\n                temp *= 1.0003;\n            }\n        }\n        \n        if (temp < 1.0) temp = 1.0;\n        if (temp > initial_temp * 2) temp = initial_temp * 2;\n        \n        // Select vertex with bias towards high A_v\n        int v;\n        {\n            vector<double> weights(N);\n            double sum_w = 0;\n            for (int i = 0; i < N; ++i) {\n                weights[i] = A[i] + 1;\n                sum_w += weights[i];\n            }\n            double r = uniform_real_distribution<double>(0, sum_w)(rng);\n            double cum = 0;\n            v = N - 1;\n            for (int i = 0; i < N; ++i) {\n                cum += weights[i];\n                if (r <= cum) {\n                    v = i;\n                    break;\n                }\n            }\n        }\n        \n        int delta = 1;\n        double up_prob = 0.75;\n        if (L[v] >= H) up_prob = 0.0;\n        if (uniform_real_distribution<double>(0, 1)(rng) > up_prob) {\n            delta = -1;\n        }\n        \n        int old_L = L[v];\n        int new_L = old_L + delta;\n        \n        if (new_L < 0 || new_L > H) {\n            iterations++;\n            total++;\n            continue;\n        }\n        if (new_L == old_L) {\n            iterations++;\n            total++;\n            continue;\n        }\n        \n        // Calculate delta_violations\n        int delta_violations = 0;\n        \n        bool v_supported_old = is_supported(v);\n        \n        int new_support_count_v = 0;\n        if (new_L > 0) {\n            for (int u : adj[v]) {\n                if (L[u] == new_L - 1) {\n                    new_support_count_v++;\n                }\n            }\n        }\n        bool v_supported_new = (new_L == 0) || (new_support_count_v > 0);\n        \n        if (v_supported_old && !v_supported_new) delta_violations++;\n        if (!v_supported_old && v_supported_new) delta_violations--;\n        \n        vector<pair<int, int>> neighbor_changes;\n        \n        for (int u : adj[v]) {\n            int old_contrib = (L[u] == old_L + 1) ? 1 : 0;\n            int new_contrib = (L[u] == new_L + 1) ? 1 : 0;\n            int delta_sc = new_contrib - old_contrib;\n            \n            if (delta_sc != 0) {\n                bool u_supported_old = (L[u] == 0) || (support_count[u] > 0);\n                int predicted_sc = support_count[u] + delta_sc;\n                bool u_supported_new = (L[u] == 0) || (predicted_sc > 0);\n                \n                int v_delta = 0;\n                if (u_supported_old && !u_supported_new) v_delta = 1;\n                if (!u_supported_old && u_supported_new) v_delta = -1;\n                \n                if (v_delta != 0) {\n                    delta_violations += v_delta;\n                }\n                neighbor_changes.push_back({u, delta_sc});\n            }\n        }\n        \n        long long delta_score = (long long)(new_L - old_L) * A[v];\n        long long delta_cost = (long long)delta_violations * PENALTY - delta_score;\n        \n        bool accept = false;\n        if (delta_cost < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-(double)delta_cost / temp);\n            if ((double)uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            L[v] = new_L;\n            support_count[v] = new_support_count_v;\n            current_score += delta_score;\n            violations += delta_violations;\n            \n            for (auto& nc : neighbor_changes) {\n                support_count[nc.first] += nc.second;\n            }\n            \n            accepted++;\n            \n            if (violations == 0) {\n                if (current_score > best_valid_score) {\n                    best_valid_score = current_score;\n                    best_L = L;\n                    best_support = support_count;\n                }\n            }\n        }\n        \n        total++;\n        iterations++;\n        \n        if (iterations % 5000 == 0) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed >= time_limit) break;\n        }\n    }\n    \n    if (violations == 0 && current_score > best_valid_score) {\n        best_valid_score = current_score;\n        best_L = L;\n        best_support = support_count;\n    }\n    \n    if (!best_L.empty()) {\n        L = best_L;\n        support_count = best_support;\n        violations = 0;\n        current_score = best_valid_score;\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M >> H)) return 0;\n    \n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    \n    adj.resize(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n    \n    // Track top 3 solutions\n    struct Solution {\n        vector<int> L;\n        vector<int> support;\n        long long score;\n    };\n    vector<Solution> top_solutions;\n    \n    auto total_start = chrono::steady_clock::now();\n    double total_time_limit = 1.9;\n    \n    // Proven 6 restarts\n    int num_restarts = 6;\n    double time_per_restart = total_time_limit / num_restarts;\n    \n    for (int restart = 0; restart < num_restarts; ++restart) {\n        mt19937 rng(chrono::steady_clock::now().time_since_epoch().count() + restart * 1000000);\n        \n        // Proven diverse configurations\n        double root_fraction = 0.06 + 0.08 * (restart % 4) / 3.0;\n        int strategy = restart % 3;\n        \n        initialize_bfs(rng, root_fraction, strategy);\n        fix_violations(rng);\n        simulated_annealing(rng, time_per_restart * 0.8);\n        \n        if (violations == 0) {\n            greedy_improve(rng, 45);\n        }\n        \n        if (violations == 0) {\n            Solution sol{L, support_count, current_score};\n            top_solutions.push_back(sol);\n            \n            // Keep top 3\n            sort(top_solutions.begin(), top_solutions.end(), [](const Solution& a, const Solution& b) {\n                return a.score > b.score;\n            });\n            if (top_solutions.size() > 3) {\n                top_solutions.resize(3);\n            }\n        }\n        \n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - total_start).count();\n        if (elapsed >= total_time_limit) break;\n    }\n    \n    // Final optimization on best solution with two perturbation cycles\n    vector<int> best_L_final(N, 0);\n    if (!top_solutions.empty()) {\n        L = top_solutions[0].L;\n        support_count = top_solutions[0].support;\n        violations = 0;\n        current_score = top_solutions[0].score;\n        \n        mt19937 final_rng(chrono::steady_clock::now().time_since_epoch().count());\n        \n        // Two smaller perturbation cycles for more gradual escape from local optima\n        perturb(final_rng, 20);\n        fix_violations(final_rng);\n        greedy_improve(final_rng, 25);\n        \n        perturb(final_rng, 20);\n        fix_violations(final_rng);\n        greedy_improve(final_rng, 25);\n        \n        best_L_final = L;\n    }\n    \n    // Reconstruct parents\n    vector<int> P(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (best_L_final[v] > 0) {\n            int target = best_L_final[v] - 1;\n            for (int u : adj[v]) {\n                if (best_L_final[u] == target) {\n                    P[v] = u;\n                    break;\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        if (i > 0) cout << \" \";\n        cout << P[i];\n    }\n    cout << endl;\n    \n    return 0;\n}","ahc042":"#include <iostream>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <utility>\n#include <random>\n#include <cmath>\n\nusing namespace std;\n\nconst char DIR_CHARS[] = {'U', 'D', 'L', 'R'};\nconst char REVERSE_DIR[] = {'D', 'U', 'R', 'L'};\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<string> grid(N);\n    vector<pair<int, int>> onis;\n    vector<vector<bool>> is_fuku(N, vector<bool>(N, false));\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] == 'x') {\n                onis.push_back({i, j});\n            } else if (grid[i][j] == 'o') {\n                is_fuku[i][j] = true;\n            }\n        }\n    }\n\n    int num_onis = onis.size();\n    vector<vector<int>> oni_id_map(N, vector<int>(N, -1));\n    for (int i = 0; i < num_onis; ++i) {\n        oni_id_map[onis[i].first][onis[i].second] = i;\n    }\n\n    int num_lines = 4 * N;\n    vector<vector<pair<int, int>>> line_onis(num_lines);\n    vector<int> max_k(num_lines, 0);\n\n    // Precompute which Oni each line can remove at each k\n    for (int j = 0; j < N; ++j) {\n        // Col j Up (0)\n        int limit = N;\n        for (int r = 0; r < N; ++r) {\n            if (is_fuku[r][j]) { limit = r; break; }\n        }\n        max_k[0 * N + j] = limit;\n        for (int r = 0; r < limit; ++r) {\n            if (oni_id_map[r][j] != -1) {\n                line_onis[0 * N + j].push_back({r + 1, oni_id_map[r][j]});\n            }\n        }\n\n        // Col j Down (1)\n        limit = N;\n        for (int r = N - 1; r >= 0; --r) {\n            if (is_fuku[r][j]) { limit = N - 1 - r; break; }\n        }\n        max_k[1 * N + j] = limit;\n        for (int r = N - 1; r >= N - limit; --r) {\n            if (oni_id_map[r][j] != -1) {\n                line_onis[1 * N + j].push_back({N - r, oni_id_map[r][j]});\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        // Row i Left (2)\n        int limit = N;\n        for (int c = 0; c < N; ++c) {\n            if (is_fuku[i][c]) { limit = c; break; }\n        }\n        max_k[2 * N + i] = limit;\n        for (int c = 0; c < limit; ++c) {\n            if (oni_id_map[i][c] != -1) {\n                line_onis[2 * N + i].push_back({c + 1, oni_id_map[i][c]});\n            }\n        }\n\n        // Row i Right (3)\n        limit = N;\n        for (int c = N - 1; c >= 0; --c) {\n            if (is_fuku[i][c]) { limit = N - 1 - c; break; }\n        }\n        max_k[3 * N + i] = limit;\n        for (int c = N - 1; c >= N - limit; --c) {\n            if (oni_id_map[i][c] != -1) {\n                line_onis[3 * N + i].push_back({N - c, oni_id_map[i][c]});\n            }\n        }\n    }\n\n    // Sort each line's onis by k\n    for (int l = 0; l < num_lines; ++l) {\n        sort(line_onis[l].begin(), line_onis[l].end());\n    }\n\n    // Count options per Oni\n    vector<int> oni_options(num_onis, 0);\n    for (int l = 0; l < num_lines; ++l) {\n        for (const auto& p : line_onis[l]) {\n            oni_options[p.second]++;\n        }\n    }\n\n    // Function to check coverage\n    auto check_coverage = [&](const vector<int>& k_vals) -> bool {\n        vector<bool> covered(num_onis, false);\n        for (int l = 0; l < num_lines; ++l) {\n            for (const auto& p : line_onis[l]) {\n                if (p.first <= k_vals[l]) {\n                    covered[p.second] = true;\n                }\n            }\n        }\n        for (int i = 0; i < num_onis; ++i) {\n            if (!covered[i]) return false;\n        }\n        return true;\n    };\n\n    // Calculate total cost\n    auto calc_cost = [&](const vector<int>& k_vals) -> int {\n        int cost = 0;\n        for (int l = 0; l < num_lines; ++l) {\n            cost += 2 * k_vals[l];\n        }\n        return cost;\n    };\n\n    // Greedy selection with difficulty weighting and randomization\n    auto run_greedy = [&](mt19937& rng, double weight_power, bool prioritize_hard) -> vector<int> {\n        vector<int> selected_k(num_lines, 0);\n        vector<bool> oni_removed(num_onis, false);\n        int removed_count = 0;\n\n        vector<double> oni_weights(num_onis);\n        for (int i = 0; i < num_onis; ++i) {\n            oni_weights[i] = pow(1.0 / oni_options[i], weight_power);\n        }\n\n        while (removed_count < num_onis) {\n            int best_line = -1;\n            int best_k = -1;\n            double best_score = -1e18;\n\n            vector<int> line_order(num_lines);\n            for (int l = 0; l < num_lines; ++l) line_order[l] = l;\n            shuffle(line_order.begin(), line_order.end(), rng);\n\n            for (int li = 0; li < num_lines; ++li) {\n                int l = line_order[li];\n                for (int try_k = selected_k[l] + 1; try_k <= max_k[l]; ++try_k) {\n                    double weighted_gain = 0;\n                    int gain_count = 0;\n                    double max_weight = 0;\n                    for (const auto& p : line_onis[l]) {\n                        if (p.first <= try_k && p.first > selected_k[l] && !oni_removed[p.second]) {\n                            weighted_gain += oni_weights[p.second];\n                            gain_count++;\n                            max_weight = max(max_weight, oni_weights[p.second]);\n                        }\n                    }\n                    \n                    if (weighted_gain > 0) {\n                        long long cost = 2LL * (try_k - selected_k[l]);\n                        double score = weighted_gain / cost;\n                        if (prioritize_hard) {\n                            score += max_weight * 0.1;\n                        }\n                        score += (rng() % 1000) * 1e-9;\n                        if (score > best_score) {\n                            best_score = score;\n                            best_line = l;\n                            best_k = try_k;\n                        }\n                    }\n                }\n            }\n\n            if (best_line == -1) break;\n\n            for (const auto& p : line_onis[best_line]) {\n                if (p.first <= best_k && !oni_removed[p.second]) {\n                    oni_removed[p.second] = true;\n                    removed_count++;\n                }\n            }\n            selected_k[best_line] = best_k;\n        }\n\n        return selected_k;\n    };\n\n    // Post-processing optimization\n    auto optimize = [&](vector<int>& selected_k) -> void {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            \n            // Try removing each operation entirely\n            for (int l = 0; l < num_lines; ++l) {\n                if (selected_k[l] == 0) continue;\n                \n                int original_k = selected_k[l];\n                selected_k[l] = 0;\n                \n                if (check_coverage(selected_k)) {\n                    improved = true;\n                } else {\n                    selected_k[l] = original_k;\n                }\n            }\n            \n            // Try reducing k values\n            for (int l = 0; l < num_lines; ++l) {\n                if (selected_k[l] == 0) continue;\n                \n                int original_k = selected_k[l];\n                \n                for (int try_k = selected_k[l] - 1; try_k >= 0; --try_k) {\n                    selected_k[l] = try_k;\n                    \n                    if (check_coverage(selected_k)) {\n                        improved = true;\n                        break;\n                    } else {\n                        selected_k[l] = original_k;\n                    }\n                }\n            }\n        }\n    };\n\n    // Enhanced local search\n    auto local_search = [&](vector<int>& selected_k, mt19937& rng) -> void {\n        int best_cost = calc_cost(selected_k);\n        int no_improve_count = 0;\n        \n        for (int iter = 0; iter < 2000 && no_improve_count < 200; ++iter) {\n            bool found_better = false;\n            \n            // Try single line changes\n            for (int trial = 0; trial < 10 && !found_better; ++trial) {\n                int l = rng() % num_lines;\n                int orig_k = selected_k[l];\n                \n                for (int delta = -5; delta <= 5; ++delta) {\n                    if (delta == 0) continue;\n                    int new_k = max(0, min(max_k[l], orig_k + delta));\n                    if (new_k == orig_k) continue;\n                    \n                    selected_k[l] = new_k;\n                    if (check_coverage(selected_k)) {\n                        int new_cost = calc_cost(selected_k);\n                        if (new_cost < best_cost) {\n                            best_cost = new_cost;\n                            found_better = true;\n                            no_improve_count = 0;\n                            break;\n                        }\n                    }\n                    selected_k[l] = orig_k;\n                }\n            }\n            \n            // Try two-line changes\n            if (!found_better) {\n                int l1 = rng() % num_lines;\n                int l2 = rng() % num_lines;\n                if (l1 == l2) continue;\n                \n                int orig_k1 = selected_k[l1];\n                int orig_k2 = selected_k[l2];\n                \n                for (int d1 = -4; d1 <= 4 && !found_better; ++d1) {\n                    for (int d2 = -4; d2 <= 4 && !found_better; ++d2) {\n                        if (d1 == 0 && d2 == 0) continue;\n                        \n                        int new_k1 = max(0, min(max_k[l1], orig_k1 + d1));\n                        int new_k2 = max(0, min(max_k[l2], orig_k2 + d2));\n                        \n                        if (new_k1 == orig_k1 && new_k2 == orig_k2) continue;\n                        \n                        selected_k[l1] = new_k1;\n                        selected_k[l2] = new_k2;\n                        \n                        if (check_coverage(selected_k)) {\n                            int new_cost = calc_cost(selected_k);\n                            if (new_cost < best_cost) {\n                                best_cost = new_cost;\n                                found_better = true;\n                                no_improve_count = 0;\n                            }\n                        }\n                        \n                        if (!found_better) {\n                            selected_k[l1] = orig_k1;\n                            selected_k[l2] = orig_k2;\n                        }\n                    }\n                }\n            }\n            \n            if (!found_better) {\n                no_improve_count++;\n            }\n        }\n    };\n\n    // Run multiple greedy searches with different parameters\n    vector<int> best_k(num_lines, 0);\n    int best_cost = 1e9;\n\n    for (int seed = 0; seed < 8; ++seed) {\n        for (double wp = 0.5; wp <= 2.5; wp += 0.5) {\n            for (bool ph : {false, true}) {\n                mt19937 rng(seed * 1000 + (int)(wp * 100) + (ph ? 500 : 0));\n                \n                vector<int> selected_k = run_greedy(rng, wp, ph);\n                optimize(selected_k);\n                local_search(selected_k, rng);\n                optimize(selected_k);\n                \n                int cost = calc_cost(selected_k);\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best_k = selected_k;\n                }\n            }\n        }\n    }\n\n    // Final cleanup: try to eliminate redundant operations\n    for (int l = 0; l < num_lines; ++l) {\n        if (best_k[l] == 0) continue;\n        \n        int original_k = best_k[l];\n        best_k[l] = 0;\n        \n        if (!check_coverage(best_k)) {\n            best_k[l] = original_k;\n        }\n    }\n\n    // Output moves\n    vector<pair<char, int>> moves;\n    moves.reserve(1600);\n    for (int l = 0; l < num_lines; ++l) {\n        if (best_k[l] > 0) {\n            int dir = l / N;\n            int idx = l % N;\n            char d = DIR_CHARS[dir];\n            char rd = REVERSE_DIR[dir];\n            for (int s = 0; s < best_k[l]; ++s) moves.push_back({d, idx});\n            for (int s = 0; s < best_k[l]; ++s) moves.push_back({rd, idx});\n        }\n    }\n\n    for (const auto& mv : moves) {\n        cout << mv.first << \" \" << mv.second << \"\\n\";\n    }\n\n    return 0;\n}","ahc044":"#include <iostream>\n#include <vector>\n#include <numeric>\n#include <algorithm>\n#include <cmath>\n#include <random>\n#include <chrono>\n#include <queue>\n\nusing namespace std;\n\nint N;\nlong long L;\nvector<int> T;\n\n// Function to simulate the process and calculate error\nlong long simulate(const vector<int>& A, const vector<int>& B, vector<int>& counts) {\n    fill(counts.begin(), counts.end(), 0);\n    int cur = 0;\n    // L weeks\n    for (int k = 0; k < L; ++k) {\n        counts[cur]++;\n        int t = counts[cur];\n        if (t % 2 != 0) {\n            cur = A[cur];\n        } else {\n            cur = B[cur];\n        }\n    }\n    long long error = 0;\n    for (int i = 0; i < N; ++i) {\n        error += abs(counts[i] - T[i]);\n    }\n    return error;\n}\n\n// Check connectivity from node 0 to all nodes with T[i] > 0\nbool is_connected(const vector<int>& A, const vector<int>& B) {\n    vector<bool> visited(N, false);\n    queue<int> q;\n    q.push(0);\n    visited[0] = true;\n    int count = 0;\n    while(!q.empty()){\n        int u = q.front();\n        q.pop();\n        if (T[u] > 0) count++;\n        \n        // Outgoing edges\n        int v1 = A[u];\n        if (!visited[v1]) {\n            visited[v1] = true;\n            q.push(v1);\n        }\n        int v2 = B[u];\n        if (!visited[v2]) {\n            visited[v2] = true;\n            q.push(v2);\n        }\n    }\n    // Check if all important nodes are visited\n    for(int i=0; i<N; ++i){\n        if(T[i] > 0 && !visited[i]) return false;\n    }\n    return true;\n}\n\nvoid fix_connectivity(vector<int>& A, vector<int>& B, vector<long long>& load) {\n    // Repeatedly ensure all T[i]>0 are reachable from 0\n    // We do this by finding an unreachable important node and adding an edge to it from a reachable node\n    // We try to minimize the disturbance to the load balance\n    \n    while (true) {\n        vector<bool> reachable(N, false);\n        queue<int> q;\n        q.push(0);\n        reachable[0] = true;\n        while(!q.empty()){\n            int u = q.front();\n            q.pop();\n            if(!reachable[A[u]]) { reachable[A[u]] = true; q.push(A[u]); }\n            if(!reachable[B[u]]) { reachable[B[u]] = true; q.push(B[u]); }\n        }\n        \n        int target = -1;\n        for(int i=0; i<N; ++i){\n            if(T[i] > 0 && !reachable[i]){\n                target = i;\n                break;\n            }\n        }\n        \n        if(target == -1) break; // All important nodes reachable\n        \n        // Find best edge to redirect to target\n        // We look for a reachable node u, and change one of its outgoing edges to target\n        // We want to minimize increase in |load[dest] - 2*T[dest]|\n        \n        long long min_cost = -1;\n        int best_u = -1;\n        int best_edge = -1; // 0 for A, 1 for B\n        int old_dest = -1;\n        \n        for(int u=0; u<N; ++u){\n            if(!reachable[u]) continue;\n            // Try changing A[u]\n            {\n                int w = A[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 0;\n                    old_dest = w;\n                }\n            }\n            // Try changing B[u]\n            {\n                int w = B[u];\n                long long current_err = abs(load[w] - 2LL * T[w]) + abs(load[target] - 2LL * T[target]);\n                long long new_err = abs(load[w] - T[u] - 2LL * T[w]) + abs(load[target] + T[u] - 2LL * T[target]);\n                long long cost = new_err - current_err;\n                if(min_cost == -1 || cost < min_cost){\n                    min_cost = cost;\n                    best_u = u;\n                    best_edge = 1;\n                    old_dest = w;\n                }\n            }\n        }\n        \n        if(best_u != -1){\n            // Apply change\n            if(best_edge == 0){\n                load[old_dest] -= T[best_u];\n                A[best_u] = target;\n                load[target] += T[best_u];\n            } else {\n                load[old_dest] -= T[best_u];\n                B[best_u] = target;\n                load[target] += T[best_u];\n            }\n        } else {\n            // Should not happen if there is at least one reachable node (0 is reachable)\n            // Fallback: force 0 to point to target\n            int w = A[0];\n            load[w] -= T[0];\n            A[0] = target;\n            load[target] += T[0];\n        }\n    }\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    if (!(cin >> N >> L)) return 0;\n    T.resize(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> T[i];\n    }\n\n    // Initial solution construction using flow balance heuristic\n    // We have 2N items, each (T[i], i). We want to assign them to buckets 0..N-1\n    // such that sum of values in bucket j is close to 2*T[j].\n    \n    vector<pair<int, int>> items;\n    items.reserve(2 * N);\n    for (int i = 0; i < N; ++i) {\n        items.push_back({T[i], i});\n        items.push_back({T[i], i});\n    }\n    \n    // Sort items descending by value\n    sort(items.begin(), items.end(), [](const pair<int,int>& a, const pair<int,int>& b){\n        return a.first > b.first;\n    });\n    \n    vector<long long> load(N, 0);\n    vector<int> A(N), B(N);\n    vector<vector<int>> outgoing(N); // Store assigned destinations for each source\n    \n    for (const auto& item : items) {\n        int val = item.first;\n        int src = item.second;\n        \n        // Find best bucket\n        int best_j = -1;\n        long long min_diff = -1;\n        \n        // To speed up, we can just scan all N. N=100 is small.\n        for (int j = 0; j < N; ++j) {\n            long long diff = abs(load[j] + val - 2LL * T[j]);\n            if (best_j == -1 || diff < min_diff) {\n                min_diff = diff;\n                best_j = j;\n            }\n        }\n        \n        load[best_j] += val;\n        outgoing[src].push_back(best_j);\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        A[i] = outgoing[i][0];\n        B[i] = outgoing[i][1];\n    }\n    \n    // Fix connectivity\n    fix_connectivity(A, B, load);\n    \n    // Evaluate initial score\n    vector<int> counts(N);\n    long long current_score = simulate(A, B, counts);\n    long long best_score = current_score;\n    vector<int> best_A = A;\n    vector<int> best_B = B;\n    \n    // Simulated Annealing\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    \n    auto start_time = chrono::steady_clock::now();\n    double time_limit = 1.9; // seconds\n    \n    double temp = 1000.0;\n    double cooling_rate = 0.9999;\n    \n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > time_limit) break;\n        \n        // Generate neighbor\n        int i = uniform_int_distribution<>(0, N - 1)(rng);\n        int type = uniform_int_distribution<>(0, 1)(rng); // 0 for A, 1 for B\n        int old_val = (type == 0) ? A[i] : B[i];\n        int new_val = uniform_int_distribution<>(0, N - 1)(rng);\n        \n        if (old_val == new_val) continue;\n        \n        // Apply change\n        if (type == 0) A[i] = new_val;\n        else B[i] = new_val;\n        \n        long long new_score = simulate(A, B, counts);\n        \n        double delta = (double)new_score - (double)current_score;\n        bool accept = false;\n        if (delta < 0) {\n            accept = true;\n        } else {\n            double prob = exp(-delta / temp);\n            if (uniform_real_distribution<>(0.0, 1.0)(rng) < prob) {\n                accept = true;\n            }\n        }\n        \n        if (accept) {\n            current_score = new_score;\n            if (current_score < best_score) {\n                best_score = current_score;\n                best_A = A;\n                best_B = B;\n            }\n        } else {\n            // Revert\n            if (type == 0) A[i] = old_val;\n            else B[i] = old_val;\n        }\n        \n        temp *= cooling_rate;\n        iter++;\n    }\n    \n    // Output best solution\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 <iostream>\n#include <vector>\n#include <algorithm>\n#include <cmath>\n#include <numeric>\n#include <set>\n#include <map>\n#include <tuple>\n#include <atcoder/dsu>\n\nusing namespace std;\nusing namespace atcoder;\n\nstruct City {\n    int id;\n    long long cx, cy;\n    int h_index;\n};\n\n// Hilbert curve functions for 2D spatial locality\nvoid rot(int n, int *x, int *y, int rx, int ry) {\n    if (ry == 0) {\n        if (rx == 1) {\n            *x = n - 1 - *x;\n            *y = n - 1 - *y;\n        }\n        std::swap(*x, *y);\n    }\n}\n\nint xy2d(int n, int x, int y) {\n    int rx, ry, s, d = 0;\n    for (s = n / 2; s > 0; s /= 2) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        rot(s, &x, &y, rx, ry);\n    }\n    return d;\n}\n\nstruct Edge {\n    int u, v;\n    long long d2;\n    bool queried;\n    int query_count;\n};\n\nstruct Group {\n    int id;\n    vector<City> cities;\n    vector<pair<int, int>> queried_edges;\n    map<pair<int,int>, int> edge_query_count;\n    int queries_done;\n};\n\nlong long dist2(const City& a, const City& b) {\n    long long dx = a.cx - b.cx;\n    long long dy = a.cy - b.cy;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> G[i];\n    }\n\n    vector<City> cities(N);\n    vector<City> city_by_id(N);\n    const int H_N = 16384;\n\n    for (int i = 0; i < N; ++i) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cities[i].id = i;\n        cities[i].cx = (0LL + lx + rx) / 2;\n        cities[i].cy = (0LL + ly + ry) / 2;\n        cities[i].h_index = xy2d(H_N, (int)cities[i].cx, (int)cities[i].cy);\n        city_by_id[i] = cities[i];\n    }\n\n    // Sort by Hilbert index for spatial locality\n    sort(cities.begin(), cities.end(), [](const City& a, const City& b) {\n        return a.h_index < b.h_index;\n    });\n\n    // Partition into groups\n    vector<Group> groups(M);\n    int cur = 0;\n    for (int i = 0; i < M; ++i) {\n        groups[i].id = i;\n        groups[i].cities.reserve(G[i]);\n        groups[i].queries_done = 0;\n        for (int j = 0; j < G[i] && cur < N; ++j) {\n            groups[i].cities.push_back(cities[cur++]);\n        }\n    }\n\n    int queries_used = 0;\n    const int OVERLAP = 2;\n\n    // Process groups: small groups first (can get exact MST with 1 query)\n    vector<int> group_order(M);\n    iota(group_order.begin(), group_order.end(), 0);\n    sort(group_order.begin(), group_order.end(), [&](int a, int b) {\n        int sa = groups[a].cities.size();\n        int sb = groups[b].cities.size();\n        // Small groups (<=L) first\n        if (sa <= L && sb > L) return true;\n        if (sa > L && sb <= L) return false;\n        // Then larger groups first (need more queries)\n        return sa > sb;\n    });\n\n    // First pass: query all small groups (size <= L)\n    for (int idx : group_order) {\n        if (queries_used >= Q) break;\n        \n        Group& g = groups[idx];\n        int S = g.cities.size();\n        \n        if (S <= 1 || S > L) continue;\n\n        // Sort cities in group by Hilbert index\n        sort(g.cities.begin(), g.cities.end(), [](const City& a, const City& b) {\n            return a.h_index < b.h_index;\n        });\n\n        vector<int> chunk_ids;\n        chunk_ids.reserve(S);\n        for (const auto& c : g.cities) {\n            chunk_ids.push_back(c.id);\n        }\n\n        cout << \"? \" << S;\n        for (int id : chunk_ids) cout << \" \" << id;\n        cout << \"\\n\";\n        cout.flush();\n\n        for (int i = 0; i < S - 1; ++i) {\n            int u, v;\n            cin >> u >> v;\n            if (u > v) swap(u, v);\n            g.queried_edges.push_back({u, v});\n            g.edge_query_count[{u, v}]++;\n        }\n        queries_used++;\n        g.queries_done++;\n    }\n\n    // Second pass: distribute remaining queries to large groups\n    int remaining_queries = Q - queries_used;\n    \n    // Calculate queries needed for each large group\n    vector<pair<int, int>> large_group_queries;\n    for (int idx : group_order) {\n        int S = groups[idx].cities.size();\n        if (S <= L) continue;\n        \n        int step = L - OVERLAP;\n        if (step < 1) step = 1;\n        int queries_needed = (S - 1 + step - 1) / step;\n        \n        large_group_queries.push_back({idx, queries_needed});\n    }\n    \n    // Allocate queries proportionally to group size\n    int total_needed = 0;\n    for (auto& p : large_group_queries) {\n        total_needed += p.second;\n    }\n    \n    vector<int> queries_allocated(M, 0);\n    int allocated = 0;\n    \n    if (total_needed > 0 && remaining_queries > 0) {\n        for (auto& p : large_group_queries) {\n            if (allocated >= remaining_queries) break;\n            int idx = p.first;\n            int S = groups[idx].cities.size();\n            int share = (S * remaining_queries) / N;\n            if (share == 0 && remaining_queries - allocated > 0) share = 1;\n            share = min(share, p.second);\n            queries_allocated[idx] = share;\n            allocated += share;\n        }\n    }\n    \n    // Distribute any remaining queries to largest groups first\n    for (auto& p : large_group_queries) {\n        if (allocated >= remaining_queries) break;\n        if (queries_allocated[p.first] < p.second) {\n            queries_allocated[p.first]++;\n            allocated++;\n        }\n    }\n    \n    // Execute queries for large groups\n    for (int idx : group_order) {\n        if (queries_used >= Q) break;\n        \n        Group& g = groups[idx];\n        int S = g.cities.size();\n        if (S <= L) continue;\n        \n        int num_queries = queries_allocated[idx];\n        if (num_queries <= 0) continue;\n        \n        // Sort cities in group by Hilbert index\n        sort(g.cities.begin(), g.cities.end(), [](const City& a, const City& b) {\n            return a.h_index < b.h_index;\n        });\n        \n        int step = L - OVERLAP;\n        if (step < 1) step = 1;\n        \n        int queries_to_exec = min(num_queries, (S - 1 + step - 1) / step);\n        \n        for (int q = 0; q < queries_to_exec && queries_used < Q; ++q) {\n            int start = q * step;\n            if (start >= S) break;\n            \n            int end = start + L;\n            if (end > S) end = S;\n            \n            if (end - start < 2) {\n                if (start > 0) {\n                    start = max(0, end - 2);\n                } else {\n                    break;\n                }\n            }\n            \n            if (end - start < 2) break;\n            \n            vector<int> chunk_ids;\n            chunk_ids.reserve(end - start);\n            for(int i = start; i < end; ++i) {\n                chunk_ids.push_back(g.cities[i].id);\n            }\n\n            cout << \"? \" << chunk_ids.size();\n            for (int id : chunk_ids) cout << \" \" << id;\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n            g.queries_done++;\n\n            int num_ret = chunk_ids.size() - 1;\n            for (int i = 0; i < num_ret; ++i) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                g.queried_edges.push_back({u, v});\n                g.edge_query_count[{u, v}]++;\n            }\n            \n            if (end == S) break;\n        }\n    }\n\n    // Third pass: use ALL remaining queries on largest groups\n    // Continue sliding window from where we left off\n    for (int idx : group_order) {\n        if (queries_used >= Q) break;\n        \n        Group& g = groups[idx];\n        int S = g.cities.size();\n        if (S <= L) continue;\n        \n        int step = L - OVERLAP;\n        if (step < 1) step = 1;\n        int queries_needed = (S - 1 + step - 1) / step;\n        int queries_done = queries_allocated[idx];\n        \n        // Continue from where we left off\n        for (int q = queries_done; q < queries_needed && queries_used < Q; ++q) {\n            int start = q * step;\n            if (start >= S) break;\n            \n            int end = start + L;\n            if (end > S) end = S;\n            \n            if (end - start < 2) {\n                if (start > 0) {\n                    start = max(0, end - 2);\n                } else {\n                    break;\n                }\n            }\n            \n            if (end - start < 2) break;\n            \n            vector<int> chunk_ids;\n            chunk_ids.reserve(end - start);\n            for(int i = start; i < end; ++i) {\n                chunk_ids.push_back(g.cities[i].id);\n            }\n\n            cout << \"? \" << chunk_ids.size();\n            for (int id : chunk_ids) cout << \" \" << id;\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n            g.queries_done++;\n\n            int num_ret = chunk_ids.size() - 1;\n            for (int i = 0; i < num_ret; ++i) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                g.queried_edges.push_back({u, v});\n                g.edge_query_count[{u, v}]++;\n            }\n            \n            if (end == S) break;\n        }\n    }\n\n    // Fourth pass: use any remaining queries on largest groups (simple loop)\n    // This ensures we use all Q queries\n    int pass = 0;\n    while (queries_used < Q && pass < 3) {\n        for (int idx : group_order) {\n            if (queries_used >= Q) break;\n            \n            Group& g = groups[idx];\n            int S = g.cities.size();\n            if (S <= L) continue;\n            \n            int step = L - OVERLAP;\n            if (step < 1) step = 1;\n            \n            // Try different starting offsets\n            int start = (pass * step / 3) % step;\n            int end = min(S, start + L);\n            \n            if (end - start < 2) continue;\n            \n            vector<int> chunk_ids;\n            chunk_ids.reserve(end - start);\n            for(int i = start; i < end; ++i) {\n                chunk_ids.push_back(g.cities[i].id);\n            }\n\n            cout << \"? \" << chunk_ids.size();\n            for (int id : chunk_ids) cout << \" \" << id;\n            cout << \"\\n\";\n            cout.flush();\n            queries_used++;\n            g.queries_done++;\n\n            int num_ret = chunk_ids.size() - 1;\n            for (int i = 0; i < num_ret; ++i) {\n                int u, v;\n                cin >> u >> v;\n                if (u > v) swap(u, v);\n                g.queried_edges.push_back({u, v});\n                g.edge_query_count[{u, v}]++;\n            }\n        }\n        pass++;\n    }\n\n    // Output final answer\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        const Group& g = groups[i];\n        int S = g.cities.size();\n        \n        // Output cities\n        for (int j = 0; j < S; ++j) {\n            if (j > 0) cout << \" \";\n            cout << g.cities[j].id;\n        }\n        cout << \"\\n\";\n\n        if (S <= 1) continue;\n\n        // Build edge pool - use complete graph within group\n        vector<Edge> pool;\n        pool.reserve(S * (S - 1) / 2 + g.queried_edges.size());\n        \n        set<pair<int,int>> q_set(g.queried_edges.begin(), g.queried_edges.end());\n\n        // Add queried edges with high priority\n        for (const auto& p : g.queried_edges) {\n            const City& c1 = city_by_id[p.first];\n            const City& c2 = city_by_id[p.second];\n            int count = 1;\n            auto it = g.edge_query_count.find(p);\n            if (it != g.edge_query_count.end()) {\n                count = it->second;\n            }\n            pool.push_back({p.first, p.second, dist2(c1, c2), true, count});\n        }\n\n        // Add all estimated edges (complete graph within group), sorted by distance\n        vector<tuple<long long, int, int>> estimated_edges;\n        estimated_edges.reserve(S * (S - 1) / 2);\n        for (int j = 0; j < S; ++j) {\n            for (int k = j + 1; k < S; ++k) {\n                int u = g.cities[j].id;\n                int v = g.cities[k].id;\n                if (u > v) swap(u, v);\n                if (q_set.count({u, v})) continue;\n                estimated_edges.push_back({dist2(g.cities[j], g.cities[k]), u, v});\n            }\n        }\n        sort(estimated_edges.begin(), estimated_edges.end());\n        \n        for (auto& [d2, u, v] : estimated_edges) {\n            pool.push_back({u, v, d2, false, 0});\n        }\n\n        // Sort: queried first, then by query count, then by distance, then lexicographic\n        sort(pool.begin(), pool.end(), [](const Edge& a, const Edge& b) {\n            if (a.queried != b.queried) return a.queried > b.queried;\n            if (a.query_count != b.query_count) return a.query_count > b.query_count;\n            if (a.d2 != b.d2) return a.d2 < b.d2;\n            if (a.u != b.u) return a.u < b.u;\n            return a.v < b.v;\n        });\n\n        // Kruskal's algorithm\n        dsu group_dsu(N);\n        int count = 0;\n        for (const auto& e : pool) {\n            if (group_dsu.same(e.u, e.v)) continue;\n            group_dsu.merge(e.u, e.v);\n            cout << e.u << \" \" << e.v << \"\\n\";\n            count++;\n            if (count == S - 1) break;\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <iostream>\n#include <vector>\n#include <string>\n#include <queue>\n#include <tuple>\n#include <algorithm>\n#include <cstring>\n\nusing namespace std;\n\nstruct Action {\n    char type;\n    char dir;\n};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& other) const {\n        return r == other.r && c == other.c;\n    }\n    bool operator!=(const Pos& other) const {\n        return !(*this == other);\n    }\n};\n\nint N, M;\nbool has_block[20][20];\nint dist_map[20][20];\nPos parent_pos[20][20];\nAction parent_act[20][20];\n\nconst int INF = 1e9;\nconst int dr[] = {-1, 1, 0, 0};\nconst int dc[] = {0, 0, -1, 1};\nconst char dir_char[] = {'U', 'D', 'L', 'R'};\n\nbool is_valid(int r, int c) {\n    return r >= 0 && r < N && c >= 0 && c < N;\n}\n\n// BFS to find shortest path from start to end\nint bfs(Pos start, Pos end, bool store_path) {\n    for(int i = 0; i < N; ++i) \n        for(int j = 0; j < N; ++j) \n            dist_map[i][j] = INF;\n    \n    queue<Pos> q;\n    dist_map[start.r][start.c] = 0;\n    q.push(start);\n    \n    while(!q.empty()) {\n        Pos curr = q.front();\n        q.pop();\n        \n        if (curr == end) return dist_map[curr.r][curr.c];\n        \n        int d = dist_map[curr.r][curr.c];\n        \n        // Try Move actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r + dr[i];\n            int nc = curr.c + dc[i];\n            if(is_valid(nr, nc) && !has_block[nr][nc]) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'M', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n        \n        // Try Slide actions\n        for(int i = 0; i < 4; ++i) {\n            int nr = curr.r;\n            int nc = curr.c;\n            while(true) {\n                int nnr = nr + dr[i];\n                int nnc = nc + dc[i];\n                if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                    break;\n                }\n                nr = nnr;\n                nc = nnc;\n            }\n            if(nr != curr.r || nc != curr.c) {\n                if(dist_map[nr][nc] == INF) {\n                    dist_map[nr][nc] = d + 1;\n                    if(store_path) {\n                        parent_pos[nr][nc] = curr;\n                        parent_act[nr][nc] = {'S', dir_char[i]};\n                    }\n                    q.push({nr, nc});\n                }\n            }\n        }\n    }\n    return INF;\n}\n\nvector<Action> get_path(Pos end) {\n    vector<Action> path;\n    Pos curr = end;\n    while(dist_map[curr.r][curr.c] != 0) {\n        path.push_back(parent_act[curr.r][curr.c]);\n        curr = parent_pos[curr.r][curr.c];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// Simulate actions and update position and block state\nPos simulate_action(Pos curr, const Action& act, bool update_blocks = false) {\n    if(act.type == 'M') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r + dr[i];\n                int nc = curr.c + dc[i];\n                // Safety check - should never happen if BFS is correct\n                if(!is_valid(nr, nc) || has_block[nr][nc]) {\n                    cerr << \"ERROR: Invalid move at (\" << curr.r << \",\" << curr.c \n                         << \") direction \" << act.dir << endl;\n                    return curr;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'S') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int nr = curr.r;\n                int nc = curr.c;\n                while(true) {\n                    int nnr = nr + dr[i];\n                    int nnc = nc + dc[i];\n                    if(!is_valid(nnr, nnc) || has_block[nnr][nnc]) {\n                        break;\n                    }\n                    nr = nnr;\n                    nc = nnc;\n                }\n                return {nr, nc};\n            }\n        }\n    } else if(act.type == 'A') {\n        for(int i = 0; i < 4; ++i) {\n            if(dir_char[i] == act.dir) {\n                int br = curr.r + dr[i];\n                int bc = curr.c + dc[i];\n                if(is_valid(br, bc)) {\n                    if(update_blocks) {\n                        has_block[br][bc] = !has_block[br][bc];\n                    }\n                }\n                return curr;\n            }\n        }\n    }\n    return curr;\n}\n\nint main() {\n    ios_base::sync_with_stdio(false);\n    cin.tie(NULL);\n    \n    if (!(cin >> N >> M)) return 0;\n    \n    vector<Pos> points(M);\n    for(int i = 0; i < M; ++i) {\n        cin >> points[i].r >> points[i].c;\n    }\n    \n    // Initialize blocks\n    memset(has_block, 0, sizeof(has_block));\n    \n    Pos curr = points[0];\n    vector<Action> all_actions;\n    \n    for(int k = 0; k < M - 1; ++k) {\n        Pos target = points[k+1];\n        \n        // Get base path without adding blocks\n        int base_dist = bfs(curr, target, true);\n        vector<Action> base_path = get_path(target);\n        \n        int best_dist = base_dist;\n        vector<Action> best_path = base_path;\n        Pos best_S = {-1, -1};\n        Pos best_adj = {-1, -1};\n        int best_dir = -1;\n        \n        // Only try adding blocks if base path is long enough to justify it\n        if(base_dist > 3) {\n            // Candidate block positions around target\n            vector<Pos> candidates;\n            for(int i = 0; i < 4; ++i) {\n                int sr = target.r + dr[i];\n                int sc = target.c + dc[i];\n                if(is_valid(sr, sc) && !has_block[sr][sc] && !(sr == curr.r && sc == curr.c)) {\n                    candidates.push_back({sr, sc});\n                }\n            }\n            \n            for(const auto& S : candidates) {\n                // Try placing block from each adjacent cell\n                for(int i = 0; i < 4; ++i) {\n                    int ar = S.r + dr[i];\n                    int ac = S.c + dc[i];\n                    if(!is_valid(ar, ac) || has_block[ar][ac]) continue;\n                    if(ar == S.r && ac == S.c) continue;\n                    \n                    // Cost to reach adjacent cell\n                    int d1 = bfs(curr, {ar, ac}, false);\n                    if(d1 == INF || d1 > best_dist) continue;\n                    \n                    // Temporarily place block\n                    has_block[S.r][S.c] = true;\n                    \n                    // Cost to reach target from adjacent cell\n                    int d2 = bfs({ar, ac}, target, false);\n                    \n                    // Remove block\n                    has_block[S.r][S.c] = false;\n                    \n                    if(d2 == INF) continue;\n                    \n                    int total = d1 + 1 + d2;\n                    \n                    if(total < best_dist) {\n                        best_dist = total;\n                        best_S = S;\n                        best_adj = {ar, ac};\n                        best_dir = i;\n                    }\n                }\n            }\n        }\n        \n        // Execute the best plan\n        if(best_S.r != -1) {\n            // 1. Move to best_adj\n            bfs(curr, best_adj, true);\n            vector<Action> p1 = get_path(best_adj);\n            \n            // Validate path before adding\n            Pos temp = curr;\n            for(const auto& act : p1) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p1.begin(), p1.end());\n            curr = best_adj;\n            \n            // 2. Alter (Place block)\n            all_actions.push_back({'A', dir_char[best_dir]});\n            has_block[best_S.r][best_S.c] = true;\n            \n            // 3. Move to target\n            bfs(curr, target, true);\n            vector<Action> p2 = get_path(target);\n            \n            // Validate path before adding\n            temp = curr;\n            for(const auto& act : p2) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), p2.begin(), p2.end());\n            curr = target;\n        } else {\n            // Execute base plan\n            // Validate path\n            Pos temp = curr;\n            for(const auto& act : base_path) {\n                temp = simulate_action(temp, act, false);\n            }\n            \n            all_actions.insert(all_actions.end(), base_path.begin(), base_path.end());\n            curr = target;\n        }\n    }\n    \n    // Final validation of all actions\n    Pos validate_pos = points[0];\n    for(const auto& act : all_actions) {\n        validate_pos = simulate_action(validate_pos, act, true);\n    }\n    \n    // Output all actions\n    for(const auto& act : all_actions) {\n        cout << act.type << \" \" << act.dir << \"\\n\";\n    }\n    \n    return 0;\n}"}}}