結果
| 問題 |
No.2786 RMQ on Grid Path
|
| コンテスト | |
| ユーザー |
tenten
|
| 提出日時 | 2024-06-17 09:35:58 |
| 言語 | Java (openjdk 23) |
| 結果 |
AC
|
| 実行時間 | 2,143 ms / 6,000 ms |
| コード長 | 5,265 bytes |
| コンパイル時間 | 4,918 ms |
| コンパイル使用メモリ | 84,888 KB |
| 実行使用メモリ | 186,552 KB |
| 最終ジャッジ日時 | 2024-06-17 09:36:58 |
| 合計ジャッジ時間 | 52,442 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 35 |
ソースコード
import java.io.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class Main {
static List<List<Integer>> graph = new ArrayList<>();
static int[] depths;
static int[][] parents;
static int[][] maxes;
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner();
int h = sc.nextInt();
int w = sc.nextInt();
int[] values = new int[h * w];
PriorityQueue<Bridge> queue = new PriorityQueue<>();
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
values[i * w + j] = sc.nextInt();
if (i > 0) {
queue.add(new Bridge((i - 1) * w + j, i * w + j, Math.max(values[(i - 1) * w + j], values[i * w + j])));
}
if (j > 0) {
queue.add(new Bridge(i * w + j - 1, i * w + j, Math.max(values[i * w + j - 1], values[i * w + j])));
}
}
}
for (int i = 0; i < h * w; i++) {
graph.add(new ArrayList<>());
}
UnionFindTree uft = new UnionFindTree(h * w);
while (queue.size() > 0) {
Bridge x = queue.poll();
if (!uft.same(x)) {
uft.unite(x);
graph.get(x.left).add(x.right);
graph.get(x.right).add(x.left);
}
}
depths = new int[h * w];
parents = new int[15][h * w];
setDepth(0, 0, 0);
maxes = new int[15][h * w];
for (int i = 0; i < h * w; i++) {
maxes[0][i] = values[i];
}
for (int i = 1; i < 15; i++) {
for (int j = 0; j < h * w; j++) {
parents[i][j] = parents[i - 1][parents[i - 1][j]];
maxes[i][j] = Math.max(maxes[i - 1][j], maxes[i - 1][parents[i - 1][j]]);
}
}
int q = sc.nextInt();
String result = IntStream.range(0, q)
.mapToObj(i -> String.valueOf(getMax((sc.nextInt() - 1) * w + sc.nextInt() - 1, (sc.nextInt() - 1) * w + sc.nextInt() - 1)))
.collect(Collectors.joining("\n"));
System.out.println(result);
}
static int getMax(int a, int b) {
int ans = 0;
for (int i = 14; i >= 0; i--) {
if (depths[a] - depths[b] >= (1 << i)) {
ans = Math.max(ans, maxes[i][a]);
a = parents[i][a];
} else if (depths[b] - depths[a] >= (1 << i)) {
ans = Math.max(ans, maxes[i][b]);
b = parents[i][b];
}
}
if (a == b) {
return Math.max(ans, maxes[0][a]);
}
for (int i = 14; i>= 0; i--) {
if (parents[i][a] != parents[i][b]) {
ans = Math.max(ans, Math.max(maxes[i][a], maxes[i][b]));
a = parents[i][a];
b = parents[i][b];
}
}
ans = Math.max(ans, Math.max(maxes[0][a], maxes[0][b]));
return Math.max(ans, maxes[0][parents[0][a]]);
}
static void setDepth(int idx, int p, int d) {
parents[0][idx] = p;
depths[idx] = d;
for (int x : graph.get(idx)) {
if (x != p) {
setDepth(x, idx, d + 1);
}
}
}
static class Bridge implements Comparable<Bridge> {
int left;
int right;
int value;
public Bridge(int left, int right, int value) {
this.left = left;
this.right = right;
this.value = value;
}
public int compareTo(Bridge another) {
return value - another.value;
}
}
static class UnionFindTree {
int[] parents;
public UnionFindTree(int size) {
parents = new int[size];
for (int i = 0; i < size; i++) {
parents[i] = i;
}
}
public int find(int x) {
return x == parents[x] ? x : (parents[x] = find(parents[x]));
}
public boolean same(int x, int y) {
return find(x) == find(y);
}
public boolean same(Bridge b) {
return same(b.left, b.right);
}
public void unite(Bridge b) {
parents[find(b.left)] = find(b.right);
}
}
}
class Scanner {
BufferedReader br;
StringTokenizer st = new StringTokenizer("");
StringBuilder sb = new StringBuilder();
public Scanner() {
try {
br = new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e) {
}
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public String next() {
try {
while (!st.hasMoreTokens()) {
st = new StringTokenizer(br.readLine());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return st.nextToken();
}
}
}
tenten