Buy Tickets----POJ_2828----线段树之单点更新

来源:互联网 发布:常用c语言编程软件 编辑:程序博客网 时间:2024/05/07 12:22

题目地址:http://poj.org/problem?id=2828

/*Author:Bob Lee2012.9.25==========================================================线段树的更新先说题意:n个人陆续到一个队列排队,但是有的人可能会插队,题目给出第i个人插在pos[i]的位置,问最后队列的情况如何。解题思路:我们可以发现越往后面插的人是有一定优先权的也就是最后一个人插入的话一定可以达到自己的目的在这里建立一颗线段树,来表示某一个区间内还有的空位数然后我们从最后一个人开始插队具体细节见代码这题还是很经典的,应该仔细研究研究*/#include<iostream>#include<cstdio>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define maxn 200005int tree[maxn<<2];int pos[maxn];int value[maxn];int ans[maxn];int lastpos;void build(int l,int r,int rt){    //初始数据就是他们之间一个人都没插    tree[rt] = r-l+1;    if(l == r)        return;    int m = (l+r)>>1;    build(lson);    build(rson);}void update(int p,int l,int r,int rt){    tree[rt]--;    if(l == r)    {        lastpos = l;        return;    }    int m = (l+r)>>1;    /*    如果左儿子的空位大于p,那么p就插到左儿子去    否则    则在右儿子这边,找一个pos = p-左儿子的空位数 的地方插    */    if(tree[rt<<1] >= p)        update(p,lson);    else    {        p = p-tree[rt<<1];        update(p,rson);    }}int main(){    int n;    while(~scanf("%d",&n))    {        build(1,n,1);        for(int i=1;i<=n;i++)            scanf("%d%d",pos+i,value+i);        for(int i=n;i>0;i--)        {            update(pos[i]+1,1,n,1);            ans[lastpos] = value[i];        }        for(int i=1;i<=n-1;i++)            printf("%d ",ans[i]);        printf("%d\n",ans[n]);    }    return 0;}


 

原创粉丝点击