51 nod 1376 最长递增子序列的数量(树状数组,同时更改两个变量 长度 方案数)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yjf3151731373/article/details/88625310

1376 最长递增子序列的数量
1 秒 131,072 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。
收起
输入
第1行:1个数N,表示数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数A[i],表示数组的元素(0 <= A[i] <= 10^9)
输出
输出最长递增子序列的数量Mod 1000000007。
输入样例
5
1
3
2
0
4
输出样例
2

#include <bits/stdc++.h>
using namespace std;
typedef  long long LL;
const int N= 1e5+1000;
const LL mod = 1e9+7;
int a[N], b[N], c[N], dp[N];
void get(int t,int &x,int &y)//x代表小于当前数的最大LIS长度,y代表方案数
{
    while(t)
    {
        if(x<c[t])x=c[t],y=dp[t];
        else if(x==c[t])y=(y+dp[t])%mod;
        t-=(t&(-t));
    }
    return ;
}
void update(int t,int x,int y)
{
    while(t<N)
    {
        if(c[t]<x)c[t]=x,dp[t]=y;
        else if(c[t]==x)dp[t]=(dp[t]+y)%mod;
        t+=(t&(-t));
    }
    return ;
}

int main()
{
    int n;
    scanf("%d", &n);
    for(int i=0;i<n;i++)
    {
        scanf("%d", &a[i]);
        b[i]=a[i];
    }
    sort(b,b+n);
    for(int i=0;i<n;i++)
    {
        a[i]=lower_bound(b,b+n,a[i])-b+1;
    }
    memset(c,0,sizeof(c));
    memset(dp,0,sizeof(dp));
    int x=0, y=0;
    for(int i=0;i<n;i++)
    {
        x=0,y=0;
        get(a[i]-1,x,y);
        x++;
        update(a[i],x,y==0?1:y);
    }
    int ans=0;
    x=0;
    get(n,x,ans);
    printf("%d\n",ans);
    return 0;
}
展开阅读全文

没有更多推荐了,返回首页