藍橋杯 PREV-31 小朋友排隊(樹狀數組)

題目鏈接:

PREV-31 小朋友排隊

思路:

分析題意不難理解出某個人的移動次數爲(排在他前面比他高的人數+排在他後面比他矮的人數);
使用樹狀數組可以高效地計算得到上面兩項數據(使用時注意將每個人的身高加1,因爲有0身高的存在);
每個人的不高興程度就是ai(ai+1)2\frac{a_i(a_i+1)}{2},其中aia_i代表此人的移動次數;

代碼:

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章