zoukankan      html  css  js  c++  java
  • 算法进阶指南—特殊排序

    题意:有N个数,每两个数之间的大小关系要通过询问来得知,但是每个数之间的大小关系不具有传递性,比如 a<b  ,  b< c不一定有a<c。

    现在问你能否在10000次询问内把这N个数排成一列,使得相邻两个数,左边比右边小。

    思路:把前  i - 1个数字排好序后,第  i  个数字应该插入到什么位置,则二分前面  i - 1 的有序序列,利用中间值mid 来判定i的插入位置。

    判定方法,若mid< i 则mid 右半边是合法的,另 l = mid,若mid >i,则 mid 左半边是合法的,另 r= mid-1;

    找到插入位置r后把  i  插入到最后一个位置,把 i 从最后一个位置一直换到第r+1个位置,然后再判断它与 r的关系若小于r,把 r 与r+1位置上的数对换。

    前i-1个排序运用了插入排序,每插入一个新的数都用二分的方法取判定它的位置。最后由于每次二分判定位置次数最多为n*log n.所以两个数比较大小的询问也最多提出n*log n次。

    加起来总共为 2*log n+3*log n+........+n*log n 其小于10000次

    下面上代码:

    class Solution {
    public:
        vector<int> specialSort(int N) {
            vector<int> res;
            res.push_back(1);
            for(int i=2;i<=N;i++)
            {
                int l=0,r=res.size()-1;
                while(l<r)
                {
                int    mid=(l+r+1)>>1;
                    if(compare(res[mid],i))
                    l=mid;
                    else
                    r=mid-1;
                 }
                 
                 res.push_back(i);
                 for(int j=res.size()-2;j>r;j--)
                 swap(res[j],res[j+1]);
                 if(!compare(res[r],res[r+1]))
                 swap(res[r],res[r+1]);      
             } 
            return res;      
            
        }
    };
  • 相关阅读:
    Codeforces 691A Fashion in Berland
    HDU 5741 Helter Skelter
    HDU 5735 Born Slippy
    HDU 5739 Fantasia
    HDU 5738 Eureka
    HDU 5734 Acperience
    HDU 5742 It's All In The Mind
    POJ Euro Efficiency 1252
    AtCoder Beginner Contest 067 C
    AtCoder Beginner Contest 067 D
  • 原文地址:https://www.cnblogs.com/rainyskywx/p/10349571.html
Copyright © 2011-2022 走看看