zoukankan      html  css  js  c++  java
  • bzoj4361 isn(树状数组优化dp+容斥)

    4361: isn

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 938  Solved: 485
    [Submit][Status][Discuss]

    Description

    给出一个长度为n的序列A(A1,A2...AN)。如果序列A不是非降的,你必须从中删去一个数,
    这一操作,直到A非降为止。求有多少种不同的操作方案,答案模10^9+7。

    Input

    第一行一个整数n。
    接下来一行n个整数,描述A。

    Output

    一行一个整数,描述答案。

    Sample Input

    4
    1 7 5 3

    Sample Output

    18

    HINT

    1<=N<=2000

    设$g(i)$为数列中长度为$i$的非降序列个数,那么我们可以利用容斥原理求得答案
    $ans=sum_{i=1}^{n}g(i)*(n-i)!-g(i+1)*(n-i-1)!*(i+1)$
    $g(i)$中的不合法情况(已经是非降序列却又再删数)一定是从$g(i+1)$转移来的,所以可以利用$g(i+1)$去掉$g(i)*(n-i)!$中的不合法情况
     
    $g(i)$怎么求呢
    设$f(i,j)$以$i$结尾,长度为$j$的非降序列的个数
    $f(i,j)=sum_{k=1}^{i-1}f(k,j-1)*[A_k<=A_i]$
    但是这是$n^3$方的
    于是我们用树状数组把$k$优化成$(logn)$
    复杂度为$O(n^2logn)$
    $g(i)=sum_{j=i}^{n}f(j,i)$
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    #define N 2005
    const ll P=1e9+7;
    int n,m,A[N],B[N],p[N];
    ll fac[N],s[N][N],f[N][N],g[N],ans;
    inline ll Md(ll a){return a<P?a:a-P;}
    void Add(int id,int x,ll v){for(;x<=n;x+=x&-x)s[id][x]=Md(s[id][x]+v);}
    ll Sum(int id,int x){ll re=0; for(;x;x-=x&-x)re=Md(re+s[id][x]); return re;}
    void prep(){
        fac[0]=1;
        for(ll i=1;i<=n;++i) scanf("%d",&A[i]),B[i]=A[i],fac[i]=fac[i-1]*i%P;
        sort(B+1,B+n+1); m=unique(B+1,B+n+1)-B-1;
        for(int i=1;i<=n;++i) p[i]=lower_bound(B+1,B+m+1,A[i])-B;//离散化
    }
    int main(){
        scanf("%d",&n); prep(); Add(0,1,1);
        for(int i=1;i<=n;++i)
            for(int j=i;j;--j)
                f[i][j]=Md(f[i][j]+Sum(j-1,p[i])),Add(j,p[i],f[i][j]);
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;++j)
                g[i]=Md(g[i]+f[j][i]);
        for(ll i=1;i<=n;++i)
            ans=Md(Md(ans+g[i]*fac[n-i]%P)-g[i+1]*fac[n-i-1]%P*(i+1)%P+P);
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    [LeetCOde] Reverse Words in a String III
    [LeetCode] Keyboard Row
    [LeetCode] Number Complement
    [LeetCode] Array Partition I
    [LeetCode] Merge Two Binary Trees
    [LeetCode] Hamming Distance
    FFmpeg在ubuntu下安装及使用
    curl命令备注
    CentOS配置防火墙
    leetcode 21 Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10792793.html
Copyright © 2011-2022 走看看