• The Battle of Chibi


    The Battle of Chibi

    给出一段长度为n的序列({a_i}),求其中长度为m的严格上升子序列个数(mod 10^9+7),(nleq 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])

    注意到这是(O(n^3))算法,优先考虑转移优化,问题实际上是要寻找前面(a_k)小于(a_i)的f前缀和,考虑给a排序,也就是给a离散化,在离散化的数组里面建立前缀和数据结构(如线段树,树状数组),每次在对应的位置上查询修改前缀和,于是可以优化为(O(n^2log^n))

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define il inline
    #define ri register
    #define yyb 1000000007
    using namespace std;
    struct Map{
        int a[1001],b[1001],n;
        il void prepare(int m,int ar[]){
            n=m;
            for(ri int i(1);i<=n;++i)
                a[i]=ar[i];sort(a+1,a+n+1);
            for(ri int i(1);i<=n;++i)b[i]=dfs(ar[i]);
        }
        il int look(int x){
            return b[x];
        }
        il int dfs(int x){
            int l(1),mid,r(n);
            while(l<=r){
                mid=l+r>>1;
                if(x>a[mid])l=mid+1;
                else r=mid-1;
            }return l;
        }
    }L;
    struct lowbit{
        int n,a[1001];
        il void prepare(int m){
            n=m,memset(a,0,sizeof(a));
        }
        il void change(int p,int v){
            while(p<=n)(a[p]+=v)%=yyb,p+=-p&p;
        }
        il int ask(int p){
            int ans(0);
            while(p)(ans+=a[p])%=yyb,p-=-p&p;return ans;
        }
    }ar;
    int a[1001],dp[1001][1001];
    il void read(int&),work();
    int main(){
        int lsy,i;read(lsy);
        for(i=1;i<=lsy;++i)printf("Case #%d: ",i),work();
        return 0;
    }
    il void work(){
        int n,m;read(n),read(m);
        for(int i(1);i<=n;++i)read(a[i]);
        L.prepare(n,a),memset(dp,0,sizeof(dp));
        for(int i(1);i<=n;++i)dp[i][1]=1;
        for(int i,j(2);j<=m;++j){
            ar.prepare(n);
            for(i=1;i<=n;++i)
                dp[i][j]=ar.ask(L.look(i)-1),
                    ar.change(L.look(i),dp[i][j-1]);
        }int ans(0);
        for(int i(1);i<=n;++i)(ans+=dp[i][m])%=yyb;
        printf("%d
    ",ans);
    }
    il void read(int &x){
        x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
    
  • 相关阅读:
    数组实现队列
    qsort用法 (转)
    枚举法
    HDU 2293
    bfs 街道赛跑
    漫谈二分查找Binary Search (转)
    qsort 结构体二级排序实例
    优化枚举法
    10项比较重要的.NET技术
    ADO.NET SQL Provider 和 ADO.NET OLE DB Provider 和 ADO.NET ODBC Provider 性能对比。
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10958341.html
Copyright © 2020-2023  润新知