你好呀,我是灰小猿,一个超会写bug的程序猿!
欢迎大家关注我的专栏“每日蓝桥”,该专栏的主要作用是和大家分享近几年蓝桥杯省赛及决赛等真题,解析其中存在的算法思想、数据结构等内容,帮助大家学习到更多的知识和技术!
标题:递增三元组
给定三个整数数组
A=[A1,A2,…AN],
B=[B1,B2,…BN],
C=[C1,C2,…CN],请你统计有多少个三元组 (i,j,k)
满足:
- 1≤i,j,k≤N
- Ai<Bj<Ck
输入格式
第一行包含一个整数 N。
第二行包含 N个整数 A1,A2,…AN。
第三行包含 N个整数 B1,B2,…BN。
第四行包含 N个整数 C1,C2,…CN。
输出格式
一个整数表示答案。
数据范围
1≤N≤10^5
0≤Ai,Bi,Ci≤10^5输入样例:
3
1 1 1
2 2 2
3 3 3
输出样例:
27
资源约定: .
峰值内存消耗(含虚拟机) < 256M
CPU消耗< 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“ 请您输...”的多余内容.
所有代码放在同-一个源文件中,调试通过后,拷贝提交该源码.
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是: Main, 否则按无效代码处理.
解题思路
本题在求解上主要还是要理解题意,对于这样一个在三个数组中找结果的提醒,很多同学想到的第一个思路应该就是遍历三个数组进行求解,在理论上这种方法是可行的,但是只是对于少量的数据,对于题中所给的数据,10^5遍历三次也就是10的15次方,这个数据是十分庞大的,所以对于该题来说是行不通的,那么我们其实可以想办法对这种方法进行优化,尽可能的减少遍历的次数。
其实对于这个题的其他解法是:用数组A[i]中对应的数后面找到一个对应B数组的一段数据,再用B[i]找出C数组中符合要求的数据。用下图来表示:
另一种解法,以B数组中的元素为参考,找出A数组中小于B数组的元素数量p,再找出C数组中大于B数组的元素数量q,则对于B[i]符合要求的数据数就是p*q个:但是这种方法在运算时,每对ans答案增加一次时,都要乘以1L,原因是因为数据在很大的时候是需要变成long型的,关于1L的解释入下:
java中经常会碰到“long c = 1L”的写法,L表示long ,long占用8个字节,表示范围:-9223372036854775808 ~ 9223372036854775807
1L其实就是1。
常量后面跟这个一般是指类型,1L表示1是长整型,如果是1f 表示是float型关于这一种解法如下图:
但是该解法最后对于超大量数据是不符合要求的,尝试了很多次还是不行,不知道是为什么,但是思路结构和第二种方法差不多,但是第二种方法就是正确答案,有些疑惑,知道为什么的小伙伴可以留言一起解答,下面把这两种解法的代码都奉上:
答案源码:
第一种解法(大量数据时运算有误)
package 一八年省赛真题; import java.sql.Array; import java.util.Arrays; import java.util.Scanner; public class Year2018_Bt6 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int N = scanner.nextInt(); int [] A = new int[N]; int [] B = new int[N]; int [] C = new int[N]; for (int i = 0; i < N; i++) { A[i] = scanner.nextInt(); } for (int i = 0; i < N; i++) { B[i] = scanner.nextInt(); } for (int i = 0; i < N; i++) { C[i] = scanner.nextInt(); } //对输入的三个数组进行升序排列 Arrays.sort(A); Arrays.sort(B); Arrays.sort(C); long ans = 0; int p = 0,q = 0; //定义一个p,q来分别表示在数组B,C中从哪一位开始的数是大于前一个数组对应数的 for (int i = 0; i < N; i++) { //找出第一个大于A[i]的数 while(p<N && A[i]>=B[p]) p++; int cq = 0; //将B数组中剩下的数进行遍历 for (int j = p; j < N; j++) { //找出第一个大于B[j]的数 while(q<N && B[j]>=C[q]) q++; //记录下每一次的起始数,为了减少下次遍历 if(j == p) cq=q; ans += (N-q); } q=cq; } System.out.println(ans); } }
第二种解法(完全正确)
package 一八年省赛真题; import java.util.Arrays; import java.util.Scanner; public class Year2018_Bt6_2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int N = scanner.nextInt(); int [] A = new int[N]; int [] B = new int[N]; int [] C = new int[N]; for (int i = 0; i < N; i++) { A[i] = scanner.nextInt(); } for (int i = 0; i < N; i++) { B[i] = scanner.nextInt(); } for (int i = 0; i < N; i++) { C[i] = scanner.nextInt(); } //对输入的三个数组进行升序排列 Arrays.sort(A); Arrays.sort(B); Arrays.sort(C); int p = 0, q = 0; long ans = 0; //由于数据比较大,所以定义为long型 for (int i = 0; i < N; i++) { while(p<N && A[p]<B[i]) p++; while(q<N && B[i]>=C[q]) q++; ans += 1L*p*(N-q); //乘以1L的目的是为了让结果称为long型 } System.out.println(ans); } }
输出样例: