zoukankan      html  css  js  c++  java
  • POJ 1631 Bridging Singnals

    110MS, O(nlog(n))的算法,怎样才能更快?那些10几个MS的是怎样实现的?

      1 Source Code
      2 Problem: 1631        User: goldenlock
      3 Memory: 628K        Time: 110MS
      4 Language: G++        Result: Accepted
      5 
      6     * Source Code
      7 
      8       /*
      9        *  ==============================================================================
     10        * 
     11        *          \file   bridging_signals_1631.cc
     12        *
     13        *        \author   pku_goldenlock@qq.com
     14        *
     15        *          \date   2009-10-28 21:41:57.539397
     16        *  
     17        *   Description:   pku 1631,
     18        *                  本质上就是求最长只增序列,编程之美上
     19        *                  有解释.下面只要提到序列就是递增序列.
     20        *                  疑问,两个左边的指向同一个右边的算相交了吗?假定不算相交
     21        *                  不算的话就允许递增序列有相同大小的元素,如果算就不能有.
     22        *                  不管算不算相交,都是求upper_bound,如果不算的化,元素全
     23        *                  不相同.恩,本题目是没有相同元素的,不会左边两个连右边
     24        *                  同一个的.但是解法并不改变.
     25        *                  思路:
     26        *                  依次求以第n个元素结尾的只增序列长度l[n],记录所有的l[]最大的一个即
     27        *                  为所求.
     28        *                  核心优化:
     29        *                  最本质的规律是前面的l[k],l[j]相等的化, 假如data[k] < data[j]
     30        *                  那么后面元素就不需要去考虑data[j]!在同等长度下,尾元素小的序
     31        *                  列优先.
     32        *                  
     33        *                  因此可以记录各个长度的序列,记录其对应的最小尾元素.
     34        *                  考虑长度为i(1,2,3,4.)这样的递增长度序列,其对应的最小尾元素t[i]也
     35        *                  是递增的.否则假如如果i > j 而t[i] < t[j] 则存在 x < t[i] < t[j]
     36        *                  l[x] = t[j]  与t[j] 是长度为j的序列的最小尾元素矛盾.
     37        *
     38        *                  因为递增长度对应的最小尾元素也递增,所以可以二分查找.
     39        *                  对于扫描到第n个元素, data[n],去最小尾元素序列二分查找
     40        *                  data[n](stl upper_bound),返回第一个比data[n]大的位置k,令t[k] = data[n],
     41        *                  即更新长度位k的序列的最小尾元素值.
     42        *                  最后返回最长的那个序列的长度即可.
     43        *
     44        *  ==============================================================================
     45        */
     46       #include <stdio.h>
     47       /*  
     48        * for spped, your response to let end >= 0
     49        * 对这个特殊的问题,没有相同元素,所以一定查找不到key
     50        * 如1 2 4 查找3 返回index 2  t[2] = 4(upper_bound!)
     51        * upper_bound和lower_bound的区别在于 upper_bound return start, lower_bound return end.
     52        * search 1.5
     53        *        1
     54        *        end start
     55        * search     0.5
     56        *            1
     57        *        end start
     58        * 最后总是start指向比key大的第一个数字位置,end指向比key小的第一个位置
     59        * the last status : end key start
     60        * TODO try std::upper_bound, the same:)
     61        */
     62       inline int upper_bound(int t[], int end, int key) {
     63         int start = 0;
     64         int mid;
     65         while (start <= end) {
     66           mid = (start + end)/2;
     67           //考虑假设有相同元素的情况(本题目没有),必须这么写,不能key <= t[mid],i
     68           //lower_bound 要写 if key > t[mid] start = mid + 1
     69           if (key < t[mid])  
     70             end = mid - 1;
     71           else
     72             start = mid + 1;
     73         }
     74         return start;
     75       }
     76 
     77       inline int maxIncreasingSequence(int data[], int len) 
     78       {
     79         //--------------------init
     80         int max_len = 0;
     81         int t[len];
     82         t[0= data[0];  
     83         int pos;
     84         //--------------------find max length
     85         for (int i = 1; i < len; i++) {
     86           pos = upper_bound(t, max_len, data[i]);
     87           if (pos > max_len)  //get longer sequence
     88             max_len = pos;
     89           //modify(or add) the smallest ending value 
     90           //for sequence with length as pos + 1
     91           t[pos] = data[i];    
     92         }
     93         //--------------------return
     94         return max_len + 1;  //due to staring index is 1 not 0
     95       }
     96 
     97       int main(int argc, char *argv[])
     98       {
     99         int test_num;
    100         scanf("%d"&test_num);
    101         int array_length;
    102         //-----------------run each test case
    103         for (int i = 0; i < test_num; i++) {
    104           //------------------------get input
    105           scanf("%d"&array_length);
    106           int data[array_length];
    107           for (int j = 0; j < array_length; j++) {
    108             scanf("%d"&data[j]); 
    109           }
    110           //------------------------print result
    111           printf("%d\n", maxIncreasingSequence(data, array_length));
    112         }
    113         return 0;
    114       }
    115 
    116 

    可以复用data数组,即不需要t数组,不过不改善什么性能.

     1 #include <stdio.h>
     2 
     3 inline int upper_bound(int data[], int end, int key) {
     4   int start = 0;
     5   int mid;
     6   while (start <= end) {
     7     mid = (start + end)/2;
     8     //考虑假设有相同元素的情况(本题目没有),必须这么写,不能key <= t[mid],i
     9     //lower_bound 要写 if key > t[mid] start = mid + 1
    10     if (key < data[mid])  
    11       end = mid - 1;
    12     else
    13       start = mid + 1;
    14   }
    15   return start;
    16 }
    17 
    18 inline int maxIncreasingSequence(int data[], int len) 
    19 {
    20   //--------------------init
    21   int max_len = 0;
    22   int pos;
    23   //--------------------find max length
    24   for (int i = 1; i < len; i++) {
    25     pos = upper_bound(data, max_len, data[i]);
    26     if (pos > max_len)     //get longer sequence
    27       max_len = pos;
    28     data[pos] = data[i];    //modify smallest tail value
    29    }
    30   //--------------------return
    31   return max_len + 1;  //due to staring index is 1 not 0
    32 }
    33 
    34 int main(int argc, char *argv[])
    35 {
    36   int test_num;
    37   scanf("%d"&test_num);
    38   int array_length;
    39   //-----------------run each test case
    40   for (int i = 0; i < test_num; i++) {
    41     //------------------------get input
    42     scanf("%d"&array_length);
    43     int data[array_length];
    44     for (int j = 0; j < array_length; j++) {
    45       scanf("%d"&data[j]); 
    46     }
    47     //------------------------print result
    48     printf("%d\n", maxIncreasingSequence(data, array_length));
    49   }
    50   return 0;
    51 }
    52 
    53 
  • 相关阅读:
    查找->静态查找表->次优查找(静态树表)
    P1993-小K的农场
    P1983-车站分级
    P1268-树的重量
    P1113-杂务
    P1265-公路修建
    P2330-[SCOI2005]繁忙的都市
    P1546-最短网络
    P1144-最短路计数
    P1462-通往奥格瑞玛的道路
  • 原文地址:https://www.cnblogs.com/rocketfan/p/1591946.html
Copyright © 2011-2022 走看看