http://poj.org/problem?id=2828

(1)注意到,最后插队的人的位置是一定的,前一个人的位置的最终稳定取决于后面的所有人。为了避免插入一个新数时要挪出位置的尴尬,更为效率考虑,

   可以从后往前插入树中(注意谁决定谁的关系的使用)。

(2)小细节:

      1) 0~n-1 而不是 1~n;

                 2)先输入,再更新(分开来);

                 3)希望今后的小错误可以尽快找出,线段树的写法虽然懂,但小错误最伤不起(很幼稚的类型,却很长时间才发现);

      4)几乎所有的线段树都是求和、最值,但是各种包装下没能看清本质,还要多练手(题库里还有大约40题)。

(3)对于每个插队的人(倒着数),要留有pos[i]个空位,自己占有第pos[i]+1个空位:

update(pos[i]+1, val[i], 0, n, 1);

 

具体代码:

View Code
#include<stdio.h>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn=201000;
int n;
int sum[maxn<<2];
int pos[maxn], val[maxn], ans[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);
}
void update(int pos, int val, int l, int r, int rt)
{
    if(l==r)
    {
        sum[rt]=0;
        ans[l]=val;
        return ;
    }
    int m=l+r>>1;
    if(sum[rt<<1]>=pos) update(pos, val, lson);
    else update(pos-sum[rt<<1], val, rson);
    pushup(rt);
}
int main()
{
    int i, j, k;
    while(scanf("%d", &n)!=EOF)
    {
        build(0, n, 1);
        for(i=0;i<n;i++) scanf("%d%d", &pos[i], &val[i]);
        for(i=n-1;i>=0;i--)
        {
            update(pos[i]+1, val[i], 0, n, 1);
        }
        printf("%d", ans[0]);
        for(i=1;i<n;i++)
            printf(" %d", ans[i]);
        printf("\n");
    }
    return 0;
}