http://poj.org/problem?id=3928
題目大意是一條大街上住著n個乒乓球愛好者,他們的水平高低用一個數值表示,他們經常舉辦比賽,比賽要三個人,一人當裁判。對裁判是有一定要求的,裁判的水平必須介於兩選手之間且必須住他們中間,計算可以舉辦多少場比賽
#include<stdio.h>#include<string.h>#define maxn 100005int c[20050]; //存放比比第i個人技能值低的人數 int xt[200050]; //樹狀數組int a[10050]; //存放每個人的技能值int n;int lowbit(int x){return x & (-x);}//一看到這個函數就知道是樹狀數組void update(int x){while(x <= maxn){xt[x] += 1;x += lowbit(x);}}//每次更新節點的時候只增加1int sum(int x){int s = 0;while(x > 0){s += xt[x];x -= lowbit(x);}return s;} //因為更新的時候數組元素的值只增加了1,所以返回的值是小於等於x的數的個數int main(){int i, j, t;__int64 ans;//結果的可能值超出1<<32, 開始wa了一次scanf("%d",&t);while(t--){memset(c,0,sizeof(c));memset(xt,0,sizeof(xt));scanf("%d",&n);for(i = 1;i <= n;i++){scanf("%d",&a[i]);update(a[i]);c[i] = sum(a[i] - 1); //因為可能有多個人的技能值是相同的,所以不能在最後計算i的左邊比a[i]小的人數}ans = 0;//別忘了初始化//我考慮第i個人做裁判的時候可能的比賽,累加得結果for(i = 2;i < n;i++){ans += (c[i]) * ((n - i) - (sum(a[i]) - c[i] - 1));//當i做裁判時i左邊有c[i]人小於a[i](前面已經計算出來了),sum(a[i]) - c[i] - 1)是i的右邊比a[i]大的人數 ans += (i - 1 - c[i]) * (sum(a[i]) - c[i] - 1);//在i 的左邊比a[i]大的有i - 1 - c[i]人,(sum(a[i]) - c[i] - 1)是i右邊比a[i]大的人數}printf("%I64d\n",ans);}return 0;}