1376 最长递增子序列的数量(dp+线段树优化)

时间:2022-10-31 19:31:10

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


题解:离线。线段树维护区间最长上升序列的长度和个数。


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define lc idx<<1
#define rc idx<<1|1
#define lson l,mid,lc
#define rson mid+1,r,rc
#define mod 1000000007

using namespace std;

typedef long long ll;

const int N=50005;

int n;
int dp[N],dn[N];

struct node
{
    int v;
    int id;
    bool operator < (const node &b)const
    {
        if(v==b.v)
            return id>b.id;
        return v<b.v;
    }
} a[N];

struct tree
{
    int Max,num;
    tree() {};
    tree(int ma,int nu)
    {
        Max=ma;
        num=nu;
    }
} T[N<<2];

void push_up(int idx)
{
    T[idx].Max=max(T[lc].Max,T[rc].Max);
    if(T[lc].Max==T[rc].Max)
    {
        T[idx].num=(T[lc].num+T[rc].num)%mod;
    }
    else
    {
        T[idx].num=T[lc].Max>T[rc].Max?T[lc].num:T[rc].num;
    }
}

void build(int l,int r,int idx)
{
    if(l==r)
    {
        T[idx].Max=0;
        T[idx].num=0;
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(idx);
}

void update(int l,int r,int idx,int x,tree y)
{
    if(l==r)
    {
        T[idx]=tree {y.Max,y.num};
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)
    {
        update(lson,x,y);
    }
    else
    {
        update(rson,x,y);
    }
    push_up(idx);
}
tree query(int l,int r,int idx,int x,int y)
{
    if(x<=l&&r<=y)
    {
        return T[idx];
    }
    int mid=(l+r)>>1;
    tree res=tree {0,0};
    if(x<=mid)
    {
        res=query(lson,x,y);
    }
    if(y>mid)
    {
        tree t=query(rson,x,y);
        if(t.Max==res.Max){
                res.num+=t.num;
                res.num%=mod;
        }
        else if(t.Max>res.Max)
        {
            res=tree {t.Max,t.num};
        }
    }
    return res;
}

int main()
{
    freopen("test.in","r",stdin);
    while(cin>>n)
    {
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i].v);
            a[i].id=i;
        }
        sort(a+1,a+n+1);
        build(1,n,1);
        for(int i=1; i<=n; i++)
        {
            tree t=query(1,n,1,1,a[i].id);
            if(t.Max==0)t.num=1;//前面没有数
            t.Max++;
            update(1,n,1,a[i].id,t);
        }
        cout<<T[1].num<<endl;
    }
    return 0;
}