HDU 5493 Queue

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5493

题意:给你n个人的身高和他前面或后面比他高的人数,求一个满足条件的最小字典序的排列方式

 

要满足最小字典序,所以我们从小到大放置,并尽量往前放

放当前的人时,后放的一定比他高,所以他前面必须要留一些位置来满足条件

那么我们可以用线段树来维护空余的位置

因为可能往前或往后看,那我们就贪心的选取前面比他大的人少的数据

之后只需要线段树单点更新就行了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define lson i<<1
#define rson i<<1|1
using namespace std;
const int N=1e5+5;
pair<int,int> a[N];
int ans[N],sum[N<<2];
void build(int i,int l,int r)
{
    sum[i]=1;
    if (l==r) return;
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    sum[i]=sum[lson]+sum[rson];
}
void update(int i,int l,int r,int k,int val)
{
    if (l==r)
    {
        ans[l]=val;
        sum[i]=0;
        return;
    }
    int mid=(l+r)>>1;
    if (sum[lson]>=k)
        update(lson,l,mid,k,val);
    else update(rson,mid+1,r,k-sum[lson],val);
    sum[i]=sum[lson]+sum[rson];
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&a[i].first,&a[i].second);
        sort(a+1,a+1+n);
        build(1,1,n);
        int flag=1;
        for(int i=1;i<=n;i++)
        {
            int t=min(a[i].second,n-i-a[i].second);
            if (t<0)
            {
                flag=0;
                break;
            }
            update(1,1,n,t+1,a[i].first);
        }
        printf("Case #%d: ",ca);
        if (flag==0)
            printf("impossible\n");
        else
        {
            for(int i=1;i<n;i++)
                printf("%d ",ans[i]);
            printf("%d\n",ans[n]);
        }
    }
    return 0;
}

  

posted @ 2017-09-13 13:41  BK_201  阅读(115)  评论(0编辑  收藏  举报