結果
| 問題 |
No.711 競技レーティング単調増加
|
| コンテスト | |
| ユーザー |
しらっ亭
|
| 提出日時 | 2017-05-23 00:48:15 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 720 ms / 2,000 ms |
| コード長 | 2,881 bytes |
| コンパイル時間 | 2,182 ms |
| コンパイル使用メモリ | 175,764 KB |
| 実行使用メモリ | 10,112 KB |
| 最終ジャッジ日時 | 2024-09-19 10:30:08 |
| 合計ジャッジ時間 | 17,500 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 41 |
ソースコード
// 想定解の「全体1インクリメント」を lazy seg tree にしたやつ。O(n log^2 n)
#include <bits/stdc++.h>
using namespace std;
const int inf = 2e9;
// 遅延 SegmentTree。range-add。クエリは区間には行わないので range-max 版(何でもいい)
// 点クエリ限定で良いので、区間add可能なデータ構造があれば、高速化できるかも
template <typename V> struct SegTreeLazy {
static const V zero = 0;
static const V def = inf;
struct Node {
V dat;
V lazy;
bool flag;
Node() : dat(def), lazy(zero), flag(false) {}
};
static V merge(const V &l, const V &r) {
return max(l, r);
}
const int N;
vector<Node> seg;
SegTreeLazy(int size) : N(p2(size)), seg(N * 2) {};
void update(int a, int b, V v) {
update(a, b, v, 0, 0, N);
}
V query(int a, int b) {
return query(a, b, 0, 0, N);
}
void set(int i, V v) {
V cur = query(i, i+1);
update(i, i+1, v - cur);
}
private:
void push(int k, int l, int r) {
if (seg[k].flag) {
seg[k].dat += seg[k].lazy;
if (r - l > 1) {
seg[k * 2 + 1].lazy += seg[k].lazy;
seg[k * 2 + 2].lazy += seg[k].lazy;
seg[k * 2 + 1].flag = true;
seg[k * 2 + 2].flag = true;
}
seg[k].lazy = zero;
seg[k].flag = false;
}
}
void update(int a, int b, V v, int k, int l, int r) {
push(k, l, r);
if (r <= a || b <= l) return;
if (a <= l && r <= b) {
seg[k].lazy = v;
seg[k].flag = true;
push(k, l, r);
}
else {
update(a, b, v, k * 2 + 1, l, (l + r) / 2);
update(a, b, v, k * 2 + 2, (l + r) / 2, r);
seg[k].dat = merge(seg[k * 2 + 1].dat, seg[k * 2 + 2].dat);
}
}
V query(int a, int b, int k, int l, int r) {
push(k, l, r);
if (r <= a || b <= l) return zero;
if (a <= l && r <= b) return seg[k].dat;
V x = query(a, b, k * 2 + 1, l, (l + r) / 2);
V y = query(a, b, k * 2 + 2, (l + r) / 2, r);
return merge(x, y);
}
static int p2(int n, int m=1) { return m >= n ? m : p2(n, m * 2); }
};
int solve() {
int n;
cin >> n;
vector<int> A(n);
for (int i = 0; i < n; i++) cin >> A[i];
SegTreeLazy<int> seg(n+1);
seg.set(0, 0);
for (int i = 0; i < n; i++) {
int a = A[i];
int lo = -1; // ok
int hi = i + 1;
while (hi - lo > 1) {
int mid = (hi + lo) / 2;
bool cond = seg.query(mid, mid+1) < a;
if (cond) lo = mid;
else hi = mid;
}
seg.update(0, i+1, 1);
if (lo >= 0) {
seg.set(lo + 1, a);
}
//for (int i = 0; i < n+1; i++) cout << seg.query(i, i+1) << ' '; cout << endl;
}
for (int j = n; j >= 0; j--) {
if (seg.query(j, j+1) < inf) {
return n - j;
}
}
assert(false);
}
int main() {
cin.tie(nullptr); ios::sync_with_stdio(false);
cout << solve() << endl;
return 0;
}
しらっ亭