Description
对于30%的数据,N<=5000
对于100%的数据,N<=10^5
Solution
从前向后扫,这个数的贡献就是前面小于这个数的个数+前面小于这个数结尾的上升子序列数和。
那么显然可以离散化以后树状数组维护。
去重的话,显然就是要减掉上一次这个数的答案。
具体有一些细节要注意下。
Code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define mo 1000000007
#define LL long long
#define N 100005
using namespace std;
int n;
LL s[N],ans,c[N],ls[N],a[N];
bool bz[N];
struct node
{
LL w,s;
}b[N];
bool cmp(node x,node y)
{
return x.s<y.s;
}
LL lowbit(LL k)
{
return k&(-k);
}
void put(LL k,LL s)
{
if(k==0) return;
while(k<=n) c[k]=(c[k]+s)%mo,k+=lowbit(k);
}
LL get(LL k)
{
LL s=0;
while(k>0) s=(s+c[k])%mo,k-=lowbit(k);
return s;
}
int main()
{
cin>>n;
fo(i,1,n) scanf("%lld",&a[i]),b[i].s=a[i],b[i].w=i;
sort(b+1,b+n+1,cmp);
int m=0;
b[0].s=-mo;
memset(s,0,sizeof(s));
memset(ls,0,sizeof(ls));
fo(i,1,n)
{
if(b[i].s!=b[i-1].s) m++;
a[b[i].w]=m;
}
memset(bz,0,sizeof(bz));
fo(i,1,n)
{
s[i]=(get(a[i]-1)-ls[a[i]]+mo)%mo;
put(a[i],s[i]+(!bz[a[i]]));
bz[a[i]]=1;
ls[a[i]]=s[i]+ls[a[i]];
ans=(ans+s[i])%mo;
}
printf("%lld\n",ans);
}