QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#184658#4897. 音符大师hos_lyric0 0ms0kbC++1414.3kb2023-09-21 02:24:422023-09-21 02:24:43

Judging History

你现在查看的是最新测评结果

  • [2023-09-21 02:24:43]
  • 评测
  • 测评结果:0
  • 用时:0ms
  • 内存:0kb
  • [2023-09-21 02:24:42]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")


// T: monoid representing information of an interval.
//   T()  should return the identity.
//   T(S s)  should represent a single element of the array.
//   T::pull(const T &l, const T &r)  should pull two intervals.
template <class T> struct SegmentTreePoint {
  int logN, n;
  vector<T> ts;
  SegmentTreePoint() : logN(0), n(0) {}
  explicit SegmentTreePoint(int n_) {
    for (logN = 0, n = 1; n < n_; ++logN, n <<= 1) {}
    ts.resize(n << 1);
  }
  template <class S> explicit SegmentTreePoint(const vector<S> &ss) {
    const int n_ = ss.size();
    for (logN = 0, n = 1; n < n_; ++logN, n <<= 1) {}
    ts.resize(n << 1);
    for (int i = 0; i < n_; ++i) at(i) = T(ss[i]);
    build();
  }
  T &at(int i) {
    return ts[n + i];
  }
  void build() {
    for (int u = n; --u; ) pull(u);
  }

  inline void pull(int u) {
    ts[u].pull(ts[u << 1], ts[u << 1 | 1]);
  }

  // Changes the value of point a to s.
  template <class S> void change(int a, const S &s) {
    assert(0 <= a); assert(a < n);
    ts[a += n] = T(s);
    for (; a >>= 1; ) pull(a);
  }

  // Applies T::f(args...) to point a.
  template <class F, class... Args>
  void ch(int a, F f, Args &&... args) {
    assert(0 <= a); assert(a < n);
    (ts[a += n].*f)(args...);
    for (; a >>= 1; ) pull(a);
  }

  // Calculates the product for [a, b).
  T get(int a, int b) {
    assert(0 <= a); assert(a <= b); assert(b <= n);
    if (a == b) return T();
    a += n; b += n;
    T prodL, prodR, t;
    for (int aa = a, bb = b; aa < bb; aa >>= 1, bb >>= 1) {
      if (aa & 1) { t.pull(prodL, ts[aa++]); prodL = t; }
      if (bb & 1) { t.pull(ts[--bb], prodR); prodR = t; }
    }
    t.pull(prodL, prodR);
    return t;
  }

  // Calculates T::f(args...) of a monoid type for [a, b).
  //   op(-, -)  should calculate the product.
  //   e()  should return the identity.
  template <class Op, class E, class F, class... Args>
#if __cplusplus >= 201402L
  auto
#else
  decltype((std::declval<T>().*F())())
#endif
  get(int a, int b, Op op, E e, F f, Args &&... args) {
    assert(0 <= a); assert(a <= b); assert(b <= n);
    if (a == b) return e();
    a += n; b += n;
    auto prodL = e(), prodR = e();
    for (int aa = a, bb = b; aa < bb; aa >>= 1, bb >>= 1) {
      if (aa & 1) prodL = op(prodL, (ts[aa++].*f)(args...));
      if (bb & 1) prodR = op((ts[--bb].*f)(args...), prodR);
    }
    return op(prodL, prodR);
  }

  // Find min b s.t. T::f(args...) returns true,
  // when called for the partition of [a, b) from left to right.
  //   Returns n + 1 if there is no such b.
  template <class F, class... Args>
  int findRight(int a, F f, Args &&... args) {
    assert(0 <= a); assert(a <= n);
    if ((T().*f)(args...)) return a;
    if (a == n) return n + 1;
    a += n;
    for (; ; a >>= 1) if (a & 1) {
      if ((ts[a].*f)(args...)) {
        for (; a < n; ) {
          if (!(ts[a <<= 1].*f)(args...)) ++a;
        }
        return a - n + 1;
      }
      ++a;
      if (!(a & (a - 1))) return n + 1;
    }
  }

  // Find max a s.t. T::f(args...) returns true,
  // when called for the partition of [a, b) from right to left.
  //   Returns -1 if there is no such a.
  template <class F, class... Args>
  int findLeft(int b, F f, Args &&... args) {
    assert(0 <= b); assert(b <= n);
    if ((T().*f)(args...)) return b;
    if (b == 0) return -1;
    b += n;
    for (; ; b >>= 1) if ((b & 1) || b == 2) {
      if ((ts[b - 1].*f)(args...)) {
        for (; b <= n; ) {
          if (!(ts[(b <<= 1) - 1].*f)(args...)) --b;
        }
        return b - n - 1;
      }
      --b;
      if (!(b & (b - 1))) return -1;
    }
  }
};

////////////////////////////////////////////////////////////////////////////////


constexpr Int INF = 1001001001001001001LL;

struct NodeMin {
  Int mn;
  NodeMin() : mn(+INF) {}
  NodeMin(Int val) : mn(val) {}
  void pull(const NodeMin &l, const NodeMin &r) {
    mn = min(l.mn, r.mn);
  }
  void ch(Int val) {
    mn = val;
  }
  void chmin(Int val) {
    if (mn > val) mn = val;
  }
  bool test(Int tar) const {
    return (mn <= tar);
  }
};
struct NodeMax {
  Int mx;
  NodeMax() : mx(-INF) {}
  NodeMax(Int val) : mx(val) {}
  void pull(const NodeMax &l, const NodeMax &r) {
    mx = max(l.mx, r.mx);
  }
  void ch(Int val) {
    mx = val;
  }
  void chmax(Int val) {
    if (mx < val) mx = val;
  }
  bool test(Int tar) const {
    return (mx >= tar);
  }
};

////////////////////////////////////////////////////////////////////////////////


int N, L;
vector<int> P;


namespace brute {
Int dp[210][260][260];
Int run() {
  const int lim = max(*max_element(P.begin(), P.end()) - L, 0);
  for (int i = 0; i <= N; ++i) {
    for (int x = 0; x <= lim; ++x) for (int y = 0; y <= lim; ++y) {
      dp[i][x][y] = INF;
    }
  }
  dp[0][0][0] = 0;
  for (int i = 0; i < N; ++i) {
    vector<pair<int, int>> es(lim + 1);
    for (int x = 0; x <= lim; ++x) {
      if (x < P[i] - L) {
        es[x] = make_pair((P[i] - L) - x, P[i] - L);
      } else if (P[i] < x) {
        es[x] = make_pair(x - P[i], P[i]);
      } else {
        es[x] = make_pair(0, x);
      }
    }
    for (int x = 0; x <= lim; ++x) for (int y = 0; y <= lim; ++y) {
      chmin(dp[i + 1][es[x].second][y], dp[i][x][y] + es[x].first);
      chmin(dp[i + 1][x][es[y].second], dp[i][x][y] + es[y].first);
    }
  }
  Int ans = INF;
  for (int x = 0; x <= lim; ++x) for (int y = 0; y <= lim; ++y) {
    chmin(ans, dp[N][x][y]);
  }
  return ans;
}
}  // brute


