51nod 1376 最长递增子序列的数量(不是dp哦,线段树 +  思维)

Posted Gealo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1376 最长递增子序列的数量(不是dp哦,线段树 +  思维)相关的知识,希望对你有一定的参考价值。

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376

 

题解:显然这题暴力的方法很容易想到就是以每个数为结尾最长的有多少个,但是这样显然会超时所以要想一个方法去优化,要么用stl要么就是数据结构

线段树是个可以考虑的对象因为这也是求区间的和于是稍微将原数组优化一下,按照大小排序一下然后再按照下标更新这样能确保有序。具体看一下代码

还有一点要提一下有时候要考虑两维的东西可以适当排一下序使其变成一维有序这样就方便很多了。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define mod 1000000007
using namespace std;
const int M = 5e4 + 10;
typedef long long ll;
struct node {
    int id , val;
}a[M];
struct TnT {
    int l , r;
    ll num;
    int Max;
}T[M << 2];
void push_up(int i) {
    T[i].Max = max(T[i << 1].Max , T[(i << 1) | 1].Max);
    if(T[i << 1].Max == T[(i << 1) | 1].Max) {
        T[i].num = T[i << 1].num % mod + T[(i << 1) | 1].num % mod;
    }
    else {
        if(T[i << 1].Max > T[(i << 1) | 1].Max) T[i].num = T[i << 1].num % mod;
        else T[i].num = T[(i << 1) | 1].num % mod;
    }
    T[i].num %= mod;
}
void build(int l , int r , int i) {
    int mid = (l + r) >> 1;
    T[i].l = l , T[i].r = r , T[i].num = 0 , T[i].Max = 0;
    if(l == r) return ;
    build(l , mid , i << 1);
    build(mid + 1 , r , (i << 1) | 1);
    push_up(i);
}
void update(int pos , int i , int Max , ll num) {
    int mid = (T[i].l + T[i].r) >> 1;
    if(T[i].l == T[i].r && T[i].l == pos) {
        T[i].Max = Max ,T[i].num = num % mod;
        return ;
    }
    if(mid < pos) update(pos , (i << 1) | 1 , Max , num);
    else update(pos , i << 1 , Max , num);
    push_up(i);
}
TnT query(int l , int r , int i) {
    int mid = (T[i].l + T[i].r) >> 1;
    if(T[i].l == l && T[i].r == r) {
        return T[i];
    }
    push_up(i);
    TnT resl , resr , res;
    if(mid < l) return query(l , r , (i << 1) | 1);
    else if(mid >= r) return query(l , r , i << 1);
    else {
        resl = query(l , mid , i << 1);
        resr = query(mid + 1 , r , (i << 1) | 1);
        if(resl.Max == resr.Max) {
            res.Max = resl.Max , res.num = resl.num % mod + resr.num % mod;
        }
        else {
            if(resl.Max > resr.Max) res.Max = resl.Max , res.num = resl.num % mod;
            else res.Max = resr.Max , res.num = resr.num % mod;
        }
        res.num %= mod;
        return res;
    }
}
bool cmp(node x , node y) {
    if(x.val == y.val) return x.id > y.id;
    return x.val < y.val;
}
int main() {
    int n;
    scanf("%d" , &n);
    for(int i = 1 ; i <= n ; i++) scanf("%d" , &a[i].val) , a[i].id = i;
    sort(a + 1 , a + 1 + n , cmp);
    build(1 , n , 1);
    for(int i = 1 ; i <= n ; i++) {
        TnT gg = query(1 , a[i].id , 1);
        update(a[i].id , 1 , gg.Max + 1 , max((ll)1 ,gg.num % mod));
    }
    printf("%lld\n" , (T[1].num + mod) % mod);
    return 0;
}

以上是关于51nod 1376 最长递增子序列的数量(不是dp哦,线段树 +  思维)的主要内容,如果未能解决你的问题,请参考以下文章

最长递增子序列的数量 51Nod - 1376

51nod 1376: 最长递增子序列的数量(二维偏序+cdq分治)

51nod1376 最长递增子序列的数量

51NOD1376最长递增子序列的数量

51nod 1376 最长递增子序列的数量

51nod1376 最长递增子序列的数量