poj 2288 Buy Tickets

这道题是从最后一个数开始建立线段树,区间存储的范围是该区间有多少个空位剩余,对于最后一个插入的数,它肯定和其插入的位置一致,例如对于测试数据的第一组,69插入2这个位置,是肯定的,它将前面占有2位置的数向后面推,同理对于倒数第二个数,占有1这个位置,如果前面有数占有1这个位置,此时前面的必定是向后面推。假设P为插入的位置,因次每次查看左区间有没有大于等于p的空位,如果有则搜索,否者搜索右孩子。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define MAXN 200005
int seg_tree[MAXN<<2];
void build_tree(int l,int r,int id);
void push_up_tree(int id);
void update_tree(int left,int right,int l,int r,int id);
int ans[MAXN],cur;
struct Node
{
    int i;
    int num;
};
Node temp[MAXN];
int main()
{
        int n,i,j,k;
    while(scanf("%d",&n)==1)
    {
        build_tree(1,n,1);
        for(i=1;i<=n;i++)
        {scanf("%d%d",&temp[i].i,&temp[i].num);}
        for(i=n;i>0;i--)
           {
               cur=temp[i].num;
               update_tree(temp[i].i+1,n,1,n,1);

                   }
        for(i=1;i<=n;i++)
        {if(i-1) printf(" ");
            printf("%d",ans[i]);
        }
        printf("\n");

    }

   
}
void build_tree(int l,int r,int id)
{
        if(l==r)
    {
        seg_tree[id]=1;
        return ;
    }
  int m=(l+r)>>1;
  build_tree(l,m,id<<1);
  build_tree(m+1,r,id<<1|1);
  push_up_tree(id);
    
}
void push_up_tree(int id)
{
    seg_tree[id]=seg_tree[id<<1]+seg_tree[id<<1|1];
}
void update_tree(int left,int right,int l,int r,int id)
{
    if(l==r)
    {
        seg_tree[id]--;
        ans[l]=cur;

        return ;
    }
    int m=(l+r)>>1;
        if(left<=seg_tree[id<<1])
        update_tree(left,right,l,m,id<<1);
    else 
    {
        left-=seg_tree[id<<1];
        update_tree(left,right,m+1,r,id<<1|1);
    }
    push_up_tree(id);
}

 

 

posted @ 2012-05-30 01:22  woaiyy  阅读(399)  评论(0)    收藏  举报