题意:一家店门口有n个人在排队,按顺序给出每个人要站在第几个人的后面,假设店是第0个人,给每个人一个代号,问最后代号的顺序是什么。
题解:因为后面的人有可能占前面的人的位置,所以倒着来,每个人位置的含义变成了给前面留多少个空位,线段树实现。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200005;
int n, s[N << 2], p[N], v[N], res[N];

void pushup(int k) {
    s[k] = s[k * 2] + s[k * 2 + 1];
}

void build(int k, int left, int right) {
    if (left == right) {
        s[k] = 1;
        return;
    }
    int mid = (left + right) / 2;
    build(k * 2, left, mid);
    build(k * 2 + 1, mid + 1, right);
    pushup(k);
}

void modify(int k, int left, int right, int pos, int val) {
    if (left == right) {
        res[left] = val;
        s[k] = 0;
        return;
    }
    int mid = (left + right) / 2;
    if (pos <= s[k * 2])
        modify(k * 2, left, mid, pos, val);
    else
        modify(k * 2 + 1, mid + 1, right, pos - s[k * 2], val);
    pushup(k);
}

int main() {
    while (scanf("%d", &n) == 1) {
        build(1, 1, n);
        for (int i = 1; i <= n; i++)
            scanf("%d%d", &p[i], &v[i]);
        for (int i = n; i >= 1; i--)
            modify(1, 1, n, p[i] + 1, v[i]);
        printf("%d", res[1]);
        for (int i = 2; i <= n; i++)
            printf(" %d", res[i]);
        printf("\n");
    }
    return 0;
}