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 
  • 相关阅读:
    HDU 2888 Check Corners (模板题)【二维RMQ】
    POJ 3264 Balanced Lineup(模板题)【RMQ】
    poj 3368 Frequent values(经典)【RMQ】
    SPOJ RPLN (模板题)(ST算法)【RMQ】
    UVA 796 Critical Links(模板题)(无向图求桥)
    UVA 315 Network (模板题)(无向图求割点)
    POJ 2029 Get Many Persimmon Trees (模板题)【二维树状数组】
    poj 3067 Japan 【树状数组】
    POJ 2481 Cows 【树状数组】
    POJ 1195 Mobile phones【二维树状数组】
  • 原文地址:https://www.cnblogs.com/rocketfan/p/1591946.html
Copyright © 2011-2022 走看看