제출 #544615

#제출 시각아이디문제언어결과실행 시간메모리
544615rainboyDemarcation (BOI14_demarcation)C11
100 / 100
145 ms8460 KiB
/* upsolve after reading analysis */
#include <stdio.h>

#define N	100000
#define M	(N * 2)

unsigned int X = 12345;

int abs(int a) { return a > 0 ? a : -a; }

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

void flip(int *xx, int *yy, int n) {
	int i, j, tmp;

	for (i = 0, j = n - 1; i < j; i++, j--) {
		tmp = xx[i], xx[i] = xx[j], xx[j] = tmp;
		tmp = yy[i], yy[i] = yy[j], yy[j] = tmp;
	}
	for (i = 0; i < n; i++)
		xx[i] = -xx[i];
}

void rotate(int *xx, int *yy, int n) {
	int i, tmp;

	for (i = 0; i < n; i++)
		tmp = xx[i], xx[i] = -yy[i], yy[i] = tmp;
}

int check1(int *xx1, int *yy1, int *xx2, int *yy2, int n) {
	int i_, j_, i, j, x, y;

	i_ = -1;
	for (i = 0; i < n; i++)
		if (i_ == -1 || xx1[i_] > xx1[i] || xx1[i_] == xx1[i] && yy1[i_] > yy1[i])
			i_ = i;
	j_ = -1;
	for (j = 0; j < n; j++)
		if (j_ == -1 || xx2[j_] > xx2[j] || xx2[j_] == xx2[j] && yy2[j_] > yy2[j])
			j_ = j;
	x = xx1[i_] - xx2[j_], y = yy1[i_] - yy2[j_];
	for (i = 0; i < n; i++)
		if (xx1[(i + i_) % n] - xx2[(i + j_) % n] != x || yy1[(i + i_) % n] - yy2[(i + j_) % n] != y)
			return 0;
	return 1;
}

int check_(int *xx1, int *yy1, int *xx2, int *yy2, int n) {
	int a, b;

	for (a = 0; a < 2; a++) {
		for (b = 0; b < 4; b++) {
			if (check1(xx1, yy1, xx2, yy2, n))
				return 1;
			rotate(xx2, yy2, n);
		}
		flip(xx2, yy2, n);
	}
	return 0;
}

int xx[N], yy[N], n;

int check(int i_, int j_, int x) {
	static int xx1[N], yy1[N], xx2[N], yy2[N];
	int n1, n2, i;

	n1 = 0;
	i = (i_ + 1) % n;
	while (1) {
		if (i == (i_ + 1) % n) {
			if (xx[i] != x) {
				xx1[n1] = x, yy1[n1] = yy[i], n1++;
				xx1[n1] = xx[i], yy1[n1] = yy[i], n1++;
			}
		} else if (i == j_) {
			if (xx[i] != x) {
				xx1[n1] = xx[i], yy1[n1] = yy[i], n1++;
				xx1[n1] = x, yy1[n1] = yy[i], n1++;
			}
			break;
		} else
			xx1[n1] = xx[i], yy1[n1] = yy[i], n1++;
		i = (i + 1) % n;
	}
	n2 = 0;
	i = (j_ + 1) % n;
	while (1) {
		if (i == (j_ + 1) % n) {
			if (xx[i] != x) {
				xx2[n2] = x, yy2[n2] = yy[i], n2++;
				xx2[n2] = xx[i], yy2[n2] = yy[i], n2++;
			}
		} else if (i == i_) {
			if (xx[i] != x) {
				xx2[n2] = xx[i], yy2[n2] = yy[i], n2++;
				xx2[n2] = x, yy2[n2] = yy[i], n2++;
			}
			break;
		} else
			xx2[n2] = xx[i], yy2[n2] = yy[i], n2++;
		i = (i + 1) % n;
	}
	return n1 == n2 && check_(xx1, yy1, xx2, yy2, n1);
}

int xx_[M], kk1[M], kk2[M], tt[M], m;
int iq[1 + M], pq[M], cnt;

