试题 历届真题 递增三元组【第九届】【省赛】【B组】

40 阅读1分钟

 本题最简单的思路就是使用3个for循环嵌套一个一个去找, 这也是我的第一思路,但是这样的暴力算法并不能通过所有的样例,只能得到75分,原因是超时,即算法不佳,愚昧的我也未能再相出其他算法~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#include<stdio.h>
using namespace std;

int A[100005];
int B[100005];
int C[100005];

int main()
{
	int  n,cn=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&A[i]);
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&B[i]);
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&C[i]);
	}
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int z=1;z<=n;z++)
			{
				if(A[i]<B[j]&&A[i]<C[z]&&B[j]<C[z])
				{
					cn++;
				}
			}
		}
	}		
	printf("%d",cn);
	return 0;
}

下面给出题解(利用排列组合中的乘法原理)

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

const int MAX = 100005;
int n,a[MAX],b[MAX],c[MAX];
typedef long long LL;
LL sum;
int main(){
 cin>>n;
 for(int i=1;i<=n;i++) cin>>a[i];
 for(int i=1;i<=n;i++) cin>>b[i];
 for(int i=1;i<=n;i++) cin>>c[i];
 sort(a+1,a+n+1);
 sort(c+1,c+n+1);//注意这里的排序区间前后 
 for(int i=1;i<=n;i++){
  LL x = (lower_bound(a + 1, a + n + 1, b[i]) - a) - 1;//这里的lower_bound是返回第一个>=b[i]的指针,如果找不到,则返回能放下b[i]的指针, 即返回a+n+1,故((a+n+1)-a)-1=n 
  LL y = n - (upper_bound(c + 1, c + n + 1, b[i]) - c) + 1;
  //upper_bound是返回第一个>b[i]的指针, 如果找不到,则返回能放下b[i]的指针,因为排过序,如果第一个c+1就大于b[i],则相当于整个c数组都大于b[i],所以需要n-(n-1)+1=n 
  sum += x*y;//是利用排列组合的乘法原理 
 }
 cout<<sum<<endl;
 return 0;
}

这里的lower_bound是返回第一个>=b[i]的指针,如果找不到,则返回能放下b[i]的指针, 即返回a+n+1,故((a+n+1)-a)-1=n

upper_bound是返回第一个>b[i]的指针, 如果找不到,则返回能放下b[i]的指针,因为排过序,如果第一个c+1就大于b[i],则相当于整个c数组都大于b[i],所以需要n-(n-1)+1=n