蓝桥杯:递增三元组

这道题可以用两种方法解,分别是快排+二分+前缀和,以及快排+双指针+前缀和,前者的思维难度较简单,但代码长,后者思维难度大,但代码短,那么我先来介绍快排+二分+前缀和;

思路如下:

1:可以发现数组的位置信息对答案没有影响,所以我们可以用讲数组排序,故sort3个数组

2:另外我们可以用额外的数组rcod[j]记录B[j]大于A数组中的多少个数字,这个可以用二分找到对应的下标;

3:将rcod进行前缀和处理;

4:对C、B数组进行与第二部相同的处理,并用变量ans存储答案,每次找到满足C[j]>B[i]的下标i,然后ans+=rcod[i];

下面是具体代码

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 100010;

long long a[N], b[N], c[N];
long long n, ans;
long long rcod[N];


int two(int x) {


	int l = 0, r = n;

	while (l < r) {

		int mid = l + r + 1 >> 1;

		if (a[mid] < x) l = mid;
		else r = mid - 1;

	}
	return l;

}

void get() {

	for (int i = 1; i <= n; i++)
	{

		int p;

		p = two(b[i]);//二分找下标
		rcod[i] = p;

	}

}


int main() {

	cin >> n;

	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	for (int i = 1; i <= n; i++) scanf("%lld", &b[i]);
	for (int i = 1; i <= n; i++) scanf("%lld", &c[i]);

	sort(a + 1, a + 1 + n); sort(b + 1, b + 1 + n); sort(c + 1, c + 1 + n);//进行排序

	get();//创建rcod数组

	for (int i = 1; i <= n; i++)//将数组进行前缀和处理
		rcod[i] += rcod[i - 1];

	for (int i = 1; i <= n; i++) {

		int l = 0, r = n;

		while (l < r) {//二分找下标

			int mid = l + r + 1 >> 1;

			if (b[mid] < c[i]) l = mid;
			else r = mid - 1;


		}

		ans += rcod[r];//累加结果

	}

	cout << ans;

}

然后是快排+双指针+前缀和;

思路如下:

1:排序;

2:利用单调性,使用双指针创建rcod数组;

3:同样利用单调性找到满足C[j]>B[i]的下标i,然后ans+=rcod[i];

代码如下;

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 100010;

long long a[N], b[N], c[N];
long long n, ans;
long long rcod[N];

int main() {

	cin >> n;

	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	for (int i = 1; i <= n; i++) scanf("%lld", &b[i]);
	for (int i = 1; i <= n; i++) scanf("%lld", &c[i]);

	sort(a + 1, a + 1 + n); sort(b + 1, b + 1 + n); sort(c + 1, c + 1 + n);


	for (int i = 1, j = 1; j <= n; j++) {//双指针创建rcod数组

		while (a[i] < b[j] && i <= n) i++;
		rcod[j] = i - 1;


	}

	for (int i = 1; i <= n; i++) rcod[i] += rcod[i - 1];//前缀和处理

	for (int i = 1, j = 1; j <= n; j++)//双指针找到对应下标
	{
		while (b[i] < c[j] && i <= n) i++;


		ans += rcod[i - 1];


	}

	cout << ans;

}

在这里我再说一下我对双指针的理解吧;

这里双指针的所以条件为”单调性“,即某一种状态可以通过另外一种状态进行一次运算得到,有点像线性dp......

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值