C - Kaiten Sushi
把壽司都放到一個堆裡,從前往後掃 \(A\) 陣列,如果當前食客 \(A_i\) 小於等於堆頂,就取出堆頂,記錄這份壽司被第 \(i\) 個人吃掉。複雜度 \(O(n\log m)\)。
D - Keep Distance
搜尋回溯,但每一步從 \(10\) 列舉到 \(m\) 會超時,剪一下枝 for (int i = 10; res.back() + i <= m - 10 * (n - siz - 1); i++)
。
F - Falling Stars
把橫線從下到上排序,開一棵線段樹記錄每個位置摞了多少層。要加入一條橫線的時候,先查詢對應區間 \([C_i,C_i+L_i-1]\) 的最小值(最高層數)\(r\),則該橫線的層數就是 \(r-1\),區間賦值 \(r-1\) 即可。
#include <bits/stdc++.h>
using namespace std;
int main() {
cin.tie(0)->sync_with_stdio(0);
int H, W, n;
cin >> H >> W >> n;
struct Bar {
int R, C, L, id;
bool operator<(const Bar& o) const {
return R > o.R;
}
};
vector<Bar> bars(n);
for (int i = 0; i < n; i++) {
Bar& b = bars[i];
cin >> b.R >> b.C >> b.L;
b.id = i;
}
sort(bars.begin(), bars.end());
class SegmentTree {
struct Node;
using NodePtr = shared_ptr<Node>;
struct Node {
int l, r, val, tag;
NodePtr ls, rs;
Node(int l, int r, int val, int tag,
NodePtr ls = nullptr,
NodePtr rs = nullptr)
: l(l), r(r), val(val), tag(tag), ls(ls), rs(rs) {}
};
private:
NodePtr root;
void refresh(NodePtr p) {
p->val = min(p->ls->val, p->rs->val);
}
void build(NodePtr& p, int l, int r) {
p = make_shared<Node>(l, r, 0, 0);
if (l == r) return;
int mid = (l + r) >> 1;
build(p->ls, l, mid);
build(p->rs, mid + 1, r);
}
void applyFillTag(NodePtr p, int v) {
p->val = p->tag = v;
}
void pushDown(NodePtr p) {
if (!p->tag) return;
applyFillTag(p->ls, p->tag);
applyFillTag(p->rs, p->tag);
p->tag = 0;
}
void fillRange(NodePtr p, int l, int r, int val) {
if (l <= p->l && p->r <= r)
return applyFillTag(p, val), void(0);
pushDown(p);
int mid = (p->l + p->r) >> 1;
if (l <= mid) fillRange(p->ls, l, r, val);
if (r > mid) fillRange(p->rs, l, r, val);
refresh(p);
}
int queryMin(NodePtr p, int l, int r) {
if (l <= p->l && p->r <= r)
return p->val;
pushDown(p);
int mid = (p->l + p->r) >> 1;
int res = INT_MAX;
if (l <= mid) res = min(res, queryMin(p->ls, l, r));
if (r > mid) res = min(res, queryMin(p->rs, l, r));
return res;
}
public:
SegmentTree(int l, int r) { build(root, l, r); }
void fillRange(int l, int r, int val) { fillRange(root, l, r, val); }
int queryMin(int l, int r) { return queryMin(root, l, r); }
};
SegmentTree tr(1, W);
tr.fillRange(1, W, H + 1);
vector<int> ans(n);
for (auto& b : bars) {
ans[b.id] = tr.queryMin(b.C, b.C + b.L - 1) - 1;
tr.fillRange(b.C, b.C + b.L - 1, ans[b.id]);
}
for (int i = 0; i < n; i++) {
cout << ans[i] << '\n';
}
return 0;
}