POJ2828 Buy Tickets

题意:一些人插队,按先后顺序给出来的人 要站的位置 和 他的编号,求解插队活动结束之后,从队头到队尾人的排列顺序

解法:对于任何一个人,他插队之后站的位置是a,如果他之后有一个人插到他前面,他就成了a+1,但是他前边的空位不会因为有人插到前边而改变,因此,从后向前来依次考虑每个人前边的空位个数。使用线段树来记录区间空位总数。

View Code
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;

int pers[200005<<2],n,ans[200005],input_p[200005],input_v[200005];

void build(int l,int r,int rt)
{
    pers[rt]=r-l+1;
    if (l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

int query(int p,int l,int r,int rt)
{
    int ret;
    pers[rt]--;
    if (l==r)
    {
        return l;
    }
    int m=(l+r)>>1;
    if (p<=pers[rt<<1]) ret=query(p,lson);
    else    ret=query(p-pers[rt<<1],rson);
    return ret;
}

int main()
{
    while (~scanf("%d",&n))
    {
        build(0,n-1,1);
        for (int i=1;i<=n;++i)
            scanf("%d%d",&input_p[i],&input_v[i]);
        for (int i=n;i>=1;--i)
            ans[query(input_p[i]+1,0,n-1,1)]=input_v[i];
        for (int i=0;i<n-1;++i)
            printf("%d ",ans[i]);
        printf("%d\n",ans[n-1]);
    }
}
posted @ 2012-04-28 12:03  Mr109  阅读(91)  评论(0)    收藏  举报