Submission #1182661

#TimeUsernameProblemLanguageResultExecution timeMemory
1182661madamadam3Radio Towers (IOI22_towers)C++20
0 / 100
4042 ms14408 KiB
#include "towers.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define all(x) (x).begin(), (x).end()
#define sz(x) (int) (x).size()

using vi = vector<int>;
using vvi = vector<vi>;

struct SegTree {
  int N, neutral;
  vi st, arr;
  function<int(int, int)> combine;

  SegTree(int _N, vi _arr, function<int(int, int)> _combine, int _neutral) {
    N = _N; arr = _arr; combine = _combine, neutral = _neutral;

    st.assign(4 * N, 0);
    build(0, 0, N);
  } 

  SegTree() : N(0), neutral(0) {};

  int build(int i, int l, int r) {
    if (l + 1 == r) return st[i] = arr[l];
    int m = l + (r - l) / 2;
    return st[i] = combine(build(2 * i + 1, l, m), build(2 * i + 2, m, r));
  }

  int query(int i, int l, int r, int ql, int qr) {
    if (r <= ql || qr <= l) return neutral;
    if (ql <= l && r <= qr) return st[i];

    int m = l + (r - l) / 2;
    return combine(query(2 * i + 1, l, m, ql, qr), query(2 * i + 2, m, r, ql, qr));
  }

  int update(int i, int l, int r, int k, int v) {
    if (!(l <= k && k < r)) return st[i];
    if (l + 1 == r) return st[i] = arr[k] = v;

    int m = l + (r - l) / 2;
    return st[i] = combine(update(2 * i + 1, l, m, k, v), update(2 * i + 2, m, r, k, v));
  }

  int query(int l, int r) {
    return query(0, 0, N, l, r);
  }

  void update(int k, int v) {
    update(0, 0, N, k, v);
  }
};

struct DSU {
  int N;
  vi par, siz, mv;
  set<int> components;

  DSU(int _N, vi _mv) {
    N = _N;
    par.resize(N); iota(par.begin(), par.end(), 0);
    siz.assign(N, 1);
    mv = _mv;
    components = set<int>(all(par));
  }

  DSU() : N(0) {};

  int find_set(int v) {
    if (v == par[v]) return v;
    return par[v] = find_set(par[v]);
  }

  void union_set(int a, int b) {
    a = find_set(a);
    b = find_set(b);

    if (a != b) {
      if (siz[a] > siz[b]) {
        siz[a] += siz[b];
        par[b] = a;
        mv[a] = min(mv[b], mv[a]);
        components.erase(b);
      } else {
        siz[b] += siz[a];
        par[a] = b;
        mv[b] = min(mv[b], mv[a]);
        components.erase(a);
      }
    }
  }
};

int n;
vi h, cmp;
SegTree maxST;

function<int(int, int)> mx = [](int a, int b) {return max(a, b);};

int gidx(int v) {
  auto it = lower_bound(all(cmp), v);
  if (it == cmp.end()) return -1;
  else return (int) (it - cmp.begin());
}

/*
  If tower i is connected to tower j, and tower j is connected to tower k (i < m1 < j < m2 < k)
  - tower i and k are connected through either m1 or m2

  dp[i][peak] = largest value of dp[j][!peak] for j > i and h[j] <= h[i] - D
  dp[i][!peak] = 1 + largest value of dp[j][peak] for j > i and h[j] >= h[i] + D
*/

void init(int N, vi H) {
  n = N; h = H;
  maxST = SegTree(n, h, mx, INT_MIN);

  cmp = h;
  sort(all(cmp));
  for (int i = 0; i < n; i++) {
    h[i] = lower_bound(all(cmp), h[i]) - cmp.begin();
  }
}

int max_towers(int L, int R, int D) {
  auto dsu = DSU(n, h);
  vvi DP(2, vi(n, 0));
  auto stPeak = SegTree(n, DP[0], mx, INT_MIN);
  auto stTrough = SegTree(n, DP[1], mx, INT_MIN);

  for (int i = R; i >= L; i--) {
    int height = cmp[h[i]];
    int low = gidx(height - D), high = gidx(height + D);

    bool lowFine = low != -1 && cmp[low] <= height - D, highFine = high != -1 && cmp[high] >= height + D;
    int vP = highFine ? stPeak.query(high, n) : -1;
    int vT = lowFine ? stTrough.query(0, low+1) : -1;

    if (lowFine) {
      stPeak.update(h[i], vT);
    }
    
    if (highFine) {
      stTrough.update(h[i], vP);
    }
  }
  
  return max({1, stPeak.query(0, n), stTrough.query(0, n)});
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...