Submission #4325867


Source Code Expand

// includes {{{
#include <algorithm>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <tuple>
#include <vector>
// #include<deque>
// #include<multiset>
// #include<bitset>
// #include<cstring>
// #include<bits/stdc++.h>
// }}}
using namespace std;
using ll = long long;

const int N = 2e5 + 10;
int fromX, fromY, toX, toY;
int n;
int x[N], y[N];

// SegmentTree( size [, initial] )
// SegmentTree( <data> )
/// --- SegmentTree {{{ ///
#include <cassert>
#include <initializer_list>
#include <iostream>
#include <iterator>
#include <vector>
template < class Monoid >
struct SegmentTree {
private:
  using T = typename Monoid::T;
  size_t n;
  vector< T > data;
  // call after touch data[i]
  void prop(int i) { data[i] = Monoid::op(data[2 * i], data[2 * i + 1]); }

public:
  SegmentTree() : n(0) {}
  SegmentTree(int n, T initial = Monoid::identity()) : n(n) {
    data.resize(n * 2, initial);
    for(int i = n - 1; i > 0; i--) data[i] = Monoid::op(data[i * 2], data[i * 2 + 1]);
  }
  template < class InputIter, class = typename iterator_traits< InputIter >::value_type >
  SegmentTree(InputIter first, InputIter last) : SegmentTree(distance(first, last)) {
    copy(first, last, begin(data) + n);
    // fill from deep
    for(int i = n - 1; i > 0; i--) prop(i);
  }
  SegmentTree(vector< T > v) : SegmentTree(v.begin(), v.end()) {}
  SegmentTree(initializer_list< T > v) : SegmentTree(v.begin(), v.end()) {}
  void set(size_t i, const T &v) {
    assert(i < n);
    data[i += n] = v;
    while(i >>= 1) prop(i); // propUp
  }
  T get(size_t i) {
    assert(i < n);
    return data[i + n];
  }
  T query(int l, int r) {
    if(l < 0) l = 0;
    if(l >= r) return Monoid::identity();
    if(r > (int) n) r = n;
    T tmpL = Monoid::identity(), tmpR = Monoid::identity();
    for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
      if(l & 1) tmpL = Monoid::op(tmpL, data[l++]);
      if(r & 1) tmpR = Monoid::op(data[--r], tmpR);
    }
    return Monoid::op(tmpL, tmpR);
  }
  inline void dum(int r = -1) {
#ifdef DEBUG
    if(r < 0) r = n;
    DEBUG_OUT << "{";
    for(int i = 0; i < min(r, (int) n); i++) DEBUG_OUT << (i ? ", " : "") << get(i);
    DEBUG_OUT << "}" << endl;
#endif
  }
};
/// }}}--- ///

/// --- Monoid examples {{{ ///
constexpr long long inf = 1e18 + 100;
#include <algorithm>
struct Nothing {
  using T = char;
  using Monoid = Nothing;
  using M = T;
  static constexpr T op(const T &, const T &) { return T(); }
  static constexpr T identity() { return T(); }
  template < class X >
  static constexpr X actInto(const M &, ll, ll, const X &x) {
    return x;
  }
};

template < class U = long long >
struct RangeMin {
  using T = U;
  static T op(const T &a, const T &b) { return min(a, b); }
  static constexpr T identity() { return T(inf); }
};

template < class U = long long >
struct RangeMax {
  using T = U;
  static T op(const T &a, const T &b) { return max(a, b); }
  static constexpr T identity() { return -T(inf); }
};

template < class U = long long >
struct RangeSum {
  using T = U;
  static T op(const T &a, const T &b) { return a + b; }
  static constexpr T identity() { return T(0); }
};

template < class U >
struct RangeProd {
  using T = U;
  static T op(const T &a, const T &b) { return a * b; }
  static constexpr T identity() { return T(1); }
};

template < class U = long long >
struct RangeOr {
  using T = U;
  static T op(const T &a, const T &b) { return a | b; }
  static constexpr T identity() { return T(0); }
};

#include <bitset>

template < class U = long long >
struct RangeAnd {
  using T = U;
  static T op(const T &a, const T &b) { return a & b; }
  static constexpr T identity() { return T(-1); }
};

template < size_t N >
struct RangeAnd< bitset< N > > {
  using T = bitset< N >;
  static T op(const T &a, const T &b) { return a & b; }
  static constexpr T identity() { return bitset< N >().set(); }
};

