http://poj.org/problem?id=2828
最后一个想到pos位置的人是真正站在pos位置的人 因为不会被插队,所以采用逆序插入。sum记录 该区间 目前还剩 sum个空位,每一次 query即插入的时候 ,如果该节点左儿子 sum>=pos,那么只要在左儿子找就可以了否则要在右儿子中 找 ,此时 pos 改为 pos-左儿子res,比如3但是1,2已经非空那么转到右边他只需要3 - 2 = 1个空位。
AC_CODE:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 200000;
struct person{
int pos;
int value;
}seg[MAX];
struct node{
int l, r, sum;
int mid(){
return (l + r) >> 1;
}
}tree[MAX << 2];
int ans[MAX];
void buildtree(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
if(l == r){
tree[rt].sum = 1;
return;
}
int mid = tree[rt].mid();
buildtree(l, mid, rt << 1);
buildtree(mid + 1, r, rt << 1 | 1);
tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
}
void update(int pos, int rt, int value){
tree[rt].sum--;
if(tree[rt].l == tree[rt].r){
ans[tree[rt].l] = value;
return;
}
int mid = tree[rt].mid();
if(pos <= tree[rt << 1].sum) update(pos, rt << 1, value);
else update(pos - tree[rt << 1].sum, rt << 1 | 1, value);
}
int main(){
// freopen("in.txt", "r", stdin);
int N;
while(scanf("%d",&N) != EOF){
buildtree(1, N, 1);
// memset(ans, 0, sizeof(ans));
for(int i=1; i<=N; i++)
scanf("%d%d",&seg[i].pos,&seg[i].value);
for(int i=N; i>0; i--)
update(seg[i].pos + 1, 1, seg[i].value);
bool flag = false;
for(int i=1; i<=N; i++){
if(flag) printf(" ");
printf("%d",ans[i]);
flag = true;
}
printf("\n");
}
return 0;
}
PS:G++TLE,C++AC! = =!