BZOJ5157 [Tjoi2014]上升子序列(洛谷P3970)

版权声明:蒟蒻Blog随意转载 https://blog.csdn.net/a1799342217/article/details/81666592

树状数组 DP

f [ i ] 表示以 i 结尾的上升子序列个数。那么有 f [ i ] = j < i , a [ j ] < a [ i ] f [ j ] + 1

我们用一个树状数组维护数 a [ i ] f [ i ] 的和,因为要去重,每次要减掉之前位置的 f [ i ] 。最终答案还要减掉长度为1的个数。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define F inline
using namespace std;
const int p=1e9+7;
int n,m,s,l[N],a[N],b[N],f[N],t[N<<1];
F char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    return l==r?EOF:*l++;
}
F int _read(){
    int x=0,f=1; char ch=readc();
    while (!isdigit(ch)) { if (ch=='-') f=-1; ch=readc(); }
    while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
    return x*f;
}
F void nsrt(int x,int w){ for (;x<=n;x+=x&-x) (t[x]+=w)%=p; }
F int srch(int x){ for (s=0;x;x-=x&-x) (s+=t[x])%=p; return s; }
int main(){
    n=_read(); for (int i=1;i<=n;i++) a[i]=b[i]=_read();
    sort(b+1,b+n+1),b[0]=unique(b+1,b+n+1)-b-1;
    for (int i=1;i<=n;i++){
        a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b,f[i]=srch(a[i]-1)+1;
        nsrt(a[i],((f[i]-f[l[a[i]]])%p+p)%p),l[a[i]]=i;
    }
    return printf("%d\n",((srch(b[0])-b[0])%p+p)%p),0;
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/81666592