/// }}}--- ///

using Seg = SegmentTree< RangeMax<> >;

// constructor(H)
// index(y, x)
// === init(doUnique) ===
// set(y, x, val)         // index(y, x) must be done
// query(yl, yr, xl, xr)
// === --- ===
// only offline
/// --- Fractional Cascading SegmentTree {{{ ///
#include <algorithm>
#include <cassert>
#include <functional>
#include <map>
#include <vector>

template < class T, class U, bool yCompress = true, class Index = ll>
struct FractionalCascadingSegmentTree {
  size_t h;
  vector< T > dat;
  vector< vector< Index > > indices;
  vector< vector< size_t > > L, R;
  U identity;
  function< void(T &, int x, const U &) > setX;
  function< void(T &, vector< Index > &) > initX;
  function< U(T &, int x1, int x2) > queryX;
  function< U(const U &, const U &) > mergeY;
  FractionalCascadingSegmentTree() {}
  FractionalCascadingSegmentTree(size_t tempH, //
                                 const function< void(T &, int, const U &) > &setX,
                                 const function< void(T &, vector< Index > &) > &initX,
                                 const function< U(T &, int, int) > &queryX,
                                 const function< U(const U &, const U &) > &mergeY,
                                 U identity = U(), T initial = T())
      : identity(identity), setX(setX), initX(initX), queryX(queryX), mergeY(mergeY) {
    h = 1;
    while(h < tempH) h <<= 1;
    dat = vector< T >(2 * h, initial);
    indices = vector< vector< Index > >(2 * h);
    L = R = vector< vector< size_t > >(2 * h);
  }
  vector< Index > ys;
  map<Index, int> ymap;
  vector< pair< Index, Index > > pre_indecies;
  void index(Index i, Index j) {
    if(yCompress) {
      ys.push_back(i);
      pre_indecies.emplace_back(i, j);
    } else {
      size_t i2 = i;
      assert(i2 < h);
      indices[i2 + h].push_back(j);
    }
  }
  void init(bool doUnique) {
    if(yCompress) {
      sort(begin(ys), end(ys));
      ys.erase(unique(begin(ys), end(ys)), end(ys));
      {
        size_t i = 0;
        for(Index &y : ys) ymap[y] = i++;
      }
      for(pair< Index, Index > idx : pre_indecies) {
        indices[ymap[idx.first] + h].push_back(idx.second);
      }
    }
    for(size_t i = h; i < h * 2; i++) {
      sort(begin(indices[i]), end(indices[i]));
      if(doUnique)
        indices[i].erase(unique(begin(indices[i]), end(indices[i])), end(indices[i]));
      initX(dat[i], indices[i]);
    }
    for(size_t i = h - 1; i >= 1; i--) {
      size_t lsz = indices[i * 2].size();
      size_t rsz = indices[i * 2 + 1].size();
      size_t nsz = lsz + rsz;
      indices[i].resize(nsz);
      L[i].resize(nsz + 1, lsz);
      R[i].resize(nsz + 1, rsz);
      size_t p1 = 0, p2 = 0;
      while(p1 < lsz || p2 < rsz) {
        L[i][p1 + p2] = p1;
        R[i][p1 + p2] = p2;
        if(p1 < lsz && (p2 == rsz || indices[i * 2][p1] <= indices[i * 2 + 1][p2])) {
          indices[i][p1 + p2] = indices[i * 2][p1];
          p1++;
        } else {
          indices[i][p1 + p2] = indices[i * 2 + 1][p2];
          p2++;
        }
      }
      initX(dat[i], indices[i]);
    }
  }

public:
  void set(Index y, Index x, const U &val) {
    if(yCompress) {
      assert(ymap.count(y));
      _set(ymap[y], x, val);
    } else {
      size_t y2 = y;
      assert(y2 < h);
      _set(y2, x, val);
    }
  }

private:
  void _set(size_t y, Index x, const U &val) {
    size_t lower = lower_bound(begin(indices[1]), end(indices[1]), x) - begin(indices[1]);
    assert(lower < indices.size());
    size_t k = 1, l = 0, r = h;
    while(k != y + h) {
      setX(dat[k], lower, val);
      size_t mid = (l + r) >> 1;
      if(y < mid) {
        lower = L[k][lower];
        k = k * 2;
        r = mid;
      } else {
        lower = R[k][lower];
        k = k * 2 + 1;
        l = mid;
      }
    }
    setX(dat[k], lower, val);
    assert(indices[k][lower] == x);
  }

public:
  U query(Index a, Index b, Index l, Index r) {
    if(a >= b || l >= r) return identity;
    size_t lower = lower_bound(begin(indices[1]), end(indices[1]), l) - begin(indices[1]);
    size_t upper = lower_bound(begin(indices[1]), end(indices[1]), r) - begin(indices[1]);
    size_t a2, b2;
    if(yCompress) {
      a2 = lower_bound(begin(ys), end(ys), a) - begin(ys);
      b2 = lower_bound(begin(ys), end(ys), b) - begin(ys);
    } else {
      a2 = a, b2 = b;
      assert(a2 < h && b2 <= h);
    }
    return query(a2, b2, lower, upper, 0, h, 1);
  }

private:
  U query(size_t a, size_t b, size_t lower, size_t upper, size_t l, size_t r, size_t k) {
    if(lower == upper) return identity;
    if(b <= l || r <= a) return identity;
    if(a <= l && r <= b) return queryX(dat[k], lower, upper);
    return mergeY(query(a, b, L[k][lower], L[k][upper], l, (l + r) >> 1, k * 2),
                  query(a, b, R[k][lower], R[k][upper], (l + r) >> 1, r, k * 2 + 1));
  }
};

