http://acm.hdu.edu.cn/showproblem.php?pid=5542
【题意】
- 给定长为n的序列,问有多少个长为m的严格上升子序列?
【思路】
- dp[i][j]表示以a[i]结尾的长度为j的严格上升子序列有多少个
- dp[i][j]=sum{dp[k][j-1]},k小于i且a[k]<a[i]
- 区间dp,复杂度为O(n^3)
- 会超时,第三层循环求和用树状数组加速
- 时间复杂度为O(n^2logn)
- 离散化的时候排序后不去重(否则WA)
【Accepted】
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=1e3+3; ll a[maxn]; ll b[maxn]; ll dp[maxn][maxn]; int cnt; int n,m; int lowbit(int x) { return x&(-x); } ll add(int x,int y,ll d) { while(x<=n) { dp[x][y]=(dp[x][y]+d)%mod; x+=lowbit(x); } } ll sum(int x,int y) { ll res=0ll; while(x) { res=(res+dp[x][y])%mod; x-=lowbit(x); } return res; } int main() { int T; scanf("%d",&T); int cas=0; while(T--) { memset(dp,0,sizeof(dp)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } memcpy(b,a,sizeof(b)); sort(a+1,a+n+1); //cnt=unique(a+1,a+n+1)-a-1; for(int i=1;i<=n;i++) { int pos=lower_bound(a+1,a+n+1,b[i])-a; for(int j=1;j<=min(i+1,m);j++) { ll tmp; if(j==1) tmp=1ll; else tmp=sum(pos-1,j-1); add(pos,j,tmp); } } ll ans=sum(n,m); printf("Case #%d: %d\n",++cas,(int)ans); } return 0; }
【疑问】
为啥不可以去重?
时间: 2024-10-25 23:49:12