poj2828 Buy Tickets

线段树的基本题。题意大概是:人们依次来排队并插队,按人到来的顺序给出每个人插队的位置(插在第几个人后面),并告知每个人的id号,输出最终的情况。

与poj2182有点像,只不过将数字的大小改成插入的先后顺序。

#include<iostream>
#include<stdio.h>
#define MAXD 200001
using namespace std;
int N,P[MAXD],V[MAXD],f[MAXD],sum[MAXD*3],D,re[MAXD];
void init()
{
    for(D=1;D<N+2;D<<=1);
    int i;
    for(i=1;i<=N;i++)
    sum[D+i]=1;
    for(i=D-1;i;i--)
    sum[i]=sum[i<<1]+sum[i<<1|1];
}

int query(int k)
{
    int i;
    for(i=1;i<D;)
    {
        if(sum[i<<1]>=k)
        i=i<<1;
        else
        k-=sum[i<<1],i=i<<1|1;
    }
    return i-D;
}

void update(int k)
{
    k+=D;
    sum[k]=0;
    for(;k^1;k>>=1)
    sum[k>>1]=sum[k]+sum[k^1];
}
int main()
{
    //freopen("test.txt","r",stdin);
    while(~scanf("%d",&N))
    {
        int i;
        for(i=1;i<=N;i++)
        scanf("%d%d",&P[i],&V[i]);
        init();
        for(i=N;i>=1;i--)
        {
            f[i]=query(P[i]+1);
            update(f[i]);
        }
        for(i=1;i<=N;i++)
        {
            re[f[i]]=i;
        }
        for(i=1;i<=N;i++)
        printf(i==N?"%d\n":"%d ",V[re[i]]);
    }
    return 0;
}

 

posted @ 2013-02-03 19:31  longlongago  Views(123)  Comments(0Edit  收藏  举报