现在的位置: 首页 > 综合 > 正文

POJ 2828 Buy Tickets 线段树 单点更新

2013年10月11日 ⁄ 综合 ⁄ 共 811字 ⁄ 字号 评论关闭

题意:夜里排队买车票,每个人都有自己的id号。排队买票时会插队,输入n对数字,每对包括了他想插入的位子,和自己的id号,后插入的人会把先插入的人挤下去

做法:把先到的人挤下去真心难模拟,那么就倒过来思考。逆序查找序列对,后查到的要往后排,这个思想我以后要记住了

然后建立树时,每个节点的值为当前的空余数,然后就可以模拟了,模拟的时候要小心...

#include<cstdio>
#include<cstring>
#define left l,m,x<<1
#define right m+1,r,x<<1|1
#define LMT  200002
int have[LMT<<2],val[LMT],ps[LMT],vl[LMT];
int id;
void build(int l,int r,int x)
{
    have[x]=r-l+1;
    if(l==r)return;
    int m=(l+r)>>1;
    build(left);
    build(right);
}
void update(int p,int l,int r,int x)
{
    if(l==r)
    {
        have[x]--;
        id=l;
        return ;
    }
    int m=(l+r)>>1;
    if(p+1<=have[x<<1])update(p,left);
    else
    {
        p-=have[x<<1];
        update(p,right);
    }
    have[x]=have[x<<1]+have[x<<1|1];
}
int main(void)
{
    int n;
    while(~scanf("%d",&n))
    {
        build(0,n-1,1);
        for(int i=0;i<n;i++)
        scanf("%d%d",&ps[i],&vl[i]);
        for(int i=n-1;i>=0;i--)
        {
            update(ps[i],0,n-1,1);
            val[id]=vl[i];
        }
        for(int i=0;i<n;i++)
          printf("%d ",val[i]);
        printf("\n");
    }
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.