第九届蓝桥杯B组第六题–递增三元组(C语言)
一.比赛题目
1.题目要求
给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:
-
1 <= i, j, k <=N
-
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;
}