码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-07-03 12:25:59      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:ref   algo   lan   names   cpp   clu   http   cst   pre   

题目链接: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哦,线段树 +  思维)

标签:ref   algo   lan   names   cpp   clu   http   cst   pre   

原文地址:http://www.cnblogs.com/TnT2333333/p/7109977.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!