/// }}}--- ///

// never forget to init SparseTable by yourself
// FC-SegmentTree Example {{{

using Under = Seg;
using Value = RangeMax<>;
using Data = Value::T;

FractionalCascadingSegmentTree< Under, Data, 1 > ecas(
    N + 1,
    // set x
    [](Under &dat, int x, const Data &val) -> void {
      // dat.set(x, Value::op(dat.get(x), val));
      dat.set(x, val);
    },
    // init x
    [](Under &dat, const vector< ll > &indices) -> void {
      dat = Under(indices.size(), 0); // serve initial?
    },
    // query [l, r) // l < r
    [](Under &dat, int l, int r) -> Data { return dat.query(l, r); },
    // merge y-direction
    [](Data a, Data b) -> Data { return max(a, b); }
    // optional
    ,
    0);
// }}}

// uniq, compress {{{
#include <algorithm>
#include <map>
#include <vector>
template < class T >
void uniq(vector< T > &v) {
  sort(v.begin(), v.end());
  v.erase(unique(v.begin(), v.end()), v.end());
}
template < class T >
map< T, int > compress(const vector< T > &v) {
  map< T, int > mp;
  int i = -1;
  for(auto &e : v) mp[e] = ++i;
  return mp;
}
// }}}

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  cin >> fromX >> fromY >> toX >> toY;
  cin >> n;
  bool revX = 0, revY = 0;
  if(fromX > toX) fromX *= -1, toX *= -1, revX = 1;
  if(fromY > toY) fromY *= -1, toY *= -1, revY = 1;
  using P = pair< int, int >;
  vector< P > v;
  toX -= fromX, toY -= fromY;
  for(int i = 0; i < n; i++) {
    cin >> x[i] >> y[i];
    if(revX) x[i] *= -1;
    if(revY) y[i] *= -1;
    x[i] -= fromX;
    y[i] -= fromY;
    if(0 <= x[i] && x[i] <= toX && 0 <= y[i] && y[i] <= toY) {
      ecas.index(x[i], y[i]);
      v.emplace_back(x[i], y[i]);
    }
  }
  fromX = fromY = 0;

  sort((v).begin(), (v).end());

  ecas.init(1);

  for(auto p : v) {
    int val = ecas.query(0, p.first, 0, p.second) + 1;
    ecas.set(p.first, p.second, val);
  }

  cout << fixed << setprecision(20);
  constexpr double PI = acos(-1);
  constexpr double A = 20 - 5 * PI;
  constexpr double B = 10 * PI - 20;

  int num = ecas.query(0, toX + 1, 0, toY + 1);

  double ans = 0;
  if(min(toX, toY) + 1 != num) {
    ans += (double) -num * A;
    ans += 100.0 * (toX + toY);
  } else {
    ans -= (double) A * (num - 1);
    ans += B;
    ans += (toX + toY) * 100.0;
  }

  cout << ans << endl;

  return 0;
}

