题目链接:http://poj.org/problem?id=2828
题目大意:人们一个一个的来排队买票并有插队情况,先给出人数n,再按人到来的顺序给出每个人插队的位置(插在第几个人后面),并告知每个人的id号,输出最终队伍的情况。
思路:n最大可能是200000,暴力法相当于插入排序,O(n^2)的复杂度,肯定超时了。按照逆序考虑每个人的插队情况,从最后一个开始,如果他插在第pos个位置后面,则说明他前面要有pos个空位。所以逆序处理每一个插队的人,每次找前面有pos个空位的空位。使用线段树的每个节点表示该区间的空位个数。
///2014.5.31
///poj2828
#include <cstdio>
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 220000;
int sum[maxn<<2];
int n,pos[maxn],val[maxn],ord[maxn];
void PushUP(int rt) {
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt) {
if (l == r) {
sum[rt] = 1;
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUP(rt);
}
int query(int pos,int l,int r,int rt) {
if ( l==r ) {
sum[rt] = 0;
return l;
}
int m = (l + r) >> 1;
int ret = 0;
if ( sum[rt<<1] >= pos ) ret = query(pos , lson);
else ret = query(pos-sum[rt<<1], rson);
PushUP(rt);
return ret;
}
int main() {
// freopen("in","r",stdin);
while( scanf("%d",&n) !=EOF ){
build(1 , n , 1);
for(int i=1 ; i<=n ; i++){
scanf("%d%d",pos+i,val+i);
}
for(int i=n ; i>0 ; i--){
ord[ query(pos[i]+1,1,n,1) ] = val[i];
}
for(int i=1 ; i<n ; i++){
printf("%d ",ord[i] );
}
printf("%d\n",ord[n] );
}
return 0;
}