POJ-2828-Buy Tickets

这个题大意是说开始有一个空的序列,有n个人要插进去,每个人都有一个属性值,给出每个人插入队列的时候拍在第pos[i]个人后面,最后让你从队首开始依顺序输出每个人的属性值,最开始没想到会有线段树,后面参考了书上以后,发现如果按所给插入顺序的逆序的话就满足线段树的性质,从最后一个开始,我们每次可以确定队列中第pos[i]+1个空位一定是对应的那个人所站的位置,剩下的就比较简单了,用线段树维护即可

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=210000;
struct Node
{
    int res;
    int val;
}t[maxn*3];
int n,a[maxn],val[maxn],ans[maxn];
void Build(int l,int r,int index)
{
    if(l==r)
    {
	t[index].res=1;
	return ;
    }
    int mid=(l+r)>>1;
    Build(l,mid,index<<1);
    Build(mid+1,r,index<<1|1);
    t[index].res=t[index<<1].res+t[index<<1|1].res;
}
int Update(int l,int r,int num,int index)
{
    if(l==r)
    {
	t[index].res=0;
	return l;
    }
    int mid=(l+r)>>1,pos=-1;
    if(t[index<<1].res<num)
	pos=Update(mid+1,r,num-t[index<<1].res,index<<1|1);
    else
	pos=Update(l,mid,num,index<<1);
    t[index].res=t[index<<1].res+t[index<<1|1].res;
    return pos;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
	for(int i=0;i<n;i++)
	    scanf("%d%d",&a[i],&val[i]);
	Build(1,n,1);
	for(int i=n-1;i>=0;i--)
	{
	    int index=Update(1,n,a[i]+1,1);
	    ans[index]=val[i];
	}
	for(int i=1;i<=n;i++)
	    printf("%d%c",ans[i],i==n?'\n':' ');
    }
    return 0;
}


你可能感兴趣的:(线段树)