int lt(int i, int j) {
	return xx_[i] != xx_[j] ? xx_[i] < xx_[j] : tt[i] > tt[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 x, int k1, int k2, int t) {
	int i = m++;

	xx_[i] = x, kk1[i] = k1, kk2[i] = k2, tt[i] = t;
	pq[i] = ++cnt, pq_up(i);
}

int pq_remove_first() {
	int i = iq[1], j = iq[cnt--];

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

int zz[1 + N], ll[1 + N], rr[1 + N], kk[1 + N], _, u_, l_, r_;

int node(int k) {
	zz[_] = rand_();
	ll[_] = rr[_] = 0;
	kk[_] = k;
	return _++;
}

void split(int u, int k) {
	int c;

	if (u == 0) {
		u_ = l_ = r_ = 0;
		return;
	}
	c = yy[k] - yy[kk[u]];
	if (c < 0) {
		split(rr[u], k);
		rr[u] = l_, l_ = u;
	} else if (c > 0) {
		split(ll[u], k);
		ll[u] = r_, r_ = u;
	} else {
		u_ = u, l_ = ll[u], r_ = rr[u];
		ll[u] = rr[u] = 0;
	}
}

int merge(int u, int v) {
	if (u == 0)
		return v;
	if (v == 0)
		return u;
	if (zz[u] < zz[v]) {
		rr[u] = merge(rr[u], v);
		return u;
	} else {
		ll[v] = merge(u, ll[v]);
		return v;
	}
}

void tr_add(int k) {
	split(u_, k);
	u_ = merge(merge(l_, node(k)), r_);
}

void tr_remove(int k) {
	split(u_, k);
	u_ = merge(l_, r_);
}

int tr_lower(int k) {
	int u = u_, k_ = -1;

	while (u)
		if (yy[kk[u]] > yy[k])
			k_ = kk[u], u = rr[u];
		else
			u = ll[u];
	return k_;
}

int tr_higher(int k) {
	int u = u_, k_ = -1;

	while (u)
		if (yy[kk[u]] < yy[k])
			k_ = kk[u], u = ll[u];
		else
			u = rr[u];
	return k_;
}

long long pp[N * 2];

void add(int i, int j, int x_) {
	if (xx[i] < xx[(i + 1) % n] && xx[j] > xx[(j + 1) % n]) {
		long long p, x;
		int x1, x2, x3, x4;

		p = j < i - 1 ? pp[i - 1] - pp[j] : pp[i - 1 + n] - pp[j];
		x1 = xx[i], x2 = xx[(j + 1) % n];
		if ((x = pp[n - 1] / 2 - p + x1 + x2) % 2 == 0) {
			x /= 2;
			x3 = xx[(i + 1) % n], x4 = xx[j];
			if (x >= x_ && x <= x3 && x <= x4)
				pq_add(x, i, j, 0);
		}
		x_ = 0;
	}
}

int main() {
	int i, i_, j, r, tmp;

	scanf("%d", &n);
	i_ = -1;
	for (i = 0; i < n; i++) {
		scanf("%d%d", &xx[i], &yy[i]);
		if (i_ == -1 || xx[i_] > xx[i] || xx[i_] == xx[i] && yy[i_] > yy[i])
			i_ = i;
	}
	if (xx[(i_ + 1) % n] != xx[i_])
		for (i = 0, j = n - 1; i < j; i++, j--) {
			tmp = xx[i], xx[i] = xx[j], xx[j] = tmp;
			tmp = yy[i], yy[i] = yy[j], yy[j] = tmp;
		}
	for (i = 0; i < n * 2; i++)
		pp[i] = abs(xx[i % n] - xx[(i + 1) % n]) + abs(yy[i % n] - yy[(i + 1) % n]);
	for (i = 1; i < n * 2; i++)
		pp[i] += pp[i - 1];
	if (pp[n - 1] % 2 != 0) {
		printf("NO\n");
		return 0;
	}
	for (r = 0; r < 2; r++) {
		int i_, j_, x_;

		m = 0, cnt = 0;
		_ = 1, u_ = 0;
		for (i = 0; i < n; i++)
			if (xx[i] != xx[(i + 1) % n]) {
				int x1 = xx[i], x2 = xx[(i + 1) % n];

				if (x1 > x2)
					tmp = x1, x1 = x2, x2 = tmp;
				pq_add(x1, i, i, 1), pq_add(x2, i, i, -1);
			}
		i_ = -1, j_ = -1, x_ = -1;
		while (cnt) {
			int h = pq_remove_first(), l, r;

			if (tt[h] == 1) {
				i = kk1[h], l = tr_lower(i), r = tr_higher(i);
				tr_add(i);
				if (l != -1)
					add(l, i, xx_[h]);
				if (r != -1)
					add(i, r, xx_[h]);
			} else if (tt[h] == -1) {
				i = kk1[h], l = tr_lower(i), r = tr_higher(i);
				tr_remove(i);
				if (l != -1 && r != -1)
					add(l, r, xx_[h] + 1);
			} else
				if (tr_higher(kk1[h]) == kk2[h]) {
					i_ = kk1[h], j_ = kk2[h], x_ = xx_[h];
					break;
				}
		}
		if (i_ != -1 && j_ != -1 && check(i_, j_, x_)) {
			if (r == 0)
				printf("%d %d %d %d\n", x_, yy[i_], x_, yy[j_]);
			else
				printf("%d %d %d %d\n", yy[i_], -x_, yy[j_], -x_);
			return 0;
		}
		rotate(xx, yy, n);
	}
	printf("NO\n");
	return 0;
}

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

demarcation.c: In function 'check1':
demarcation.c:38:57: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   38 |   if (i_ == -1 || xx1[i_] > xx1[i] || xx1[i_] == xx1[i] && yy1[i_] > yy1[i])
      |                                       ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
demarcation.c:42:57: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   42 |   if (j_ == -1 || xx2[j_] > xx2[j] || xx2[j_] == xx2[j] && yy2[j_] > yy2[j])
      |                                       ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
demarcation.c: In function 'main':
demarcation.c:254:53: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  254 |   if (i_ == -1 || xx[i_] > xx[i] || xx[i_] == xx[i] && yy[i_] > yy[i])
      |                                     ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
demarcation.c:250:2: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  250 |  scanf("%d", &n);
      |  ^~~~~~~~~~~~~~~
demarcation.c:253:3: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  253 |   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...