Queue HDU - 5493 二分

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n,ans[N],tr[N],hi[N];
struct node
{
	int h,k,id;
} po[N];
int cmp(node a,node b)
{
	return a.h>b.h;
}
int cmp1(node a,node b)
{
	//按照前面比它小的个数排序,从小到大
	if(a.h==b.h)
		return a.k<b.k;
	return a.h<b.h;
}
inline int lowbit(int x)
{
	return x&(-x);
}
inline void update(int x)
{
	for(int i=x;i<=n;i+=lowbit(i))
		tr[i]++;
}
inline int query(int x)
{
	int s=0;
	for(int i=x;i;i-=lowbit(i))
		s+=tr[i];
	return s;
}
int main()
{
	int t,Case=0;
	scanf("%d",&t);
	while(t--)
	{
		printf("Case #%d:",++Case);
		scanf("%d",&n);
		for(int i=1; i<=n; i++)
			scanf("%d%d",&po[i].h,&po[i].k),po[i].id=i;
		//按照身高排序
		sort(po+1,po+n+1,cmp);
		int flag=0,num=0;
		po[0].h=-1;
		for(int i=1; i<=n; i++)
		{
			//前面比他高的
			if(po[i].h!=po[i-1].h)
				num=i-1;
			//如果k比这个大,那么就一定不行,构建不出来
			if(po[i].k>num)
			{
				flag=1;
				break;
			}
			//前面比他高的
			hi[i]=num;
		}
		if(flag)
			printf(" impossible\n");
		else
		{
			//构建最小字典序
			for(int i=1; i<=n; i++)
				po[i].k=min(po[i].k,hi[i]-po[i].k),tr[i]=0;
			//按身高排序
			sort(po+1,po+n+1,cmp1);
			for(int i=1; i<=n; i++)
			{
				//前面比他高的是k
				//所以位置是k+1 ~ n
				int l=po[i].k+1,r=n;
				//二分这个数的位置
				while(l<r)
				{
					//二分这个数的位置
					int mid=(l+r)>>1;
					// mid是这个数的位置
					//query mid  求的是前面已经插进去多少个比他小的数字
					if(mid-query(mid)-1>=po[i].k)
						r=mid;
					else
						l=mid+1;
				}
				//这个数 放在第几位
				ans[r]=po[i].h;
				update(r);
			}
			for(int i=1; i<=n; i++)
				printf(" %d",ans[i]);
			printf("\n");
		}
	}
	return 0;
}
posted @ 2020-05-07 16:12  晴屿  阅读(116)  评论(0编辑  收藏  举报