1 条题解
-
0
考虑扫描序列时动态维护函数 ,注意到 ,容易用线段树维护。
#include <bits/stdc++.h> using namespace std; const int D = (1 << 17) - 1; const int N = 2.7e5 + 12; int a[N], amax[N], b[N]; void reset(int n, int ll, int rr, int b) { a[b] = 0; amax[b] = 0; if (n < ll) return; if (ll == rr) return; int mid = (ll + rr) >> 1; reset(n, ll, mid, b + b); reset(n, mid + 1, rr, b + b + 1); } void add(int l, int r, int ll, int rr, int b) { if (r < 0) return; if (l == ll && r == rr) { a[b]++; amax[b]++; return; } if (a[b]) { a[b + b] += a[b]; amax[b + b] += a[b]; a[b + b + 1] += a[b]; amax[b + b + 1] += a[b]; a[b] = 0; } int mid = (ll + rr) >> 1; int cl = min(r, mid); int cr = max(l, mid + 1); if (l <= mid) add(l, cl, ll, mid, b + b); if (r > mid) add(cr, r, mid + 1, rr, b + b + 1); amax[b] = max(amax[b + b], amax[b + b + 1]); } int get(int l, int r, int ll, int rr, int b) { if (l == ll && r == rr) return amax[b]; if (a[b]) { a[b + b] += a[b]; amax[b + b] += a[b]; a[b + b + 1] += a[b]; amax[b + b + 1] += a[b]; a[b] = 0; } int mid = (ll + rr) >> 1; int ans = 0; int cl = min(r, mid); int cr = max(l, mid + 1); if (l <= mid) ans = max(ans, get(l, cl, ll, mid, b + b)); if (r > mid) ans = max(ans, get(cr, r, mid + 1, rr, b + b + 1)); return ans; } int find(int x, int ll, int rr, int b) { if (amax[b] <= x) return rr; if (ll == rr) return -1; if (a[b]) { a[b + b] += a[b]; amax[b + b] += a[b]; a[b + b + 1] += a[b]; amax[b + b + 1] += a[b]; a[b] = 0; } int mid = (ll + rr) >> 1; int ans = find(x, ll, mid, b + b); if (ans != mid) return ans; return max(mid, find(x, mid + 1, rr, b + b + 1)); } int main() { int n; while (cin >> n) { int m = 0; for (int i = 1; i <= n; i++) { cin >> b[i]; m = max(m, b[i]); } for (int i = 1; i <= m; i++) add(i, D, 0, D, 1); for (int i = 1; i <= n; i++) if (b[i]) add(0, find(b[i] - 1, 0, D, 1), 0, D, 1); for (int i = 0; i <= m - 1; i++) cout << get(i, i, 0, D, 1) << ' '; cout << get(m, m, 0, D, 1) << endl; reset(m, 0, D, 1); } return 0; }
- 1
信息
- ID
- 252
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 2
- 已通过
- 2
- 上传者