POJ 2828

受虐的晚上==

感谢大神的博客http://www.cnblogs.com/crazyapple/p/3233149.html

题意:第一行是整数N,代表队伍一共有N个人。然后N行,第一个数字代表N进队的时候前边有几个人,第二个数字是第I个人的标识符。

求最后队伍的顺序,一次输出标识符。

思路:思路是大神的思路,我又抄袭真是可耻==

第一步是倒序的思想,最后一个人前边应该有几个空位置,倒数第二个人有几个空位置依次确定。

第二步,根据线段树的思想,记录该线段中有几个空位置。(屌丝一开始的思路是记录该线段之前的空位置的个数,在分治的时候需要处理的线段太多,超时==)

第三步,确定每一个人最终的位置,输出。(思想是每个人都要更新一下父亲线段的空位置数,同时判断父亲线段左儿子的空位置数,如果左儿子的空位置数大于我们要找的位置数,在左儿子中找,否则减掉左儿子的位置数之后在右儿子中找)

#include<iostream>

#include<stdio.h>

#include<string.h>

using namespace std;

struct tr

{

    int l,r,pos;

};

tr me[200000*3];

int shun[200001];

short his[200001];

short ans[200001];

void build(int s,int e,int k)

{

    me[k].l=s;

    me[k].r=e;

    me[k].pos=e-s+1;

    if(s==e)

        return;

    int m=(s+e)>>1;

    build(s,m,k<<1);

    build(m+1,e,k<<1|1);

}

void update(int i,int k,int c)

{

    me[k].pos--;

    if(me[k].r==me[k].l)

    {

        ans[me[k].r]=his[i];

        return;

    }

    if(me[k<<1].pos>c)

        update(i,k<<1,c);

    else

        update(i,k<<1|1,c-me[k<<1].pos);



}

int main()

{

    short tmp;

    int n,w,i;

    while(scanf("%d",&n)!=EOF)

    {

        memset(ans,-1,sizeof(ans));

        build(1,n,1);

        for(i=1;i<=n;i++)

        {

            scanf("%d%d",&shun[i],&his[i]);

        }

        for(i=n;i>=1;i--)

        {

            update(i,1,shun[i]);

        }

        for(i=1;i<=n;i++)

            printf("%d ",ans[i]);

        printf("\n");

    }

    return 0;

}

 

你可能感兴趣的:(poj)