本题为线段树的变体, 整体思路是将输入转化为一个逆序的插入操作,每次更新都要找到第pos[i] + 1个位置对其进行插入。
//
// main.cpp
// POJ2828
//
// Created by dan on 16/10/19.
// Copyright © 2016年 dan. All rights reserved.
//
#include <iostream>
#define MAXN 200005
int sum[MAXN << 2];
int ans[MAXN << 2];
int pos[MAXN], value[MAXN];
void build(int l, int r, int savPos){
sum[savPos] = r - l + 1;
if (l == r)
return;
int m = (l + r) >> 1;
build(l, m, savPos << 1);
build(m + 1, r, savPos << 1 | 1);
//创建时无需对其进行update,因为是固定的
}
void pushUp(int i){
sum[i] = sum[i << 1] + sum[i << 1 | 1];
}
void update(int kongwei, int addNum, int l, int r, int savPos){
if(l == r){//单点更新,找到要插入的位置后对其上的空位--(实际就是置为0),同时ans数组记录该位置的数值。
sum[savPos]--;
ans[savPos] = addNum;
return;
}
int m = (l + r) >> 1;
if (kongwei <= sum[savPos << 1])
update(kongwei, addNum, l, m, savPos << 1);
else
update(kongwei - sum[savPos << 1], addNum, m + 1, r, savPos << 1 | 1);
//右边插入时,要减去左边的空位值。
pushUp(savPos);
}
void print(int l, int r, int savPos){
if (l == r){
printf("%d ", ans[savPos]);
return;
}
int m = (r + l) >> 1;
print(l, m, savPos << 1);
print(m + 1, r, savPos << 1 | 1);
}
int main(int argc, const char * argv[]) {
int n;
while(~scanf("%d", &n)){
for (int i = 0; i < n; i++)
scanf("%d%d", &pos[i], &value[i]);
build(1, n, 1);
for (int i = n - 1; i >= 0; i--){
update(pos[i] + 1, value[i], 1, n, 1);
//插入pos[i]+1的原因是保证其前面有pos[i]个空位,即将其插入到pos[i]+1;
}
print(1, n, 1);
printf("\n");
}
return 0;
}