제출 #681531

#제출 시각아이디문제언어결과실행 시간메모리
681531peijarFinancial Report (JOI21_financial)C++17
100 / 100
412 ms58384 KiB
#include <bits/stdc++.h>
#define int long long
using namespace std;

namespace std {
template <typename T> ostream &operator<<(ostream &out, const vector<T> &vec) {
  out << "[";
  for (int i = 0; i < (int)vec.size(); ++i) {
    out << vec[i];
    if (i + 1 < (int)vec.size())
      out << ", ";
  }
  return out << "]";
}
} // namespace std

void dbg_out() { cout << endl; }
template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) {
  cout << ' ' << H;
  dbg_out(T...);
}

#ifdef DEBUG
#define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
#define dbg(...)
#endif

struct UnionFind {
  vector<int> id;
  vector<int> smallest;

  UnionFind() {}
  UnionFind(int N) {
    id.assign(N, -1);
    smallest.resize(N);
    iota(smallest.begin(), smallest.end(), 0);
  }

  int find(int u) {
    if (id[u] < 0)
      return u;
    return id[u] = find(id[u]);
  }

  bool merge(int u, int v) {
    u = find(u), v = find(v);
    if (u == v)
      return false;
    if (id[u] > id[v])
      swap(u, v);
    id[u] += id[v];
    id[v] = u;
    smallest[u] = min(smallest[u], smallest[v]);
    return true;
  }
};

const int INF = 1e18;

signed main(void) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);

  int N, D;
  cin >> N >> D;

  vector<int> A(N);
  for (int &x : A)
    cin >> x;

  vector<int> order(N);
  iota(order.begin(), order.end(), 0);

  sort(order.begin(), order.end(), [&](int i, int j) { return A[i] < A[j]; });

  set<int> starts;
  UnionFind dsu(N);
  vector<int> firstBad(N);

  int curAdded = N - 1;
  for (int i = N - 1; i >= 0; --i) {
    int x = A[order[i]];
    while (x < A[order[curAdded]]) {
      int j = order[curAdded];
      if (j and A[j - 1] > x)
        dsu.merge(j - 1, j);
      if (j + 1 < N and A[j + 1] > x)
        dsu.merge(j, j + 1);
      int id = dsu.find(j);
      if (-dsu.id[id] >= D)
        starts.insert(dsu.smallest[id]);
      curAdded--;
    }

    auto it = starts.lower_bound(order[i]);
    firstBad[order[i]] = it == starts.end() ? N : min(N, *it + D);
  }

  dbg(firstBad);

  int start = 1;
  while (start < N)
    start *= 2;
  vector<int> seg(2 * start);

  auto setPos = [&](int pos, int x) {
    pos += start;
    seg[pos] = x;
    while (pos > 1) {
      pos /= 2;
      seg[pos] = max(seg[2 * pos], seg[2 * pos + 1]);
    }
  };

  auto query = [&](int deb, int fin) {
    int ret = 0;

    deb += start, fin += start;
    while (deb < fin) {
      if (deb % 2)
        ret = max(ret, seg[deb++]);
      if (fin % 2)
        ret = max(ret, seg[--fin]);
      deb /= 2;
      fin /= 2;
    }
    return ret;
  };

  vector<int> pos(N);
  for (int i = 0; i < N; ++i)
    pos[order[i]] = i;

  vector<int> sortedA = A;
  sort(sortedA.begin(), sortedA.end());

  vector<vector<int>> toDelete(N);
  for (int i = 0; i < N; ++i)
    if (firstBad[i] < N)
      toDelete[firstBad[i]].push_back(i);

  for (int i = 0; i < N; ++i) {

    for (int j : toDelete[i])
      setPos(pos[j], 0);

    auto fin =
        lower_bound(sortedA.begin(), sortedA.end(), A[i]) - sortedA.begin();

    int LIS = query(0, fin) + 1;
    dbg(i, fin, LIS);
    setPos(pos[i], LIS);
  }
  cout << query(0, N) << endl;
}
#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...