原题链接:蓝桥杯2018年第九届真题-递增三元组
做法1:暴力枚举
首先考虑暴力做法,三个数组嵌套枚举,O(n3)的时间复杂度
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
using ll=long long;
const int N=1e5+10;
int a[N],b[N],c[N];
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;cin>>n;
int res=0;
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];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
if(a[i]<b[j]&&b[j]<c[k])
res++;
}
}
}
cout<<res;
return 0;
}尝试通过枚举的次序进行优化本题,先枚举B数组,在A中寻找小于B[i]的数的个数cnt1,在C中寻找大于B[i]的数的个数cnt2,带有B[i]的合法选择数就是cnt1*cnt2。
//前缀和优化
#include <iostream>
#include <string.h>
using namespace std;
const int N=100005;
int n,a[N],b[N],c[N];
int cnt=0;
int num[N],s[N];
int as[N],cs[N];
int main(){
cin>>n;//输入
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<n;i++) cin>>c[i];
//处理as
for(int i=0;i<n;i++) num[a[i]]++;// 记录a[i]出现的次数
for(int i=0;i<=N;i++) s[i]=s[i-1]+num[i];// 递推求得关于a[i]的所有前缀和s[i]
for(int i=0;i<n;i++) as[i]=s[b[i]-1];// as代表比b[i]小的数的前缀和
//还原数组
memset(num,0,sizeof(num));
memset(s,0,sizeof(s));
//处理cs
for(int i=0;i<n;i++) num[c[i]]++;// 记录c[i]出现的次数
for(int i=0;i<=N;i++) s[i]=s[i-1]+num[i];// 递推求得关于c[i]的所有前缀和s[i]
for(int i=0;i<n;i++) cs[i]=s[N]-s[b[i]];// cs代表比b[i]大的数的前缀和;
//注意不能是s[N-b[i]],这样求得的是从0到N-b[i]的前缀和,不是b[i]到N的前缀和
//求结果
long long res=0;// 数据量较大,用long long
for(int i=0;i<n;i++)
res+=(long long)as[i]*cs[i];
cout<<res<<endl;
return 0;
} 0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复