Submission #466854

#TimeUsernameProblemLanguageResultExecution timeMemory
466854rainboyHexagonal Territory (APIO21_hexagon)C++17
100 / 100
815 ms75116 KiB
#include "hexagon.h" #include <stdlib.h> #include <string.h> #include <vector> using namespace std; typedef vector<int> vi; const int N = 200000, MD = 1000000007, V2 = 500000004, V6 = 166666668; int min(int a, int b) { return a < b ? a : b; } int max(int a, int b) { return a > b ? a : b; } int abs_(int a) { return a > 0 ? a : -a; } unsigned int X = 12345; int rand_() { return (X *= 3) >> 1; } int dx[] = { 1, 1, 0, -1, -1, 0 }; int dy[] = { 0, 1, 1, 0, -1, -1 }; int sum1(int n) { return (long long) n * (n + 1) % MD * V2 % MD; } int sum2(int n) { return (long long) n * (n + 1) % MD * (n * 2 + 1) % MD * V6 % MD; } long long cross2(int x1, int y1, int x2, int y2) { return (long long) x1 * y2 - (long long) x2 * y1; } long long cross(int x0, int y0, int x1, int y1, int x2, int y2) { return cross2(x1 - x0, y1 - y0, x2 - x0, y2 - y0); } int hh[N], len[N], ii[N * 2], xx[N], yy[N], xx_[N * 2 * 2 * 2], yy_[N * 2 * 2], n, n_, n1; int compare(int i, int j) { int i0 = i >> 1, i1 = (i0 + 1) % n, j0 = j >> 1, j1 = (j0 + 1) % n, tmp; long long c; if ((i & 1) != 0) tmp = i0, i0 = i1, i1 = tmp; if ((j & 1) != 0) tmp = j0, j0 = j1, j1 = tmp; if (yy[i0] != yy[j0]) return yy[i0] - yy[j0]; if (xx[i0] != xx[j0]) return xx[i0] - xx[j0]; if ((yy[i1] < yy[i0]) != (yy[j1] < yy[j0])) return yy[i1] < yy[i0] ? -1 : 1; c = cross(xx[i0], yy[i0], xx[i1], yy[i1], xx[j1], yy[j1]); if (yy[i1] < yy[i0]) c = -c; return c == 0 ? 0 : (c < 0 ? -1 : 1); } 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) { int c = compare(ii[j], i_); if (c == 0) j++; else if (c < 0) { 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 zz[1 + N], ll[1 + N], rr[1 + N], ii_[1 + N], _, u_, l_, r_; int node(int i) { zz[_] = rand_(); ll[_] = rr[_] = 0; ii_[_] = i; return _++; } int compare_(int i, int j) { int i_ = (i + 1) % n, j_ = (j + 1) % n, tmp; long long c1, c2; if (i == j) return 0; if (yy[i] > yy[i_]) tmp = i, i = i_, i_ = tmp; if (yy[j] > yy[j_]) tmp = j, j = j_, j_ = tmp; c1 = cross(xx[i], yy[i], xx[i_], yy[i_], xx[j], yy[j]); c2 = cross(xx[i], yy[i], xx[i_], yy[i_], xx[j_], yy[j_]); if (c1 == 0 || c2 == 0 || (c1 > 0) == (c2 > 0)) return c1 + c2 < 0 ? -1 : 1; c1 = cross(xx[j], yy[j], xx[j_], yy[j_], xx[i], yy[i]); c2 = cross(xx[j], yy[j], xx[j_], yy[j_], xx[i_], yy[i_]); return c1 + c2 > 0 ? -1 : 1; } void split(int u, int i) { int c; if (u == 0) { u_ = l_ = r_ = 0; return; } c = compare_(ii_[u], i); if (c < 0) { split(rr[u], i); rr[u] = l_, l_ = u; } else if (c > 0) { split(ll[u], i); 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; } } 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 y_; int eval(int i) { return xx[i] + (xx[(i + 1) % n] - xx[i]) / (yy[(i + 1) % n] - yy[i]) * (y_ - yy[i]); } int *ej[N * 2], eo[N * 2]; void append(int i, int j) { int o = eo[i]++; if (o >= 2 && (o & o - 1) == 0) ej[i] = (int *) realloc(ej[i], o * 2 * sizeof *ej[i]); ej[i][o] = j; } int ii1[N]; int begin_trapezoid(int i, int j) { int i1 = ii1[i] = n1++; ej[i1 << 1 | 0] = (int *) malloc(2 * sizeof *ej[i1 << 1 | 0]), eo[i1 << 1 | 0] = 0; ej[i1 << 1 | 1] = (int *) malloc(2 * sizeof *ej[i1 << 1 | 1]), eo[i1 << 1 | 1] = 0; append(i1 << 1 | 0, i1 << 1 | 1), append(i1 << 1 | 1, i1 << 1 | 0); xx_[(i1 << 1 | 0) << 1 | 0] = eval(i), xx_[(i1 << 1 | 0) << 1 | 1] = eval(j), yy_[i1 << 1 | 0] = y_; return i1; } int end_trapezoid(int i, int j) { int i1 = ii1[i]; xx_[(i1 << 1 | 1) << 1 | 0] = eval(i), xx_[(i1 << 1 | 1) << 1 | 1] = eval(j), yy_[i1 << 1 | 1] = y_; return i1; } int intersect(int i, int j) { return min(xx_[i << 1 | 1], xx_[j << 1 | 1]) - max(xx_[i << 1 | 0], xx_[j << 1 | 0]) + 1; } int sum_trapezoid(int i, int z) { int j, x, y, d; j = i ^ 1, y = abs_(yy_[j] - yy_[i]); if (y == 0) return (long long) z * -intersect(i, j) % MD; d = ((xx_[j << 1 | 1] - xx_[j << 1 | 0]) - (xx_[i << 1 | 1] - xx_[i << 1 | 0])) / y; x = xx_[i << 1 | 1] - xx_[i << 1 | 0] + 1; /* * sum_{h=1}^{y-1} (x + d h) (z + h) * = sum_{h=1}^{y-1} d h^2 + (x + z d) h + x z * = d sum2(y - 1) + (x + z d) sum1(y - 1) + x z (y - 1) */ return ((long long) sum2(y - 1) * d % MD + (long long) sum1(y - 1) * (x + z * d) % MD + (long long) + (y - 1) * x % MD * z % MD) % MD; } void process(int i, int j) { int l, r, p, q, type, hasi, hasj, a, b, c; split(u_, i), hasi = u_ != 0, l = l_; split(r_, j), hasj = u_ != 0, r = r_; p = l ? ii_[last(l)] : -1, q = r ? ii_[first(r)] : -1, type = p != -1 && ii1[p] != -1; if (!hasi && !hasj) { if (type == 0) begin_trapezoid(i, j); else { a = end_trapezoid(p, q), b = begin_trapezoid(p, i), c = begin_trapezoid(j, q); append(a << 1 | 1, b << 1 | 0), append(b << 1 | 0, a << 1 | 1); append(a << 1 | 1, c << 1 | 0), append(c << 1 | 0, a << 1 | 1); } u_ = merge(merge(l, merge(node(i), node(j))), r); } else if (!hasi && hasj) { if (type == 0) a = end_trapezoid(j, q), b = begin_trapezoid(i, q); else a = end_trapezoid(p, j), b = begin_trapezoid(p, i); append(a << 1 | 1, b << 1 | 0), append(b << 1 | 0, a << 1 | 1); u_ = merge(merge(l, node(i)), r); } else if (hasi && !hasj) { if (type == 0) a = end_trapezoid(i, q), b = begin_trapezoid(j, q); else a = end_trapezoid(p, i), b = begin_trapezoid(p, j); append(a << 1 | 1, b << 1 | 0), append(b << 1 | 0, a << 1 | 1); u_ = merge(merge(l, node(j)), r); } else { if (type == 0) end_trapezoid(i, j); else { a = end_trapezoid(p, i), b = end_trapezoid(j, q), c = begin_trapezoid(p, q); append(a << 1 | 1, c << 1 | 0), append(c << 1 | 0, a << 1 | 1); append(b << 1 | 1, c << 1 | 0), append(c << 1 | 0, b << 1 | 1); } u_ = merge(l, r); } } void trapezoidal_decomposition() { int h, i, j, x, y; n_ = 0, x = 0, y = 0; for (i = 0; i < n; i++) { xx[i] = x, yy[i] = y; x += dx[hh[i]] * len[i], y += dy[hh[i]] * len[i]; } n_ = 0; for (i = 0; i < n; i++) if (yy[i] != yy[(i + 1) % n]) ii[n_++] = i << 1 | 0, ii[n_++] = i << 1 | 1; sort(ii, 0, n_); memset(ii1, -1, n * sizeof *ii1), n1 = 0, _ = 1; for (h = 0; h < n_; h += 2) { i = ii[h] >> 1, j = ii[h + 1] >> 1; y_ = yy[(ii[h] & 1) == 0 ? i : (i + 1) % n], process(i, j); } } int dfs(int p, int i, int d) { int o, sum; sum = (long long) d * (xx_[i << 1 | 1] - xx_[i << 1 | 0] + 1) % MD; for (o = eo[i]; o--; ) { int j = ej[i][o]; if (j != p) { sum = (sum + dfs(i, j, d + abs_(yy_[i] - yy_[j]))) % MD; if ((i ^ j) == 1) sum = (sum + sum_trapezoid(i, d)) % MD; else sum = (sum - (long long) d * intersect(i, j)) % MD; } } return sum; } int solve() { int i, ans; trapezoidal_decomposition(); ans = 0; for (i = 0; i < n1 * 2; i++) if (yy_[i] == 0 && xx_[i << 1 | 0] <= 0 && 0 <= xx_[i << 1 | 1]) { ans = dfs(-1, i, 0); break; } for (i = 0; i < n1 * 2; i++) free(ej[i]); return ans; } int draw_territory(int n_, int a, int b, vi hh_, vi len_) { int h, i, x, y, ans1, ans2; long long area2, boundary, internal; n = n_; for (i = 0; i < n; i++) hh[i] = hh_[i] - 1, len[i] = len_[i]; x = 0, y = 0, area2 = 0, boundary = 0; for (i = 0; i < n; i++) { h = hh[i]; area2 += cross2(x, y, x + dx[h] * len[i], y + dy[h] * len[i]); boundary += len[i]; x += dx[h] * len[i], y += dy[h] * len[i]; } if (area2 < 0) area2 = -area2; internal = (area2 - boundary) / 2 + 1; ans1 = (boundary + internal) % MD; ans2 = 0; for (h = 0; h < 3; h++) { ans2 = (ans2 + solve()) % MD; for (i = 0; i < n; i++) hh[i] = (hh[i] + 1) % 6; } if (ans2 < 0) ans2 += MD; ans2 = (long long) ans2 * V2 % MD; return ((long long) ans1 * a + (long long) ans2 * b) % MD; }

Compilation message (stderr)

hexagon.cpp: In function 'void append(int, int)':
hexagon.cpp:161:23: warning: suggest parentheses around '-' in operand of '&' [-Wparentheses]
  161 |  if (o >= 2 && (o & o - 1) == 0)
      |                     ~~^~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...