http://acm.timus.ru/problem.aspx?space=1&num=1523
Consider a permutation a1, a2, …, an (all ai are different integers in range from 1 to n). Let us call k-inversion a sequence of numbers i1, i2, …, ik such that 1 ≤ i1 < i2 < … < ik ≤ n and ai1 > ai2 > … > aik. Your task is to evaluate the number of different k-inversions in a given permutation.
Input
The first line of the input contains two integers n and k (1 ≤ n ≤ 20000, 2 ≤ k ≤ 10). The second line is filled with n numbers ai.
Output
Output a single number — the number of k-inversions in a given permutation. The number must be taken modulo 109.
Samples
input | output |
---|---|
3 2 3 1 2 |
2 |
5 3 5 4 3 2 1 |
10 |
求k-1次逆序数,树状数组的应用
//关键在于理解求逆序数的含义
//其实求一次逆序就是求2个递减数对个数
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 20001 #define M 1000000000 int now,n,k; int a[N],c[N],d[2][N]; int low(int x) { return x&(-x); } void modify(int x,int v) { for(;x<=n;x+=low(x)) c[x]=(c[x]+v)%M; } int query(int x) { int sum=0; for(;x>0;x-=low(x)) sum=(sum+c[x])%M; return sum; } int main() { int temp,sum; while(scanf("%d %d",&n,&k)!=EOF) { now=0; for(int i=1;i<=n;i++) d[1][i]=1,scanf("%d",a+i); for(int i=1;i<k;i++,now^=1) { memset(c,0,sizeof(c)); sum=0; for(int j=i;j<=n;j++) { sum=(sum+d[now^1][j])%M; modify(a[j],d[now^1][j]); temp=query(a[j]); if(sum<=temp) sum+=M; d[now][j]=sum-temp; if(sum>M) sum-=M;//开始这里忘记减回去了、WA了 } } sum=0; for(int i=k;i<=n;i++) sum=(sum+d[now^1][i])%M; printf("%d\n",sum); } return 0; }