• 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

  • 相关阅读:
    第二阶段冲刺之站立会议5
    第二阶段冲刺之站立会议4
    第二阶段冲刺之站立会议3
    “加减乘除”使用说明
    第二阶段冲刺之站立会议2
    Kali学得好,监狱蹲到老,最新版Kali 2020
    【Linux】Centos7密码登录失败锁定设置_20200313
    【Linux】如何设置Linux开机 ,默认进入图形界面或命令行界面?
    【Linux】使用 PXE+Kickstart 无人值守批量安装系统
    【Linux】Linux修改openfile和max user processes?
  • 原文地址:https://www.cnblogs.com/00isok/p/9902014.html
Copyright © 2020-2023  润新知