Submission #1306873

#TimeUsernameProblemLanguageResultExecution timeMemory
1306873orzorzorzGame (IOI13_game)C++20
80 / 100
3808 ms199696 KiB
#include "game.h"
#include <algorithm>

using namespace std;

typedef long long ll;

// 題目提供的 GCD 函數
long long gcd2(long long X, long long Y) {
    long long tmp;
    while (X != Y && Y != 0) {
        tmp = X;
        X = Y;
        Y = tmp % Y;
    }
    return X;
}

// ---------------------------------------------------------
// 內層線段樹 (Y軸 - 列 Columns)
// ---------------------------------------------------------
struct NodeY {
    int left_child;
    int right_child;
    ll val; // 儲存區間 GCD
};

// 記憶體池:內層節點數量龐大,需要開大一點
const int MAX_NODES_Y = 250000*50; 
NodeY treeY[MAX_NODES_Y];
int ptrY = 1; // 0 保留給空節點 (NULL)

int get_nodeY() {
    return ptrY++;
}

// 內層:更新位置 pos 的值為 k
void updateY(int &node, int l, int r, int pos, ll k) {
    if (!node) node = get_nodeY();
    
    if (l == r) {
        treeY[node].val = k;
        return;
    }
    
    int mid = l + (r - l) / 2;
    if (pos <= mid) updateY(treeY[node].left_child, l, mid, pos, k);
    else updateY(treeY[node].right_child, mid + 1, r, pos, k);
    
    treeY[node].val = gcd2(treeY[treeY[node].left_child].val, 
                           treeY[treeY[node].right_child].val);
}

// 內層:查詢區間 [ql, qr] 的 GCD
ll queryY(int node, int l, int r, int ql, int qr) {
    if (!node || l > qr || r < ql) return 0;
    if (ql <= l && r <= qr) return treeY[node].val;
    
    int mid = l + (r - l) / 2;
    return gcd2(queryY(treeY[node].left_child, l, mid, ql, qr),
                queryY(treeY[node].right_child, mid + 1, r, ql, qr));
}

// ---------------------------------------------------------
// 外層線段樹 (X軸 - 行 Rows)
// ---------------------------------------------------------
struct NodeX {
    int left_child;
    int right_child;
    int rootY; // 指向內層線段樹的根
};

// 外層節點數量較少 (N_U * log R)
const int MAX_NODES_X = 250000*50; 
NodeX treeX[MAX_NODES_X];
int ptrX = 1;
int rootX = 0;

int R_MAX, C_MAX;

// 輔助:從某個內層樹查詢單點 val (用來合併外層節點)
ll get_val_at_col(int inner_root, int col) {
    return queryY(inner_root, 0, C_MAX - 1, col, col);
}

// 外層:更新 (P, Q) 為 K
void updateX(int &node, int l, int r, int P, int Q, ll K) {
    if (!node) {
        node = ptrX++;
        treeX[node].rootY = 0; // 初始內層樹為空
    }
    
    // 1. 如果是葉子節點 (特定的行 P)
    if (l == r) {
        // 直接在內層樹更新列 Q
        updateY(treeX[node].rootY, 0, C_MAX - 1, Q, K);
        return;
    }
    
    int mid = l + (r - l) / 2;
    if (P <= mid) updateX(treeX[node].left_child, l, mid, P, Q, K);
    else updateX(treeX[node].right_child, mid + 1, r, P, Q, K);
    
    // 2. 如果是內部節點 (行區間)
    // 我們需要在這個節點的「內層樹」中,更新列 Q 的值。
    // 這個值應該是:GCD(左子樹在Q的值, 右子樹在Q的值)
    
    ll val_left = 0, val_right = 0;
    if (treeX[node].left_child) 
        val_left = get_val_at_col(treeX[treeX[node].left_child].rootY, Q);
    
    if (treeX[node].right_child)
        val_right = get_val_at_col(treeX[treeX[node].right_child].rootY, Q);
        
    ll new_gcd = gcd2(val_left, val_right);
    
    // 更新當前外層節點的內層樹
    updateY(treeX[node].rootY, 0, C_MAX - 1, Q, new_gcd);
}

// 外層:查詢矩形
ll queryX(int node, int l, int r, int P, int Q, int U, int V) {
    if (!node || l > U || r < P) return 0;
    
    // 如果行範圍完全被包含
    if (P <= l && r <= U) {
        // 直接查詢該節點的內層樹 (列範圍 Q~V)
        return queryY(treeX[node].rootY, 0, C_MAX - 1, Q, V);
    }
    
    int mid = l + (r - l) / 2;
    return gcd2(queryX(treeX[node].left_child, l, mid, P, Q, U, V),
                queryX(treeX[node].right_child, mid + 1, r, P, Q, U, V));
}

// ---------------------------------------------------------
// 介面實作
// ---------------------------------------------------------

void init(int R, int C) {
    R_MAX = R;
    C_MAX = C;
    ptrX = 1;
    ptrY = 1;
    rootX = 0;
}

void update(int P, int Q, long long K) {
    updateX(rootX, 0, R_MAX - 1, P, Q, K);
}

long long calculate(int P, int Q, int U, int V) {
    return queryX(rootX, 0, R_MAX - 1, P, Q, U, 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...