Acwing_241樓蘭圖騰_樹狀數組

題目鏈接:https://www.acwing.com/problem/content/243/

解題思路:
由於輸入的序列是一個1 - n的一個排列,所以我們可以不用離散化,直接按照順序依次在樹狀數組中插入對於的數a[i], 然後每次插入前先詢問一次以得到左邊比這個數小的數的個數,然後 l_big = i - 1 - l_less, r_less = a[i] - 1 - l_less, r_big = n - a[i] - l_big;然後直接使用2個數進行累加即可。
注意點:
在lowbit, query, insert,的時候仔細一些,別寫錯了,剛開始我就是寫錯了一個變量,找了好久才找到了錯誤的地方(調試了好久)。
貼上代碼:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

typedef unsigned long long ULL;

const int maxn = 2e5 + 5;

int n;
int a[maxn], t[maxn];

inline int lowbit(int x) { 
	int y = -x;
	int tmp = x & y;
	return tmp; 
}

inline ULL query(int x) {
	ULL res = 0;
	while(x) {
		res += t[x];
		x -= lowbit(x);
	}
	
	return res;
}

inline void insert(int x) {
	int tmp = x;
	while(x <= n) {
		t[x] ++;
		x += lowbit(x); 
	}
}

int main(void) {
//	freopen("in.txt", "r", stdin);
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++)
		scanf("%d", &a[i]);
	
	ULL ans = 0, res = 0;
	ULL l_less, r_less, l_big, r_big;
	insert(a[1]); 
	for(int i = 2; i <= n - 1; i ++) {
		l_less = query(a[i]);
		l_big = i - 1 - l_less;
		r_less = a[i] - 1 - l_less;
		r_big = n - a[i] - l_big;
		
		ans = ans + l_big * r_big;
		res = res + l_less * r_less;
		
		insert(a[i]); 
	}

	printf("%lu %lu", ans, res);
		
	return 0;
}

總結:通過這道題目,我發現樹狀數組似乎就是一種優化後的前綴和數組,相當於是在前綴和的基礎上加上了二進制的思想,使得每次inser 和 query 的時間複雜度都是log n, 而前綴和的insert 的時間複雜度是 0(n), query的時間複雜度是0(1)。感覺就像是進行了一種平衡。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章