如果从正面考虑的话,求出每个人的位置比较困难。
一开始,位置1-n都设置为1,即v[1…n] = 1。
可以从倒着考虑,依次求出每个人的位置p,将v[p]设置为0。
因此问题变成了如何求第k个1的值,如果考虑二分+线段树的话,时间复杂度是O(nlogn^2)。考虑线段树的性质,求出第k个1,可以直接在线段树上操作,因此时间复杂度为O(nlogn)
#include <iostream>
#include <cstring>
using namespace std;
const int N = 200005;
int pos[N], v[N], answer[N];
struct Node
{
int l, r, v;
}tr[4 * N];
void pushup(int u)
{
tr[u].v = tr[u << 1].v + tr[u << 1 | 1].v;
}
void build(int u, int l, int r)
{
tr[u] = {l, r, 1};
if (l == r) return;
int mid = l + r >> 1;
build (u << 1, l, mid), build (u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int x, int v)
{
if (tr[u].l == tr[u].r)
{
tr[u].v = v;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if (x <= mid) modify(u << 1, x, v);
else modify(u << 1 | 1, x, v);
pushup(u);
}
int get_k(int u, int k)
{
if (tr[u].l == tr[u].r)
{
return tr[u].l;
}
if (tr[u << 1].v >= k) return get_k(u << 1, k);
else return get_k(u << 1 | 1, k - tr[u << 1].v);
}
int main()
{
int n;
while (scanf("%d", &n) != -1)
{
build(1, 1, n);
for (int i = 1; i <= n; i ++)
scanf("%d%d", &pos[i], &v[i]);
for (int i = n; i >= 1; i --)
{
int p = get_k(1, pos[i] + 1);
// cout << p << endl;
modify(1, p, 0);
answer[p] = v[i];
}
for (int i = 1; i <= n; i ++)
printf("%d ", answer[i]);
puts("");
}
}