首页 > 代码库 > BestCoder Round#8 1003
BestCoder Round#8 1003
dp[i][j] 表示以i结尾的长度为j的递增子序列
dp[i][j] = sum(dp[k][j]) k<i && a[i] >a[j]
如果只是单纯的循环
for(j=2; j<=m; ++j)
for(i=1; i<=n; ++i)
for(k=1; k<i; ++k)
if(a[i] > a[j])
dp[i][j] += dp[k][j-1];
时间复杂度是O(n * n * m) TLE
但是k循环可以用树状数组来优化,k循环可以看做是一个区间求和的过程,即求出小于i的dp[k][j-1]有多少个
那么时间复杂度变为O(n * m * logn)
1 #include <algorithm> 2 using namespace std; 3 typedef long long LL; 4 const int N = 10000 + 10; 5 6 LL a[N],b[N],c[N]; 7 int n; 8 LL dp[N][N]; 9 int lowbit(int t)10 {11 return t & (-t);12 }13 void update(int pos, LL val)14 {15 while(pos <= n)16 {17 c[pos] += val;18 pos += lowbit(pos);19 }20 }21 LL query(int pos)22 {23 LL ans = 0;24 while(pos >= 1)25 {26 ans += c[pos] % 123456789;27 pos -= lowbit(pos);28 }29 return ans;30 }31 int main()32 {33 int m, i, j;34 while(scanf("%d%d",&n, &m) != EOF)35 {36 memset(dp, 0, sizeof(dp));37 38 for(i=1; i<=n; ++i)39 {40 dp[i][1] = 1;41 scanf("%I64d",&a[i]);42 b[i] = a[i];43 }44 sort(b+1, b+n+1);45 for(j=2; j<=m; ++j)46 {47 memset(c, 0, sizeof(c));48 for(i=1; i<=n; ++i)49 {50 int index = lower_bound(b+1, b+n+1,a[i]) - b ;//离散化,index 表示a[i]在数列中第几大51 dp[i][j] = query(index-1);//找出小于index的长度为j-1的递增子序列有多少个52 update(index,dp[i][j-1]);//更新以i结尾的,长度为j-1的递增子序列有多少个53 }54 }55 LL ans = 0;56 for(i=1; i<=n; ++i)57 ans = (ans + dp[i][m]) % 123456789;58 printf("%I64d\n",ans);59 }60 }
BestCoder Round#8 1003
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。