链接:http://poj.org/problem?id=2828

题意:n个人排队,每个人有一个权值,给出他们插队的位置,求最后的顺序,按顺序输出权值。

思路:看到这题目,我想这货和线段树什么关系啊,这货怎么能用线段树来做呢。诶,大千世界无奇不有,线段树就是这么的神奇,叹叹!!!闲话少说,走起。

逆着想,最后一个人插队后, 他的位置就是确定了下来的。倒数第二个人插的话,位置在最后一个的前面,最后一个对他无影响,位置在最后一个后面,则最后一个对他有影响,他必须往后移一位。

线段树叶子节点保存的是这个位置上的空位数,初始化为1,如果这个位置上有了一个数,那么减一。但是我不明白在查找的时候,为什么用当前人要插入的位置和空位数进行比较,这个位置可以理解为空位数么???求指点。

#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=200005;
int sum[maxn<<2];
int ans[maxn],pos[maxn],val[maxn];

void PushUP(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=1;
        return;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    PushUP(rt);
}
void query(int p,int v,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]-=1;
        ans[r]=v;
        return;
    }
    int m=(l+r)/2;
    if(p<=sum[rt<<1]) query(p,v,lson);//不明白
    else query(p-sum[rt<<1],v,rson);
    PushUP(rt);
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        build(1,n,1);
        for(int i=0;i<n;i++)
            scanf("%d%d",&pos[i],&val[i]);

        for(int i=n-1;i>=0;i--)
            query(pos[i]+1,val[i],1,n,1);
        for(int i=1;i<=n;i++)
            printf("%d ",ans[i]);
        printf("\n");
    }
    return 0;
}
View Code

 

这题也可以用树状数组写,后面再贴上来。

 

 

 posted on 2013-08-21 20:07  ∑求和  阅读(220)  评论(0编辑  收藏  举报