动态规划+树状数组 BZOJ4361 isn

4361: isn

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 289  Solved: 146
[Submit][Status][Discuss]

Description

给出一个长度为n的序列A(A1,A2...AN)。如果序列A不是非降的,你必须从中删去一个数,
这一操作,直到A非降为止。求有多少种不同的操作方案,答案模10^9+7。

Input

第一行一个整数n。
接下来一行n个整数,描述A。

Output

一行一个整数,描述答案。

Sample Input

4
1 7 5 3

Sample Output

18

HINT

1<=N<=2000
 
好题
 
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int mod=1000000007;
 7 int n,cnt;
 8 long long ans;
 9 int a[2010],b[2010],c[2010];
10 long long fact[2010],g[2010],num[2010][2010],f[2010][2010];
11 void add(int tmp,int pos,long long d){
12     for(int i=pos;i<=n;i+=i&(-i)) num[tmp][i]=(num[tmp][i]+d)%mod;//!!!
13 }
14 long long ask(int tmp,int pos){
15     long long ret=0;
16     for(int i=pos;i;i-=i&(-i)) ret=(ret+num[tmp][i])%mod;//!!!
17     return ret;
18 }
19 int main(){
20     scanf("%d",&n);
21     for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
22     sort(b+1,b+n+1);
23     for(int i=1;i<=n;i++)
24         if(i==1||b[i]!=b[i-1]) c[++cnt]=b[i];
25     for(int i=1;i<=n;i++) a[i]=lower_bound(c+1,c+cnt+1,a[i])-c;
26     fact[0]=1;
27     for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%mod;
28     add(0,1,1);
29     for(int i=1;i<=n;i++)
30         for(int j=i;j>=1;j--){
31             f[i][j]=ask(j-1,a[i])%mod;
32             add(j,a[i],f[i][j]);
33         }
34     for(int i=1;i<=n;i++)
35         for(int j=i;j<=n;j++) g[i]=(g[i]+f[j][i])%mod;
36     for(int i=1;i<=n;i++) ans=(((ans+g[i]*fact[n-i])%mod-g[i+1]*fact[n-i-1]%mod*(i+1)%mod)%mod+mod)%mod;
37     printf("%lld",ans);
38     return 0; 
39 } 
原文地址:https://www.cnblogs.com/zwube/p/7261150.html