• hdu 5493 (树状数组)


    题意:在一个队列中,你知道一个人在他左边或者右边比他高的人的个数,求字典序最小的答案

    思路:先将人按  矮-->高 排序,然后算出在每个人前面需要预留的位置。树状数组(也可以线段树)解决时,先二分查找合适的位置,如果合理则标记,每次查找时    枚举的人数 - 前面已占的人数 = 可预留位置

    判断分别在它左边 或者 右边时可能的最小值进行比较。

    预留的位置①:pnode[i].num(即比他高的人数,全在左) 

                      ②:n - ( pnode[i].num + i) (当比他高,和前面加入的全在右边时) //为了字典序最小


    /* 当时是一点头绪都没有- -,没想到是可以用线段树和二维数组,果然太年轻


    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MAXN 100010
    using namespace std;
    
    const int N = 1e5 + 5;
    int n,m;
    int tree[N];
    struct node
    {
        int id,num,position;
    }pnode[N];
    
    bool cmp(node a,node b)
    {
            return a.id < b.id;
    }
    bool cmp2(node a,node b)
    {
            return a.position < b.position;
    }
    
    void add(int x , int dx)
    {
        while(x < N)
        {
            tree[x] += dx ;
            x += x&(-x) ;
        }
    }
    int query(int x)
    {
        int sum = 0 ;
        while(x)
        {
            sum += tree[x] ;
            x -= x&(-x) ;
        }
        return sum ;
    }
    
    int fin(int l,int r,int x)
    {
        if(x < 0)
            return -1;
        while(l <= r)
        {
            int mid = (l + r)/2;
            int tt= mid - query(mid);  //找出前面有多少空位
            if(tt < x)
                l  =mid + 1;
            else
                r = mid - 1;
        }
        return l;
    }
    
    void ini()
    {
        for(int i = 0;i <= n;i++)
            tree[i] = 0;
    }
    
    int main()
    {
        int t,cas = 1;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
    
            for(int i = 1;i <= n;i++)
                scanf("%d%d",&pnode[i].id,&pnode[i].num);
            sort(pnode+1,pnode+1+n,cmp);
            ini();
            int flag = 0;
            for(int i = 1;i <= n;i++)
            {
                int p = n - (i - 1) ;         //求还剩下多少位置
                int tp = pnode[i].num;        
                if(p <= tp)                   //判断剩下的能否预留合理位置
                    flag = true;
                int x1 = fin(1,n,pnode[i].num + 1);
                int x2 = fin(1,n,n -pnode[i].num-i + 1);
                pnode[i].position = min(x1,x2);
                add(pnode[i].position,1);
            }
    
           printf("Case #%d: ", cas++);
           if(flag )
           {
               printf("impossible
    ");
               continue;
           }
           sort(pnode+1,pnode+n+1,cmp2);
            printf("%d", pnode[1].id);
            for (int i = 2; i <= n; i++)
                printf(" %d", pnode[i].id);
            printf("
    ");
    
        }
        return 0;
    }
    

      

    ps.如果没有东西值得你为之努力,那你和一条咸鱼有什么区别? 






  • 相关阅读:
    uGUI知识点剖析之RectTransform
    C#中的结构体要使用new来实例化吗?
    LOL数值分析
    【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则
    AnimationCurve
    Unity3D 自动添加Fbx Animation Event
    unity 代码添加AnimationEvent
    untiy AnimationEvent添加返回参数
    Windows CreateEvent,SetEvent,WaitForSingleObject的用法
    C++ Socket编程步骤
  • 原文地址:https://www.cnblogs.com/Przz/p/5409741.html
Copyright © 2020-2023  润新知