結果
| 問題 |
No.2786 RMQ on Grid Path
|
| コンテスト | |
| ユーザー |
GoldIngot
|
| 提出日時 | 2024-06-14 21:54:59 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 3,970 ms / 6,000 ms |
| コード長 | 3,701 bytes |
| コンパイル時間 | 4,567 ms |
| コンパイル使用メモリ | 262,256 KB |
| 最終ジャッジ日時 | 2025-02-21 21:57:41 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 35 |
ソースコード
#include <bits/stdc++.h>
#include <atcoder/all>
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep2(i,m,n) for(int (i)=(m);(i)<(n);(i)++)
#define rep2ll(i,m,n) for(ll (i)=(m);(i)<(n);(i)++)
#define ALL(obj) (obj).begin(), (obj).end()
#define rALL(obj) (obj).rbegin(), (obj).rend()
using namespace std;
using ll = long long;
using P = pair<ll,ll>;
using mint = atcoder::modint998244353;
using VL = vector<ll>;
using VVL = vector<VL>;
using VVVL = vector<VVL>;
using VM = vector<mint>;
using VVM = vector<VM>;
using VVVM = vector<VVM>;
using VD = vector<double>;
using VVD = vector<VD>;
using VVVD = vector<VVD>;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
template <typename T, int LOG>
struct PersistentArray {
struct Node {
T data;
Node *child[1 << LOG] = {};
Node() {}
Node(const T &data) : data(data) {}
};
Node *root;
PersistentArray() : root(nullptr) {}
T get(Node *t, int k) {
if (k == 0) return t->data;
return get(t->child[k & ((1 << LOG) - 1)], k >> LOG);
}
T get(const int &k) { return get(root, k); }
pair<Node *, T *> mutable_get(Node *t, int k) {
t = t ? new Node(*t) : new Node();
if (k == 0) return {t, &t->data};
auto p = mutable_get(t->child[k & ((1 << LOG) - 1)], k >> LOG);
t->child[k & ((1 << LOG) - 1)] = p.first;
return {t, p.second};
}
T *mutable_get(const int &k) {
auto ret = mutable_get(root, k);
root = ret.first;
return ret.second;
}
Node *build(Node *t, const T &data, int k) {
if (!t) t = new Node();
if (k == 0) {
t->data = data;
return t;
}
auto p = build(t->child[k & ((1 << LOG) - 1)], data, k >> LOG);
t->child[k & ((1 << LOG) - 1)] = p;
return t;
}
void build(const vector<T> &v) {
root = nullptr;
for (int i = 0; i < v.size(); i++) {
root = build(root, v[i], i);
}
}
};
/*
* @brief Persistent-Union-Find(永続Union-Find)
*/
struct PersistentUnionFind {
PersistentArray<int, 3> data;
PersistentUnionFind() {}
PersistentUnionFind(int sz) { data.build(vector<int>(sz, -1)); }
int find(int k) {
int p = data.get(k);
return p >= 0 ? find(p) : k;
}
int size(int k) { return (-data.get(find(k))); }
bool unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) return false;
auto u = data.get(x);
auto v = data.get(y);
if (u < v) {
auto a = data.mutable_get(x);
*a += v;
auto b = data.mutable_get(y);
*b = x;
} else {
auto a = data.mutable_get(y);
*a += u;
auto b = data.mutable_get(x);
*b = y;
}
return true;
}
};
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
ll h, w; cin>>h>>w;
VVL a(h, VL(w)); rep(x,h) rep(y,w) cin>>a[x][y], a[x][y]--;
vector<vector<P>> b(h*w);
rep(x,h) rep(y,w){
if(x){
b[max(a[x][y], a[x-1][y])].emplace_back(w*x+y, w*(x-1)+y);
}
if(y){
b[max(a[x][y], a[x][y-1])].emplace_back(w*x+y, w*x+(y-1));
}
}
vector<PersistentUnionFind> uf(h*w+1);
uf[0] = PersistentUnionFind(h*w);
rep(i,h*w){
uf[i+1] = uf[i];
for(auto [u,v]:b[i]) uf[i+1].unite(u, v);
}
ll q; cin>>q;
while(q--){
ll rs1, cs1, rt1, ct1; cin>>rs1>>cs1>>rt1>>ct1; rs1--,cs1--,rt1--,ct1--;
ll u = w*rs1+cs1, v = w*rt1+ct1;
ll ng = 0, ok = h*w+1;
while(ng+1<ok){
ll c = (ng + ok) / 2;
(uf[c].find(u) == uf[c].find(v) ? ok:ng) = c;
}
cout<<ok<<'\n';
}
return 0;
}
GoldIngot