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)。感觉就像是进行了一种平衡。

发布了136 篇原创文章 · 获赞 0 · 访问量 2988

猜你喜欢

转载自blog.csdn.net/weixin_42596275/article/details/102559831
今日推荐