제출 #218872

#제출 시각아이디문제언어결과실행 시간메모리
218872rama_pangTwo Antennas (JOI19_antennas)C++14
100 / 100
744 ms36800 KiB
#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9 + 100;

class SegmentTree {
 private:
  int sz;
  vector<int> C; // C[i] = H[i] if i is active, -INF otherwise. We hold maximum C for each node.
  vector<int> D; // D[i] = max(C[i] - H[j]) so far. We hold maximum D for each node.
  vector<int> L; // lazy propagation, we have to update D[k] = max(D[k], C[k] - L) on segment

  void Push(int n) {
    if (L[n] != INF) {
      L[n * 2] = min(L[n * 2], L[n]); // in order to maximize C[k] - L
      L[n * 2 + 1] = min(L[n * 2 + 1], L[n]);

      D[n * 2] = max(D[n * 2], C[n * 2] - L[n]); // lazy propagation
      D[n * 2 + 1] = max(D[n * 2 + 1], C[n * 2 + 1] - L[n]);

      L[n] = INF;
    }
  }

  void Pull(int n) {
    C[n] = max(C[n * 2], C[n * 2 + 1]); // C helps in lazy propagation to update maximum C - L quickly
    D[n] = max(D[n * 2], D[n * 2 + 1]);
  }

  void PointSetUpdate(int n, int tl, int tr, int k, int H) {
    if (tl == tr) return void(C[n] = H);
    Push(n);
    int mid = (tl + tr) / 2;
    if (k <= mid) {
      PointSetUpdate(n * 2, tl, mid, k, H);
    } else {
      PointSetUpdate(n * 2 + 1, mid + 1, tr, k, H);
    }
    Pull(n);
  }

  void RangeUpdate(int n, int tl, int tr, int l, int r, int H) {
    if (tr < l || r < tl || tl > tr || l > r) return;
    if (l <= tl && tr <= r) {
      D[n] = max(D[n], C[n] - H);
      L[n] = min(L[n], H);
      return;
    }
    Push(n);
    int mid = (tl + tr) / 2;
    RangeUpdate(n * 2, tl, mid, l, r, H);
    RangeUpdate(n * 2 + 1, mid + 1, tr, l, r, H);
    Pull(n);
  }

  int RangeMaximumQuery(int n, int tl, int tr, int l, int r) {
    if (tr < l || r < tl || tl > tr || l > r) return -INF;
    if (l <= tl && tr <= r) return D[n];
    Push(n);
    int mid = (tl + tr) / 2;
    return max(RangeMaximumQuery(n * 2, tl, mid, l, r), 
                RangeMaximumQuery(n * 2 + 1, mid + 1, tr, l, r));
  }
  
 public:
  SegmentTree(int n) : sz(n) {
    C.assign(4 * sz, -INF);
    D.assign(4 * sz, -INF);
    L.assign(4 * sz, INF);
  }

  void PointSetUpdate(int k, int H) { // set C[k] = H
    return PointSetUpdate(1, 0, sz - 1, k, H);
  }

  void RangeUpdate(int l, int r, int H) { // for each k, l <= k <= r, D[k] = max(D[k], C[k] - H)
    return RangeUpdate(1, 0, sz - 1, l, r, H);
  }

  int RangeMaximumQuery(int l, int r) { // RMQ on the array D
    return RangeMaximumQuery(1, 0, sz - 1, max(l, 0), r);
  }
};

vector<int> answer;

void Solve(int N, int Q, vector<int> H, vector<int> A, vector<int> B, 
            vector<int> L, vector<int> R) {
  
  int a;
  vector<vector<pair<int, int>>> events(N); // (type, x)
  // type = 1  -> set C[x] = H[x]
  // type = 2 -> set C[x] = -INF
  // type <= 0  -> query (x, current), query id is -type

  for (int i = 0; i < N; i++) {
    int l = i + A[i], r = i + B[i] + 1; // antenna i is active on segment [l, r)
    if (l < N) events[l].emplace_back(1, i);
    if (r < N) events[r].emplace_back(2, i);
  }

  for (int i = 0; i < Q; i++) {
    events[R[i]].emplace_back(-i, L[i]);
  }

  SegmentTree seg(N);

  for (int t = 0; t < N; t++) {
    reverse(begin(events[t]), end(events[t]));

    while (!events[t].empty()) { // updates
      if (events[t].back().first <= 0) break;
      int type = events[t].back().first;
      int x = events[t].back().second;
      events[t].pop_back();

      if (type == 1) {
        seg.PointSetUpdate(x, H[x]);
      } else {
        seg.PointSetUpdate(x, -INF);
      }
    }

    // for k, t - B[t] <= k <= t - A[t], we update D[k] = max(D[k], C[k] - H[t])
    seg.RangeUpdate(t - B[t], t - A[t], H[t]);

    while (!events[t].empty()) { // queries
      int ql = events[t].back().second;
      int qr = t;
      int qi = -events[t].back().first;
      events[t].pop_back();
      answer[qi] = max(answer[qi], seg.RangeMaximumQuery(ql, qr));
    }
  }
}

void Solve() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);

  int N;
  cin >> N;
  
  vector<int> H(N), A(N), B(N);
  for (int i = 0; i < N; i++) {
    cin >> H[i] >> A[i] >> B[i];
  }

  int Q;
  cin >> Q;

  vector<int> L(Q), R(Q);
  for (int i = 0; i < Q; i++) {
    cin >> L[i] >> R[i];
    L[i]--, R[i]--;
  }

  answer.assign(Q, -1);

  auto Reverse = [&]() {
    // reverse the array
    reverse(begin(H), end(H));
    reverse(begin(A), end(A));
    reverse(begin(B), end(B));
    for (int i = 0; i < Q; i++) {
      L[i] = N - 1 - L[i];
      R[i] = N - 1 - R[i];
      swap(L[i], R[i]);
    }
  };

  Solve(N, Q, H, A, B, L, R);
  Reverse();
  Solve(N, Q, H, A, B, L, R);
}

void Write() {
  for (auto &ans : answer) {
    cout << ans << "\n";
  }
}

int main() {
  Solve();
  Write();
  return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

antennas.cpp: In function 'void Solve(int, int, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
antennas.cpp:90:7: warning: unused variable 'a' [-Wunused-variable]
   int a;
       ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...