Submission #1325552

#TimeUsernameProblemLanguageResultExecution timeMemory
1325552ereringGame (IOI13_game)C++20
63 / 100
1158 ms32384 KiB
//gemini optimized memory

#include "game.h"
#include <algorithm>

using namespace std;

typedef long long ll;

ll gcd2(ll X, ll Y) {
    while (Y) {
        X %= Y;
        swap(X, Y);
    }
    return X;
}

struct Node {
    int l, r;
    ll val;
};

// Global pools to stay under 250MB
// Inner nodes: ~6.5M * 24 bytes ≈ 156MB
// Outer nodes: ~45k * 24 bytes ≈ 1MB
Node tree_inner[6500000];
Node tree_outer[45000];
int inner_ptr = 1, outer_ptr = 1;
int outer_roots[45000]; // Maps outer node to its inner tree root

int R_max, C_max;

void update_inner(int &cur, int lo, int hi, int pos, ll val, bool leaf) {
    if (!cur) cur = inner_ptr++;
    if (lo == hi) {
        tree_inner[cur].val = leaf ? val : val; // Logic handled by caller
        return;
    }
    int mid = lo + (hi - lo) / 2;
    if (pos <= mid) update_inner(tree_inner[cur].l, lo, mid, pos, val, leaf);
    else update_inner(tree_inner[cur].r, mid + 1, hi, pos, val, leaf);
    
    tree_inner[cur].val = gcd2(tree_inner[tree_inner[cur].l].val, tree_inner[tree_inner[cur].r].val);
}

ll query_inner(int cur, int lo, int hi, int ql, int qr) {
    if (!cur || ql > hi || qr < lo) return 0;
    if (ql <= lo && hi <= qr) return tree_inner[cur].val;
    int mid = lo + (hi - lo) / 2;
    return gcd2(query_inner(tree_inner[cur].l, lo, mid, ql, qr),
                query_inner(tree_inner[cur].r, mid + 1, hi, ql, qr));
}

void update_outer(int &cur, int lo, int hi, int r, int c, ll val) {
    if (!cur) cur = outer_ptr++;
    if (lo != hi) {
        int mid = lo + (hi - lo) / 2;
        if (r <= mid) update_outer(tree_outer[cur].l, lo, mid, r, c, val);
        else update_outer(tree_outer[cur].r, mid + 1, hi, r, c, val);
        
        // Non-leaf: val is the GCD of children's results at column c
        ll g1 = query_inner(outer_roots[tree_outer[cur].l], 0, C_max - 1, c, c);
        ll g2 = query_inner(outer_roots[tree_outer[cur].r], 0, C_max - 1, c, c);
        update_inner(outer_roots[cur], 0, C_max - 1, c, gcd2(g1, g2), false);
    } else {
        // Leaf: directly update the value
        update_inner(outer_roots[cur], 0, C_max - 1, c, val, true);
    }
}

ll query_outer(int cur, int lo, int hi, int r1, int r2, int c1, int c2) {
    if (!cur || r1 > hi || r2 < lo) return 0;
    if (r1 <= lo && hi <= r2) return query_inner(outer_roots[cur], 0, C_max - 1, c1, c2);
    int mid = lo + (hi - lo) / 2;
    return gcd2(query_outer(tree_outer[cur].l, lo, mid, r1, r2, c1, c2),
                query_outer(tree_outer[cur].r, mid + 1, hi, r1, r2, c1, c2));
}

int root = 0;

void init(int R, int C) {
    R_max = R; C_max = C;
}

void update(int P, int Q, ll K) {
    update_outer(root, 0, R_max - 1, P, Q, K);
}

ll calculate(int P, int Q, int U, int V) {
    return query_outer(root, 0, R_max - 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...