제출 #1323315

#제출 시각아이디문제언어결과실행 시간메모리
1323315buzdi게임 (IOI13_game)C++20
100 / 100
4450 ms46428 KiB
#include "game.h" #include <cstdio> #include <algorithm> #include <cstdlib> using namespace std; // --- Helper: GCD --- long long gcd2(long long X, long long Y) { long long tmp; while (X != 0 && Y != 0) { if (X > Y) X %= Y; else Y %= X; } return X + Y; } // --- Treap (Y-Dimension) --- // Standard Treap supporting point update and range GCD query. struct Treap { int key; // Column index int prio; // Random priority long long val; // Value at this column long long gcd_val; // GCD of the subtree Treap *l, *r; Treap(int k, long long v) : key(k), prio(rand()), val(v), gcd_val(v), l(NULL), r(NULL) {} }; // Update the gcd_val of a node based on children void update_gcd(Treap *t) { if (!t) return; t->gcd_val = t->val; if (t->l) t->gcd_val = gcd2(t->gcd_val, t->l->gcd_val); if (t->r) t->gcd_val = gcd2(t->gcd_val, t->r->gcd_val); } // Split treap 't' by key 'k' into 'l' (keys <= k) and 'r' (keys > k) void split(Treap *t, int k, Treap *&l, Treap *&r) { if (!t) { l = r = NULL; } else if (t->key <= k) { split(t->r, k, t->r, r); l = t; } else { split(t->l, k, l, t->l); r = t; } update_gcd(t); } // Merge treaps 'l' and 'r' void merge(Treap *&t, Treap *l, Treap *r) { if (!l || !r) { t = (l ? l : r); } else if (l->prio > r->prio) { merge(l->r, l->r, r); t = l; } else { merge(r->l, l, r->l); t = r; } update_gcd(t); } // Insert or Update a value in the Treap // If key exists, update value. If not, insert. void treap_update(Treap *&t, int key, long long val) { Treap *t1, *t2, *t3; // Split into < key, == key, > key split(t, key, t2, t3); // t2 has <= key split(t2, key - 1, t1, t2); // t1 has < key, t2 has == key // t2 is now the node with 'key' if it exists, or NULL if (t2) { t2->val = val; update_gcd(t2); } else { t2 = new Treap(key, val); } // Merge back: t1 + t2 + t3 merge(t2, t1, t2); merge(t, t2, t3); } // Query GCD in range [ql, qr] on the Treap long long treap_query(Treap *t, int ql, int qr) { Treap *t1, *t2, *t3; // Split to isolate the range [ql, qr] split(t, qr, t2, t3); // t2 <= qr, t3 > qr split(t2, ql - 1, t1, t2); // t1 < ql, t2 is range [ql, qr] long long res = (t2 ? t2->gcd_val : 0); // Merge back to restore structure merge(t2, t1, t2); merge(t, t2, t3); return res; } // Fast point query helper for calculating internal X-nodes // (Avoids split/merge overhead) long long treap_get_val(Treap *t, int key) { while (t) { if (key == t->key) return t->val; if (key < t->key) t = t->l; else t = t->r; } return 0; } // --- Segment Tree (X-Dimension) --- // Dynamic Segment Tree on rows. struct NodeX { NodeX *l, *r; Treap *rootY; // The Y-dimension structure for this row range NodeX() : l(NULL), r(NULL), rootY(NULL) {} }; NodeX *rootX = NULL; int R_global, C_global; // Update the 2D structure // node: current X-node // nl, nr: current row range // r, c: target coordinate // val: new value void updateX(NodeX *&node, int nl, int nr, int r, int c, long long val) { if (!node) node = new NodeX(); // If we are at the exact row (leaf of X-tree) if (nl == nr) { treap_update(node->rootY, c, val); return; } int mid = nl + (nr - nl) / 2; if (r <= mid) updateX(node->l, nl, mid, r, c, val); else updateX(node->r, mid + 1, nr, r, c, val); // Update logic for internal nodes: // The value at (row_range, c) in the X-tree should be: // gcd( value at (left_child, c), value at (right_child, c) ) long long v1 = (node->l) ? treap_get_val(node->l->rootY, c) : 0; long long v2 = (node->r) ? treap_get_val(node->r->rootY, c) : 0; treap_update(node->rootY, c, gcd2(v1, v2)); } // Query the 2D structure long long queryX(NodeX *node, int nl, int nr, int r1, int r2, int c1, int c2) { if (!node || nl > r2 || nr < r1) return 0; // If the X-range is fully within the query range if (nl >= r1 && nr <= r2) { return treap_query(node->rootY, c1, c2); } int mid = nl + (nr - nl) / 2; return gcd2(queryX(node->l, nl, mid, r1, r2, c1, c2), queryX(node->r, mid + 1, nr, r1, r2, c1, c2)); } // --- Interface --- void init(int R, int C) { R_global = R; C_global = C; srand(2013); // Seed for Treap priorities rootX = new NodeX(); } void update(int P, int Q, long long K) { updateX(rootX, 0, R_global - 1, P, Q, K); } long long calculate(int P, int Q, int U, int V) { return queryX(rootX, 0, R_global - 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...