This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "bits/stdc++.h"
#include "game.h"
#ifdef mlocal
#include "grader.c"
#endif
using namespace std;
#define for_(i, s, e) for (int i = s; i < (int) e; i++)
#define for__(i, s, e) for (ll i = s; i < e; i++)
typedef long long ll;
typedef vector<int> vi;
typedef array<int, 2> ii;
#define endl '\n'
int MXR, MXC;
struct SegmentTree {
public:
vector<ii> c;
vi l, r;
vector<ll> tree;
int pt = 1;
void update(int &i, ll &val, int p) {
if (l[p] == r[p]) {
tree[p] = val;
return;
}
int mid = (l[p]+r[p])/2, s = i > mid;
if (!c[p][s]) {
// Key memory heuristic: if no child in this direction, then ONLY create the leaf node and NOT all intervals
tree.resize(pt+1); c.resize(pt+1); l.push_back(i); r.push_back(i);
c[p][s] = pt++;
} else if (l[c[p][s]] > i or r[c[p][s]] < i) {
// If there already exists a node in this direction and this is not the interval we need,
// then find the last interval such that this existing node and the new leaf node lie in different sides.
// It then reduces to the previous case for this newly create interval node.
int cl = l[p], cr = r[p], cmid = (cl+cr)/2;
while (!((r[c[p][s]] <= cmid) ^ (i <= cmid))) {
if (i <= cmid) cr = cmid;
else cl = cmid+1;
cmid = (cl+cr)/2;
}
tree.resize(pt+1); c.resize(pt+1); l.push_back(cl); r.push_back(cr);
c[pt][r[c[p][s]] > cmid] = c[p][s];
c[p][s] = pt++;
}
update(i, val, c[p][s]);
tree[p] = __gcd(c[p][0] ? tree[c[p][0]] : 0, c[p][1] ? tree[c[p][1]] : 0);
}
ll query(int &i, int &j, int p) {
if (l[p] > j or r[p] < i) return 0;
if (l[p] >= i and r[p] <= j) return tree[p];
return __gcd(c[p][0] ? query(i, j, c[p][0]) : 0, c[p][1] ? query(i, j, c[p][1]) : 0);
}
SegmentTree() {
c.resize(1); tree.resize(1); l.push_back(0); r.push_back(MXC);
}
};
struct SegmentTree2D {
public:
vector<ii> c;
vector<SegmentTree> tree;
int pt = 1;
void update(int &i, int &j, ll &val, int l, int r, int p) {
if (l != r) {
int mid = (l+r)/2, s = i > mid;
if (!c[p][s]) {
tree.resize(pt+1); c.resize(pt+1);
c[p][s] = pt++;
}
update(i, j, val, s ? mid+1 : l, s ? r : mid, c[p][s]);
}
if (l != r) val = __gcd(c[p][0] ? tree[c[p][0]].query(j, j, 0) : 0, c[p][1] ? tree[c[p][1]].query(j, j, 0) : 0);
tree[p].update(j, val, 0);
}
ll query(int &xi, int &xj, int &yi, int &yj, int l, int r, int p) {
if (l > xj or r < xi) return 0;
if (l >= xi and r <= xj) return tree[p].query(yi, yj, 0);
int mid = (l+r)/2;
return __gcd(c[p][0] ? query(xi, xj, yi, yj, l, mid, c[p][0]) : 0, c[p][1] ? query(xi, xj, yi, yj, mid+1, r, c[p][1]) : 0);
}
SegmentTree2D() {
c.resize(1); tree.resize(1);
}
};
SegmentTree2D tree;
void init(int R, int C) {
// Wait, do I even need to do something here? :)
MXR = R, MXC = C;
}
void update(int P, int Q, ll K) {
tree.update(P, Q, K, 0, MXR, 0);
}
ll calculate(int P, int Q, int U, int V) {
return tree.query(P, U, Q, V, 0, MXR, 0);
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |