Submission #545929

#TimeUsernameProblemLanguageResultExecution timeMemory
545929rainboyBuilding Skyscrapers (CEOI19_skyscrapers)C11
100 / 100
338 ms35516 KiB
#include <stdio.h>
#include <string.h>

#define N	150000

int min(int a, int b) { return a < b ? a : b; }

unsigned int X = 12345;

int rand_() {
	return (X *= 3) >> 1;
}

int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1 };
int dy[] = { 1, 0, -1, 0, 1, 1, -1, -1 };

int xx[N], yy[N];

void sort(int *ii, int l, int r) {
	while (l < r) {
		int i = l, j = l, k = r, i_ = ii[l + rand_() % (r - l)], tmp;

		while (j < k)
			if (ii[j] == i_)
				j++;
			else if (xx[ii[j]] < xx[i_] || xx[ii[j]] == xx[i_] && yy[ii[j]] < yy[i_]) {
				tmp = ii[i], ii[i] = ii[j], ii[j] = tmp;
				i++, j++;
			} else {
				k--;
				tmp = ii[j], ii[j] = ii[k], ii[k] = tmp;
			}
		sort(ii, l, i);
		l = k;
	}
}

int ds[N * 8];

int find(int i) {
	return ds[i] < 0 ? i : (ds[i] = find(ds[i]));
}

void join(int i, int j) {
	i = find(i);
	j = find(j);
	if (i == j)
		return;
	if (ds[i] > ds[j])
		ds[i] = j;
	else {
		if (ds[i] == ds[j])
			ds[i]--;
		ds[j] = i;
	}
}

int jj[N][8], ta[N], tb[N];

void dfs(int f, int i) {
	static int time;
	int h;

	ta[i] = tb[i] = ++time;
	for (h = 0; h < 8; h++) {
		int j = jj[i][h];

		if (j == -1)
			continue;
		if (!ta[j]) {
			dfs(i * 8 + h, j);
			if (tb[j] < ta[i])
				join(i * 8 + h, f);
			tb[i] = min(tb[i], tb[j]);
		} else if (ta[j] < ta[i]) {
			join(i * 8 + h, f);
			tb[i] = min(tb[i], ta[j]);
		}
	}
}

int next[N * 4], prev[N * 4], kk[N];

int ok(int i) {
	int h, r, j, k;

	r = -1;
	for (h = 0; h < 8; h++)
		if (jj[i / 4][h] != -1) {
			if (r == -1)
				r = find(i / 4 * 8 + h);
			else if (find(i / 4 * 8 + h) != r)
				return 0;
		}
	k = 1;
	for (j = next[i]; j != i && j / 4 == i / 4; j = next[j])
		k++;
	if (j == i)
		return 1;
	for (j = prev[i]; j / 4 == i / 4; j = prev[j])
		k++;
	return kk[i / 4] == k;
}

int pq[N], iq[1 + N], cnt;

int lt(int i, int j) { return i > j; }

int p2(int p) {
	return (p *= 2) > cnt ? 0 : (p < cnt && lt(iq[p + 1], iq[p]) ? p + 1 : p);
}

void pq_up(int i) {
	int p, q, j;

	for (p = pq[i]; (q = p / 2) && lt(i, j = iq[q]); p = q)
		iq[pq[j] = p] = j;
	iq[pq[i] = p] = i;
}

void pq_dn(int i) {
	int p, q, j;

	for (p = pq[i]; (q = p2(p)) && lt(j = iq[q], i); p = q)
		iq[pq[j] = p] = j;
	iq[pq[i] = p] = i;
}

void pq_add(int i) {
	if (!pq[i])
		pq[i] = ++cnt, pq_up(i);
}

void pq_remove(int i) {
	if (pq[i]) {
		int j = iq[cnt--];

		if (j != i)
			pq[j] = pq[i], pq_up(j), pq_dn(j);
		pq[i] = 0;
	}
}

int pq_first() { return iq[1]; }

