數組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;
}