• UVa 1471


    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4217

    题意:

    给一个长度为n(n≤200000)的序列,你的任务是删除一个连续子序列,
    使得剩下的序列中有一个长度最大的连续递增子序列。
    例如,将序列{5, 3, 4, 9, 2, 8, 6, 7, 1}中的{9, 2, 8}删除,
    得到的序列{5, 3, 4, 6, 7, 1}中包含一个长度为4的连续递增子序列{3,4,6,7}。
    序列中每个数均为不超过1e9的正整数。

    分析:

    设L(i)为以第i个元素结尾的最长递增子序列长度,R(j)为以第j个元素开头的最长递增子序列长度,
    则最终的答案为最大的 L[i] + R[j] 。枚举j,在一个单调队列里用二分查找快速找到一个i(i<j),
    使得 a[i] < a[j] 且 L[i] 最大。则这个单调队列应该满足 a[i] < a[j] 且 L[i] < L[j] (i<j)。
    每枚举完一个j,就更新这个单调队列。可以用set来完成上述要求。

    代码:

     1 #include <cstdio>
     2 #include <set>
     3 using namespace std;
     4 
     5 const int UP = 2e5 + 5;
     6 
     7 struct TYPE {
     8     int a, L;
     9     bool operator < (const TYPE& that) const {
    10         return a < that.a;
    11     }
    12 };
    13 
    14 int a[UP], L[UP], R[UP];
    15 
    16 int main(){
    17     int T;
    18     scanf("%d", &T);
    19     while(T--){
    20         int n;
    21         scanf("%d", &n);
    22         for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    23 
    24         L[0] = 1; //以i结尾的最长连续子序列长度
    25         for(int i = 1; i < n; i++) L[i] = a[i-1] < a[i] ? L[i-1] + 1 : 1;
    26 
    27         R[n-1] = 1; //以i开头的最长连续子序列长度
    28         for(int i = n - 2; i >= 0; i--) R[i] = a[i] < a[i+1] ? R[i+1] + 1 : 1;
    29 
    30         int ans = 1;
    31         set<TYPE> S;
    32         S.insert((TYPE){a[0], L[0]});
    33         for(int i = 1; i < n; i++){
    34             bool keep = true;
    35             TYPE t = (TYPE){a[i], L[i]};
    36             set<TYPE>::iterator it = S.lower_bound(t);
    37             if(it != S.begin()){
    38                 int len = R[i] + (--it)->L;
    39                 ans = max(ans, len);
    40                 if(t.L <= it->L) keep = false;
    41             }
    42             if(keep){
    43                 S.erase(t); //由于set的特性,当两个TYPE变量的a相同时,这两个变量被认为是相同的。且t.L不会比原来的小
    44                 S.insert(t);
    45                 it = ++S.find(t);
    46                 while(it != S.end() && it->L <= t.L) S.erase(it++);
    47             }
    48         }
    49         printf("%d
    ", ans);
    50     }
    51     return 0;
    52 }
  • 相关阅读:
    DOM深度优先遍历算法
    DOM事件
    DOM修改
    DOM的方法和属性
    DOM简介
    JSON.stringify()
    JSON解析
    JSON对象
    JSON语法
    JSON对比XML
  • 原文地址:https://www.cnblogs.com/hkxy125/p/8116623.html
Copyright © 2020-2023  润新知