Submission #521623

#TimeUsernameProblemLanguageResultExecution timeMemory
521623amunduzbaevIOI Fever (JOI21_fever)C++14
100 / 100
2172 ms54864 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; const ll INF = 1e18; // returns number of elements strictly smaller than v in vec template<class T> int bins(const vector<T>& vec, T v) { int low = 0; int high = vec.size(); while(low != high) { int mid = (low + high) >> 1; if (vec[mid] < v) low = mid + 1; else high = mid; } return low; } // Struct for priority queue operations on index set [0, n-1] // push(i, v) overwrites value at position i if one already exists // decKey is faster but requires that the new key is smaller than the old one struct Prique { const ll INF = (ll)1e18; vector<pair<ll, int>> data; const int n; Prique(int siz) : n(siz), data(2*siz, {INF, -1}) { data[0] = {-INF, -1}; } bool empty() const { return data[1].second >= INF; } pair<ll, int> top() const { return data[1]; } void push(int i, ll v) { data[i+n] = {v, (v >= INF ? -1 : i)}; for (i += n; i > 1; i >>= 1) data[i>>1] = min(data[i], data[i^1]); } void decKey(int i, ll v) { for (int j = i+n; data[j].first > v; j >>= 1) data[j] = {v, i}; } pair<ll, int> pop() { auto res = data[1]; push(res.second, INF); return res; } }; // Segment tree for range minimum and range capping class SegTree { private: const ll INF = (ll)1e18; vector<ll> mn, cap, base; int h = 1; void apply(int i, ll v) { cap[i] = min(cap[i], v); mn[i] = min(mn[i], base[i] + cap[i]); } void push(int i) { apply(2*i, cap[i]); apply(2*i+1, cap[i]); cap[i] = INF; } void recApply(int a, int b, ll v, int i, int ia, int ib) { if (ib <= a || b <= ia) return; if (a <= ia && ib <= b) { apply(i, v); } else { push(i); int im = (ia + ib) >> 1; recApply(a, b, v, 2*i, ia, im); recApply(a, b, v, 2*i+1, im, ib); mn[i] = min(mn[2*i], mn[2*i+1]); } } public: SegTree(int n) { while(h < n) h *= 2; mn.resize(2*h, 2*INF); base.resize(2*h, INF); cap.resize(2*h, INF); } void rangeCap(int a, int b, ll v) { recApply(a, b+1, v, 1, 0, h); } ll getMinVal() { return mn[1]; } void setBase(int i, ll v) { i += h; base[i] = v; mn[i] = base[i] + cap[i]; for (i >>= 1; i > 0; i >>= 1) { base[i] = min(base[2*i], base[2*i+1]); mn[i] = min(cap[i] + base[i], min(mn[2*i], mn[2*i+1])); } } pair<ll, int> getMin() { int i = 1; ll res = mn[1]; while(i < h) { push(i); if (mn[2*i] == mn[i]) i = 2*i; else i = 2*i+1; } return {res, i - h}; } }; pair<int, int> rotate(pair<int, int> dir) { return {dir.second, -dir.first}; } int sign(ll v) { return (v < 0 ? -1 : v > 0); } int solve(const vector<pair<ll, ll>>& pts) { int n = pts.size(); vector<int> dir(n); // RIGHT DOWN LEFT UP dir[0] = 0; for (int i = 1; i < n; ++i) { ll dx = pts[i].first, dy = pts[i].second; if (abs(dx) > abs(dy)) { if (dx < 0) dir[i] = 0; else dir[i] = 2; } else if (abs(dy) > abs(dx) || dx > 0) { if (dy < 0) dir[i] = 3; else dir[i] = 1; } else { dir[i] = 0; } } vector<pair<int, int>> diffs(8); diffs[0] = {1, 0}; diffs[1] = {1, -1}; diffs[2] = {0, -1}; diffs[3] = {-1, -1}; diffs[4] = {-1, 0}; diffs[5] = {-1, 1}; diffs[6] = {0, 1}; diffs[7] = {1, 1}; vector<vector<array<ll, 4>>> ords(8); for (int i = 0; i < n; ++i) { int dx = sign(diffs[2*dir[i]].first); int dy = sign(diffs[2*dir[i]].second); for (int j = 0; j < 8; ++j) { if (sign(diffs[j].first) != -dx && sign(diffs[j].second) != -dy) continue; array<ll, 4> off; off[0] = dir[i]; pair<int, int> tar = diffs[j]; pair<int, int> ortho = rotate(tar); off[1] = ortho.first * pts[i].first + ortho.second * pts[i].second; off[2] = tar.first * pts[i].first + tar.second * pts[i].second; off[3] = i; ords[j].push_back(off); } } for (int j = 0; j < 8; ++j) sort(ords[j].begin(), ords[j].end()); vector<SegTree> segs; for (int j = 0; j < 8; ++j) { segs.emplace_back(ords[j].size()); for (int i = 0; i < ords[j].size(); ++i) { if (ords[j][i][3] == 0) { segs[j].setBase(i, 0); segs[j].rangeCap(i, i, 0); } else { segs[j].setBase(i, ords[j][i][2]); } } } Prique pq(8); for (int j = 0; j < 8; ++j) pq.decKey(j, segs[j].getMin().first); vector<ll> times(n, INF); for (int j = pq.pop().second; j != -1; j = pq.pop().second) { auto opt = segs[j].getMin(); segs[j].setBase(opt.second, INF); pq.decKey(j, segs[j].getMinVal()); int i = ords[j][opt.second][3]; ll t = opt.first; if (t >= INF / 2) break; if (t >= times[i]) continue; times[i] = t; int d = dir[i]; for (int j2 = 0; j2 < 8; ++j2) { array<ll, 4> ind; // Desired direction if (j2 == (2*d+7) % 8) ind[0] = (d+1) % 4; else if (j2 == 2*d) ind[0] = (d + 2) % 4; else if (j2 == (2*d+1) % 8) ind[0] = (d+3) % 4; else continue; // Desired line pair<int, int> ortho = rotate(diffs[j2]); ind[1] = ortho.first * pts[i].first + ortho.second * pts[i].second; // Desired min coordinate ll base = diffs[j2].first * pts[i].first + diffs[j2].second * pts[i].second; ind[2] = t + base; // OK indices ind[3] = -1; int i0 = bins(ords[j2], ind); ind[2] = INF; int i1 = bins(ords[j2], ind); segs[j2].rangeCap(i0, i1 - 1, -base); pq.decKey(j2, segs[j2].getMinVal()); } } int res = 0; for (ll& v : times) res += (v < INF); return res; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); int n; cin >> n; vector<pair<ll, ll>> pts(n); for (int i = 0; i < n; ++i) { int y, x; cin >> y >> x; pts[i] = {y, x}; } for (int i = 1; i < n; ++i) { pts[i].first -= pts[0].first; pts[i].second -= pts[0].second; } pts[0] = {0, 0}; // Decide direction person 1 goes to int res = 0; res = max(res, solve(pts)); // Right for (auto& pr : pts) pr.first = -pr.first; res = max(res, solve(pts)); // Left for (auto& pr : pts) swap(pr.first, pr.second); res = max(res, solve(pts)); // Up for (auto& pr : pts) pr.first = -pr.first; res = max(res, solve(pts)); // Down cout << res << '\n'; }

Compilation message (stderr)

fever.cpp: In constructor 'Prique::Prique(int)':
fever.cpp:25:12: warning: 'Prique::n' will be initialized after [-Wreorder]
   25 |  const int n;
      |            ^
fever.cpp:24:24: warning:   'std::vector<std::pair<long long int, int> > Prique::data' [-Wreorder]
   24 |  vector<pair<ll, int>> data;
      |                        ^~~~
fever.cpp:27:2: warning:   when initialized here [-Wreorder]
   27 |  Prique(int siz) : n(siz), data(2*siz, {INF, -1}) { data[0] = {-INF, -1}; }
      |  ^~~~~~
fever.cpp: In function 'int solve(const std::vector<std::pair<long long int, long long int> >&)':
fever.cpp:161:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::array<long long int, 4> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  161 |   for (int i = 0; i < ords[j].size(); ++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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...