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;
}

浙公网安备 33010602011771号