• 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

    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
    ",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
    ",sm[1]);
    61     return 0;
    62 }
  • 相关阅读:
    电路原理图分析
    GPIO学习——用户空间操作
    在Android上运行Java和C程序
    Android命令行工具学习总结
    Android蓝牙学习笔记
    33 把数组排成最小的数
    233 Number of Digit One
    32 从1到n整数中1出现的次数
    31 连续子数组的最大和
    《大型网站技术架构》学习笔记
  • 原文地址:https://www.cnblogs.com/patricksu/p/7885661.html
Copyright © 2020-2023  润新知