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

数组A包含N个整数(可能包含相同的值)。设S为A的子序列且S中的元素是递增的,则S为A的递增子序列。如果S的长度是所有递增子序列中最长的,则称S为A的最长递增子序列(LIS)。A的LIS可能有很多个。例如A为:{1 3 2 0 4},1 3 4,1 2 4均为A的LIS。给出数组A,求A的LIS有多少个。由于数量很大,输出Mod 1000000007的结果即可。相同的数字在不同的位置,算作不同的,例如 {1 1 2} 答案为2。
Input
第1行:1个数N,表示数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数A[i],表示数组的元素(0 <= A[i] <= 10^9)
Output
输出最长递增子序列的数量Mod 1000000007。
Input示例
5
1
3
2
0
4
Output示例
2


题解:nlogn树状数组维护,维护树状数组管辖区域内的最大值 c[i], 及该最大值相对应的最长上升子序列数量 dp[i].

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 5e4+10, mod = 1000000007;
 4 int a[N], b[N], c[N], dp[N];
 5 void update(int n, int x, int y){
 6     for(int i = n; i < N; i += i&-i){
 7         if(c[i] < x)
 8             c[i] = x, dp[i] = y;
 9         else if(c[i] == x){
10             dp[i] += y;
11             if(dp[i] >= mod) dp[i] %= mod;
12         }
13     }
14 }
15 void get(int n, int& x, int& y){
16     x = y = 0;
17     for(int i = n; i; i -= i&-i){
18         if(x < c[i])
19             x = c[i], y = dp[i];
20         else if(x == c[i]){
21             y += dp[i];
22             if(y >= mod) y %= mod;
23         }
24     }
25 }
26 
27 int main(){
28     int n; scanf("%d", &n);
29     for(int i = 0; i < n; i++)
30         scanf("%d", a+i), b[i] = a[i];
31     sort(b, b+n);
32     for(int i = 0; i < n; i++)
33         a[i] = lower_bound(b, b+n, a[i])-b+1;
34     int x, y, ans = 0;
35     for(int i = 0; i < n; i++){
36         get(a[i]-1, x, y);
37         x++;
38         update(a[i], x, x == 1? 1: y);
39     }
40     get(n, x, ans);
41     printf("%d
", ans);
42     return 0;
43 }
View Code
原文地址:https://www.cnblogs.com/dirge/p/5958808.html