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

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

时间:2017-11-23 19:42:23      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:input   max   eof   log   clr   algo   线段树   query   pre   

题目描述

数组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

Solution

转移十分显而易见

f[i].x表示长度,f[i].y表示当前长度的个数.

f[i].x=max{f[j].y}+1,a[j]<a[i]

f[i].y=∑f[j].y,f[j].x=f[i].x-1

可以用线段树或是BIT来维护最大值以及最大值出现的个数log转移即可

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cctype>
 4 #include<algorithm>
 5 using namespace std;
 6 #define rep(i,s,t) for(int i=s;i<=t;i++)
 7 #define dwn(i,s,t) for(int i=s;i>=t;i--)
 8 #define clr(x,c) memset(x,c,sizeof(x))
 9 #define lson l,mid,x<<1
10 #define rson mid+1,r,x<<1|1
11 int read(){
12     int x=0;char c=getchar();
13     while(!isdigit(c)) c=getchar();
14     while(isdigit(c)) x=x*10+c-0,c=getchar();
15     return x;
16 }
17 const int nmax=5e4+5;
18 const int inf=0x7f7f7f7f;
19 const int mod=1e9+7;
20 int a[nmax],b[nmax],mx[nmax<<2],sm[nmax<<2];
21 int qmax(int tl,int tr,int l,int r,int x){
22     if(tl<=l&&tr>=r) return mx[x];
23     int mid=(l+r)>>1,ans=0;
24     if(tl<=mid) ans=max(ans,qmax(tl,tr,lson));
25     if(tr>mid) ans=max(ans,qmax(tl,tr,rson));
26     return ans;
27 }
28 int query(int tl,int tr,int p,int l,int r,int x){
29     if(tl<=l&&tr>=r) return mx[x]==p?sm[x]:0;
30     int mid=(l+r)>>1,ans=0;
31     if(tl<=mid) ans+=query(tl,tr,p,lson);
32     if(tr>mid) ans+=query(tl,tr,p,rson);
33     return ans>=mod?ans-mod:ans;
34 }
35 void update(int p,int a,int b,int l,int r,int x){
36     if(mx[x]<a) mx[x]=a,sm[x]=b;
37     else if(mx[x]==a) sm[x]=(sm[x]+b)%mod;
38     if(l==r) return ;
39     int mid=(l+r)>>1;
40     p<=mid?update(p,a,b,lson):update(p,a,b,rson);
41 }
42 void print(int l,int r,int x){
43     printf("%d %d:%d %d\n",l,r,mx[x],sm[x]);
44     if(l==r) return ;
45     int mid=(l+r)>>1;
46     print(lson);print(rson);
47 }
48 int main(){
49     int n=read();
50     rep(i,1,n)a[i]=b[i]=read();
51     sort(b+1,b+n+1);
52     int cnt=unique(b+1,b+n+1)-b-1;
53     rep(i,1,n)a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
54     int u,v,d;
55     rep(i,1,n){
56         u=a[i]==1?1:qmax(1,a[i]-1,1,cnt,1)+1;
57         v=u==1?1:query(1,a[i]-1,u-1,1,cnt,1);
58         update(a[i],u,v,1,cnt,1);
59     }
60     printf("%d\n",sm[1]);
61     return 0;
62 }

 

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

标签:input   max   eof   log   clr   algo   线段树   query   pre   

原文地址:http://www.cnblogs.com/patricksu/p/7885661.html

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