This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
//replace Ofast with O3 for floating-point accuracy
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2,popcnt,lzcnt,abm,bmi,bmi2,fma")
#include <bits/stdc++.h>
#ifdef __cplusplus
extern "C" {
#endif
void init(int R, int C);
void update(int P, int Q, long long K);
long long calculate(int P, int Q, int U, int V);
#ifdef __cplusplus
}
#endif
using num = int64_t;
using namespace std;
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define REPI(t, n) for (num t = 0; t < n; ++t)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
#ifdef TESTING
#define DEBUG(...) __VA_ARGS__
#else
#define DEBUG(...)
#endif
struct node;
struct treap { node *root; treap(node *r = nullptr) : root(r) {} };
std::mt19937 irand(std::random_device{}()); //std::mt19937_64 for 64-bit priority
struct node {
num pri;
num val, assoc, total;
int sze;
treap left, right;
node() {}
node(num x, num a) : pri(irand()), val(x), assoc(a), total(a), sze(1), left(), right() { }
};
node* newTNode(num val, num a) { return new node(val, a); }
num total(treap t) { return t.root ? t.root->total : 0; }
int sze(treap t) { return t.root ? t.root->sze : 0; }
static inline void push(treap t) {}
void update(treap t) {
if (!t.root) return;
treap &left = t.root->left, &right = t.root->right;
push(left), push(right);
t.root->sze = sze(left)+sze(right)+1;
t.root->total = __gcd(t.root->assoc, __gcd(total(t.root->left), total(t.root->right)));
}
treap merge(treap left, treap right) {
push(left), push(right);
treap n;
if (!left.root || !right.root) n = left.root ? left : right;
else if (left.root->pri > right.root->pri) left.root->right = merge(left.root->right, right), n = left;
else right.root->left = merge(left, right.root->left), n = right;
update(n);
return n;
}
//pos: pos elements in left treap
//val: all elements in < val in left treap, all elements >= val in right treap
std::pair<treap, treap> splitByVal(treap t, num val) {
if (!t.root) return {{}, {}};
push(t); //Add update(t) if updates affect size of left/right nodes
treap &left = t.root->left, &right = t.root->right;
if (t.root->val < val) {
auto pr = splitByVal(right, val);
t.root->right = pr.first;
update(t);
return {{t.root}, pr.second};
}
auto pr = splitByVal(left, val);
t.root->left = pr.second;
update(t);
return {pr.first, {t.root}};
}
struct segtree2d {
int root = 1;
int sze = 1;
int mnX, mxX, mnY, mxY;
vector<int> lc, rc;
vector<treap> st;
segtree2d() {}
segtree2d(int R, int C) : mnX(0), mxX(R-1), mnY(0), mxY(C-1), lc(300000), rc(300000), st(300000) {}
int newNode() {
++sze;
if (sze >= sz(lc)) {
lc.push_back(0);
rc.push_back(0);
st.push_back({});
}
return sze;
}
num getVal(int n, int y1, int y2) {
if (n == 0) return 0;
treap l, r, rl, rr;
tie(l, r) = splitByVal(st[n], y1);
tie(rl, rr) = splitByVal(r, y2+1);
num ans = total(rl);
st[n] = merge(l, merge(rl, rr));
return ans;
}
num queryH(int x1, int y1, int x2, int y2, int lo, int hi, int &node) {
if ((x2 < lo) || (hi < x1) || (node == 0)) return 0;
if ((x1 <= lo) && (hi <= x2)) return getVal(node, y1, y2);
int mid = (lo+hi)/2;
return __gcd(queryH(x1, y1, x2, y2, lo, mid, lc[node]), queryH(x1, y1, x2, y2, mid+1, hi, rc[node]));
}
num query(int x1, int y1, int x2, int y2) {
return queryH(x1, y1, x2, y2, mnX, mxX, root);
}
void updateH(int x, int y, num newV, int lo, int hi, int &node) {
if ((x < lo) || (hi < x)) return;
if (node == 0) node = newNode();
if (lo != hi) {
int mid = (lo+hi)/2;
updateH(x, y, newV, lo, mid, lc[node]);
updateH(x, y, newV, mid+1, hi, rc[node]);
newV = __gcd(getVal(lc[node], y, y), getVal(rc[node], y, y));
}
treap l, r, rl, rr;
tie(l, r) = splitByVal(st[node], y);
tie(rl, rr) = splitByVal(r, y+1);
st[node] = merge(l, merge(treap(newTNode(y, newV)), rr));
}
void update(int x, int y, num newV) {
return updateH(x, y, newV, mnX, mxX, root);
}
};
segtree2d data;
void init(int R, int C) {
data = segtree2d(R, C);
}
void update(int P, int Q, long long V) {
data.update(P, Q, V);
}
long long calculate(int P, int Q, int U, int V) {
return data.query(P, Q, U, V);
}
# | 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... |