Advertisement
Guest User

IOI Fever

a guest
Mar 20th, 2021
462
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.13 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. const ll INF = 1e18;
  5.  
  6. // returns number of elements strictly smaller than v in vec
  7. template<class T>
  8. int bins(const vector<T>& vec, T v) {
  9.     int low = 0;
  10.     int high = vec.size();
  11.     while(low != high) {
  12.         int mid = (low + high) >> 1;
  13.         if (vec[mid] < v) low = mid + 1;
  14.         else high = mid;
  15.     }
  16.     return low;
  17. }
  18.  
  19. // Struct for priority queue operations on index set [0, n-1]
  20. // push(i, v) overwrites value at position i if one already exists
  21. // decKey is faster but requires that the new key is smaller than the old one
  22. struct Prique {
  23.     const ll INF = (ll)1e18;
  24.     vector<pair<ll, int>> data;
  25.     const int n;
  26.  
  27.     Prique(int siz) : n(siz), data(2*siz, {INF, -1}) { data[0] = {-INF, -1}; }
  28.     bool empty() const { return data[1].second >= INF; }
  29.     pair<ll, int> top() const { return data[1]; }
  30.  
  31.     void push(int i, ll v) {
  32.         data[i+n] = {v, (v >= INF ? -1 : i)};
  33.         for (i += n; i > 1; i >>= 1) data[i>>1] = min(data[i], data[i^1]);
  34.     }
  35.     void decKey(int i, ll v) {
  36.         for (int j = i+n; data[j].first > v; j >>= 1) data[j] = {v, i};
  37.     }
  38.     pair<ll, int> pop() {
  39.         auto res = data[1];
  40.         push(res.second, INF);
  41.         return res;
  42.     }
  43. };
  44.  
  45. // Segment tree for range minimum and range capping
  46. class SegTree {
  47.     private:
  48.         const ll INF = (ll)1e18;
  49.         vector<ll> mn, cap, base;
  50.         int h = 1;
  51.  
  52.         void apply(int i, ll v) {
  53.             cap[i] = min(cap[i], v);
  54.             mn[i] = min(mn[i], base[i] + cap[i]);
  55.         }
  56.         void push(int i) {
  57.             apply(2*i, cap[i]);
  58.             apply(2*i+1, cap[i]);
  59.             cap[i] = INF;
  60.         }
  61.  
  62.         void recApply(int a, int b, ll v, int i, int ia, int ib) {
  63.             if (ib <= a || b <= ia) return;
  64.             if (a <= ia && ib <= b) {
  65.                 apply(i, v);
  66.             } else {
  67.                 push(i);
  68.                 int im = (ia + ib) >> 1;
  69.                 recApply(a, b, v, 2*i, ia, im);
  70.                 recApply(a, b, v, 2*i+1, im, ib);
  71.                 mn[i] = min(mn[2*i], mn[2*i+1]);
  72.             }
  73.         }
  74.     public:
  75.         SegTree(int n) {
  76.             while(h < n) h *= 2;
  77.             mn.resize(2*h, 2*INF); base.resize(2*h, INF); cap.resize(2*h, INF);
  78.         }
  79.         void rangeCap(int a, int b, ll v) { recApply(a, b+1, v, 1, 0, h); }
  80.         ll getMinVal() { return mn[1]; }
  81.        
  82.         void setBase(int i, ll v) {
  83.             i += h;
  84.             base[i] = v;
  85.             mn[i] = base[i] + cap[i];
  86.             for (i >>= 1; i > 0; i >>= 1) {
  87.                 base[i] = min(base[2*i], base[2*i+1]);
  88.                 mn[i] = min(cap[i] + base[i], min(mn[2*i], mn[2*i+1]));
  89.             }
  90.         }
  91.  
  92.         pair<ll, int> getMin() {
  93.             int i = 1;
  94.             ll res = mn[1];
  95.             while(i < h) {
  96.                 push(i);
  97.                 if (mn[2*i] == mn[i]) i = 2*i;
  98.                 else i = 2*i+1;
  99.             }
  100.             return {res, i - h};
  101.         }
  102. };
  103.  
  104. pair<int, int> rotate(pair<int, int> dir) {
  105.     return {dir.second, -dir.first};
  106. }
  107. int sign(ll v) {
  108.     return (v < 0 ? -1 : v > 0);
  109. }
  110.  
  111. int solve(const vector<pair<ll, ll>>& pts) {
  112.     int n = pts.size();
  113.     vector<int> dir(n); // RIGHT DOWN LEFT UP
  114.     dir[0] = 0;
  115.     for (int i = 1; i < n; ++i) {
  116.         ll dx = pts[i].first, dy = pts[i].second;
  117.         if (abs(dx) > abs(dy)) {
  118.             if (dx < 0) dir[i] = 0;
  119.             else dir[i] = 2;
  120.         } else if (abs(dy) > abs(dx) || dx > 0) {
  121.             if (dy < 0) dir[i] = 3;
  122.             else dir[i] = 1;
  123.         } else {
  124.             dir[i] = 0;
  125.         }
  126.     }
  127.  
  128.     vector<pair<int, int>> diffs(8);
  129.     diffs[0] = {1, 0};
  130.     diffs[1] = {1, -1};
  131.     diffs[2] = {0, -1};
  132.     diffs[3] = {-1, -1};
  133.     diffs[4] = {-1, 0};
  134.     diffs[5] = {-1, 1};
  135.     diffs[6] = {0, 1};
  136.     diffs[7] = {1, 1};
  137.    
  138.     vector<vector<array<ll, 4>>> ords(8);
  139.     for (int i = 0; i < n; ++i) {
  140.         int dx = sign(diffs[2*dir[i]].first);
  141.         int dy = sign(diffs[2*dir[i]].second);
  142.         for (int j = 0; j < 8; ++j) {
  143.             if (sign(diffs[j].first) != -dx && sign(diffs[j].second) != -dy) continue;
  144.             array<ll, 4> off;
  145.             off[0] = dir[i];
  146.            
  147.             pair<int, int> tar = diffs[j];
  148.             pair<int, int> ortho = rotate(tar);
  149.             off[1] = ortho.first * pts[i].first + ortho.second * pts[i].second;
  150.             off[2] = tar.first * pts[i].first + tar.second * pts[i].second;
  151.             off[3] = i;
  152.  
  153.             ords[j].push_back(off);
  154.         }
  155.     }
  156.     for (int j = 0; j < 8; ++j) sort(ords[j].begin(), ords[j].end());
  157.    
  158.     vector<SegTree> segs;
  159.     for (int j = 0; j < 8; ++j) {
  160.         segs.emplace_back(ords[j].size());
  161.         for (int i = 0; i < ords[j].size(); ++i) {
  162.             if (ords[j][i][3] == 0) {
  163.                 segs[j].setBase(i, 0);
  164.                 segs[j].rangeCap(i, i, 0);
  165.             } else {
  166.                 segs[j].setBase(i, ords[j][i][2]);
  167.             }
  168.         }
  169.     }
  170.  
  171.     Prique pq(8);
  172.     for (int j = 0; j < 8; ++j) pq.decKey(j, segs[j].getMin().first);
  173.  
  174.     vector<ll> times(n, INF);
  175.    
  176.     for (int j = pq.pop().second; j != -1; j = pq.pop().second) {
  177.         auto opt = segs[j].getMin();
  178.         segs[j].setBase(opt.second, INF);
  179.         pq.decKey(j, segs[j].getMinVal());
  180.  
  181.         int i = ords[j][opt.second][3];
  182.         ll t = opt.first;
  183.  
  184.         if (t >= INF / 2) break;
  185.         if (t >= times[i]) continue;
  186.         times[i] = t;
  187.        
  188.         int d = dir[i];
  189.         for (int j2 = 0; j2 < 8; ++j2) {
  190.             array<ll, 4> ind;
  191.  
  192.             // Desired direction
  193.             if (j2 == (2*d+7) % 8) ind[0] = (d+1) % 4;
  194.             else if (j2 == 2*d) ind[0] = (d + 2) % 4;
  195.             else if (j2 == (2*d+1) % 8) ind[0] = (d+3) % 4;
  196.             else continue;
  197.  
  198.             // Desired line
  199.             pair<int, int> ortho = rotate(diffs[j2]);
  200.             ind[1] = ortho.first * pts[i].first + ortho.second * pts[i].second;
  201.  
  202.             // Desired min coordinate
  203.             ll base = diffs[j2].first * pts[i].first + diffs[j2].second * pts[i].second;
  204.             ind[2] = t + base;
  205.  
  206.             // OK indices
  207.             ind[3] = -1;
  208.            
  209.             int i0 = bins(ords[j2], ind);
  210.  
  211.             ind[2] = INF;
  212.            
  213.             int i1 = bins(ords[j2], ind);
  214.  
  215.             segs[j2].rangeCap(i0, i1 - 1, -base);
  216.             pq.decKey(j2, segs[j2].getMinVal());
  217.         }
  218.     }
  219.  
  220.     int res = 0;
  221.     for (ll& v : times) res += (v < INF);
  222.     return res;
  223. }
  224.  
  225. int main() {
  226.     ios_base::sync_with_stdio(false);
  227.     cin.tie(0);
  228.  
  229.     int n;
  230.     cin >> n;
  231.  
  232.     vector<pair<ll, ll>> pts(n);
  233.     for (int i = 0; i < n; ++i) {
  234.         int y, x;
  235.         cin >> y >> x;
  236.         pts[i] = {y, x};
  237.     }
  238.     for (int i = 1; i < n; ++i) {
  239.         pts[i].first -= pts[0].first;
  240.         pts[i].second -= pts[0].second;
  241.     }
  242.     pts[0] = {0, 0};
  243.  
  244.     // Decide direction person 1 goes to
  245.     int res = 0;
  246.     res = max(res, solve(pts)); // Right
  247.     for (auto& pr : pts) pr.first = -pr.first;
  248.     res = max(res, solve(pts)); // Left
  249.     for (auto& pr : pts) swap(pr.first, pr.second);
  250.     res = max(res, solve(pts)); // Up
  251.     for (auto& pr : pts) pr.first = -pr.first;
  252.     res = max(res, solve(pts)); // Down
  253.  
  254.     cout << res << '\n';
  255. }
  256.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement