제출 #1223909

#제출 시각아이디문제언어결과실행 시간메모리
1223909madamadam3자리 배치 (IOI18_seats)C++20
31 / 100
4093 ms204336 KiB
#include "seats.h" #include <bits/stdc++.h> using namespace std; using vi = vector<int>; const int NULLV = -100; struct Node { int C1, C2, R1, R2, area; Node() : C1(NULLV), C2(NULLV), R1(NULLV), R2(NULLV), area(0) {}; Node(int row, int col) : C1(col), C2(col), R1(row), R2(row), area(1) {}; Node(Node left, Node right) { if (left.C1 == NULLV && right.C1 == NULLV) C1 = NULLV, C2 = NULLV, R1 = NULLV, R2 = NULLV, area = 0; else if (left.C1 == NULLV) C1 = right.C1, C2 = right.C2, R1 = right.R1, R2 = right.R2, area = right.area; else if (right.C1 == NULLV) C1 = left.C1, C2 = left.C2, R1 = left.R1, R2 = left.R2, area = left.area; else { C1 = min({left.C1, left.C2, right.C1, right.C2}); C2 = max({left.C1, left.C2, right.C1, right.C2}); R1 = min({left.R1, left.R2, right.R1, right.R2}); R2 = max({left.R1, left.R2, right.R1, right.R2}); area = (C2 - C1 + 1) * (R2 - R1 + 1); } } }; struct SegTree { int n; vector<Node> st; vi rows, cols; SegTree() : n(0) {}; SegTree(int w, int h, vi &Rows, vi &Cols) { n = w*h; rows = Rows; cols = Cols; st.assign(4*n, Node()); build(0, 0, n); } Node build(int i, int l, int r) { if (l + 1 == r) return st[i] = Node(rows[l], cols[l]); int m = l + (r - l) / 2; return st[i] = Node(build(2*i+1, l, m), build(2*i+2, m, r)); } Node update(int i, int l, int r, int k, int vrow, int vcol) { if (!(l <= k && k < r)) return st[i]; if (l + 1 == r) return st[i] = Node(vrow, vcol); int m = l + (r - l) / 2; return st[i] = Node(update(2*i+1, l, m, k, vrow, vcol), update(2*i+2, m, r, k, vrow, vcol)); } Node query(int i, int l, int r, int ql, int qr) { if (r <= ql || qr <= l) return Node(); if (ql <= l && r <= qr) return st[i]; int m = l + (r - l) / 2; return Node(query(2*i+1, l, m, ql, qr), query(2*i+2, m, r, ql, qr)); } Node prefix_query(int r) { return query(0, 0, n, 0, r+1); } void swap_nodes(int a, int b) { swap(cols[a], cols[b]); swap(rows[a], rows[b]); update(0, 0, n, a, rows[a], cols[a]); update(0, 0, n, b, rows[b], cols[b]); } }; struct LazySegTree { int n; vi st, lazy; LazySegTree() : n(0) {}; LazySegTree(int w, int h) { n = w*h; st.assign(4*n, 0); lazy.assign(4*n, 0); } void apply(int i, int l, int r, int op) { if (op == 0) return; int length = r - l; lazy[i] = op; if (op == 1) st[i] = 0; else st[i] = length; } void push_down(int i, int l, int r) { int m = l + (r - l) / 2; apply(2*i+1, l, m, lazy[i]); apply(2*i+2, m, r, lazy[i]); lazy[i] = 0; } int range_assign(int i, int l, int r, int ql, int qr, int v) { if (r <= ql || qr <= l) return st[i]; if (ql <= l && r <= qr) { apply(i, l, r, v == 0 ? 1 : 2); return st[i]; } push_down(i, l, r); int m = l + (r - l) / 2; return st[i] = range_assign(2*i+1, l, m, ql, qr, v) + range_assign(2*i+2, m, r, ql, qr, v); } int query(int i, int l, int r, int ql, int qr) { if (r <= ql || qr <= l) return 0; if (ql <= l && r <= qr) return st[i]; push_down(i, l, r); int m = l + (r - l) / 2; return query(2*i+1, l, m, ql, qr) + query(2*i+2, m, r, ql, qr); } void set_zero(int l, int r) { range_assign(0, 0, n, l, r+1, 0); } void set_one(int i) { range_assign(0, 0, n, i, i+1, 1); } int get_beautiful() { return query(0, 0, n, 0, n); } }; int ssqrt(int v) { int s = (int) sqrt(v) - 10; if (s <= 0) s = 1; while (s*s < v) s++; return s; } struct BlockDecomp { int h, w; int SX, SY; vector<int> seg; BlockDecomp() : h(0), w(0) {} BlockDecomp(int H, int W) : h(H), w(W), SX(4 * W), SY(4 * H), seg(1LL * SX * SY, INT_MIN) {} inline int idx(int nx, int ny) const { return nx * SY + ny; } void updateY(int nx, int ny, int ly, int ry, int y, int val) { if (ly == ry) { seg[idx(nx, ny)] = val; return; } int mid = (ly + ry) >> 1; if (y <= mid) updateY(nx, ny << 1, ly, mid, y, val); else updateY(nx, ny << 1 | 1, mid + 1, ry, y, val); seg[idx(nx, ny)] = max(seg[idx(nx, ny << 1)], seg[idx(nx, ny << 1 | 1)]); } void mergeY(int nx, int ny, int ly, int ry, int childL, int childR, int y) { if (ly == ry) { seg[idx(nx, ny)] = max(seg[idx(childL, ny)], seg[idx(childR, ny)]); return; } int mid = (ly + ry) >> 1; if (y <= mid) mergeY(nx, ny << 1, ly, mid, childL, childR, y); else mergeY(nx, ny << 1 | 1, mid + 1, ry, childL, childR, y); seg[idx(nx, ny)] = max(seg[idx(nx, ny << 1)], seg[idx(nx, ny << 1 | 1)]); } void updateX(int nx, int lx, int rx, int x, int y, int val) { if (lx == rx) { updateY(nx, 1, 0, h - 1, y, val); return; } int mid = (lx + rx) >> 1; if (x <= mid) updateX(nx << 1, lx, mid, x, y, val); else updateX(nx << 1 | 1, mid + 1, rx, x, y, val); mergeY(nx, 1, 0, h - 1, nx << 1, nx << 1 | 1, y); } void set(int x, int y, int val) { updateX(1, 0, w - 1, x, y, val); } int queryY(int nx, int ny, int ly, int ry, int y1, int y2) const { if (ry < y1 || y2 < ly) return INT_MIN; if (y1 <= ly && ry <= y2) return seg[idx(nx, ny)]; int mid = (ly + ry) >> 1; return max(queryY(nx, ny << 1, ly, mid, y1, y2), queryY(nx, ny << 1 | 1, mid + 1, ry, y1, y2)); } int queryX(int nx, int lx, int rx, int x1, int x2, int y1, int y2) const { if (rx < x1 || x2 < lx) return INT_MIN; if (x1 <= lx && rx <= x2) return queryY(nx, 1, 0, h - 1, y1, y2); int mid = (lx + rx) >> 1; return max(queryX(nx << 1, lx, mid, x1, x2, y1, y2), queryX(nx << 1 | 1, mid + 1, rx, x1, x2, y1, y2)); } int query(int x1, int y1, int x2, int y2) const { return queryX(1, 0, w - 1, x1, x2, y1, y2); } }; int h, w; vi rows, cols; SegTree st; LazySegTree prev_ans; BlockDecomp rmq; void give_initial_chart(int H, int W, vi R, vi C) { h = H; w = W; rows = R; cols = C; st = SegTree(w, h, rows, cols); prev_ans = LazySegTree(w, h); rmq = BlockDecomp(H, W); for (int i = 0; i < w*h; i++) rmq.set(cols[i], rows[i], i); } int queries = 0; int swap_seats(int a, int b) { if (a > b) swap(a, b); queries++; swap(rows[a], rows[b]); swap(cols[a], cols[b]); st.swap_nodes(a, b); rmq.set(cols[a], rows[a], a); rmq.set(cols[b], rows[b], b); int start = a, end = b+1; if (queries <= 1) start = 0, end = h*w; prev_ans.set_zero(start, end - 1); for (int i = start; i < end;) { Node cur = st.prefix_query(i); if (cur.area == i+1) { prev_ans.set_one(i); i++; } else { i = max(cur.area - 1, rmq.query(cur.C1, cur.R1, cur.C2, cur.R2)); } } return prev_ans.get_beautiful(); }
#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...