Submission Info

Submission Time
Task C - Fountain Walk
User luma
Language C++14 (GCC 5.4.1)
Score 900
Code Size 11579 Byte
Status AC
Exec Time 1345 ms
Memory 245948 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 900 / 900
Status
AC × 3
AC × 47
Set Name Test Cases
Sample sample_01.txt, sample_02.txt, sample_03.txt
All sample_01.txt, sample_02.txt, sample_03.txt, sample_01.txt, sample_02.txt, sample_03.txt, subtask_1_01.txt, subtask_1_02.txt, subtask_1_03.txt, subtask_1_04.txt, subtask_1_05.txt, subtask_1_06.txt, subtask_1_07.txt, subtask_1_08.txt, subtask_1_09.txt, subtask_1_10.txt, subtask_1_11.txt, subtask_1_12.txt, subtask_1_13.txt, subtask_1_14.txt, subtask_1_15.txt, subtask_1_16.txt, subtask_1_17.txt, subtask_1_18.txt, subtask_1_19.txt, subtask_1_20.txt, subtask_1_21.txt, subtask_1_22.txt, subtask_1_23.txt, subtask_1_24.txt, subtask_1_25.txt, subtask_1_26.txt, subtask_1_27.txt, subtask_1_28.txt, subtask_1_29.txt, subtask_1_30.txt, subtask_1_31.txt, subtask_1_32.txt, subtask_1_33.txt, subtask_1_34.txt, subtask_1_35.txt, subtask_1_36.txt, subtask_1_37.txt, subtask_1_38.txt, subtask_1_39.txt, subtask_1_40.txt, subtask_1_41.txt
Case Name Status Exec Time Memory
sample_01.txt AC 66 ms 69888 KB
sample_02.txt AC 66 ms 69888 KB
sample_03.txt AC 66 ms 69888 KB
subtask_1_01.txt AC 66 ms 69888 KB
subtask_1_02.txt AC 66 ms 69888 KB
subtask_1_03.txt AC 66 ms 69888 KB
subtask_1_04.txt AC 66 ms 69888 KB
subtask_1_05.txt AC 66 ms 69888 KB
subtask_1_06.txt AC 67 ms 69888 KB
subtask_1_07.txt AC 66 ms 69888 KB
subtask_1_08.txt AC 67 ms 69888 KB
subtask_1_09.txt AC 79 ms 70528 KB
subtask_1_10.txt AC 94 ms 71040 KB
subtask_1_11.txt AC 78 ms 70272 KB
subtask_1_12.txt AC 1006 ms 243420 KB
subtask_1_13.txt AC 96 ms 71168 KB
subtask_1_14.txt AC 80 ms 70528 KB
subtask_1_15.txt AC 77 ms 70272 KB
subtask_1_16.txt AC 991 ms 243420 KB
subtask_1_17.txt AC 91 ms 70912 KB
subtask_1_18.txt AC 90 ms 70784 KB
subtask_1_19.txt AC 93 ms 71808 KB
subtask_1_20.txt AC 993 ms 243420 KB
subtask_1_21.txt AC 1005 ms 243292 KB
subtask_1_22.txt AC 1003 ms 243420 KB
subtask_1_23.txt AC 1026 ms 243420 KB
subtask_1_24.txt AC 67 ms 69888 KB
subtask_1_25.txt AC 67 ms 69888 KB
subtask_1_26.txt AC 67 ms 69888 KB
subtask_1_27.txt AC 67 ms 69888 KB
subtask_1_28.txt AC 129 ms 77440 KB
subtask_1_29.txt AC 126 ms 76160 KB
subtask_1_30.txt AC 1345 ms 245820 KB
subtask_1_31.txt AC 883 ms 243676 KB
subtask_1_32.txt AC 910 ms 243420 KB
subtask_1_33.txt AC 899 ms 243420 KB
subtask_1_34.txt AC 917 ms 243420 KB
subtask_1_35.txt AC 871 ms 243420 KB
subtask_1_36.txt AC 1212 ms 243420 KB
subtask_1_37.txt AC 859 ms 245948 KB
subtask_1_38.txt AC 881 ms 243420 KB
subtask_1_39.txt AC 880 ms 243420 KB
subtask_1_40.txt AC 880 ms 243420 KB
subtask_1_41.txt AC 871 ms 243420 KB