UVA1428 - Ping pong(樹狀數(shù)組)
題目鏈接
題目大意:有N個人,每個人都有一個技能值ai,現(xiàn)在要開展乒乓球比賽,要求要有兩個選手和一個裁判,要求裁判需要在兩名選手的中間而且技能值也是在兩名選手的中間,問可以開展多少場比賽。
解題思路:對于第i個選手當裁判的話,設它前面位置的選手有ci個技能值比它低的,那么就有i - 1 - ci個比它高的,對于第i選手后面的位置,同樣有di個技能值比它低的,那么就有N - i - di個比它高的。組合一下:ci?(N - i - di) + (i - 1 - ci) ? di.那么對于ci的值,根據(jù)i的位置,將Xi標為0或者1(在i位置前面就是1,后面就是0)。di類似求得。
代碼:
#include <cstdio>
#include <cstring>
const int maxn = 1e5 + 5;
const int N = 2e4 + 5;
typedef long long ll;
int C[maxn];
int A[maxn];
ll c[N], d[N];
int lowbit(int x) { return x&-x; }
void Add (int x, int d) {
while (x < maxn) {
C[x] += d;
x += lowbit(x);
}
}
int Sum (int x) {
int ret = 0;
while (x > 0) {
ret += C[x];
x -= lowbit(x);
}
return ret;
}
void init () {
memset (C, 0, sizeof (C));
}
int main () {
int T;
int n;
int num[N];
scanf ("%d", &T);
while (T--) {
scanf ("%d", &n);
init();
for (int i = 0; i < n; i++) {
scanf ("%d", &num[i]);
Add(num[i], 1);
c[i] = Sum (num[i]) - 1;
}
init();
for (int i = n - 1; i >= 0; i--) {
Add(num[i], 1);
d[i] = Sum (num[i]) - 1;
}
ll ans = 0;
for (int i = 0; i < n; i++) {
// printf ("%lld %lld
", c[i], d[i]);
ans += c[i] * (n - i - 1 - d[i]) + (i - c[i]) * d[i];
}
printf ("%lld
", ans);
}
return 0;
}
下一篇 談談分布式計算的算子層