POJ 2828 Buy Tickets

题意: 有N 个人站队,告诉每个人想插队的位置,要求确定最终的站队位置。

分析:   越往后插队的人位置越固定,因此可以从后向前插入,每个人插入的位置为从第1 个位置起的第 pos+1 空位置。

         用sum[i] 表示 I 区间的人数之和,用线段树维护即可。

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define maxn 200005
struct  P
{
    int pos,val;
}q[maxn];
int sum[maxn<<3];
int va[maxn<<3];
void creat(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=1;
        return;
    }
    int m=(l+r)>>1;
    creat(l,m,rt<<1);
    creat(m+1,r,rt<<1|1);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int pos,int l,int r,int rt,int v)
{
    if(l==r){
        va[l]=v;
        sum[rt]=0;
        return;
    }
    int m=(l+r)>>1;
    if(sum[rt<<1]>=pos)
         update(pos,l,m,rt<<1,v);    
    else update(pos-sum[rt<<1],m+1,r,rt<<1|1,v);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int main()
{
    int n,i;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<n;i++)
            scanf("%d%d",&q[i].pos,&q[i].val);
        creat(1,n,1);
        for(i=n-1;i>=0;i--)
            update(q[i].pos+1,1,n,1,q[i].val);
        for(i=1;i<=n;i++)
            printf("%d%c",va[i],i==n?'\n':' ');
    }
    return 0;
}

 

posted @ 2012-08-09 11:01  'wind  阅读(207)  评论(0编辑  收藏  举报