C - K-inversions URAL - 1523 -dp-权值树

24 篇文章 0 订阅
  • C - K-inversions

     URAL - 1523
  • 题意:给出一个1-n的排列求一下长度为k的  位置与数值满足这个关系的 子序列个数:
  • 1 ≤  i 1 <  i 2 < … <  ik ≤  n and ai 1 >  ai 2 > … >  aik.
  • 思路:dp转移,dp[i][j]    i 代表新的长度为k的序列中第i个数 , j代表的是原来长度为n序列中第j个数
  • 存的值是方案数,这个位置的方案数可以有上一个位置的方案数,求和得到,前面位置那些数
  • 目前按顺序访问已经满足了,位置正序,但是大小是否合适,就要权值线段树访问上一层并且比当前值
  • 大的数的和,树状数组也可以实现,转移方程为:
  • dp[i][j]=(query(n)-query(s[j])+mod)%mod

  • #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mod 1000000000
    #define maxn 234567
    ll tree[maxn],ans;
    int s[maxn],n,k;
    ll dp[15][maxn],lhk;
    int inline lowbit(int x)
    {
        return x&(-x);
    }
    void updata(int  x,ll d)
    {
        while(x<=n)
        {
            tree[x]+=d;
            x+=lowbit(x);
        }
    }
    ll query(int x)
    {
        ll ans=0;
        while(x>0)
        {
            ans+=tree[x];
            ans%=mod;
            x-=lowbit(x);
        }
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&s[i]);
            dp[1][i]=1;
        }
        for(int i=2; i<=k; i++)
        {
            memset(tree,0,sizeof(tree));
            for(int j=1; j<=n; j++)
            {
                updata(s[j],dp[i-1][j]);
                dp[i][j]=(query(n)-query(s[j])+mod)%mod;
                if(i==k)
                    lhk=(lhk+dp[k][j])%mod;
            }
        }
        printf("%lld\n",lhk);
        return 0;
    }
    

     

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值