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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}