您的位置:首页 > 产品设计 > UI/UE

hdu5493 Queue 线段树

2015-10-03 15:08 429 查看
题意:

给你n个人,并且知道每个人的高(具有唯一性)与其在队列中前或者后的人数,求出字典序最小的一个排列。

方法:

1.利用线段树,表示每一段还有多少个空位未填。

2.对于队列中第i高的人,至少需要满足k[i]<=n-i;即他看到的比他高的人不可能多于实际比他高的人的人数。

3.按身高从小到大依次插入,若当前插入的人看到了k[i]个人比他高,则说明他插入时还有他前面刚好有k[i](或n-i-k[i])个空位,这些未填空位的人的身高一定比当前人高。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int N=1e5+10;
const int INF=0x3f3f3f3f;
struct node{
int h,K;
bool operator < (const node &B)const{
return h<B.h;
}
}a
;
int n,ans
;
bool check(){
for(int i=1;i<=n;i++)if(a[i].K>n-i)
return false;
return true;
}
int t[N<<2];
#define LL rt<<1
#define RR rt<<1|1
#define MID mid=((l)+(r))>>1
void pushup(int rt){
t[rt]=t[LL]+t[RR];
}
void build(int rt,int l,int r){
if(l==r){
t[rt]=1;
return;
}
int MID;
build(LL,l,mid);
build(RR,mid+1,r);
pushup(rt);
}
int val;
void update(int rt,int l,int r,int pos){
if(l==r){
t[rt]=0;
ans[l]=val;
return;
}
int MID;
if(pos<=t[LL])
update(LL,l,mid,pos);
else update(RR,mid+1,r,pos-t[LL]);
pushup(rt);
}
bool solve(){
sort(a+1,a+1+n);
if(!check())
return false;
build(1,1,n);
for(int i=1;i<=n;i++){
int t1,t2;
t1=a[i].K;t2=n-i-a[i].K;
val=a[i].h;
if(t1<t2)
update(1,1,n,t1+1);
else update(1,1,n,t2+1);
}
return true;
}
void work(){
int T;
int tt=1;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
printf("Case #%d:",tt++);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].h,&a[i].K);
if(!solve())
puts(" impossible");
else{
for(int i=1;i<=n;i++)printf(" %d",ans[i]);
printf("\n");
}
}
}
int main(){
freopen("data_in.txt","r",stdin);
freopen("data_out.txt","w",stdout);
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: