POJ 2828 Buy Tickets 線段樹

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

題意:有一些人在排隊買票,但是有些人會插隊。現在給出這些插隊的信息,問最後人的順序。

思路:一道線段樹的好題。我們從前向後考慮的話,當第i個人插隊的時候,他插隊到第posi個人的後面,也就是說,此時,他前面已經有了posi個人。因此,我們可以從後向前考慮,這樣,第i個人插隊到第posi個人的後面,說明了他的前方還有posi個空位置。因此,就可以用線段樹了,線段樹的結點保存的是該區間有多少個空位置。

ac代碼:

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;

const int N = 200020;
int id;
struct people
{
    int pos,val;
}pp[N];
struct tree
{
    int lp,rp,cnt;
    int getmid()
    {
        return (lp + rp) / 2;
    }
}tt[N * 4];
void built_tree(int lp,int rp,int pos)
{
    tt[pos].lp = lp;
    tt[pos].rp = rp;
    tt[pos].cnt = 0;
    if(lp == rp)
    {
        tt[pos].cnt = 1;
        return;
    }
    int mid = tt[pos].getmid();
    built_tree(lp,mid,pos*2);
    built_tree(mid+1,rp,pos*2+1);
    tt[pos].cnt = tt[pos*2].cnt + tt[pos*2+1].cnt;
}
void update(int num,int pos)
{
    if(tt[pos].lp == tt[pos].rp)
    {
        tt[pos].cnt = 0;
        id = tt[pos].lp;
        return;
    }
    if(num <= tt[pos*2].cnt)
    {
        update(num,pos*2);
    }
    else
    {
        update(num - tt[pos*2].cnt,pos*2+1);
    }
    tt[pos].cnt = tt[pos*2].cnt + tt[pos*2+1].cnt;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int n;
    while(scanf("%d",&n) != EOF)
    {
        built_tree(1,n,1);
        for(int i = 0; i < n; ++i)
        {
            scanf("%d%d",&pp[i].pos,&pp[i].val);
        }
        int ans[N];
        for(int i = n-1; i >= 0; --i)
        {
            update(pp[i].pos + 1,1);
            ans[id] = pp[i].val;
        }
        for(int i = 1; i < n; ++i)
        {
            printf("%d ",ans[i]);
        }
        printf("%d\n",ans[n]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值