XJTUOJ 14 树状数组

探讨了在特定条件下计算有序k元组数量的问题。通过分析队列中人们的身高顺序,利用离散数学与算法技巧,实现了高效求解方案。

wmq的队伍

时间限制: 2000ms   内存限制: 512M

交大上课需要打卡,于是在上课前的几分钟打卡机前往往会排起长队。

平时早睡早起早早打卡的wmq昨晚失眠,今天起晚了,于是他也加入了打卡队伍中。

这个时候,wmq发现了神奇的现象,打卡队伍可以按人们的身高看成一个队列,左边是队头,右边是队尾。

对于队列a1...an,wmq想知道其中存在多少的有序k元组l1...lk

使得1l1<l2<...<lkn,并且有al1>al2>...>alk

输入有多组数据

第一行是一个正整数T1T15,代表数据组数

每组数据第一行是两个正整数nk1n21041kmin(n,100)

n代表队列的人数,k 的含义见题面

接下来一行有n个正整数,代表1n的一个排列,表示队伍的身高情况

对于每组数据,输出一个整数,代表有序k元组的个数

考虑到数字可能很大,将答案对109+7取模之后输出

 复制
3
2 2
1 2
2 2
2 1
22 3
1 2 3 4 5 16 6 7 8 9 10 19 11 12 14 15 17 18 21 22 20 13
0
1
8

题解:定义C[i][j]为选了i个数  以小于等于j的数结尾的方案有多少

那么每次for到一个数  把它加到C[1][num]

然后第二层就是加上第一层所有结尾大于a[i]的方案数

第三层加上第二层。。。

这样递推下去

ans每次加上以a[i]结尾的方案数


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll C[105][20005];
ll a[20005],b[20005],cnt;
void change(ll k,ll pos,ll x){
    while(pos<=cnt){
        C[k][pos]+=x;
        C[k][pos]%=1000000007;
        pos+=(pos&-pos);
    }
}
ll sum(ll k,ll n){
    ll ss=0;
    while(n>0){
        ss=(ss+C[k][n])%1000000007;
        n-=(n&-n);
    }
    return ss;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll n,i,j,k;
        scanf("%lld%lld",&n,&k);
        for(i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        cnt=unique(b+1,b+1+n)-b-1;
        for(i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+cnt,a[i])-b;
        for(i=0;i<=k;i++){
            for(j=0;j<=cnt;j++)C[i][j]=0;
        }
        ll ans=0;
        for(i=1;i<=n;i++){
            change(1,a[i],1);
            for(j=2;j<=k;j++){
                change(j,a[i],sum(j-1,cnt)-sum(j-1,a[i]));
            }
            ans=((ans+sum(k,a[i])-sum(k,a[i]-1))%1000000007+1000000007)%1000000007;
        }
        cout<<ans<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值