ちびの戦い

ちびの戦い

系列長Nの所定の期間(\ \ {a_iを\} \)の長さがmのシーケンス上昇厳格な要件の数であり、\(MOD \を^ 9 + 10 7 \) \(N \ ^ 10 3のLeq \) 。

ソリューション

設定は考えにくい\(F [i] [j]は\) i番目の終わりの位置を表し、jはLSIの長さである、我々は持っています

\ [F [I] [J] = \ sum_ {k = 1、a_iを> a_k} ^ {I-1} F [k]は[J-1] \]

ボーダー:([1] = 1、I = 1,2、...、N- \ F [I])\、残りは0であります

答え:\(\ sum_ = {I} 1 ^ NF [I] [M] \)。

これがあることに注意してください\(O(N ^ 3) \) アルゴリズムは、優先転送の最適化問題は、実際にフロント見つけることです\(\ a_k)未満である(a_iを\)\プレフィックスとFを、また、並べ替えを与えることを検討しますそれは離散、データ構造及び接頭ディスクリート、各クエリの配列と対応するプレフィックスの位置を変更する(例えば、ツリーライン、フェンウィック木)の確立を与えることで、その後に最適化され得る(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\n",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();
}

おすすめ

転載: www.cnblogs.com/a1b3c7d9/p/10958341.html