int main() {
	static int ii[N], hh[N], ii_[N * 4], ans[N];
	int n, n_, t, h, i, j, k;

	scanf("%d%d", &n, &t);
	for (i = 0; i < n; i++) {
		scanf("%d%d", &xx[i], &yy[i]);
		ii[i] = i;
	}
	sort(ii, 0, n);
	memset(ds, -1, n * 8 * sizeof *ds);
	for (h = 0; h < 8; h++)
		for (i = 0, j = 0; i < n; i++) {
			int x = xx[ii[i]] + dx[h], y = yy[ii[i]] + dy[h];

			while (j < n && (xx[ii[j]] < x || xx[ii[j]] == x && yy[ii[j]] < y))
				j++;
			if (j < n && xx[ii[j]] == x && yy[ii[j]] == y) {
				join(ii[i] * 8 + h, ii[j] * 8 + h ^ 2);
				jj[ii[i]][h] = ii[j];
			} else
				jj[ii[i]][h] = -1;
		}
	dfs(-1, 0);
	for (i = 0; i < n; i++)
		if (!ta[i]) {
			printf("NO\n");
			return 0;
		}
	i = ii[0], h = 0, k = 0;
	do {
		hh[i] = h, kk[i]++, ii_[k++] = i * 4 + h;
		if (jj[i][h + 4] != -1)
			i = jj[i][h + 4], h = (h + 3) % 4;
		else if (jj[i][h] != -1)
			i = jj[i][h];
		else
			h = (h + 1) % 4;
	} while (i != ii[0] || h != 0);
	for (h = 0; h < k; h++)
		next[ii_[h]] = ii_[(h + 1) % k], prev[ii_[(h + 1) % k]] = ii_[h];
	for (h = 0; h < k; h++)
		if (ok(ii_[h]))
			pq_add(ii_[h] / 4);
		else
			pq_remove(ii_[h] / 4);
	n_ = 0;
	while (cnt) {
		int i_, j_;

		i = pq_first(), pq_remove(i);
		ans[n_++] = i;
		if (n_ == n)
			break;
		for (h = 0; h < 8; h++)
			if (jj[i][h] != -1)
				jj[jj[i][h]][h ^ 2] = -1, jj[i][h] = -1;
		i_ = i * 4 + hh[i];
		while (i_ / 4 == i)
			i_ = prev[i_];
		j_ = i * 4 + hh[i];
		while (j_ / 4 == i)
			j_ = next[j_];
		kk[i_ / 4]--, kk[j_ / 4]--;
		i = i_ / 4, h = i_ % 4, k = 0;
		do {
			hh[i] = h, kk[i]++, ii_[k++] = i * 4 + h;
			if (jj[i][h + 4] != -1)
				i = jj[i][h + 4], h = (h + 3) % 4;
			else if (jj[i][h] != -1)
				i = jj[i][h];
			else
				h = (h + 1) % 4;
		} while (i != j_ / 4 || h != j_ % 4);
		hh[i] = h, kk[i]++, ii_[k++] = i * 4 + h;
		for (h = 0; h + 1 < k; h++)
			next[ii_[h]] = ii_[h + 1], prev[ii_[h + 1]] = ii_[h];
		for (h = 0; h < k; h++)
			if (ok(ii_[h]))
				pq_add(ii_[h] / 4);
			else 
				pq_remove(ii_[h] / 4);
	}
	printf("YES\n");
	while (n_--)
		printf("%d\n", ans[n_] + 1);
	return 0;
}

Compilation message (stderr)

skyscrapers.c: In function 'sort':
skyscrapers.c:26:55: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   26 |    else if (xx[ii[j]] < xx[i_] || xx[ii[j]] == xx[i_] && yy[ii[j]] < yy[i_]) {
      |                                   ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
skyscrapers.c: In function 'main':
skyscrapers.c:161:53: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  161 |    while (j < n && (xx[ii[j]] < x || xx[ii[j]] == x && yy[ii[j]] < y))
      |                                      ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
skyscrapers.c:164:35: warning: suggest parentheses around arithmetic in operand of '^' [-Wparentheses]
  164 |     join(ii[i] * 8 + h, ii[j] * 8 + h ^ 2);
      |                         ~~~~~~~~~~^~~
skyscrapers.c:150:2: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  150 |  scanf("%d%d", &n, &t);
      |  ^~~~~~~~~~~~~~~~~~~~~
skyscrapers.c:152:3: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  152 |   scanf("%d%d", &xx[i], &yy[i]);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...