Files
python/TangDou/AcWing/SegmentTree/POJ2828.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

75 lines
2.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 200010;
int n, res[N];
int p[N], v[N]; // 在p[i]的后面,v[i]:权值
struct Node {
int l, r;
int sum; // 此区间内空位置的数量
} tr[N << 2];
void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r;
if (l == r) {
tr[u].sum = 1; // 每个叶子节点初始化为1,表示此区间内空位置的数量是1
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u); // 叶子有初始值1,所以这里需要向上更新信息
}
// 此处的x,是指在第x个空白位置上,不是普通前缀和的第x个位置的概念
void modify(int u, int x, int v) {
if (tr[u].l == tr[u].r) {
tr[u].sum = 0; // 此点被占用了,区间内空位置数量修改为0
// 注意:因为是魔改的线段树区间和,所以tr[u].l=tr[u].r≠x
// x含义:第x个空白位置
res[tr[u].l] = v; // 用结果数组记录最后此位置上是v这个权值
return;
}
// 下面也是魔改的关键部分:
// 如果修改的位置在左侧(左侧空白位置数>=x),递归左子树
if (x <= tr[u << 1].sum)
modify(u << 1, x, v);
else // 如果在右侧,递归右子树,注意 x 减去 左侧的空白数量
modify(u << 1 | 1, x - tr[u << 1].sum, v);
// 更新父节点信息
pushup(u);
}
/*
参考答案:
77 33 69 51
31492 20523 3890 19243
*/
int main() {
#ifndef ONLINE_JUDGE
freopen("POJ2828.in", "r", stdin);
#endif
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
while (cin >> n) {
build(1, 1, n); // 构建一个叶子节点值为1的线段树,描述此区间内空位置的数量
// p[i]:在p[i]的后面,即p[i]+1的位置上
// v[i]: 权值
for (int i = 1; i <= n; i++) cin >> p[i] >> v[i];
// 倒序枚举,以终为始,这样才不会破坏每个人的位置相对信息概念
for (int i = n; i; i--) modify(1, p[i] + 1, v[i]);
// 输出
for (int i = 1; i <= n; i++) printf("%d ", res[i]);
puts("");
}
return 0;
}