uva1471 二叉搜索树

时间:2022-06-18 00:44:52

此题紫书上面有详细分析,关键是运用Set优化实现O(nlgn)复杂度

AC代码:

#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;

const int maxn = 2e5+5;
int num[maxn], h[maxn], g[maxn];

//g[i] - num[i] is the Last
//h[i] - num[i] is the First

struct node{
    int val, lenth;
    node(){}
    node(int val, int lenth):val(val), lenth(lenth){}
    bool operator < (const node &p) const {
        return val < p.val;
    }
};

#define It set<node>::iterator

int solve(int n){
    set<node> Set;
    int ans = g[0];
    Set.insert(node(num[0], g[0]));
    for(int i = 1; i < n; ++i){
        node c(num[i], g[i]);
        It it = Set.lower_bound(c); //得到迭代器
        bool ok = 1; //keep
        if(it != Set.begin()){
            node pre = *(--it);
            ans = max(ans, pre.lenth + h[i]);
            if(pre.lenth >= c.lenth) ok = 0;
        }
        if(ok){ //intsert C
            Set.erase(c);
            Set.insert(c);
            it = Set.find(c);
            it++;
            while(it != Set.end() && it->lenth <= c.lenth) Set.erase(it++);
        }
    }
    return ans;
}

int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; ++i) scanf("%d", &num[i]);
        // 处理g[i]
        g[0] = 1;
        for(int i = 1; i < n; ++i) {
            if(num[i] > num[i-1]) g[i] = g[i-1] + 1;
            else g[i] = 1;
        }
        // 处理h[i]
        h[n-1]=1;
        for(int i = n-2; i >= 0; --i) {
            if(num[i] < num[i+1]) h[i] = h[i+1] + 1;
            else h[i] = 1;
        }
        printf("%d\n",solve(n));
    }
    return 0;
}

如有不当之处欢迎指出!