Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <array>
- #include <assert.h>
- #include <bitset>
- #include <chrono>
- #include <cmath>
- #include <complex>
- #include <cstring>
- #include <functional>
- #include <fstream>
- #include <iomanip>
- #include <iostream>
- #include <istream>
- #include <map>
- #include <math.h>
- #include <numeric>
- #include <ostream>
- #include <queue>
- #include <set>
- #include <stack>
- #include <string>
- #include <unordered_map>
- #include <unordered_set>
- #include <vector>
- namespace asl
- {
- typedef long long i64;
- #include <stdint.h>
- template <typename A, typename B>
- std::istream &operator>>(std::istream &is, std::pair<A, B> &p)
- {
- return is >> p.first >> p.second;
- }
- template <typename T>
- using vec = std::vector<T>;
- template <typename T>
- std::istream &operator>>(std::istream &is, std::vector<T> &vec)
- {
- for (auto &value : vec)
- is >> value;
- return is;
- }
- }
- #include <experimental/optional>
- #define optional std::experimental::optional
- namespace asl
- {
- template <typename T, typename U = T>
- class SegmentTree
- {
- int size;
- std::function<void(T &, U &)> _update;
- std::function<T(T &, T &)> _merge;
- std::function<optional<U>(T &)> _get_lazy;
- void push(int p, int l, int r)
- {
- auto lazy = _get_lazy(ds[p]);
- if (lazy)
- {
- _update(ds[l], *lazy);
- _update(ds[r], *lazy);
- }
- }
- void update(int p, int b, int e, int x, int y, U &upd)
- {
- if (x <= b && e <= y)
- {
- _update(ds[p], upd);
- }
- else
- {
- int m = (b + e) >> 1, l = p + 1, r = p + ((m - b) << 1);
- push(p, l, r);
- if (x < m)
- update(l, b, m, x, y, upd);
- if (m < y)
- update(r, m, e, x, y, upd);
- ds[p] = _merge(ds[l], ds[r]);
- }
- }
- T query(int p, int b, int e, int x, int y)
- {
- if (x <= b && e <= y)
- {
- return ds[p];
- }
- else
- {
- int m = (b + e) >> 1, l = p + 1, r = p + ((m - b) << 1);
- push(p, l, r);
- if (x < m)
- {
- auto le = query(l, b, m, x, y);
- if (m < y)
- {
- auto ri = query(r, m, e, x, y);
- return _merge(le, ri);
- }
- else
- {
- return le;
- }
- }
- else
- {
- return query(r, m, e, x, y);
- }
- }
- }
- void init(int size,
- std::function<void(T &, U &)> update,
- std::function<T(T &, T &)> merge,
- std::function<optional<U>(T &)> get_lazy)
- {
- this->size = size;
- this->_update = update;
- this->_merge = merge;
- this->_get_lazy = get_lazy;
- this->ds = std::vector<T>(2 * size - 1);
- }
- public:
- std::vector<T> ds;
- SegmentTree(
- int size,
- std::function<void(T &, U &)> update,
- std::function<T(T &, T &)> merge = [](T &l, T &r) { return l + r; },
- std::function<optional<U>(T &)> get_lazy = [](T &value) { return optional<U>(); })
- {
- init(size, update, merge, get_lazy);
- }
- void update(int x, U upd)
- {
- update(0, 0, size, x, x + 1, upd);
- }
- T query(int x, int y)
- {
- return query(0, 0, size, x, y);
- }
- };
- }
- #include <utility>
- #include <tuple>
- #include <random>
- #define endl '\n'
- using namespace std;
- using namespace asl;
- const i64 inf = 8e9;
- void my_update(i64 &a, i64 b) { a = b; }
- i64 my_merge(i64 &a, i64 &b) { return min(a, b); }
- i64 go(vec<pair<i64, i64>> &a)
- {
- sort(a.begin(), a.end());
- int p = 0;
- while (p < a.size() && a[p].first <= 0)
- ++p;
- vec<SegmentTree<i64, i64>> sts(4, SegmentTree<i64, i64>(p, my_update, my_merge));
- vec<i64> his(p);
- vec<i64> los(p);
- i64 hi = 0, lo = 0;
- for (int i = 0; i < p; ++i)
- {
- his[i] = hi;
- los[i] = lo;
- i64 dist = -a[i].first;
- assert(dist >= 0);
- for (int m = 0; m < 4; ++m)
- {
- i64 cur = dist + (m & 2) * hi + (m & 1) * lo;
- sts[m].update(i, cur);
- }
- hi = max(hi, a[i].second);
- lo = max(lo, -a[i].second);
- }
- i64 solution = inf;
- auto check_interval = [&](int b, int e, i64 delta, int index) {
- if (b < e)
- solution = min(solution, sts[index].query(b, e) + delta);
- };
- hi = 0, lo = 0;
- for (int i = a.size() - 1; i >= 0 && a[i].first >= 0; --i)
- {
- i64 dist = 2 * a[i].first;
- int hi_pos = lower_bound(his.begin(), his.end(), hi) - his.begin();
- int lo_pos = lower_bound(los.begin(), los.end(), lo) - los.begin();
- check_interval(0, min(lo_pos, hi_pos), 2 * hi + lo + dist, 0);
- check_interval(lo_pos, hi_pos, 2 * hi + dist, 1);
- check_interval(hi_pos, lo_pos, lo + dist, 2);
- check_interval(max(lo_pos, hi_pos), p, dist, 3);
- hi = max(hi, a[i].second);
- lo = max(lo, -a[i].second);
- }
- return solution;
- }
- void solve()
- {
- int n;
- cin >> n;
- vec<pair<i64, i64>> a(n);
- cin >> a;
- i64 big = 1e9 + 1;
- a.push_back({0, 0});
- i64 solution = inf;
- for (int x = 0; x < 2; ++x)
- {
- for (int y = 0; y < 2; ++y)
- {
- solution = min(solution, go(a));
- for (auto &p : a)
- p.second *= -1;
- }
- for (auto &p : a)
- p.first *= -1;
- }
- cout << solution << endl;
- }
- int main()
- {
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- int t;
- cin >> t;
- for (int i = 1; i <= t; ++i)
- {
- solve();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment