UVA 1471 Defense Lines (STL + 二分)

来源:互联网 发布:刷单网站源码 编辑:程序博客网 时间:2024/04/29 12:13

大体题意:

给你一个长度为n(n < 2e5)的序列,你的任务是删除一个连续的子序列,使得剩下的序列中有一个长度最大的连续递增子序列。求最大序列长度?

思路:

因为要删除一个连续的子序列,所以会分成左右两部分之和的形式,我们枚举右边一部分的起点位置i,快速的找到左边一个合适的位置j,使得a[j] < a[i] 并且 g[j]尽量大。

(注: g[i]表示以i 位置结束的最长上升连续子序列的长度,f[i]表示以i位置开始的最长上升连续子序列的长度)

这样我们可以利用set 来维护当前合法的左边位置的值。

什么是合法的?  必须是a[i] > a[j] 并且 g[i] > g[j], 这样我们可以按照a[i]排序,那么g[i]也一定是升序的, 

这样我们加入一个  就删除不合法的。

利用set里的二分查找lower_bound  便很快的查到合法的位置了。

详细见代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <set>#define Max(a,b)((a)<(b)?(b):(a))using namespace std;const int maxn = 2e5 + 10;int T, n;int g[maxn], f[maxn], a[maxn];struct Node{    int id;    int len;    Node(int id = 0,int len = 0):id(id),len(len){}    bool operator < (const Node& rhs) const {        return a[id] < a[rhs.id] || (a[id] == a[rhs.id ] && len < rhs.len);    }    bool operator == (const Node & rhs) const {        return id == rhs.id && len == rhs.len;    }};set<Node>s;set<Node>::iterator it,it2,it3;int main(){    scanf("%d",&T);    while(T--){        scanf("%d",&n);        s.clear();        for (int i = 1; i <= n; ++i)scanf("%d",a+i);        g[1] = 1;        for (int i = 2; i <= n; ++i){            if (a[i] > a[i-1]){                g[i] = g[i-1] + 1;            }            else g[i] = 1;        }        f[n] = 1;        for (int i = n-1; i >= 1; --i){            if (a[i] < a[i+1] ) f[i] = f[i+1] + 1;            else f[i] = 1;        }        int ans = 1;        for (int i = 1; i <= n; ++i)ans = Max(ans,f[i]);        s.insert(Node(1,1));        for (int i = 2; i <= n; ++i){            Node v = Node(i,g[i]);            it = s.lower_bound(v);            if (it != s.begin()){                --it;                Node u = *it;                ans = Max(ans,u.len + f[i]);                ++it;            }            --it;            s.insert(v);            it = s.find(v);            it2 = it;            if (it2 != s.begin()){                --it2;                Node u = *it2;                if (a[u.id] <= a[v.id]){                    if (u.len>= v.len) {                        s.erase(it);                        continue;                    }                }            }            it2 = it;            ++it2;            for ( ;it2 != s.end(); ){                Node u = *it2;                if (a[u.id] >= a[v.id]){                    if (u.len <= v.len) it2 = s.erase(it2);                    else break;;                }            }        }        printf("%d\n",ans);    }    return 0;}/**295 3 4 9 2 8 6 7 171 2 3 10 4 5 6**/

0 0