首页 > 代码库 > 51nod 1376 最长递增子序列的数量(不是dp哦,线段树 + 思维)
51nod 1376 最长递增子序列的数量(不是dp哦,线段树 + 思维)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376
题解:显然这题暴力的方法很容易想到就是以每个数为结尾最长的有多少个,但是这样显然会超时所以要想一个方法去优化,要么用stl要么就是数据结构
线段树是个可以考虑的对象因为这也是求区间的和于是稍微将原数组优化一下,按照大小排序一下然后再按照下标更新这样能确保有序。具体看一下代码
还有一点要提一下有时候要考虑两维的东西可以适当排一下序使其变成一维有序这样就方便很多了。
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#define mod 1000000007using 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哦,线段树 + 思维)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。