題目鏈接:
PREV-31 小朋友排隊
思路:
分析題意不難理解出某個人的移動次數爲(排在他前面比他高的人數+排在他後面比他矮的人數);
使用樹狀數組可以高效地計算得到上面兩項數據(使用時注意將每個人的身高加1,因爲有0身高的存在);
每個人的不高興程度就是,其中代表此人的移動次數;
代碼:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, top, h[maxn], bit[1000005];
long long cnt[maxn];
inline void add(int i) {
while(i <= top) ++bit[i], i += i & -i;
}
inline int sum(int i) {
int s = 0;
while(i) s += bit[i], i -= i & -i;
return s;
}
int main() {
#ifdef MyTest
freopen("Sakura.txt", "r", stdin);
#endif
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", &h[i]), ++h[i], top = max(top, h[i]);
for(int i = 1; i <= n; ++i) {
add(h[i]);
cnt[i] = i - sum(h[i]);
}
memset(bit, 0, sizeof(bit));
for(int i = n; i >= 1; --i) {
add(h[i]);
cnt[i] += sum(h[i] - 1);
}
long long ans = 0;
for(int i = 1; i <= n; i++) ans += (cnt[i] + 1) * cnt[i] >> 1;
printf("%lld", ans);
return 0;
}