結果
| 問題 |
No.529 帰省ラッシュ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2017-06-11 04:01:47 |
| 言語 | Java (openjdk 23) |
| 結果 |
AC
|
| 実行時間 | 4,297 ms / 4,500 ms |
| コード長 | 7,495 bytes |
| コンパイル時間 | 2,827 ms |
| コンパイル使用メモリ | 84,100 KB |
| 実行使用メモリ | 163,856 KB |
| 最終ジャッジ日時 | 2024-09-24 15:53:01 |
| 合計ジャッジ時間 | 43,708 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 18 |
ソースコード
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
class Main implements Runnable {
public static void main(String[] args) {
new Thread(null, new Main(), "", Runtime.getRuntime().maxMemory()).start();
}
class State {
int i;
int parent;
int j;// 操作後g[i][j]に潜る
public State(int i_, int parent_, int j_) {
i = i_;
parent = parent_;
j = j_;
}
}
int two_edge_connected_componets(ArrayList<Integer>[] g, int[] col) {
int n = g.length;
Arrays.fill(col, -1);
int cols = 0;
int[] low = new int[n];
int[] ord = new int[n];
boolean[] marked = new boolean[n];
Arrays.fill(low, -1);
Arrays.fill(ord, -1);
int order = 0;
ArrayDeque<State> stk = new ArrayDeque<>();
ArrayDeque<Integer> pnd = new ArrayDeque<>();
for (int ii = 0; ii < n; ++ii) {
if (ord[ii] == -1) {
stk.add(new State(ii, -1, 0));
}
while (!stk.isEmpty()) {
State s = stk.pollFirst();
if (ord[s.i] == -1) {
low[s.i] = (ord[s.i] = order++);
pnd.addFirst(s.i);
}
if (s.j > 0 && s.parent != g[s.i].get(s.j - 1) && !marked[g[s.i].get(s.j - 1)]) {
if (low[g[s.i].get(s.j - 1)] == -1) {
throw new AssertionError();
}
low[s.i] = Math.min(low[s.i], low[g[s.i].get(s.j - 1)]);
}
if (s.j == g[s.i].size() && low[s.i] == ord[s.i]) {
while (true) {
int v = pnd.pollFirst();
col[v] = cols;
marked[v] = true;
if (v == s.i)
break;
}
++cols;
continue;
}
if (s.j == g[s.i].size())
continue;
int v = g[s.i].get(s.j);
stk.addFirst(new State(s.i, s.parent, s.j + 1));
if (ord[v] == -1) {
stk.addFirst(new State(v, s.i, 0));
} else if (v != s.parent && !marked[v]) {
low[s.i] = Math.min(low[s.i], low[v]);
}
}
}
return cols;
}
@SuppressWarnings("unchecked")
public void run() {
Scanner sc = new Scanner(System.in);
PrintWriter pw = new PrintWriter(System.out);
int n = sc.nextInt();
int m = sc.nextInt();
int q = sc.nextInt();
ArrayList<Integer>[] g = new ArrayList[n];
for (int i = 0; i < n; ++i) {
g[i] = new ArrayList<>();
}
for (int i = 0; i < m; ++i) {
int a = sc.nextInt() - 1;
int b = sc.nextInt() - 1;
g[a].add(b);
g[b].add(a);
}
int[] col = new int[n];
int cols = two_edge_connected_componets(g, col);
ArrayList<Integer>[] h = new ArrayList[cols];
PriorityQueue<Long>[] w = new PriorityQueue[cols];
for (int i = 0; i < cols; ++i) {
w[i] = new PriorityQueue<>(new Comparator<Long>() {
@Override
public int compare(Long o1, Long o2) {
return -Long.compare(o1, o2);
}
});
}
for (int i = 0; i < cols; ++i) {
w[i].add(-1L);
}
for (int i = 0; i < cols; ++i) {
h[i] = new ArrayList<>();
}
for (int i = 0; i < n; ++i) {
for (int j : g[i]) {
int a = col[i];
int b = col[j];
if (a == b)
continue;
if (h[a].contains(b))
continue;
h[a].add(b);
h[b].add(a);
}
}
for (int i = 0; i < cols; ++i) {
Collections.sort(h[i]);
for (int j = 0; j < h[i].size(); ++j) {
while (j + 1 < h[i].size() && h[i].get(j) == h[i].get(j + 1)) {
h[i].remove(j + 1);
}
}
}
HLDecomposition hl = new HLDecomposition(cols);
for (int i = 0; i < cols; ++i) {
for (int j : h[i]) {
if (i > j) {
hl.ae(i, j);
}
}
}
hl.pre();
SegmentTree st = new SegmentTree(cols);
int[] ref = new int[cols];
Arrays.fill(ref, -1);
for (int i = 0; i < cols; ++i) {
ref[hl.id[i]] = i;
}
while (q-- > 0) {
int t = sc.nextInt();
if (t == 1) {// modification query
int u = sc.nextInt() - 1;
long v = sc.nextInt();
u = col[u];
w[u].add(v);
st.setVal(hl.id[u], w[u].peek());
} else {// ouput query
int src = sc.nextInt() - 1;
int dst = sc.nextInt() - 1;
src = col[src];
dst = col[dst];
long v = output(src, dst, hl, st);
pw.println(v == -1 ? v : v >> 32);
if (v != -1) {
w[ref[(int) v]].poll();
st.setVal((int) v, w[ref[(int) v]].peek());
}
}
}
pw.close();
}
long output(int a, int b, HLDecomposition hl, SegmentTree st) {
long ea = -1;
long eb = -1;
while (hl.head[a] != hl.head[b]) {
if (hl.depth[hl.head[a]] < hl.depth[hl.head[b]]) {
int tmp = a;
a = b;
b = tmp;
long tmp_e = ea;
ea = eb;
eb = tmp_e;
}
ea = merge(st.query(hl.id[hl.head[a]], hl.id[a] + 1), ea);
a = hl.parent[hl.head[a]];
}
if (hl.depth[a] < hl.depth[b]) {
int tmp = a;
a = b;
b = tmp;
long tmp_e = ea;
ea = eb;
eb = tmp_e;
}
return merge(eb, merge(st.query(hl.id[b], hl.id[a] + 1), ea));
}
long merge(long a, long b) {
return Math.max(a, b);
}
class SegmentTree {
int n;
long[] Vs;
public SegmentTree(int n_) {
n = 1;
while (n < n_) {
n *= 2;
}
Vs = new long[2 * n - 1];
for (int i = 0; i < n; ++i) {
Vs[i + n - 1] = -1;
}
for (int i = n - 2; i >= 0; --i) {
Vs[i] = merge(Vs[2 * i + 1], Vs[2 * i + 2]);
}
}
void setVal(int k, long val) {
k += n - 1;
if (val != -1)
Vs[k] = val << 32 | (k - (n - 1));
else
Vs[k] = -1;
while (k > 0) {
k = (k - 1) / 2;
Vs[k] = merge(Vs[2 * k + 1], Vs[2 * k + 2]);
}
}
// [a,b),[l,r)
long query(int a, int b) {
return query(a, b, 0, n, 0);
}
long query(int a, int b, int l, int r, int k) {
if (b <= l || r <= a) {
return -1L;
}
if (a <= l && r <= b) {
return Vs[k];
} else {
long vl = query(a, b, l, (l + r) / 2, 2 * k + 1);
long vr = query(a, b, (l + r) / 2, r, 2 * k + 2);
return merge(vl, vr);
}
}
}
class HLDecomposition {
int n;
int[] depth;
int[] head;
int[] heavy;
int[] parent;
int[] sz;
ArrayList<Integer>[] g;
int[] id;
@SuppressWarnings("unchecked")
public HLDecomposition(int n) {
this.n = n;
depth = new int[n];
head = new int[n];
heavy = new int[n];
parent = new int[n];
id = new int[n];
sz = new int[n];
g = new ArrayList[n];
for (int i = 0; i < n; ++i) {
g[i] = new ArrayList<>();
}
Arrays.fill(head, -1);
Arrays.fill(id, -1);
Arrays.fill(parent, -1);
}
void ae(int a, int b) {
g[a].add(b);
g[b].add(a);
}
void pre() {
dfs(0, -1);
bfs();
}
void bfs() {
ArrayDeque<Integer> pend = new ArrayDeque<>();
int gen = 0;
pend.add(0);
while (!pend.isEmpty()) {
int v = pend.pollFirst();
int top = v;
for (; v != -1; v = heavy[v]) {
id[v] = gen++;
head[v] = top;
for (int d : g[v]) {
if (d == parent[v] || d == heavy[v]) {
continue;
}
pend.add(d);
}
}
}
}
int lca(int u, int v) {
if (head[u] != head[v]) {
if (depth[head[u]] < depth[head[v]]) {
int tmp = u;
u = v;
v = tmp;
}
return lca(parent[head[u]], v);
} else {
if (depth[u] > depth[v]) {
int tmp = u;
u = v;
v = tmp;
}
return u;
}
}
int dfs(int c, int p) {
parent[c] = p;
int s = 1;
int to = -1;
for (int d : g[c]) {
if (d == p)
continue;
depth[d] = depth[c] + 1;
s += dfs(d, c);
if (to == -1 || sz[d] > sz[to]) {
to = d;
}
}
sz[c] = s;
heavy[c] = to;
return s;
}
}
static void tr(Object... objects) {
System.out.println(Arrays.deepToString(objects));
}
}