제출 #545907

#제출 시각아이디문제언어결과실행 시간메모리
545907rainboyBuilding Bridges (CEOI17_building)C11
100 / 100
94 ms8656 KiB
#include <stdio.h>

#define N	100000
#define INF	0x3f3f3f3f3f3f3f3fLL

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

unsigned int X = 12345;

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

long long xx[N], yy[N];

long long cross2(long long x1, long long y1, long long x2, long long y2) {
	return x1 * y2 - x2 * y1;
}

long long cross(int i, int j, int k) {
	return cross2(xx[j] - xx[i], yy[j] - yy[i], xx[k] - xx[i], yy[k] - yy[i]);
}

int zz[1 + N * 2], ll[1 + N * 2], rr[1 + N * 2], ii[1 + N * 2], jj[1 + N * 2], u_, l_, r_;

int node(int i, int j) {
	static int _ = 1;

	zz[_] = rand_();
	ii[_] = i, jj[_] = j;
	return _++;
}

void split_x(int u, int i) {
	if (u == 0) {
		l_ = r_ = 0;
		return;
	}
	if (xx[ii[u]] < xx[i] || xx[ii[u]] == xx[i] && yy[ii[u]] <= yy[i]) {
		split_x(rr[u], i);
		rr[u] = l_, l_ = u;
	} else {
		split_x(ll[u], i);
		ll[u] = r_, r_ = u;
	}
}

int mode;

int compare(int i, int j, int k) {
	return (mode == 0) == (cross(i, j, k) > 0) ? -1 : 1;
}

void split_c(int u, int i) {
	if (u == 0) {
		l_ = r_ = 0;
		return;
	}
	if (compare(ii[u], jj[u], i) < 0) {
		split_c(rr[u], i);
		rr[u] = l_, l_ = u;
	} else {
		split_c(ll[u], i);
		ll[u] = r_, r_ = u;
	}
}

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

int first(int u) { return ll[u] == 0 ? u : first(ll[u]); }
int last(int u) { return rr[u] == 0 ? u : last(rr[u]); }

int il, ir;

void update(int i) {
	if (il == -1)
		il = ir = i;
	else if (xx[il] > xx[i] || xx[il] == xx[i] && yy[il] > yy[i]) {
		mode = 1, split_c(u_, i), u_ = merge(node(i, r_ ? ii[first(r_)] : ir), r_);
		il = i;
	} else if (xx[ir] < xx[i] || xx[ir] == xx[i] && yy[ir] < yy[i]) {
		mode = 0, split_c(u_, i), u_ = merge(l_, node(l_ ? jj[last(l_)] : il, i));
		ir = i;
	} else {
		int u, l, r;

		if (il == ir)
			return;
		split_x(u_, i);
		l = l_, r = r_, u = last(l);
		if (cross(ii[u], jj[u], i) < 0) {
			mode = 0, split_c(l, i), l = merge(l_, node(l_ ? jj[last(l_)] : il, i));
			mode = 1, split_c(r, i), r = merge(node(i, r_ ? ii[first(r_)] : ir), r_);
		}
		u_ = merge(l, r);
	}
}

long long eval(int i, int x, int y) {
	return xx[i] * x + yy[i] * y;
}

long long query(int x, int y) {
	int u;
	long long z;

	if (il == ir)
		return eval(il, x, y);
	u = u_, z = -INF;
	while (u) {
		long long zi = eval(ii[u], x, y), zj = eval(jj[u], x, y);
		
		z = max(z, max(zi, zj));
		u = zi > zj ? ll[u] : rr[u];
	}
	return z;
}

int main() {
	static int hh[N];
	static long long ww[N], dp[N];
	int n, i;

	scanf("%d", &n);
	for (i = 0; i < n; i++)
		scanf("%d", &hh[i]);
	for (i = 0; i < n; i++)
		scanf("%lld", &ww[i]);
	for (i = 1; i < n; i++)
		ww[i] += ww[i - 1];
	il = ir = -1;
	dp[0] = 0;
	xx[0] = hh[0] * 2, yy[0] = dp[0] + (long long) hh[0] * hh[0] - ww[0], update(0);
	for (i = 1; i < n; i++) {
		dp[i] = -query(hh[i], -1) + (long long) hh[i] * hh[i] + ww[i - 1];
		xx[i] = hh[i] * 2, yy[i] = dp[i] + (long long) hh[i] * hh[i] - ww[i], update(i);
	}
	printf("%lld\n", dp[n - 1]);
	return 0;
}

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

building.c: In function 'split_x':
building.c:39:46: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   39 |  if (xx[ii[u]] < xx[i] || xx[ii[u]] == xx[i] && yy[ii[u]] <= yy[i]) {
      |                           ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
building.c: In function 'update':
building.c:90:45: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   90 |  else if (xx[il] > xx[i] || xx[il] == xx[i] && yy[il] > yy[i]) {
      |                             ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
building.c:93:47: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   93 |  } else if (xx[ir] < xx[i] || xx[ir] == xx[i] && yy[ir] < yy[i]) {
      |                               ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
building.c: In function 'main':
building.c:136:2: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  136 |  scanf("%d", &n);
      |  ^~~~~~~~~~~~~~~
building.c:138:3: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  138 |   scanf("%d", &hh[i]);
      |   ^~~~~~~~~~~~~~~~~~~
building.c:140:3: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  140 |   scanf("%lld", &ww[i]);
      |   ^~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...