You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.3 KiB

2 years ago
#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;
}