Submission #1255905

#TimeUsernameProblemLanguageResultExecution timeMemory
1255905biankRadio Towers (IOI22_towers)C++20
100 / 100
540 ms36928 KiB
#include <bits/stdc++.h> using namespace std; #define forsn(i, s, n) for (int i = int(s); i < int(n); i++) #define forn(i, n) forsn(i, 0, n) #define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--) #define dforn(i, n) dforsn(i, 0, n) #define sz(x) int(x.size()) #define all(x) begin(x), end(x) using ii = pair<int, int>; using vi = vector<int>; using ll = long long; using vll = vector<ll>; #define fst first #define snd second #define pb push_back #define eb emplace_back const int INF = 2e9 + 9; struct PersistentSegTree { int n; vi st, l, r; PersistentSegTree(int _n) : n(_n), st(1, 0), l(1, 0), r(1, 0) {} int new_node(int u) { st.pb(st[u]); l.pb(l[u]); r.pb(r[u]); return sz(st) - 1; } int update(int pos, int toAdd, int lo, int hi, int node) { node = new_node(node); if (hi - lo == 1) { st[node] += toAdd; return node; } int mid = (lo + hi) / 2; if (pos < mid) { l[node] = update(pos, toAdd, lo, mid, l[node]); } else { r[node] = update(pos, toAdd, mid, hi, r[node]); } st[node] = st[l[node]] + st[r[node]]; return node; } int update(int pos, int toAdd, int root) { return update(pos, toAdd, 0, n, root); } int query(int s, int e, int lo, int hi, int node) { if (e <= lo || hi <= s) { return 0; } if (s <= lo && hi <= e) { return st[node]; } int mid = (lo + hi) / 2; return query(s, e, lo, mid, l[node]) + query(s, e, mid, hi, r[node]); } int query(int s, int e, int root) { return query(s, e, 0, n, root); } int findFirst(int s, int e, int lo, int hi, int node) { if (e <= lo || hi <= s || !st[node]) { return -1; } if (hi - lo == 1) { return lo; } int mid = (lo + hi) / 2; int k = findFirst(s, e, lo, mid, l[node]); if (k != -1) return k; return findFirst(s, e, mid, hi, r[node]); } int findFirst(int s, int e, int root) { return findFirst(s, e, 0, n, root); } int findLast(int s, int e, int lo, int hi, int node) { if (e <= lo || hi <= s || !st[node]) { return -1; } if (hi - lo == 1) { return lo; } int mid = (lo + hi) / 2; int k = findLast(s, e, mid, hi, r[node]); if (k != -1) return k; return findLast(s, e, lo, mid, l[node]); } int findLast(int s, int e, int root) { return findLast(s, e, 0, n, root); } }; template<typename T> struct SegTree { int n; vector<T> st; T neutr; SegTree() {} SegTree(vector<T> &a, T null) : n(sz(a)), st(2 * n), neutr(null) { forn(i, n) st[i + n] = a[i]; dforsn(i, 1, n) st[i] = max(st[2 * i], st[2 * i + 1]); } T query(int l, int r) { T ans = neutr; for (l += n, r += n; l < r; l /= 2, r /= 2) { if (l & 1) ans = max(ans, st[l++]); if (r & 1) ans = max(st[--r], ans); } return ans; } }; struct Node { ll maxi = -INF, mini = INF, bestDiff1 = 0, bestDiff2 = 0; }; Node merge(Node a, Node b) { Node c; c.maxi = max(a.maxi, b.maxi); c.mini = min(a.mini, b.mini); c.bestDiff1 = max({a.bestDiff1, b.bestDiff1, a.maxi - b.mini}); c.bestDiff2 = max({a.bestDiff2, b.bestDiff2, b.maxi - a.mini}); return c; } struct OtherSegTree { int n; vector<Node> st; OtherSegTree() {} OtherSegTree(vi &h) { n = 1; while (n < sz(h)) n *= 2; st.resize(2 * n); forn(i, sz(h)) st[i + n].maxi = st[i + n].mini = h[i]; dforsn(i, 1, n) st[i] = merge(st[2 * i], st[2 * i + 1]); } Node query(int l, int r) { Node leftRes, rightRes; for (l += n, r += n; l < r; l /= 2, r /= 2) { if (l & 1) leftRes = merge(leftRes, st[l++]); if (r & 1) rightRes = merge(st[--r], rightRes); } return merge(leftRes, rightRes); } }; int n; vi h, val; vi l, r; vi Ds, roots; PersistentSegTree persistent_segtree(0); SegTree<ii> minH; OtherSegTree segtree; void init(int N, vi H) { n = N, h = H; l.resize(N), r.resize(N); forn(i, N) { int j = i - 1; while (j >= 0 && H[j] > H[i]) j = l[j]; l[i] = j; } dforn(i, N) { int j = i + 1; while (j < N && H[j] > H[i]) j = r[j]; r[i] = j; } segtree = OtherSegTree(H); vi negR(N); vector<ii> negH(N); forn(i, N) negH[i] = {-h[i], i}; minH = SegTree<ii>(negH, ii{-INF, -1}); vi a(N + 2, INF); forn(i, N) a[i + 1] = H[i]; SegTree st(a, -INF); val.resize(N); forn(i, N) val[i] = min(st.query(l[i] + 1, i + 2), st.query(i + 1, r[i] + 2)) - H[i]; vi order(N); iota(all(order), 0); sort(all(order), [&](const int &lhs, const int &rhs) { return val[lhs] > val[rhs]; }); Ds = val; Ds.pb(INF); sort(all(Ds)); Ds.erase(unique(all(Ds)), end(Ds)); reverse(all(Ds)); int i = 0; int root = 0; persistent_segtree = PersistentSegTree(n); for (int D : Ds) { while (i < N && val[order[i]] >= D) { root = persistent_segtree.update(order[i++], 1, root); } roots.pb(root); } } int max_towers(int L, int R, int D) { int lo = 0, hi = sz(Ds); while (hi - lo > 1) { int mid = (lo + hi) / 2; if (D <= Ds[mid]) lo = mid; else hi = mid; } int cant = persistent_segtree.query(L, R + 1, roots[lo]); int leftmost = persistent_segtree.findFirst(L, R + 1, roots[lo]); int rightmost = persistent_segtree.findLast(L, R + 1, roots[lo]); if (cant == 0) { leftmost = rightmost = minH.query(L, R + 1).snd; assert(leftmost != -1); cant++; } if (segtree.query(L, leftmost).bestDiff2 >= D) cant++; if (segtree.query(rightmost + 1, R + 1).bestDiff1 >= D) cant++; return cant; }
#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...