递增三元组个数(树状数组解法)

递增三元组个数的三种思路(附代码)

问题描述

这是蓝桥杯模拟赛的一道题目,给定数列,寻找递增三元组的数目,具体如下图:
在这里插入图片描述

思路

  1. 穷举所有三元组,检查是否符合a_i < a_j < a_k ,符合则count+=1,时间复杂度为O(n^3),只能过50%的点
  2. 对a_i,遍历其左边的数,比它小则 pre[i] += 1,比它大则 post[i] += 1 ,最后求 pre[i] * post[i] 即以 i 为中心的三元组个数, 复杂度为O(n^2) , 只能过80% 的点
  3. 观察思路2,我们发现每次求pre[i]和post[i]我们需要花O(n)的复杂度,这一步可以使用树状数组来优化,时间复杂度为O(nlogn) , 详见代码注释

代码

思路2 O(n^2)

#include<iostream>
using namespace std;
const int maxn = 1e5 + 7; 
int a[maxn]; //输入的数据
long long pre[maxn], post[maxn];//数k的左边有多少个数,右边有多少个数
long long ans=0;//递增三元组个数
int main()
{
	int n; cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j < i; j++) {
			if (a[j] < a[i]) pre[i]++;
		}
		for (int j = i + 1; j <= n; j++) {
			if (a[j] > a[i]) post[i]++;
		}
	}
	for (int i = 1; i <= n; i++) {
		ans += pre[i] * post[i];
	}
	cout << ans;
	return 0;
}

思路3 O(nlogn)

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1e5 + 7; 
int a[maxn]; //输入的数据
long long pre[maxn], post[maxn];//数k的左边有多少个数,右边有多少个数
const int maxn2=100 + 7;//数值范围1~100
int C[maxn];//部分和
long long ans=0;//递增三元组个数
int lowbit(int x) { return x & -x; }
int sum(int x) {
	int res = 0;
	while (x > 0) {
		res += C[x];
		x -= lowbit(x);
	}
	return res;
}
void update(int x) {
	while (x <= maxn2) {
		x += lowbit(x);
		C[x] += 1;
	}
}
int main()
{
	int n; cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	//在线处理,从左往右看
	memset(C, 0, sizeof(C));
	for (int i = 1; i <= n; i++) {
		pre[i] = sum(a[i] - 1);//数值为1~(a[i]-1)的元素个数
		update(a[i]);
	}
	memset(C, 0, sizeof(C));
	//从右往左看
	for (int i = n; i >=1; i--) {
		int x1 = sum(maxn2);
		int x2 = sum(a[i] + 1);
		post[i] = x1-x2;//数值为(a[i]+1)~maxn的元素个数
		update(a[i]);
	}
	for (int i = 1; i <= n; i++) {
		ans += pre[i] * post[i];
	}
	cout << ans;
	return 0;
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值