找出i<j<k且a[i]<a[k]<a[j] 的个数。
先求出x>y(z)的个数,再求出x>y>z的个数。(small[i]记录当前 1—i-1元素间比a[i]小的个数,high[i]记录当前i+1—n元素比a[i]大的个数),那么x>y>z的个数就为 small[i]*high[i]....
small可以用树状数组求出来!!!!
题意:给你一个1到n的排列,让求满足posx < posy < posz && x < z < y 的组数有多少。
思路:树状数组的题目。首先我们可以得到所有满足题目条件的组数为x < y ? z 减去 x < y < z的数目。其中x < y ? z 是x < y ,但是y 与 z的关系不知道,x 与z 的关系也不知道。假设第i个数后面有n个数比它大,则x < y ? z 的组数为C(n,2),x < y < z的组数可以 用树状数组算出来。
2 6 1 3 2 6 5 4 5 3 5 2 4 1
Case #1: 10 Case #2: 1
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n; const int maxn=111111; int a[maxn],b[maxn]; __int64 small[maxn],high[maxn]; void update(int x,int num) { while(x<=n){ a[x]+=num; x+=x&(-x); } } __int64 getsum(int x) { __int64 s=0; while(x>0){ s+=a[x]; x-=x&(-x); } return s; } int main() { int i,j,t; __int64 ans; while(scanf("%d",&t)!=EOF){ for(int _=1;_<=t;_++){ memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); scanf("%d",&n); ans=0; for(i=1;i<=n;i++){ scanf("%d",&b[i]); small[i]=getsum(b[i]); high[i]=n-b[i]-(i-1-small[i]); update(b[i],1); } for(i=1;i<=n;i++){ ans+=high[i]*(high[i]-1)/2-small[i]*high[i]; } printf("Case #%d: %d\n",_,ans%100000007); } } return 0; }