题目链接:http://oj.xjtuacm.com/problem/14/【分析】二元的逆序对应该都会求,可以用树状数组。这个题要求K元,我们可以看成二元的。我们先从后往前求二元逆序对数,
然后对于每一个数就可以求出在这个数后面的比他小的数的数量。然后我们再加一元时,当前扫到a[i],那么在树状数组中,对于那些比他大的数的 逆序对数+=上一元a[i]的逆序对数。
#include <bits/stdc++.h> #define met(a,b) memset(a,b,sizeof a) #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lowbit(x) (x&(-x)) using namespace std; typedef long long ll; ll mod = 1e9+7; const int N=2e4+50; const int M=N*N+10; int n,m,k,a[N]; ll tre[N],ans1[N],ans2[N]; void add(int x,ll s){ while(x<=n){ tre[x]+=s; tre[x]%=mod; x+=lowbit(x); } } ll Sum(int x){ ll ret=0; while(x>0){ ret+=tre[x]; ret%=mod; x-=lowbit(x); } return ret; } int main() { int u,v; int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]),ans2[i]=1; if(m==1){ printf("%d\n",n);continue; } for(int t=2;t<=k;t++){ for(int i=1;i<=n;i++)ans1[i]=ans2[i],ans2[i]=tre[i]=0; for(int i=n;i>=1;i--){ ans2[a[i]]=Sum(a[i]); add(a[i],ans1[a[i]]); } } ll ans=0; for(int i=1;i<=n;i++)ans=(ans+ans2[i])%mod; printf("%lld\n",ans); } return 0; }
时间: 2024-10-16 21:04:44