题意:问你有多少个序列满足Ai < Aj > Ak and i < j < k.
思路:对每个数求它之前和之后分别有多少个个数比它小,两边相乘。最后求和。具体实现先用树状数组正序求,再反过来再用一遍树状数组。
代码:特别要注意的是题目中Ai的范围是从0开始,但是树状数组不能从0开始,所以统一加一处理。但是可惜的是题目并没有出现0这样的数据,让一些并不正确的代码过了。
1 #include<stdio.h> 2 #include<string.h> 3 int lowbit(int x) 4 { 5 return x&-x; 6 } 7 const int N=5e4+111,Max=32769; 8 int c[N],a[N],ans[N],n; 9 void add(int i,int x) 10 { 11 i++; 12 while(i<Max) 13 { 14 c[i]+=x; 15 i+=lowbit(i); 16 } 17 } 18 int q(int i) 19 { 20 i++; 21 int sum=0; 22 while(i) 23 { 24 sum+=c[i]; 25 i-=lowbit(i); 26 } 27 return sum; 28 } 29 int main() 30 { 31 while(scanf("%d",&n)!=EOF) 32 { 33 long long Ans=0; 34 memset(c,0,sizeof(c)); 35 for(int i=1;i<=n;i++) 36 { 37 scanf("%d",&a[i]); 38 ans[i]=q(a[i]-1); 39 add(a[i],1); 40 } 41 memset(c,0,sizeof(c)); 42 for(int i=n;i;i--) 43 { 44 Ans+=ans[i]*q(a[i]-1); 45 add(a[i],1); 46 } 47 printf("%lld ",Ans); 48 } 49 return 0; 50 }