POJ 2828 Buy Tickets 线段树

题意:给出一些人和每个人的入队时在队列的位置。每个人都有一个值val,输出俺顺序输出队列的val,数据量 200000

如果用链表肯定超时,于是乎,用二叉树,but TLE了,才醒悟过来,如果二叉树是个左斜树或右斜树不就跟链表复杂度一样的么。。。

百度是个好东西,原来是线段树,不管什么数据量,可以达到logN,不过题目一般都会让人动脑子,要会转化等等,该题有个小特点,最后插入的数的位置,一定是最终位置,

所以要从后往前放入线段树。最后自己写了一组数据死活过不了,一提交AC,系统有问题?还真不是,那是一组不靠谱的错误数据。。。囧,写数据也要合理才行

 

每个线段有一个num值,记录该区间可以放几个数

根据数的序号把数加入线段树,之后,这个位置所在的区间可以放得数就减少一个,上推。。。整个区间可以放得数个数也减少一个

代码:

/*
线段树
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define nMAX 200015
using namespace std;
struct Tree
{
    int l,r,num;
}tree[nMAX*4];
struct Node
{
    int val,id;
}node[nMAX];
int n,mark,ans[nMAX];
void create(int l,int r,int u)
{
    tree[u].num=r-l+1;
    tree[u].l=l, tree[u].r=r;
    if(l==r)
        return ;
    int mid=(l+r)/2;
    create(l,mid,2*u);
    create(mid+1,r,2*u+1);
}
void update(int u)
{
    tree[u].num--;
    if(tree[u].l==tree[u].r)
    {ans[tree[u].l]=node[mark].val;return;}
    if(node[mark].id<=tree[2*u].num) update(2*u);
    else
    {
        node[mark].id-=tree[2*u].num;
        update(2*u+1);
    }
}
int main()
{
    int i,j;
    while(~scanf("%d",&n))
    {
        for(i=1;i<=n;i++)
        {
          scanf("%d%d",&node[i].id,&node[i].val);
          node[i].id++;
        }
        create(1,n,1);
        for(i=n;i>=1;i--)
        {
            mark=i;
            update(1);
        }
        for(i=1;i<=n;i++)
        {
            if(i==1)printf("%d",ans[i]);
            else printf(" %d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

  

posted @ 2012-08-13 21:37  快乐.  阅读(168)  评论(1编辑  收藏  举报