UESTC 1217 The Battle of Chibi

dp+树状数组优化。

dp[i][j]表示以a[i]结尾,最长上升序列长度为j的方案数。dp[i][j]=sum{dp[k][j-1]} 其中k<i&&a[k]<a[i]。 离散化后,可以用1000个树状数组维护。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi = acos(-1.0), eps = 1e-8;
void File()
{
    freopen("D:\\in.txt", "r", stdin);
    freopen("D:\\out.txt", "w", stdout);
}
inline int read()
{
    char c = getchar();  while (!isdigit(c)) c = getchar();
    int x = 0;
    while (isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); }
    return x;
}

int mod=1000000007;
const int maxn=1010;
int a[maxn],b[maxn],c[maxn][maxn],dp[maxn][maxn],ans;
int T,n,m;

int lowbit(int x) { return x&(-x); }
int sum(int r,int p) { int res=0; for(int i=p;i>0;i=i-lowbit(i)) res=(res+c[r][i])%mod; return res; }
void update(int r,int p,int v) { for(int i=p;i<=1001;i=i+lowbit(i)) c[r][i]=(c[r][i]+v)%mod; }

int main()
{
    scanf("%d",&T); int cas=1;
    while(T--)
    {
        scanf("%d%d",&n,&m); memset(c,0,sizeof c); ans=0;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i-1]=a[i];
        sort(b, b + n); int sz = unique(b, b + n) - b;
        for(int i=1;i<=n;i++) a[i]=lower_bound(b, b + sz, a[i])-b+2;
        for(int i=1;i<=n;i++)
        {
            dp[i][1]=1; update(1,a[i],dp[i][1]);
            for(int j=2;j<=m;j++) { dp[i][j]=sum(j-1,a[i]-1); update(j,a[i],dp[i][j]); }
        }
        for(int i=1;i<=n;i++) ans=(ans+dp[i][m])%mod;
        printf("Case #%d: %d\n",cas++,ans);
    }
    return 0;
}
时间: 2024-10-22 15:07:33

UESTC 1217 The Battle of Chibi的相关文章

DP+BIT(优化复杂度) UESTC 1217 The Battle of Chibi

题目传送门 题意:问n长度的序列,找出长度m的上升子序列的方案数. 分析:这个问题就是问:dp[i][j] = sum (dp[i-1][k]) (1 <= k <= n, a[k] < a[j]),当前长度i一层,最后下标j一层,之前的最后下标k一层,这样是n^3的复杂度.然后树状数组可以优化j,k的复杂度,就是j扫描一遍的同时,将a[j]的信息更新到树上,那么扫描就可以用 logn时间统计出k的信息,在这之前先对a[]离散化. /***************************

CDOJ 1217 The Battle of Chibi

The Battle of Chibi Time Limit: 6000/4000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Cao Cao made up a big army and was going to invade the whole South China. Yu Zhou was worried about it. He thought the only way to beat Cao Cao is

uestc oj 1217 The Battle of Chibi (dp + 离散化 + 树状数组)

题目链接:http://acm.uestc.edu.cn/#/problem/show/1217 给你一个长为n的数组,问你有多少个长度严格为m的上升子序列. dp[i][j]表示以a[i]结尾长为j的上升子序列个数.常规是三个for. 这里用树状数组优化一下,类似前缀和的处理,两个for就好了. 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #incl

2015南阳CCPC C - The Battle of Chibi DP

C - The Battle of Chibi Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description Cao Cao made up a big army and was going to invade the whole South China. Yu Zhou was worried about it. He thought the only way to beat Cao Cao is to have a spy in Cao

HDU - 5542 The Battle of Chibi(LIS+树状数组优化)

The Battle of Chibi Cao Cao made up a big army and was going to invade the whole South China. Yu Zhou was worried about it. He thought the only way to beat Cao Cao is to have a spy in Cao Cao's army. But all generals and soldiers of Cao Cao were loya

The Battle of Chibi

The Battle of Chibi 给出一段长度为n的序列\(\{a_i\}\),求其中长度为m的严格上升子序列个数\(mod\ 10^9+7\),\(n\leq 10^3\). 解 不难想到设\(f[i][j]\)表示以第i个位置结尾,长度为j的LSIS,因此我们有 \[f[i][j]=\sum_{k=1,a_i>a_k}^{i-1}f[k][j-1]\] 边界:\(f[i][1]=1,i=1,2,...,n\),其余为0 答案:\(\sum_{i=1}^nf[i][m]\) 注意到这是\

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

HDU5542 The Battle of Chibi(dp)

题意: 给你一个长度为n(1e3)的数列,让你找出长度为m的上升子序列的个数 思路: f[i][j]表示以第i个数为结尾,长度为j的上升子序列的个数,枚举i和j是n^2的,统计的时候用树状数组维护一下 /* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <

ccpc_南阳 C The Battle of chibi dp + 树状数组

题意:给你一个n个数的序列,要求从中找出含m个数的严格递增子序列,求能找出多少种不同的方案 dp[i][j]表示以第i个数结尾,形成的严格递增子序列长度为j的方案数 那么最终的答案应该就是sigma(dp[i][m]); 显然有:dp[i][j] = sigma(dp[k][j - 1]); 其中 1 <= k < i 且 a[k] < a[i]; 题目要求严格递增,这个限制怎么解决? hdu4719这道题同样是这样处理,即我们只需要从小到大dp就行了. 但是复杂度是O(n^3)的,显然