이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
#include "game.h"
#pragma GCC optimize ("O3")
using namespace std;
using LL = long long;
constexpr int LIM = 1e9 + 1;
int R;
int C;
LL gcd2(LL X, LL Y) {
LL tmp;
while (X != Y && Y != 0) {
tmp = X;
X = Y;
Y = tmp % Y;
}
return X;
}
struct treap {
int x, y;
int a, b;
LL mg, tg;
treap * l = nullptr;
treap * r = nullptr;
treap(int _x, LL _g = 0) : x(_x), y(rand()), a(_x), b(_x), mg(_g), tg(_g) {}
~treap() {
if (l) delete l;
if (r) delete r;
}
friend LL g(treap* t) { return t ? t->tg : 0LL; }
friend int geta(treap* t) { return t ? t->a : LL(1e12); }
friend int getb(treap* t) { return t ? t->b : LL(-1e12); }
friend void upd(treap* t) {
if (t) {
t->a = min(t->x, geta(t->l));
t->b = max(t->x, getb(t->r));
t->tg = gcd2(gcd2(t->mg, g(t->l)), g(t->r));
}
}
friend void split(treap* t, int x, treap*& l, treap*& r) {
if (!t)
l = r = nullptr;
else if (t->x <= x)
split(t->r, x, t->r, r), l = t;
else
split(t->l, x, l, t->l), r = t;
upd(l);
upd(r);
}
friend void merge(treap*& t, treap* l, treap* r) {
if (!l || !r)
t = l ? l : r;
else if (l->y > r->y)
merge(l->r, l->r, r), t = l;
else
merge(r->l, l, r->l), t = r;
upd(t);
}
friend void insert(treap*& t, treap* nw) {
if (!t)
t = nw;
else if (nw->y > t->y)
split(t, nw->x, nw->l, nw->r), t = nw;
else
insert(t->x <= nw->x ? t->r : t->l, nw);
upd(t);
}
friend void erase(treap*& t, int x) {
if (!t) return;
if (t->x == x) {
treap* tmp = t;
merge(t, t->l, t->r);
tmp->l = tmp->r = nullptr;
delete tmp;
} else {
erase(x <= t->x ? t->l : t->r, x);
}
upd(t);
}
friend LL query(treap* const t, int l, int r) {
if (!t || r <= t->a || t->b < l) return 0LL;
if (l <= t->a && t->b < r) return t->tg;
LL ans = gcd2(query(t->l, l, r), query(t->r, l, r));
if (l <= t->x && t->x < r) ans = gcd2(ans, t->mg);
return ans;
}
};
struct st {
static st * new_st(int a = 0, int b = R) {
auto ret = new st;
ret->a = a;
ret->b = b;
return ret;
}
int a, b;
st * l = nullptr;
st * r = nullptr;
treap * son = nullptr;
st() {}
~st() {
if (l) delete l;
if (r) delete r;
if (son) delete son;
}
friend void st_update(st * const n, const int p, const int q, const LL k) {
if (!(n->a <= p && p < n->b)) return;
if (n->b - n->a <= 1) {
erase(n->son, q);
insert(n->son, new treap(q, k));
return;
}
// don't update the son if b-a != 1!
// you can't just overwrite all the values in the same row, like in 1d
int m = (n->a+n->b) / 2;
if (p < m) {
if (!n->l) n->l = new_st(n->a, m);
st_update(n->l, p, q, k);
} else {
if (!n->r) n->r = new_st(m, n->b);
st_update(n->r, p, q, k);
}
// suppose n->l and n->r are either zero or up to date
// rebuild n->son properly
// update the intervals with q in n->son
rebuild(n, q);
}
friend void rebuild(st * const n, const int q) {
treap * sl = n->l ? n->l->son : nullptr;
treap * sr = n->r ? n->r->son : nullptr;
erase(n->son, q);
insert(n->son, new treap(q, gcd2(query(sl, q, q+1), query(sr, q, q+1))));
sl = sr = nullptr;
delete sl;
delete sr;
}
friend LL st_query(const st * const n, const int p, const int q, const int u, const int v) {
if (!n || u <= n->a || n->b <= p) return 0LL;
if (p <= n->a && n->b <= u) return query(n->son, q, v);
return gcd2(st_query(n->l, p, q, u, v), st_query(n->r, p, q, u, v));
}
};
st * root;
void cleanup() {
delete root;
}
void init(int r, int c) {
R = r+5; C = c+5;
root = st::new_st();
assert(atexit(cleanup) == 0);
}
void update(int p, int q, LL k) {
st_update(root, p, q, k);
}
long long calculate(int p, int q, int u, int v) {
return st_query(root, p, q, u+1, v+1);
}
# | 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... |