Submission #556180

#TimeUsernameProblemLanguageResultExecution timeMemory
556180ZaniteGame (IOI13_game)C++17
100 / 100
2871 ms78404 KiB
#include "game.h" #include <bits/stdc++.h> using namespace std; #define ll long long long long gcd2(long long X, long long Y) { if (!X) return Y; if (!Y) return X; return gcd2(Y, X % Y); } mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); struct Treap { struct Node { ll val, g; ll prior, pos, mn, mx; Node *left, *right; Node(ll _pos, ll _val) { pos = mn = mx = _pos; val = g = _val; prior = rng(); left = right = nullptr; } void update() { g = val; if (left) {g = gcd2(g, left->g);} if (right) {g = gcd2(g, right->g);} mn = (left ? left->mn : pos); mx = (right ? right->mx : pos); } }; Node *root; Treap() : root(nullptr) {} void split(Node *T, Node *&L, Node *&R, ll sep) { // splits T into L = [mn..pos] and R = [pos+1..mx] if (!T) { L = R = nullptr; return; } if (T->pos <= sep) { split(T->right, T->right, R, sep); L = T; } else { split(T->left, L, T->left, sep); R = T; } T->update(); } void merge(Node *&T, Node *L, Node *R) { // merges L and R into T, assuming that all elements in L < R if (!L || !R) { T = (L ? L : R); return; } if (L->prior >= R->prior) { merge(L->right, L->right, R); T = L; } else { merge(R->left, L, R->left); T = R; } T->update(); } bool find(ll pos) { // returns TRUE if the node with position pos is present in the treap Node *cur = root; while (cur) { if (cur->pos == pos) {return true;} if (cur->pos < pos) {cur = cur->right;} else {cur = cur->left;} } return false; } void updateNode(Node *cur, ll pos, ll val) { // updates node at position pos with val, assuming the node exists if (cur->pos == pos) { cur->val = val; cur->update(); return; } if (cur->pos < pos) { updateNode(cur->right, pos, val); } else { updateNode(cur->left, pos, val); } cur->update(); } void update(ll pos, ll val) { // if the node exists, update it if (find(pos)) {updateNode(root, pos, val);} else { // insert a new node Node *tmp = new Node(pos, val); Node *t1, *t2; split(root, t1, t2, pos); merge(root, t1, tmp); merge(root, root, t2); } } ll query(Node *T, ll L, ll R) { // returns sum of all nodes in the range [L..R] under node T if (!T) return 0; if (T->mx < L || R < T->mn) return 0; if (L <= T->mn && T->mx <= R) { //cout << "{" << T->mn << ", " << T->mx << ": " << T->g << "} "; return T->g; } ll ret; if (L <= T->pos && T->pos <= R) { //cout << "{" << T->pos << ", " << T->pos << ": " << T->val << "} "; ret = T->val; } else { ret = 0; } if (T->left) {ret = gcd2(ret, query(T->left, L, R));} if (T->right) {ret = gcd2(ret, query(T->right, L, R));} return ret; } ll query(ll L, ll R) { // returns sum of all nodes in the range [L..R] return query(root, L, R); } void print(Node *T) { if (!T) return; cout << T->pos << ' ' << T->val << ' ' << T->g << ' ' << T->mn << ' ' << T->mx << '\n'; print(T->left); print(T->right); } void print() { print(root); } }; struct DynamicSegtreeBBST { struct Node { Treap inner; Node* left; Node* right; Node() { inner = Treap(); left = right = nullptr; } void update(ll pos) { ll tmp = 0; if (left) {tmp = gcd(tmp, left->inner.query(pos, pos));} if (right) {tmp = gcd(tmp, right->inner.query(pos, pos));} inner.update(pos, tmp); } }; Node* root; ll dim1, dim2; DynamicSegtreeBBST(ll _dim1, ll _dim2) { root = new Node(); dim1 = _dim1, dim2 = _dim2; } void update(Node* cur, ll l, ll r, ll d1, ll d2, ll upd) { if (l == r) { cur->inner.update(d2, upd); return; } ll m = (l + r) >> 1; if (d1 <= m) { if (!cur->left) {cur->left = new Node();} update(cur->left, l, m, d1, d2, upd); } else { if (!cur->right) {cur->right = new Node();} update(cur->right, m+1, r, d1, d2, upd); } cur->update(d2); } ll query(Node* cur, ll l, ll r, ll d1l, ll d1r, ll d2l, ll d2r) { if (l > d1r || d1l > r) {return 0;} if (d1l <= l && r <= d1r) { //debug(l); debug(r); //cur->inner.print(); //cout << "{" << l << ", " << r << "} : "; ll ret = cur->inner.query(d2l, d2r); //cout << ": " << ret << '\n'; //debug(ret); return ret; } ll m = (l + r) >> 1, ret = 0; if (cur->left) {ret = gcd2(ret, query(cur->left, l, m, d1l, d1r, d2l, d2r));} if (cur->right) {ret = gcd2(ret, query(cur->right, m+1, r, d1l, d1r, d2l, d2r));} return ret; } void print() { for (ll i = 1; i <= dim1; i++) { for (ll j = 1; j <= dim2; j++) { cout << query(root, 1, dim1, i, i, j, j) << ' '; } cout << '\n'; } cout << '\n'; } }; DynamicSegtreeBBST *D; int R, C; void init(int R, int C) { ::R = R; ::C = C; D = new DynamicSegtreeBBST(R, C); } void update(int P, int Q, long long K) { D->update(D->root, 1, R, P+1, Q+1, K); //D->print(); } long long calculate(int P, int Q, int U, int V) { return D->query(D->root, 1, R, P+1, U+1, Q+1, V+1); }
#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...