POJ2828 思维难度较好的一道线段树

题目大意:一条队伍 ,给你每个人插队的状态,得到最后的队伍状态

思路:容易从后方去思考,首先最后一个百分之百可以确定的 而倒数第二个  倒着来看 他之前必定还有pos[i]个人 (未包括后面的人)所以能需要空pos[i]个人的位置就是倒数第二个人的位置,同理可得倒数第三 倒数第四,而线段树就去维护空位的信息

#include<stdio.h>
#define maxn 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int empty[maxn<<2];
int A[maxn],B[maxn],C[maxn];
int Pushup(int rt)
{
    empty[rt]=empty[rt<<1]+empty[rt<<1|1];
}
int build(int l,int r,int rt)
{
    if(l==r) {empty[rt]=1;return 0;}
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    Pushup(rt);
}
int query(int x,int l,int r,int rt)
{
    int temp,m;
    m=(l+r)>>1;
    if(l==r) {empty[rt]--;return l;}
    if(x<=empty[rt<<1])
        temp=query(x,lson);
    else x=x-empty[rt<<1],temp=query(x,rson);
    Pushup(rt);
    return temp;
}
int main()
{
    freopen("poj2828.in","r",stdin);
    freopen("poj2828.out","w",stdout);
    int N,i;
    while(~scanf("%d",&N))
        {
            build(1,N,1);
            for(i=1;i<=N;i++)
                scanf("%d%d",&A[i],&B[i]);
            for(i=N;i>=1;i--)
                C[query(A[i]+1,1,N,1)]=B[i];
            for(i=1;i<=N;i++)
                printf("%d ",C[i]);
            printf("\n");
        }
    return 0;
}


原文地址:https://www.cnblogs.com/zy691357966/p/5480499.html