做题感悟:开始想到用 2^n 这样来求子序列但是这样会多算很多(因为你不知道前面比它小的数的顺序是怎样的),很纠结看解题报告+自己理解用了一个晚上。
解题思路:注意:这题如果出现 1 1 1 结果也是 7,并不是 3 。这题需要用到DP 的思想,假设dp[ i ] 为 i 时a[i] 所形成的不递减子序列,那么dp[ i ] = sum ( dp[ j ] ) +1 ( j < i && a[ i ] > a[ j ] ) 即:小于a[ i ] 且在 i 前面的所形成的子序列的和。但是这样是不行的 0< n < 100000 如果这样做必定超时。其实仔细观察一下,这要做和求逆序数差不多,向上更新,向下查询,于是要用到树状数组,但是 0 < ai < 2^31 这么大的数肿么办??? 离散化(具体见代码)。
代码:
#include<stdio.h>
#include<iostream>
#include<map>
#include<stack>
#include<string>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std ;
#define LEN sizeof(struct node)
#define lld __int64
const double PI = 3.1415926535898 ;
const int INF = 99999999 ;
const double esp = 1e-8 ;
const lld mod= 1000000007 ;
const lld MX = 100005 ;
int n ;
int c[MX],b[MX] ;
struct node
{
int x,y ;
}T[MX] ;
bool cmp(node a,node b)
{
return a.x < b.x ;
}
int lowbit(int x)
{
return x&(-x) ;
}
int get_su(int x) // 求和
{
int ans=0 ;
while(x>0)
{
ans=(ans+c[x])%mod ;
x-=lowbit(x) ;
}
return ans ;
}
void update(int x,int nx)//更新
{
while(x<=n)
{
c[x]=(c[x]+nx)%mod ;
x+=lowbit(x) ;
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(c,0,sizeof(c)) ;
for(int i=1 ;i<=n ;i++)
{
scanf("%d",&T[i].x) ;
T[i].y=i ;
}
stable_sort(T+1,T+1+n,cmp) ;// 切记稳定排序
for(int i=1 ;i<=n ;i++)
b[T[i].y]=i ;
for(int i=1 ;i<=n ;i++)
{
int x=get_su(b[i])+1 ;// 自身也是一个 so +1
update(b[i],x) ;// 在比它大的值那更新
}
printf("%d\n",get_su(n)) ;
}
return 0 ;
}