1. 程式人生 > >樹狀陣列(LA4329,UVaLive4329,Ping pong)

樹狀陣列(LA4329,UVaLive4329,Ping pong)

通過這題,對樹狀陣列稍微有了一點模糊的認識,不過還是不太懂。。。(這題做的真的心累。。。最後參考別人的程式碼才A了的)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 20000 + 5;
const int maxg = 100000 + 5;
 
int a[maxn];
int c[maxn];//i左邊 比i等級低的個數
int d[maxn];//i右邊 比i頂級低的個數
int C[maxg];//輔助陣列 
int n; 

//void print_x() {  //列印x 
//	cout << "x[i] = ";
//	for(int i = 1; i <= n; i++) {
//		  cout << x[i] << " ";
//	}
//	cout << endl;
//}
//
//void print_C() { //列印C
//	cout << "C[i] = ";
//	for(int i = 1; i <= n; i++) {
//		cout << C[i] << " ";
//	} 
//	cout << endl;
//} 

int lowbit(int i) {
	return i&(-i);
}

int sum(int i) {
	int ret = 0;
	while(i > 0) {
		ret += C[i];
		i -= lowbit(i);
	}
	return ret;
}

void add(int i,int d) {
	while(i <= maxg-1){   //對於等級  而不是對於選手 
		C[i] += d;
		i += lowbit(i);
	}
}

int main() {
	int T;
	cin >> T;
	while(T--) {
		cin >> n;
		for(int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		memset(C, 0, sizeof(C));
		for(int i = 1; i <= n; i++) {//從左往右掃描 
			c[i] = sum(a[i]-1);  //i左邊等級比i等級低的總和
			add(a[i], 1);   //將存在的等級  加入輔助陣列C中 
		}
		memset(C, 0, sizeof(C)); 
		for(int i = n; i >= 1; i--) { 
			d[i] = sum(a[i]-1); 
			add(a[i], 1); 
		}
		long long ans = 0;
		for(int i = 2; i <= n-1; i++) 
			ans += c[i]*(n-i-d[i]) + (i-1-c[i])*d[i]; 
		cout << ans << endl;
	}
	return 0;
}