poj 2828 Buy Tickets

http://poj.org/problem?id=2828

后序遍历,假设 x  号人插入到队伍中的某一个位子,那么他的位子是安全的,因为他后没有其他人,也就不会挤掉他的位子,所以,我们可以先接受完所有的数据,然后按照后序遍历就相当于,拿人来找空位,

0 77
1 51
1 33
2 69  就相当于, 69号人来了,找地3个空位子,然后他站到那里,  33  来了,找一个空位子,站在那里。。。。。。。当所有的人都找到位子之后,整个序列就完整了。

#include<cstdio>
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;
int sum[800010],value[800010],pos[800010],num[800010];
void build(int l,int r,int root)
{
    sum[root] = (r - l) +1;//整个区间的空位子的个数,等于区间的长度
    if(l == r) return ;
    int mid = (l + r) /2;
    build(l,mid,2*root);
    build(mid+1,r,2*root+1);
}
int update(int x,int l ,int r,int root)
{
    int mid = (l + r)/2;
    sum[root] -= 1;//该区间内会有一个人找到位子,所以,sum  值 减去1
    if(l == r) return l; //如果找到了位子,返回位子的编号
    if(sum[2*root] >= x)// 如果左孩子的空位子个数满足我们要找的空位子编号,在做孩子找
    update(x,l,mid,2*root);
    else
    {
        x -= sum[2*root];
        /*如果左孩子的空位子不够,就在右孩子找,
        这时候相当于前面已经有了左孩子的空位子的个数,
        要找的位子的编号应该减掉左孩子空位子的个数*/
        update(x,mid+1,r,2*root+1);
    }
}
int main()
{
    int n,i,a,b;

    while(cin>>n)
    {
        memset(value,0,sizeof(value));
        memset(pos,0,sizeof(pos));
        memset(num,0,sizeof(num));
        for(i = 1; i <= n; i++)//注意把 pos 的各个值都加上1
            scanf("%d%d",&pos[i],&value[i]),pos[i]++;
        build(1,n,1);
        for(i = n; i > 0; i--)
        {
            int id = update(pos[i],1,n,1); //找到位子,然后把该位子的人的值记录下来
            num[id] = value[i];
        }
        cout<<num[1];
        for(i = 2; i <= n; i++)
        printf(" %d",num[i]);//cout<<" "<<num[i];
        cout<<endl;
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值