namespace fast {
struct Node {
  int l, r;
  Int mn[3], lz;
  Node() : l(0), r(0), mn{INF, INF, INF}, lz(0) {}
  void add(Int val) {
    for (int k = 0; k < 3; ++k) mn[k] += val;
    lz += val;
  }
};
int V;
Node nodes[20'000'010];

void push(int u) {
  const int l = nodes[u].l;
  const int r = nodes[u].r;
  Int &lz = nodes[u].lz;
  if (lz) {
    if (l) nodes[l].add(lz);
    if (r) nodes[r].add(lz);
    lz = 0;
  }
}
void pull(int u) {
  const int l = nodes[u].l;
  const int r = nodes[u].r;
  for (int k = 0; k < 3; ++k) nodes[u].mn[k] = min(nodes[l].mn[k], nodes[r].mn[k]);
}

void init() {
  V = 1;
}
void rangeAdd(int u, Int val) {
  nodes[u].add(val);
}
Int rangeMin(int u, int L, int R, int a, int b, int k) {
  if (b <= L || R <= a) return INF;
  if (a <= L && R <= b) return nodes[u].mn[k];
  push(u);
  const int Mid = (L + R) >> 1;
  const Int resL = rangeMin(nodes[u].l, L, Mid, a, b, k);
  const Int resR = rangeMin(nodes[u].r, Mid, R, a, b, k);
  pull(u);
  return min(resL, resR);
}
int merge(int u, int v) {
  if (!u) return v;
  if (!v) return u;
  if (!nodes[u].l && !nodes[u].r && !nodes[v].l && !nodes[v].r) {
    for (int k = 0; k < 3; ++k) chmin(nodes[u].mn[k], nodes[v].mn[k]);
    return u;
  }
  push(u);
  push(v);
  nodes[u].l = merge(nodes[u].l, nodes[v].l);
  nodes[u].r = merge(nodes[u].r, nodes[v].r);
  pull(u);
  return u;
}
int pointChmin(int u, int L, int R, int a, const Int *val) {
  if (!u) {
    u = V++;
    nodes[u] = Node();
  }
  if (L + 1 == R) {
    for (int k = 0; k < 3; ++k) chmin(nodes[u].mn[k], val[k]);
    return u;
  }
  push(u);
  const int Mid = (L + R) >> 1;
  if (a < Mid) {
    nodes[u].l = pointChmin(nodes[u].l, L, Mid, a, val);
  } else {
    nodes[u].r = pointChmin(nodes[u].r, Mid, R, a, val);
  }
  pull(u);
  return u;
}
void dfs(int u, int L, int R) {
  if (L + 1 == R) {
    if (nodes[u].mn[0] < INF || nodes[u].mn[1] < INF || nodes[u].mn[2] < INF) {
      cerr << L << ":" << nodes[u].mn[0] << "," << nodes[u].mn[1] << "," << nodes[u].mn[2] << " ";
    }
    return;
  }
  push(u);
  const int Mid = (L + R) >> 1;
  dfs(nodes[u].l, L, Mid);
  dfs(nodes[u].r, Mid, R);
}

int dp[50010][2];
int xsLen;
vector<int> xs;

Int rangeMin(int u, int a, int b, int k) {
  return rangeMin(u, 0, xsLen, a, b, k);
}
void update(int i, int j, int x, Int c) {
// cerr<<COLOR("93")<<"update i="<<i<<" j="<<j<<" x="<<x<<" c="<<c<<COLOR()<<endl;
  const int l = lower_bound(xs.begin(), xs.end(), x) - xs.begin();
  const Int val[3] = {c - x, c, c + x};
  dp[i][j] = pointChmin(dp[i][j], 0, xsLen, l, val);
}

Int run() {
  vector<pair<int, int>> pis(N);
  for (int i = 0; i < N; ++i) {
    pis[i] = make_pair(P[i], i);
  }
  sort(pis.begin(), pis.end());
  SegmentTreePoint<NodeMin> seg(N);
  for (int h = 0; h < N; ++h) {
    seg.at(h) = pis[h].second;
  }
  seg.build();
  
  // not included in [x, x + L]
  auto getNext = [&](int x) -> int {
    const int posL = lower_bound(pis.begin(), pis.end(), make_pair(x, -1)) - pis.begin();
    const int posR = lower_bound(pis.begin(), pis.end(), make_pair(x + L + 1, -1)) - pis.begin();
    Int mn = N;
    chmin(mn, seg.get(0, posL).mn);
    chmin(mn, seg.get(posR, N).mn);
    return (int)mn;
  };
  // not included in [x0, x0 + L] \cup [x1, x1 + L]
  auto getNext2 = [&](int x0, int x1) -> int {
    const int pos0L = lower_bound(pis.begin(), pis.end(), make_pair(x0, -1)) - pis.begin();
    const int pos0R = lower_bound(pis.begin(), pis.end(), make_pair(x0 + L + 1, -1)) - pis.begin();
    const int pos1L = lower_bound(pis.begin(), pis.end(), make_pair(x1, -1)) - pis.begin();
    const int pos1R = lower_bound(pis.begin(), pis.end(), make_pair(x1 + L + 1, -1)) - pis.begin();
    Int mn = N;
    chmin(mn, seg.get(0, pos0L).mn);
    if (pos0R < pos1L) {
      chmin(mn, seg.get(pos0R, pos1L).mn);
    }
    chmin(mn, seg.get(pos1R, N).mn);
    return (int)mn;
  };
  
  xs.resize((N << 1) + 1);
  for (int i = 0; i < N; ++i) {
    xs[i << 1    ] = P[i] - L;
    xs[i << 1 | 1] = P[i];
  }
  xs[N << 1] = 0;
  sort(xs.begin(), xs.end());
  xs.erase(unique(xs.begin(), xs.end()), xs.end());
  xsLen = xs.size();
// cerr<<"xs = "<<xs<<endl;
  
  init();
  // dp[i][j]: previous hand at (i, j), segtree for another hand
  memset(dp, 0, sizeof(dp));
  Int ans = INF;
  {
    const int i = getNext(0);
    if (i == N) {
      chmin(ans, 0LL);
    } else {
      assert(0 < P[i] - L);
      update(i, 0, 0, P[i] - L);
    }
  }
  for (int i = 0; i < N; ++i) {
    {
      const int h = lower_bound(pis.begin(), pis.end(), make_pair(P[i], i)) - pis.begin();
      seg.change(h, N);
    }
    for (int j = 0; j < 2; ++j) {
      const int x = P[i] + L * (j - 1);
      const int ii = getNext(x);
// cerr<<"i = "<<i<<", j = "<<j<<", x = "<<x<<", ii = "<<ii<<endl;
// cerr<<"  dp["<<i<<"]["<<j<<"] = "<<dp[i][j]<<": ";dfs(dp[i][j],0,xsLen);cerr<<endl;
      if (ii == N) {
        const Int res = rangeMin(dp[i][j], 0, xsLen, 1);
// cerr<<"  "<<__LINE__<<" chmin(ans, "<<res<<")"<<endl;
        chmin(ans, res);
      } else {
        // move another hand to cover ii
        const int posL = lower_bound(xs.begin(), xs.end(), P[ii] - L) - xs.begin();
        const int posR = upper_bound(xs.begin(), xs.end(), P[ii]) - xs.begin();
// cerr<<"  posL = "<<posL<<", posR = "<<posR<<endl;
        {
          const Int res = rangeMin(dp[i][j], 0, posL, 0);
          if (res < INF) {
            update(ii, 0, x, res + (P[ii] - L));
          }
        }
        for (int l = posL; l < posR; ++l) {
          const Int res = rangeMin(dp[i][j], l, l + 1, 1);
          if (res < INF) {
            Int x0 = x, x1 = xs[l];
            if (x0 > x1) {
              swap(x0, x1);
            }
            const int iii = getNext2(x0, x1);
// cerr<<"    l = "<<l<<", res = "<<res<<", iii = "<<iii<<endl;
            if (iii == N) {
              chmin(ans, res);
// cerr<<"  "<<__LINE__<<" chmin(ans, "<<res<<")"<<endl;
            } else {
              // cover iii
              if (P[iii] < x0) {
                update(iii, 1, x1, res + (x0 - P[iii]));
              } else if (x0 < P[iii] - L && P[iii] < x1) {
                update(iii, 0, x1, res + ((P[iii] - L) - x0));
                update(iii, 1, x0, res + (x1 - P[iii]));
              } else if (x1 < P[iii] - L) {
                update(iii, 0, x0, res + ((P[iii] - L) - x1));
              } else {
                assert(false);
              }
            }
          }
        }
        {
          const Int res = rangeMin(dp[i][j], posR, xsLen, 2);
          if (res < INF) {
            update(ii, 1, x, res - P[ii]);
          }
        }
        // move previous hand to cover ii
        if (P[ii] < x) {
          rangeAdd(dp[i][j], x - P[ii]);
          dp[ii][1] = merge(dp[ii][1], dp[i][j]);
        } else if (x < P[ii] - L) {
          rangeAdd(dp[i][j], (P[ii] - L) - x);
          dp[ii][0] = merge(dp[ii][0], dp[i][j]);
        } else {
          assert(false);
        }
      }
    }
  }
cerr<<"V = "<<V<<endl;
  return ans;
}
}  // fast


