题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376
基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
收藏
关注
数组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
题解:
1.由于要统计个数,所以就不能用之前所谓的O(n^2)或O(nlogn)方法(这两种方法求的是LIS的长度,而不是个数)。
2.因此需要利用线段树进行统计:将输入的值进行离散化,然后在离散化后数组之上建立线段树(即以值建树而不是以下标建树)。线段树的每个结点需要记录两个信息: 该段的LIS的长度及个数。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 5e4+10; 18 19 pair<int,int> getMax(pair<int,int> x, pair<int,int>y) 20 { 21 if(x.first<y.first) x = y; 22 else if(x.first==y.first) x.second = (x.second+y.second)%MOD; 23 return x; 24 } 25 26 pair<int,int> len[MAXN*4]; 27 void build(int u, int l, int r) 28 { 29 if(l==r) 30 { 31 len[u].first = len[u].second = 0; 32 return; 33 } 34 int mid = (l+r)>>1; 35 build(u*2,l,mid); 36 build(u*2+1,mid+1,r); 37 len[u] = getMax(len[u*2],len[u*2+1]); 38 } 39 40 void add(int u, int l, int r, int pos, pair<int,int> val) 41 { 42 if(l==r) 43 { 44 len[u] = getMax(len[u],val); 45 return; 46 } 47 int mid = (l+r)>>1; 48 if(pos<=mid) add(u*2,l,mid,pos,val); 49 else add(u*2+1,mid+1,r,pos,val); 50 len[u] = getMax(len[u*2],len[u*2+1]); 51 } 52 53 pair<int,int> query(int u, int l, int r, int x, int y) 54 { 55 if(x<=l&&r<=y) return len[u]; 56 57 int mid = (l+r)>>1; 58 pair<int,int> ret = make_pair(0,0); 59 if(x<=mid) ret = getMax(ret,query(u*2,l,mid,x,y)); 60 if(y>=mid+1) ret = getMax(ret,query(u*2+1,mid+1,r,x,y)); 61 return ret; 62 } 63 64 int a[MAXN], M[MAXN], m; 65 int main() 66 { 67 int n; 68 while(scanf("%d",&n)!=EOF) 69 { 70 for(int i = 1; i<=n; i++) 71 scanf("%d",&a[i]); 72 73 memcpy(M+1,a+1,n*sizeof(a[0])); 74 M[n+1] = -INF; //在最前面加个无穷小,防止区间溢出 75 sort(M+1,M+1+n+1); //离散化 76 m = unique(M+1,M+1+n+1)-(M+1); 77 78 build(1,1,m); 79 for(int i = 1; i<=n; i++) 80 { 81 int pos = lower_bound(M+1,M+1+m,a[i])-(M+1); //找到a[i]的上一个值的位置(这也是为什么要在离散化数组里加个无穷小) 82 pair<int,int> t = query(1,1,m,1,pos); 83 if(t.first==0) t.first = t.second = 1; //如果在前面没人比它小,则自己作为第一个 84 else t.first++; //如果前面有人比它小,则长度+1(加上自己) 85 add(1,1,m,pos+1,t); //插入 86 } 87 printf("%d ", query(1,1,m,1,m).second); 88 } 89 }