51nod 1376 最長遞增子序列的數量(不是dp哦,線段樹 + 思維)
阿新 • • 發佈:2017-07-03
sort 是個 can stream const 方便 long 序列 printf
題目鏈接: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哦,線段樹 + 思維)