int main() {
  for (; ~scanf("%d%d", &N, &L); ) {
    P.resize(N);
    for (int i = 0; i < N; ++i) {
      scanf("%d", &P[i]);
    }
cerr<<"N = "<<N<<", L = "<<L<<endl;
// cerr<<"P = "<<P<<endl;
    
    const Int ans = fast::run();
    printf("%lld\n", ans);
#ifdef LOCAL
if(N<=200&&*max_element(P.begin(),P.end())<=200){
 const Int brt=brute::run();
 if(brt!=ans)cerr<<N<<" "<<L<<" "<<P<<": "<<brt<<" "<<ans<<endl;
 assert(brt==ans);
}
cerr<<string(80,'=')<<endl;
#endif
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Subtask #1:

score: 0
Memory Limit Exceeded

Test #1:

score: 0
Memory Limit Exceeded

input:

200 20
78 30 163 87 97 53 96 76 81 138 156 200 124 93 173 119 115 93 150 99 22 80 88 131 61 126 47 103 143 142 129 186 89 105 101 143 178 110 13 77 79 178 21 108 200 146 87 105 54 61 136 69 161 195 13 105 18 151 25 191 30 35 90 110 17 98 181 58 120 102 139 71 59 24 72 84 33 12 28 82 23 80 128 96 115...

output:

3669

result:


Subtask #2:

score: 0
Memory Limit Exceeded

Test #19:

score: 0
Memory Limit Exceeded

input:

50000 0
957304147 455870042 888520405 388924006 685268286 213595280 898496267 50362797 310595209 105517171 706682592 663787741 927429771 306122736 1352192 453945549 31881610 943782347 779421515 543589796 209926777 908434673 845417119 374441290 190474943 606994057 30091060 491598457 644246786 4649716...

output:

7861788079227

result:


Subtask #3:

score: 0
Skipped

Dependency #2:

0%

Subtask #4:

score: 0
Skipped

Dependency #3:

0%