template<class T>
struct seg_tree {
private:
const T INF = numeric_limits<T>::max() >> 1;
struct node {
T sum = 0, min = 0, max = 0;
node(T v) : sum(v), min(v), max(v) {}
node(T sum, T min, T max) : sum(sum), min(min), max(max) {}
};
const node identity{0, 0, 0};
int N;
vector<node> tree;
node merge(node l, node r) {
node ret = {l.sum + r.sum, min(l.min, r.min), max(l.max, r.max)};
return ret;
}
void update(int n, int nl, int nr, int i, T v) {
if (nl > i || nr < i) return;
if (nl == nr) {
tree[n] = merge(tree[n], node(v)); // diff or assign?
return;
}
int m = (nl + nr) >> 1;
update(n * 2, nl, m, i, v);
update(n * 2 + 1, m + 1, nr, i, v);
tree[n] = merge(tree[n * 2], tree[n * 2 + 1]);
}
node query(int n, int nl, int nr, int l, int r) {
if (nl > r || nr < l) return identity;
if (nl >= l && nr <= r) return tree[n];
int m = (nl + nr) >> 1;
return merge(query(n * 2, nl, m, l, r), query(n * 2 + 1, m + 1, nr, l, r));
}
public:
seg_tree(int N) : N(N) {
int tree_size = 1 << ((int) ceil(log2(N)) + 1);
tree = vector<node>(tree_size, identity);
}
void update(int i, T v) { update(1, 0, N - 1, i, v); }
node query(int l, int r) { return query(1, 0, N - 1, l, r); };
};
void solve() {
int n;
cin >> n;
vi a(n);
fv(a);
vi mn(n);
mn[0] = a[0];
for (int i = 1; i < n; i++) mn[i] = min(mn[i - 1], a[i]);
seg_tree<int> seg(n), seg3(n), seg2(200001);
vi idx(n);
iota(all(idx), 0);
sort(all(idx), [&](int i, int j) { return a[i] < a[j]; });
vi m_idx_possible(n, 1e9);
for (int i = n - 1; i >= 0; i--) {
int back_cnt = n - 1 - (i + 1) + 1;
if (back_cnt / 2 < a[i]) {
} else {
int l = 0, r = 1e6, order = -1;
while (l <= r) {
int m = l + (r - l) / 2;
if (seg2.query(1, m).sum >= a[i] * 2) {
order = m, r = m - 1;
} else l = m + 1;
}
m_idx_possible[i] = order;
assert(~order);
}
seg2.update(a[i], 1);
}
vi midx(n);
iota(all(midx), 0);
sort(all(midx), [&](int i, int j) {
return m_idx_possible[i] < m_idx_possible[j];
});
pi ans = {-1, -1};
vi first_idx(200001, -1);
for (int i = 0; i < n; i++) if (first_idx[a[i]] == -1) first_idx[a[i]] = i;
for (int i = 1, j = 0, mj = 0; i <= 200000; i++) {
while (j < n && a[idx[j]] <= i) {
seg.update(idx[j], 1);
j++;
}
while (mj < n && m_idx_possible[midx[mj]] <= i) {
seg3.update(midx[mj], a[midx[mj]]);
mj++;
}
if (first_idx[i] == -1) continue;
int n_idx = first_idx[i];
int m_mx = seg3.query(n_idx + 1, n - 1).max;
if (m_mx) {
maxa(ans, mp(i, m_mx));
}
// n_idx 보다 뒤에 있는 것 중 m_idx를 고르고 m_idx 뒤에 a[m_idx] * 2 개 이상이 있어야 한다.
// m_idx 가 가능하게 되는 시점도 스위핑?
}
if (ans.fi == -1) cout << -1;
else cout << ans.fi << ' ' << ans.se;
}
Comments