• UVa 1471


    原题链接

    紫书的例题,不错的题。可以用O(n)的空间one pass解决,因为有二分,时间应该是O(nlogn)。

    基本思路是用当前递增子序列的起始元素去匹配之前递增子序列的末尾元素,如果起始元素 A[i] > 末尾元素A[j] 则两个子序列可以组合成新的子序列。

    关键点:

    1. 每种长度的子序列只需保留末尾元素最小的一个,所以只需一个数组minR即可,index是长度,value是该长度的子序列的有末尾元素。
    2. 当找到一个新的子序列后,需要从这个子序列的开头开始遍历一遍,假设当前元素下标为k:1)以k开始的子序列(也即当前子序列的右半部份)可能可以匹配到新的子序列,因为A[k] > A[k-1]; 2) 以k结束的子序列子序列(也即当前子序列的左半部份)可能可以更新已有的子序列(长度一样,末尾元素更小)。换言之,我们还需要考虑当前子序列的子序列,而不是仅仅将当前找到的子序列当作整体处理。

    上代码。一般的case可以过,提交两次都WA,也懒得调试了,主要看气质吧。

     1 class UVa1471{
     2 public:
     3     int FindLongestCombinedSubSeq(vector<int> &v){
     4         size_t len = v.size();
     5         // Index is the length of existing sub sequence, value is the rightmost value of the subsequence
     6         vector<int> minR(len, RMAX);
     7         int prev = INT_MIN, seq = 0, maxSeqLen = 0;
     8         for(size_t i = 0; i < len; i++){
     9             if(v[i] > prev){
    10                 seq++;
    11             }else{
    12                 int lo = i - seq;
    13                 for(int k = 0; k < seq; k++){
    14                     int num = v[lo + k];
    15                     // Consider right part of current sequence, num as left element, find previous sub sequcence which right end element < num.
    16                     int prevSeqLen = binSearch(minR, num);
    17                     maxSeqLen = max(maxSeqLen, prevSeqLen + seq - k);
    18                     // Consider left part of current sequence, num as right element, replace existing sub sequence if its righ end element > num.
    19                     int leftPartLen = k + 1;
    20                     minR[leftPartLen] = min(minR[leftPartLen], num);
    21                 }
    22                 seq = 1;
    23             }
    24             prev = v[i];
    25         }        
    26         int lo = len - seq;
    27         for(int k = 0; k < seq; k++){
    28             int prevSeqLen = binSearch(minR, v[lo + k]);
    29             maxSeqLen = max(maxSeqLen, prevSeqLen + seq - k);
    30         }        
    31         return maxSeqLen;
    32     }
    33     
    34 private:
    35     const int RMAX = 0x3f3f3f3f;
    36     int binSearch(vector<int> &v, int k){
    37         size_t lo = 0, hi = v.size() - 1;
    38         // invariant: the largest element < k is in [lo, hi]
    39         while(lo < hi){
    40             size_t m = lo + (hi - lo + 1)/2;
    41             if(v[m] >= k){
    42                 hi = m - 1;
    43             }else{
    44                 lo = m;
    45             }
    46         }
    47         return lo;
    48     }
    49 };

     参考:http://blog.csdn.net/keshuai19940722/article/details/39297525

  • 相关阅读:
    越狱-监狱地图
    老K说故事系列(003)
    老K说故事系列(001)
    面向对象软件开发培训
    别让思想老去,重燃激情火焰
    软件产品界面设计-培训PPT发布
    读“道法自然”的非技术有感
    老K说故事系列(002)
    游戏规则
    基于C# Socket实现多人网络聊天室
  • 原文地址:https://www.cnblogs.com/k330/p/UVa_1471_Defense_Lines.html
Copyright © 2020-2023  润新知