zoukankan      html  css  js  c++  java
  • hdu 1025 Constructing Roads In JGShining's Kingdom(最长上升子序列(LIS)O(nlogn)算法)

    这一题很容易抽象成最长上升子序列问题:

    最长上升子序列问题:

    给出一个由n个数组成的序列x[1..n],找出它的最长单调上升子序列。即求最大的m和a1,
    a2……,am,使得a1<a2<……<am且x[a1]<x[a2]<……<x[am]。

     动态规划求解思路分析:(O(n^2))

    经典的O(n^2)的动态规划算法,设A[i]表示序列中的第i个数,F[i]表示从1到i这一段中以i结尾的最长上升子序列的长度,初始时设F[i] = 0(i = 1, 2, ..., len(A))。则有动态规划方程:F[i] = max{1, F[j] + 1} (j = 1, 2, ..., i - 1, 且A[j] < A[i])。 

    贪心+二分查找:(O(nlogn))   
    开辟一个栈,每次取栈顶元素s和读到的元素a做比较,如果a>s,  则加入栈;如果a<s,则二分查找栈中的比a大的第1个数,并替换。  最后序列长度为栈的长度。  
    这也是很好理解的,对x和y,如果x<y且E[y]<E[x],用E[x]替换  E[y],此时的最长序列长度没有改变但序列Q的''潜力''增大。  
    举例:原序列为1,5,8,3,6,7  
    栈为1,5,8,此时读到3,则用3替换5,得到栈中元素为1,3,8,  再读6,用6替换8,得到1,3,6,再读7,得到最终栈为1,3,6,7  ,最长递增子序列为长度4。 

    用贪心+二分的方法很容易模拟出来,需要注意的就是二分的写法,而且需要输出最长上升子序列时,直接输出栈中的元素就行了。

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 const int MAXN = 500000 + 5;
     5 int s[MAXN];                                        //s[]数组用来模拟栈
     6 int binsearch(int *a, int l, int r, int val)        
     7 {
     8     while (l <= r)
     9     {
    10         int mid = (l + r) >> 1;
    11         if (val < a[mid])
    12             r = mid - 1;
    13         else if (val > a[mid])
    14             l = mid + 1;
    15         else
    16             return mid;
    17     }
    18     return l;
    19 }
    20 int main()
    21 {
    22     int n, p, r, a[MAXN];
    23     s[0] = INT_MIN;
    24     int icase = 0;
    25     while (scanf("%d", &n) != EOF)
    26     {
    27         ++icase;
    28         for (int i = 0; i < n; ++i)
    29         {
    30             scanf("%d %d", &p, &r);
    31             a[p] = r;
    32         }
    33         int val, t = 1;                    //t标记数组最后一个元素的下一位置,起始为1
    34         for (int i = 1; i <= n; ++i)
    35         {
    36             val = a[i];
    37             if (val > s[t-1])
    38                 s[t++] = val;
    39             else
    40                 s[binsearch(s, 1, t - 1, val)] = val;
    41         }
    42         if (t - 1 == 1)
    43             printf("Case %d:\nMy king, at most %d road can be built.\n\n", icase, t - 1);
    44         else
    45             printf("Case %d:\nMy king, at most %d roads can be built.\n\n", icase, t - 1);
    46     }
    47     return 0;
    48 }
  • 相关阅读:
    初识计算机
    前端html css
    mysql高级
    mysql多表查询
    mysql数据库查询
    mysql表关系
    mysql数据类型
    mysql数据库介绍
    异步回调 协程
    GIL-全局解释器锁
  • 原文地址:https://www.cnblogs.com/PegasusWang/p/3084173.html
Copyright © 2011-2022 走看看