This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/*
ID: USACO_template
LANG: C++
PROG: USACO
*/
#include <iostream> //cin , cout
#include <fstream> //fin, fout
#include <stdio.h> // scanf , pringf
#include <cstdio>
#include <algorithm> // sort , stuff
#include <stack> // stacks
#include <queue> // queues
#include <map>
#include <string>
#include "game.h"
using namespace std;
typedef pair<int, int> pii;
typedef vector<int> vi; /// adjlist without weight
typedef vector<pii> vii; /// adjlist with weight
typedef vector<pair<int,pii>> vpip; /// edge with weight
typedef long long ll;
#define mp make_pair
#define fst first
#define snd second
#define pb push_back
#define trav(u, adj_v) for (auto& u: adj_v)
const int MOD = 1e9+7; // 998244353;
const int MX = 2e5+5; //
const ll INF = 1e18; //
#define MAXV 100007
#define MAXE 100007
const int xdir[4] = {1,0,-1,0}, ydir[4] = {0,1,0,-1}; /// 4 directions
struct NODE {
int x, y;
int val;
int visited;
bool operator< (NODE b) const { return (x == b.x) ? (y < b.y) : (x < b.x); }
};
struct EDGE {
int from, to;
ll weight;
bool operator<(EDGE other) const { return weight < other.weight; }
};
/// code from USACO examples
void setIO(string name) {
ios_base::sync_with_stdio(0); cin.tie(0);
freopen((name+".in").c_str(),"r",stdin);
freopen((name+".out").c_str(),"w",stdout);
}
bool debug = false, submit = true;
long long gcd2(long long X, long long Y) {
if(X == 0) return Y;
if(Y == 0) return X;
long long tmp;
while (X != Y && Y != 0) {
tmp = X; X = Y;
Y = tmp % Y;
}
return X;
}
/*
Naively, inserting N elements into a sparse segment tree requires O(N log C) memory, giving a bound of O(N log^2C) on 2D segment tree memory.
This is usually too much for N=C=10^5 and 256 MB
Possible ways to get around this:
- Use arrays of fixed size rather than pointers.
- Reduce the memory usage of sparse segment tree to $O(N)$ while maintaining the same O(N\log C) insertion time
(see the solution for IOI Game below for details).
- Use BBSTs instead of sparse segment trees: https://cp-algorithms.com/data_structures/treap.html
*/
/// 2D segment tree
struct NODEY {
NODEY *lp, *rp; // left ptr, right ptr
ll g, val;
NODEY() : lp(NULL), rp(NULL), g(0), val(0) {}
};
int NYseg[2];
void pullY(NODEY *pny) {
ll g1 = (!pny->lp) ? 0 : pny->lp->g;
ll g2 = (!pny->rp) ? 0 : pny->rp->g;
pny->g = gcd2(gcd2(g1, g2), pny->val);
}
void updY(int vty, ll val, NODEY *pny, int l = NYseg[0], int r = NYseg[1]){
if(l == r) { pny->g = val; pny->val = val; return; } // leaf
int mid = (l + r) / 2;
if(vty == mid) {
pny->val = val;
} else if (vty < mid) {
if(mid-1 >= l) {
if(!pny->lp) pny->lp = new NODEY();
updY(vty, val, pny->lp, l, mid -1);
}
} else {
if(mid+1 <= r) {
if(!pny->rp) pny->rp = new NODEY();
updY(vty, val, pny->rp, mid+1, r);
}
}
pullY(pny);
}
ll queY(int qle, int qri, NODEY *pny, int l = NYseg[0], int r = NYseg[1]) {
if(r < qle || l > qri) return 0LL;
if(qle <= l && r <= qri) return pny->g;
int mid = (l + r) / 2;
ll g1 = (!pny->lp) ? 0LL : ( (mid-1 >= l) ? queY(qle, qri, pny->lp, l, mid-1) : 0LL );
ll g2 = (!pny->rp) ? 0LL : ( (mid+1 <= r) ? queY(qle, qri, pny->rp, mid+1, r) : 0LL );
ll g3 = (qle <= mid && mid <= qri) ? pny->val : 0LL;
return gcd2(gcd2(g1, g2), g3);
}
struct NODEX {
NODEX *lp, *rp; // left ptr, right ptr
NODEY *pny;
NODEX() : lp(NULL), rp(NULL), pny(NULL) {}
};
NODEX nx;
int NXseg[2];
void pullX(int vty, NODEX *pnx) {
ll g1 = (!pnx->lp) ? 0LL : queY(vty, vty, pnx->lp->pny);
ll g2 = (!pnx->rp) ? 0LL : queY(vty, vty, pnx->rp->pny);
ll g0 = gcd2(g1, g2);
updY(vty, g0, pnx->pny);
}
void updX(int vtx, int vty, ll val, NODEX *pnx, int l = NXseg[0], int r = NXseg[1]){
if(!pnx->pny) pnx->pny = new NODEY();
if(l == r) { updY(vty, val, pnx->pny); return; } // leaf
int mid = (l + r) / 2;
if (vtx <= mid) {
if(!pnx->lp) pnx->lp = new NODEX();
updX(vtx, vty, val, pnx->lp, l, mid);
} else {
if(!pnx->rp) pnx->rp = new NODEX();
updX(vtx, vty, val, pnx->rp, mid+1, r);
}
pullX(vty, pnx);
}
ll queX(int qxle, int qxri, int qyle, int qyri, NODEX *pnx, int l = NXseg[0], int r = NXseg[1]) { // [l, r]
if(r < qxle || l > qxri) return 0LL;
if(qxle <= l && r <= qxri) return queY(qyle, qyri, pnx->pny);
int mid = (l + r) / 2;
ll g1 = (!pnx->lp) ? 0LL : queX(qxle, qxri, qyle, qyri, pnx->lp, l, mid);
ll g2 = (!pnx->rp) ? 0LL : queX(qxle, qxri, qyle, qyri, pnx->rp, mid+1, r);
return gcd2(g1, g2);
}
void init(int R, int C) {
NXseg[0] = 0; NXseg[1] = C - 1;
NYseg[0] = 0; NYseg[1] = R - 1;
}
void update(int P, int Q, long long K) {
updX(Q, P, K, &nx);
}
long long calculate(int y10, int x10, int y20, int x20) {
int x1 = min(x10, x20), x2 = max(x10, x20);
int y1 = min(y10, y20), y2 = max(y10, y20);
return queX(x1, x2, y1, y2, &nx);
}
Compilation message (stderr)
game.cpp: In function 'void setIO(std::string)':
game.cpp:55:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
55 | freopen((name+".in").c_str(),"r",stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
game.cpp:56:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
56 | freopen((name+".out").c_str(),"w",stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | 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... |