题意: 插队问题,有n个人,每个人都有一个val,第i个人插在第j(0 <= j < i)个人后面,问最后队列中从前到后的val。
思路: 线段树的单点修改。从后往前看,当第i人插到第j个人后面时,他的前面必然有 j个空位。所以当他开始插队时,就可以利用线段树找到要查对的位置。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 200010;
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
int n, m;
int sgt[N<<2], ans[N];
struct node{
int id, val;
}a[N];
inline void pushup(int x)
{
sgt[x] = sgt[ls(x)] + sgt[rs(x)];
}
void build(int x, int l, int r)
{
if(l > r) return ;
if(l == r) {
sgt[x] = 1;
return ;
}
int mid = l + r >> 1;
build(ls(x), l, mid);
build(rs(x), mid+1, r);
pushup(x);
}
inline void update(int x, int l, int r, int k, int v)
{
int mid = l + r >> 1;
if(l == r) {
ans[l] = v;
sgt[x] --;
return ;
}
if(sgt[ls(x)] >= k) update(ls(x), l, mid, k, v);
else update(rs(x), mid+1, r, k - sgt[ls(x)], v);
pushup(x);
}
int main()
{
while(scanf("%d", &n) != EOF) {
build(1, 1, n);
for(int i = 1;i <= n; ++ i)
scanf("%d%d", &a[i].id, &a[i].val);
for(int i = n;i >= 1; -- i) {
update(1, 1, n, a[i].id + 1, a[i].val);
}
for(int i = 1;i <= n; ++ i)
printf("%d ", ans[i]);
puts("");
}
}