• codeforces 597C C. Subsequences(dp+树状数组)


    题目链接:

    C. Subsequences

    time limit per test
    1 second
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    For the given sequence with n different elements find the number of increasing subsequences with k + 1 elements. It is guaranteed that the answer is not greater than 8·10^18.

    Input
     

    First line contain two integer values n and k (1 ≤ n ≤ 10^5, 0 ≤ k ≤ 10) — the length of sequence and the number of elements in increasing subsequences.

    Next n lines contains one integer ai (1 ≤ ai ≤ n) each — elements of sequence. All values ai are different.

    Output
     

    Print one integer — the answer to the problem.

    Examples

    input
    5 2
    1
    2
    3
    5
    4
    output
    7

    题意:

    问在有n个不同的数组成的序列中,有k+1个数的递增子序列的个数是多少;

    思路:
      
    k不大n也不大看起来好像是dp,假设dp[i][j]表示在前i个数中长度为j的递增子序列并且a[i]是这个序列的最后一位的个数;
       ans[j]=dp[1][j]+dp[2][j]+...+dp[n][j];
       dp[i][j]=dp[x][j-1](x为按a[]序列中数值比它小且在它前面的)
    举一个例子:第一行为输入的a[]第二行为最后一个为递增子序列且最后位为a[i]的个数,再把第二行做成一个树状数组再查询,k-1次后就得到结果
    6 10 9 7 1 2 8 5 4 3 ans
    0 1 1 1 0 1 4 2 2 2 14
    0 0 0 0 0 0 2 1 1 1 5

    AC代码:
    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e5+4;
    int a[N],n,k;
    long long dp[N],sum[N],b[N];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int x,long long num)
    {
        while(x<=n)
        {
            sum[x]+=num;
            x+=lowbit(x);
        }
    }
    long long query(int x)
    {
        long long s=0;
        while(x>0)
        {
            s+=sum[x];
            x-=lowbit(x);
        }
        return s;
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        {
            b[i]=1;
            scanf("%d",&a[i]);
            dp[i]=query(a[i]);
            update(a[i],b[i]);
        }
        for(int i=2;i<=k;i++)
        {
            memset(sum,0,sizeof(sum));
            for(int j=1;j<=n;j++)
            {
                b[j]=dp[j];
                dp[j]=query(a[j]);
                update(a[j],b[j]);
            }
        }
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=dp[i];
        }
        if(!k)cout<<n<<"
    ";//注意k==0的情况
        else cout<<ans<<"
    ";
        return 0;
    }
     
  • 相关阅读:
    树的遍历
    动态规划之背包问题
    Dijkstra算法
    最短路径
    关于数学公式Markdown
    子集数
    O、Θ、Ω
    AT212 P-CASカードと高橋君
    vector的使用方法
    P3512 [POI2010]PIL-Pilots 单调队列的应用
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5316729.html
Copyright © 2020-2023  润新知