第九届蓝桥杯B组第六题--递增三元组(C语言)

第九届蓝桥杯B组第六题–递增三元组(C语言)

一.比赛题目

1.题目要求

给定三个整数数组

A = [A1, A2, … AN],

B = [B1, B2, … BN],

C = [C1, C2, … CN],

请你统计有多少个三元组(i, j, k) 满足:

  1. 1 <= i, j, k <=N

  2. Ai < Bj < Ck

2.输入与输出

输入:
第一行包含一个整数N。

第二行包含N个整数A1, A2, … AN。

第三行包含N个整数B1, B2, … BN。

第四行包含N个整数C1, C2, … CN。

对于30%的数据,1 <= N <= 100

对于60%的数据,1 <= N <= 1000

对于100%的数据,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000

输出:
一个整数表示答案

样例输入:
3
1 1 1
2 2 2
3 3 3
样例输出:
27

二.分析过程

三元组最重要的是知道中间的元素,然后查找有多少小于它的元素和大于它的元素,就能够知道总共能组出多少个递增三元组

1.排序

对于递增三元组,首先我们需要分别将每个元素组排序才能够更好的去比较:
最方便快捷的就是使用快速排序,利用O(logn)的时间排好序;
下面我就用qsort函数进行排序演示:

int compare(const void *a,const void *b)
{
	return *(int *)a-*(int *)b; 
}


	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
	for(int i=0;i<n;i++)
		scanf("%d",&b[i]);
	for(int i=0;i<n;i++)
		scanf("%d",&c[i]);
	qsort(a,n,sizeof(int),compare);
	qsort(b,n,sizeof(int),compare);
	qsort(c,n,sizeof(int),compare);

2.比较

因为这道题的数据会达到10的5次方,所以利用顺序查找的话,时间复杂度是O(n2),这样的话就会超时;

所以我们利用二分查找进行时间上的优化:

要知道a数组里面有多少小于b[i]的值,也就是等价于找到第一个大于等于b[i]的元素位置;

要知道c数组里面有多少大于b[i]的值,也就是等价于找到最后一个小于等于b[i]的元素位置;

for(int i=0;i<=n-1;i++)
	{
		int low=0,high=n-1;
		while(low<=high){
			int mid=(low+high)/2;
			if(a[mid]<b[i])	low=mid+1;
			else	high=mid-1;	
		}
		int t1=high+1;
		//查找a数组里面第一个大于等于b[i]的元素位置
		//得到小于b[i]的元素个数
		low=0,high=n-1;
		while(low<=high){
			int mid=(low+high)/2;
			if(c[mid]<=b[i])	low=mid+1;
			else	high=mid-1;	
		}
		int t2=n-low;
		//查找c数组里面最后一个小于等于b[i]的元素位置
		//并用t2来计算n-小于等于的数,
		//得到大于b[i]的元素个数
	}

三.整体代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXN 100010
typedef long long ll;
int n;
int a[MAXN],b[MAXN],c[MAXN];
int compare(const void *a,const void *b)
{
	return *(int *)a-*(int *)b; 
}
int main()
{
	ll sum=0;
		//sum计算总数
	scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);
	for(int i=0;i<n;i++)
		scanf("%d",&b[i]);
	for(int i=0;i<n;i++)
		scanf("%d",&c[i]);
	qsort(a,n,sizeof(int),compare);
	qsort(b,n,sizeof(int),compare);
	qsort(c,n,sizeof(int),compare);
	//排序
	for(int i=0;i<=n-1;i++)
	{
		int low=0,high=n-1;
		while(low<=high){
			int mid=(low+high)/2;
			if(a[mid]<b[i])	low=mid+1;
			else	high=mid-1;	
		}
		int t1=high+1;
		
		low=0,high=n-1;
		while(low<=high){
			int mid=(low+high)/2;
			if(c[mid]<=b[i])	low=mid+1;
			else	high=mid-1;	
		}
		int t2=n-low;
		sum+=t1*t2;
	}
	//二分查找优化
	printf("%lld",sum);
	return 0;
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值