結果
問題 |
No.1170 Never Want to Walk
|
ユーザー |
|
提出日時 | 2025-01-03 22:14:06 |
言語 | Java (openjdk 23) |
結果 |
MLE
|
実行時間 | - |
コード長 | 4,852 bytes |
コンパイル時間 | 2,903 ms |
コンパイル使用メモリ | 92,696 KB |
実行使用メモリ | 802,756 KB |
最終ジャッジ日時 | 2025-01-03 22:15:52 |
合計ジャッジ時間 | 46,929 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 MLE * 1 |
other | AC * 19 TLE * 12 MLE * 6 |
ソースコード
import java.util.Arrays; import java.util.Scanner; import java.util.function.IntConsumer; import java.util.stream.IntStream; public class Main { public static void main(String[] args) { try (Scanner scanner = new Scanner(System.in)) { int n = scanner.nextInt(), a = scanner.nextInt(), b = scanner.nextInt(); Integer[] x = IntStream.range(0, n).map(i -> scanner.nextInt()).boxed().toArray(Integer[]::new); DivideInterval di = new DivideInterval(n); UnionFind uf = new UnionFind(di.b << 1); int[] num = new int[di.b << 1]; Arrays.fill(num, 0); IntStream.range(0, n).forEach(i -> num[di.b + i] = 1); IntBiConsumer f = (p, q) -> num[p] += num[q]; IntConsumer rec = new IntConsumer() { @Override public void accept(int c) { if (di.b <= c) { return; } for (int t = 0; t < 2; t++) { if (!uf.same(c, (c << 1) + t)) { uf.unite(c, (c << 1) + t, f); accept((c << 1) + t); } } } }; IntStream.range(0, n).forEach(i -> { int l = lowerBound(x, x[i] + a), r = lowerBound(x, x[i] + b + 1); di.apply(l, r, j -> { uf.unite(i + di.b, j, f); rec.accept(j); }); }); StringBuilder sb = new StringBuilder(); IntStream.range(0, n).forEach(i -> sb.append(num[uf.find(di.b + i)]).append(System.lineSeparator())); System.out.print(sb.toString()); System.out.flush(); } } private static int lowerBound(Integer[] x, int value) { return ~Arrays.binarySearch(x, value, (a, b) -> (a.compareTo(b) >= 0) ? 1 : -1); } /** * セグ木状に区間を分割したときの処理<br/> * https://github.com/NyaanNyaan/library/blob/master/data-structure/divide-interval.hpp を参考に作成 * * 2*B 個の頂点を持つグラフを考える。<br/> * B+i が元のグラフの頂点 i に対応する */ private static class DivideInterval { final int n, b; DivideInterval(int n) { this.n = n; int b = 1; while (b < n) { b <<= 1; } this.b = b; } /** * O(N) 根から葉方向へ push する * * @param f f(p,c) : p -> c へ伝播 */ @SuppressWarnings("unused") void push(IntBiConsumer f) { for (int p = 1; p < b; p++) { f.accept(p, p << 1); f.accept(p, (p << 1) | 1); } } /** * O(N) 葉から根の方向に update する * * @param f f(p, c1, c2) : c1 と c2 の結果を p へマージ */ @SuppressWarnings("unused") void update(IntTriConsumer f) { for (int p = b - 1; p > 0; p--) { f.accept(p, p << 1, (p << 1) | 1); } } /** * [l, r) に対応する index の列を返す * * 順番は左から右へ並んでいる<br/> * 例: [1, 11) : [1, 2), [2, 4), [4, 8), [8, 10), [10, 11) * * @param l * @param r * @return [l, r) に対応する index の列 */ int[] range(int l, int r) { if (!((0 <= l) && (l <= r) && (r <= n))) { throw new IllegalArgumentException("l=" + l + ", r=" + r + ", n=" + n); } int[] il = new int[n], ir = new int[n]; int lIndex = 0, rIndex = 0; for (l += b, r += b; l < r; l >>= 1, r >>= 1) { if (1 == (1 & l)) { il[lIndex++] = l++; } if (1 == (1 & r)) { ir[rIndex++] = --r; } } int[] result = new int[lIndex + rIndex]; System.arraycopy(il, 0, result, 0, lIndex); for (int i = rIndex - 1; i >= 0; i--) { result[lIndex++] = ir[i]; } return result; } /** * [l, r) に対応する index に対してクエリを投げる(区間は昇順) * * @param l * @param r * @param f f(i) : 区間 i にクエリを投げる */ void apply(int l, int r, IntConsumer f) { if (!((0 <= l) && (l <= r) && (r <= n))) { throw new IllegalArgumentException("l=" + l + ", r=" + r + ", n=" + n); } for (int i : range(l, r)) { f.accept(i); } } } static interface IntBiConsumer { void accept(int a, int b); } static interface IntTriConsumer { void accept(int a, int b, int c); } /** * Union Find(Disjoint Set Union)<br/> * https://github.com/NyaanNyaan/library/blob/master/data-structure/union-find.hpp を参考に作成 */ private static class UnionFind { final int[] data; UnionFind(int n) { data = new int[n]; Arrays.fill(data, -1); } int find(int k) { return (data[k] < 0) ? k : (data[k] = find(data[k])); } @SuppressWarnings("unused") boolean unite(int x, int y) { return unite(x, y, null); } boolean unite(int x, int y, IntBiConsumer f) { if ((x = find(x)) == (y = find(y))) { return false; } if (data[x] > data[y]) { int t = x; x = y; y = t; } data[x] += data[y]; data[y] = x; if (null != f) { f.accept(x, y); } return true; } @SuppressWarnings("unused") int size(int k) { return -data[find(k)]; } boolean same(int x, int y) { return find(x) == find(y); } } }