제출 #1125374

#제출 시각아이디문제언어결과실행 시간메모리
1125374sleepntsheepRoad Construction (JOI21_road_construction)C11
65 / 100
10093 ms150084 KiB
#pragma GCC optimize("Ofast,unroll-loops") #pragma GCC target("avx2,tune=native") #include <stdio.h> #include <stdlib.h> #define N 250000 #define M (250000 * 20 * 2) #define assert_(x) if (!((x))) __builtin_trap() int n, k, ii[N], /* indices sorted by x */ ii2[N], /* indices sorted by y */ rt[1 + N]; int x3[N], y3[N]; /* x2[x3[i]] = x[i] */ long long x[N], y[N]; /* inputs, transformed to (x+y, x-y) */ int x2[N], y2[N]; /* sorted x[] and y[] */ unsigned ee[N * 2]; /* answers */ int eo; int A[M], L[M], R[M], jj; /* persistent segment tree */ int *tt[N * 2], to[N * 2]; /* merge sort tree */ int pool[M], alloc; /* for merge sort tree */ int *pool_alloc(int n); long long max(long long a, long long b); unsigned distance(int i, int j); void input(); void prepare(); void answer(); int lower_bound(int *a, int n, long long x); int prev_upper_bound(int *a, int n, long long x); int persist_new(int lc, int rc, int v); int persist_add(int v, int l, int r, int p, int k); int persist_sum(int v, int l, int r, int x, int y); void fetch_not_exceeding(unsigned dist); void construct_merge_sort_tree(); unsigned kth(int k); long long count(long long v); int direction(long long x) { return x > 0 ? 1 : (x ? -1 : 0); } int cci(const void *i, const void *j) { return direction(*(int*)i * 1ll - *(int*)j); } int ccu(const void *i, const void *j) { return direction((long long)(*(unsigned*)i) - (long long)(*(unsigned*)j)); } int ccx(const void *i, const void *j) { return direction((long long)x[*(int*)i] - (long long)x[*(int*)j]); } int ccy(const void *i, const void *j) { return direction((long long)y[*(int*)i] - (long long)y[*(int*)j]); } int main() { input(); prepare(); construct_merge_sort_tree(); answer(); return 0; } void input() { int i, xx, yy; (void)scanf("%d%d", &n, &k); for (i = 0; i < n; ++i) { (void)scanf("%d%d", &xx, &yy); x[i] = xx + yy; y[i] = xx - yy; x2[i] = x[i]; y2[i] = y[i]; } } void prepare() { int i; qsort(x2, n, sizeof *x2, cci); qsort(y2, n, sizeof *y2, cci); for (i = 0; i < n; ++i) { ii[i] = i; ii2[i] = i; } qsort(ii, n, sizeof *ii, ccx); qsort(ii2, n, sizeof *ii2, ccy); for (i = 0; i < n; ++i) { x3[i] = lower_bound(x2, n, x[i]); y3[i] = lower_bound(y2, n, y[i]); } } void answer() { unsigned last; int i; last = kth(k); fprintf(stderr, "kth(%d) = %u\n", k, last); jj = 0; for (i = 0; i < n; ++i) rt[i] = 0; fetch_not_exceeding(last - 1); fetch_not_exceeding(last); qsort(ee, eo, sizeof *ee, ccu); for (i = 0; i < k; ++i) printf("%u\n", ee[i]); } int lower_bound(int *a, int n, long long x) { int lower, upper, mid; lower = -1; upper = n; while (upper - lower > 1) { mid = lower + (upper - lower) / 2; if (a[mid] >= x) upper = mid; else lower = mid; } return upper; } int prev_upper_bound(int *a, int n, long long x) { int lower, upper, mid; lower = -1; upper = n; while (upper - lower > 1) { mid = lower + (upper - lower) / 2; if (a[mid] <= x) lower = mid; else upper = mid; } return lower; } int persist_new(int lc, int rc, int v) { int i; i = ++jj; A[i] = A[lc] + A[rc] + v; L[i] = lc; R[i] = rc; return i; } int persist_add(int v, int l, int r, int p, int k) { if (l == r) return persist_new(0, 0, A[v] + k); if (p <= (l + r) / 2) return persist_new(persist_add(L[v], l, (l + r) / 2, p, k), R[v], 0); return persist_new(L[v], persist_add(R[v], (l + r) / 2 + 1, r, p, k), 0); } int persist_sum(int v, int l, int r, int x, int y) { if (r < x || y < l) return 0; if (x <= l && r <= y) return A[v]; return persist_sum(L[v], l, (l + r) / 2, x, y) + persist_sum(R[v], (l + r) / 2 + 1, r, x, y); } long long max(long long a, long long b) { return a > b ? a : b; } unsigned distance(int i, int j) { return max(llabs(x[i] - x[j]), llabs(y[i] - y[j])); } unsigned kth(int k) { unsigned lower, upper, mid; lower = 0; upper = 4e9 + 1; while (upper - lower > 1) { mid = lower + (upper - lower) / 2; if (count(mid) >= k) upper = mid; else lower = mid; } return upper; } void construct_merge_sort_tree() { int i, j; for (i = 0; i < n; ++i) for (j = x3[ii2[i]] + n; j; j /= 2) ++to[j]; for (i = 1; i < 2 * n; ++i) { tt[i] = pool_alloc(to[i]); to[i] = 0; } for (i = 0; i < n; ++i) for (j = x3[ii2[i]] + n; j; j /= 2) tt[j][to[j]++] = ii2[i]; } void make_edge(int i, int j) { if (i == j || eo >= k) return; if (persist_sum(rt[i], 0, n, j, j)) return; rt[i] = persist_add(rt[i], 0, n, j, 1); rt[j] = persist_add(rt[j], 0, n, i, 1); ee[eo++] = distance(i, j); } void fetch_in_node(int i, int v, long long dist) { int j, lower, upper, mid; lower = -1, upper = to[v]; while (upper - lower > 1) { mid = lower + (upper - lower) / 2; if (y[tt[v][mid]] >= y[i] - dist) upper = mid; else lower = mid; } j = upper; while (eo < k && j < to[v] && y[tt[v][j]] <= y[i] + dist) make_edge(i, tt[v][j++]); } void fetch_(int i, int l, int r, long long dist) { for (l += n, r += n + 1; l < r; l /= 2, r /= 2) { if (l & 1) fetch_in_node(i, l++, dist); if (r & 1) fetch_in_node(i, --r, dist); } } void fetch_not_exceeding(unsigned dist) { int w, i; for (i = 0; eo < k && i < n; ++i) { w = prev_upper_bound(x2, n, dist + x[i]); fetch_(i, x3[i], w, dist); } } void prepare_count() { static int f = 0; if (!f) ++f; else return; int i; if (!rt[1]) { jj = 0; rt[0] = 0; for (i = 0; i < n; ++i) rt[i + 1] = persist_add(rt[i], 0, n, y3[ii[i]], 1); } } long long count(long long v) { long long z; int i, p_left, p_right, y_1, y_2; prepare_count(); z = 0; p_left = 0; p_right = 0; for (i = 0; i < n; ++i) { while (p_right < n && x[ii[p_right]] <= v + x[ii[i]]) ++p_right; while (p_left < i && x[ii[p_left]] + v < x[ii[i]]) ++p_left; y_1 = lower_bound(y2, n, y[ii[i]] - v); y_2 = prev_upper_bound(y2, n, y[ii[i]] + v); z += persist_sum(rt[p_right], 0, n, y_1, y_2) - persist_sum(rt[p_left], 0, n, y_1, y_2); } return (z - n) / 2; } int *pool_alloc(int n) { int *u; u = pool + alloc; alloc += n; return u; }

컴파일 시 표준 에러 (stderr) 메시지

road_construction.c: In function 'input':
road_construction.c:86:9: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
   86 |   (void)scanf("%d%d", &n, &k);
      |         ^~~~~~~~~~~~~~~~~~~~~
road_construction.c:89:11: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
   89 |     (void)scanf("%d%d", &xx, &yy);
      |           ^~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...