제출 #1125297

#제출 시각아이디문제언어결과실행 시간메모리
1125297sleepntsheepRoad Construction (JOI21_road_construction)C11
0 / 100
10094 ms92248 KiB
#include <stdio.h>
#include <stdlib.h>

#define N 250000
#define M (250000 * 30)

#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], L[M], R[M], jj,
    eo;

int x3[N], y3[N];
long long x[N], y[N],
     x2[N], y2[N],
     ee[N * 2];

long long A[M]; /* persistent segment tree */

int direction(long long x)
{
  return x > 0 ? 1 : (x ? -1 : 0);
}

int cc(const void *i, const void *j)
{
  return direction(*(long long*)i - *(long long*)j);
}

int ccx(const void *i, const void *j)
{
  return direction(x[*(int*)i] - x[*(int*)j]);
}

int ccy(const void *i, const void *j)
{
  return direction(y[*(int*)i] - y[*(int*)j]);
}

int lower_bound(long long *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(long long *a, int n, int 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, long long 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);
}

long long 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 count(long long v)
{
  long long z;
  int i, p_left, p_right;

  jj = 0;
  rt[0] = 0;

  for (i = 0; i < n; ++i)
    rt[i + 1] = persist_add(rt[i], 0, n, y3[ii[i]], 1);

  z = 0;

  p_left = 0;
  p_right = 0;
  for (i = 0; i < n; ++i)
  {
    int y_1, y_2;

    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;
    assert_(p_left <= i);
    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 / 2;
}

void input()
{
  int i, xx, yy;

  scanf("%d%d", &n, &k);
  for (i = 0; i < n; ++i)
  {
    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, cc);
  qsort(y2, n, sizeof *y2, cc);

  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]);
  }
}

unsigned kth(int k)
{
  unsigned lower, upper;
  lower = 0;
  upper = 4e9 + 1;
  while (upper - lower > 1)
  {
    unsigned mid;
    mid = lower + (upper - lower) / 2;
    if (count(mid) >= k)
      upper = mid;
    else 
      lower = mid;
  }
  return upper;
}

long long max(long long a, long long b)
{
  return a > b ? a : b;
}

long long distance(int i, int j)
{
  return max(llabs(x[i] - x[j]), llabs(y[i] - y[j]));
}

void make_edge(int i, int j, long long threshold)
{
  long long dd;
  dd = distance(i, j);

  if (eo >= k)
    return;
  if (persist_sum(rt[i], 0, n, j, j))
    return;
  if (dd > threshold)
    return;

  rt[i] = persist_add(rt[i], 0, n, j, 1);
  ee[eo++] = distance(i, j);
}

void fetch_not_exceeding(long long d)
{
  int i, j, k;

  j = 0;
  for (i = 0; i < n; ++i)
  {
    while (j < n && x[ii[j]] <= x[ii[i]] + d)
      ++j;
    for (k = i + 1; k < j; ++k)
      make_edge(ii[i], ii[k], d);
  }

  j = 0;
  for (i = 0; i < n; ++i)
  {
    while (j < n && y[ii2[j]] <= y[ii2[i]] + d)
      ++j;
    for (k = i + 1; k < j; ++k)
      make_edge(ii2[i], ii2[k], d);
  }
}

void answer()
{
  unsigned last;
  int i;

  last = kth(k);

  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, cc);
  for (i = 0; i < k; ++i)
      printf("%lld\n", ee[i]);
}

void debug()
{
  int i;
  return;
  printf("x2[] : ");
  for (i = 0; i < n; ++i) printf(" %lld", x2[i]);
  puts("");
  printf("y2[] : ");
  for (i = 0; i < n; ++i) printf(" %lld", y2[i]);
  puts("");

  printf("x3[] : ");
  for (i = 0; i < n; ++i) printf(" %d", x3[i]);
  puts("");
  printf("y3[] : ");
  for (i = 0; i < n; ++i) printf(" %d", y3[i]);
  puts("");
  printf("ii[] : ");
  for (i = 0; i < n; ++i) printf(" %d", ii[i]);
  puts("");
  printf("count(1) = %lld\n",count(1));
  printf("count(10) = %lld\n",count(10));
}

int main()
{
  input();
  prepare();
  debug();
  answer();
  return 0;
}

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

road_construction.c: In function 'input':
road_construction.c:142:3: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  142 |   scanf("%d%d", &n, &k);
      |   ^~~~~~~~~~~~~~~~~~~~~
road_construction.c:145:5: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  145 |     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...