HDU 5493 Queue 【线段树】

<题目链接>

题目大意:
给你n个人的身高和他前面或者后面身高大于他的人的个数,求一个字典序最小的满足此条件的序列,如果不存在输出“impossible”。

解题分析:

因为要保证字典序最小,所以我们先将所有的人按身高排序,先给矮的人分配位置,并且位置尽可能的靠左。接下来就是分两种情况考虑,:

一:k个人在i前面,所以i的前面至少要留k个空格(因为是按从小到大分配人的位置,所以比i先插入的都是比他矮的);

二:k个人在i的后面,所以i的后面至少要留k个空格,所以i的前面需要留cnt-k个空格(cnt代表总的空格数,因为要按字典序最小,所以前面的空格越少越好,因为空格以后都是要放比i高的人)。

在上面两种情况中,选出i前面所需放的空格数最少的一种情况即可。

不过本题单纯的用线段树有点慢,可以考虑用二分+树状数组做。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 #define Lson rt<<1,l,mid
 7 #define Rson rt<<1|1,mid+1,r
 8 const int M = 1e5+10;
 9 
10 struct Node{
11     int h,num;
12 }node[M];
13 int sum[M<<2],val[M];    //val[]代表该点人的高度,sum[]代表该区间内的空格数
14 bool comp(Node x,Node y){return x.h<y.h;}
15 void Pushup(int rt){
16     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
17 }
18 void build(int rt,int l,int r){
19     if(l==r){
20         sum[rt]=1;
21         return;
22     }
23     int mid=(l+r)>>1;
24     build(Lson);
25     build(Rson);
26     Pushup(rt);
27 }
28 void update(int rt,int l,int r,int cur,int h){
29     if(l==r){
30         val[l]=h;    //更新该点的高度
31         sum[rt]=0;    
32         return;
33     }
34     int mid=(l+r)>>1;
35     if(cur<=sum[rt<<1])update(Lson,cur,h);   //如果左儿子区间中的空格数满足sum[rt<<1],那么就直接在左儿子区间内选择前面有p个空格的位置
36     else update(Rson,cur-sum[rt<<1],h);   //如果左儿子中的空格数<cur,则需要到右儿子区间内查询前面有cur个空格的位置
37     Pushup(rt);
38 }
39 int main(){
40     int T,n;scanf("%d",&T);
41     int ncase=0;
42     while(T--){
43         scanf("%d",&n);
44         for(int i=1;i<=n;i++)
45             scanf("%d%d",&node[i].h,&node[i].num);
46         sort(node+1,node+1+n,comp);
47         build(1,1,n);
48         bool flag=false;
49         for(int i=1;i<=n;i++){
50             int cnt=n-i;    //剩余的空格数
51             int tmp=cnt-node[i].num;   //此处表示将node[i].num个高的人放到i的后面,即i的后面要留node[i].num个人,因为总共有cnt个空格,即i的前面需要有cnt-node[i].num个空格
52             tmp=min(node[i].num,tmp);  //因为要求字典序最小,所以在两种情况中选取i劲量靠前的方案,即选则在i前面至少要留的空格数最少的情况
53             if(tmp<0){   //不符合的情况
54                 flag=true;break;
55             }
56             update(1,1,n,tmp+1,node[i].h);    //寻找前面有tmp个空格的位置(因为要包括自己,所以是tmp+1)
57         }
58         printf("Case #%d: ",++ncase);
59         if(flag)printf("impossible
");
60         else{
61             for(int i=1;i<=n;i++)
62                 i==n?printf("%d
",val[i]):printf("%d ",val[i]);
63         }    }
64     return 0;
65 }

2018-11-03

原文地址:https://www.cnblogs.com/00isok/p/9902014.html