POJ-2828-Buy Tickets(根据区间和找到单点位置并更新且储存 ) 好题 !!!

题目

Sample Input

4
0 77
1 51
1 33
2 69
4
0 20523
1 19243
1 3890
0 31492

Sample Output

77 33 69 51
31492 20523 3890 19243
在这里插入图片描述
emmm。不知道说什么好。。以后再说吧。。。
每个数的位置dex[i]++。插在第dex[i]的空格上。根据这个值判断插入到哪个子树中。

#include <cstdio>
using namespace std;
const int N=200005*4;
int sum[N],ans[N];       //sum[]是指区间空格数
int dex[N],x[N];
void build(int l,int r,int pos)
{
    if(l==r)
    {
        sum[pos]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,pos<<1);
    build(mid+1,r,pos<<1|1);
    sum[pos]=sum[pos<<1]+sum[pos<<1|1];    
}
void update(int num,int val,int l,int r,int pos)
{
    if(l==r)
    {
        sum[pos]=0;          //该点存放val这个数 则该点区间的空格数为0;
        ans[l]=val;             //储存该点的信息。注意是ans[l]=val;
        return;
    }
    int mid=(l+r)>>1;
    if(sum[pos<<1]>=num)             //左子树的空格不够
        update(num,val,l,mid,pos<<1);
    else
        update(num-sum[pos<<1],val,mid+1,r,pos<<1|1);//插到右子树第num-sum[pos<<1]个空格中
    sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        build(1,n,1);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&dex[i],&x[i]);
        for(int i=n;i>=1;i--)
            update(dex[i]+1,x[i],1,n,1);
        for(int i=1;i<=n;i++)
           printf("%d%c",ans[i],(i==n)?'\n':' ');
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/87882861