Submission #1246587

#TimeUsernameProblemLanguageResultExecution timeMemory
1246587aykhn게임 (IOI13_game)C++20
10 / 100
448 ms321536 KiB
#include "game.h"
#include <bits/stdc++.h>
using namespace std;

// We’ll use std::gcd on long long
// (C++17 <numeric> is included via <bits/stdc++.h>)

struct NodeY {
    long long val = 0;
    NodeY *l = nullptr, *r = nullptr;
};

struct NodeX {
    NodeX *l = nullptr, *r = nullptr;
    NodeY *treeY = nullptr;
};

int n, m;
NodeX* root = nullptr;

// Merge two Y‑trees over [ly, ry], return a newly built tree
NodeY* mergeY(NodeY* A, NodeY* B, int ly, int ry) {
    if (!A && !B) return nullptr;
    NodeY* node = new NodeY();
    if (ly == ry) {
        long long va = A ? A->val : 0;
        long long vb = B ? B->val : 0;
        node->val = std::gcd(va, vb);
        return node;
    }
    int my = (ly + ry) >> 1;
    node->l = mergeY(A ? A->l : nullptr, B ? B->l : nullptr, ly, my);
    node->r = mergeY(A ? A->r : nullptr, B ? B->r : nullptr, my+1, ry);
    long long vl = node->l ? node->l->val : 0;
    long long vr = node->r ? node->r->val : 0;
    node->val = std::gcd(vl, vr);
    return node;
}

// Point‐set update on Y‑tree at fixed X‑node
void updateY(NodeY*& node, int ly, int ry, int y, long long v) {
    if (!node) node = new NodeY();
    if (ly == ry) {
        node->val = v;
        return;
    }
    int my = (ly + ry) >> 1;
    if (y <= my) updateY(node->l, ly, my, y, v);
    else          updateY(node->r, my+1, ry, y, v);
    long long vl = node->l ? node->l->val : 0;
    long long vr = node->r ? node->r->val : 0;
    node->val = std::gcd(vl, vr);
}

// Update X‑tree: set a[x][y]=v
void updateX(NodeX*& node, int lx, int rx, int x, int y, long long v) {
    if (!node) node = new NodeX();
    if (lx == rx) {
        // leaf in X: just update its Y‑tree
        updateY(node->treeY, 0, m-1, y, v);
        return;
    }
    int mx = (lx + rx) >> 1;
    if (x <= mx) updateX(node->l, lx, mx, x, y, v);
    else         updateX(node->r, mx+1, rx, x, y, v);
    // after children are updated, merge their Y‑trees
    node->treeY = mergeY(
        node->l ? node->l->treeY : nullptr,
        node->r ? node->r->treeY : nullptr,
        0, m-1
    );
}

// GCD query on a single Y‑tree
long long queryY(NodeY* node, int ly, int ry, int y1, int y2) {
    if (!node || ry < y1 || ly > y2) return 0;
    if (y1 <= ly && ry <= y2) return node->val;
    int my = (ly + ry) >> 1;
    return std::gcd(
        queryY(node->l, ly, my, y1, y2),
        queryY(node->r, my+1, ry, y1, y2)
    );
}

// Submatrix GCD query on [x1,x2]×[y1,y2]
long long queryX(NodeX* node, int lx, int rx,
                 int x1, int x2, int y1, int y2) {
    if (!node || rx < x1 || lx > x2) return 0;
    if (x1 <= lx && rx <= x2) {
        // fully covered in X → query its Y‑tree
        return queryY(node->treeY, 0, m-1, y1, y2);
    }
    int mx = (lx + rx) >> 1;
    return std::gcd(
        queryX(node->l, lx, mx, x1, x2, y1, y2),
        queryX(node->r, mx+1, rx, x1, x2, y1, y2)
    );
}

// game.h interface
void init(int R, int C) {
    n = R;
    m = C;
    root = nullptr;
}

void update(int P, int Q, long long K) {
    // set a[P][Q] = K
    updateX(root, 0, n-1, P, Q, K);
}

long long calculate(int P, int Q, int U, int V) {
    // query GCD on [P..U]×[Q..V]
    return queryX(root, 0, n-1, P, U, Q, V);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...