51nod1376 最长递增子序列的数量

来源:互联网 发布:淘宝直通车上分 编辑:程序博客网 时间:2024/06/05 10:48

做法类似上个题.

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int mod=1000000007;int dp[50010][2],a[50010];struct Tree{        int l,r,val,mx;}tree[50000<<2];void create(int l,int r,int k){        tree[k].l=l;        tree[k].r=r;        tree[k].val=0;        tree[k].mx=-1;        if(l==r)                return;        int m=l+r>>1;        create(l,m,k<<1);        create(m+1,r,k<<1|1);}Tree ret;void seek(int l,int r,int k){        if(l==tree[k].l&&r==tree[k].r)        {                if(tree[k].mx>ret.mx)                        ret=tree[k];                else if(tree[k].mx==ret.mx)                        ret.val=(ret.val+tree[k].val)%mod;                return;        }        int m=tree[k].l+tree[k].r>>1;        if(r<=m)                seek(l,r,k<<1);        else if(l>m)                seek(l,r,k<<1|1);        else        {                seek(l,m,k<<1);                seek(m+1,r,k<<1|1);        }}void update(int x,int val,int len,int k){        if(tree[k].l==tree[k].r)        {                if(tree[k].mx==len)                        tree[k].val=(tree[k].val+val)%mod;                else if(tree[k].mx<len)                        tree[k].mx=len,tree[k].val=val;                return;        }        int m=tree[k].l+tree[k].r>>1;        if(x<=m)                update(x,val,len,k<<1);        else                update(x,val,len,k<<1|1);        if(tree[k<<1].mx>tree[k<<1|1].mx)                tree[k].mx=tree[k<<1].mx,tree[k].val=tree[k<<1].val;        else if(tree[k<<1].mx<tree[k<<1|1].mx)                tree[k].mx=tree[k<<1|1].mx,tree[k].val=tree[k<<1|1].val;        else                tree[k].mx=tree[k<<1].mx,tree[k].val=(tree[k<<1].val+tree[k<<1|1].val)%mod;}map<int,int>mp;map<int,int>::iterator it;int main(){      freopen("in","r",stdin);        int n,m=0;        cin>>n;        for(int i=0;i<n;i++)        {                scanf("%d",a+i);                mp[a[i]];        }        for(it=mp.begin();it!=mp.end();it++)                it->second=++m;        create(0,m,1);        for(int i=0;i<n;i++)        {                ret.mx=-1;                seek(0,mp[a[i]]-1,1);                if(ret.mx==-1)                {                        dp[i][0]=dp[i][1]=1;                        update(mp[a[i]],1,1,1);                        if(i>0)                        {                                if(dp[i][0]==dp[i-1][0])                                        dp[i][1]=(dp[i][1]+dp[i-1][1])%mod;                                else if(dp[i][0]<dp[i-1][0])                                        dp[i][0]=dp[i-1][0],dp[i][1]=dp[i-1][1];                        }                        continue;                }                ret.mx++;                update(mp[a[i]],ret.val,ret.mx,1);                if(ret.mx>dp[i-1][0])                        dp[i][0]=ret.mx,dp[i][1]=ret.val;                else if(ret.mx==dp[i-1][0])                        dp[i][0]=ret.mx,dp[i][1]=(dp[i-1][1]+ret.val)%mod;                else                        dp[i][0]=dp[i-1][0],dp[i][1]=dp[i-1][1];        }        cout<<dp[n-1][1];        return 0;}



基准时间限制: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示例
513204
Output示例
2

0 0