递增三元组
三种做法
给定三个整数数组
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。
对于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
3
1 2 3
2 3 5
3 4 5
【样例输出】
27
7
思路
思路很简单的一道题但想拿满分却不容易。
第一感觉肯定是直接三重循环暴力,看了一下范围,直接path。
然后思考怎样可以减少循环?
Ai < Bj < Ck
既然b数组在中间,可以设置两重循环,外面控制b,里面套a和c数组(计算数组b的每一个元素对映的小于它的a数组中有多少个元素,大于它的c数组中有多少元素),然后又想可以先排序,然后就可以继续减少循环
代码如下
#include<bits/stdc++.h>
using namespace std;
int a[100002],b[100002],c[100002],n,shang[100002],xia[100002];
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];
sort(a,a+n);
sort(b,b+n);
sort(c,c+n);
long long sum=0,i=n-1,j=n-1;
for(int i=0;i<n;i++)
{
int x=0,y=0;
for(int j=0;j<n;j++)
{
if(a[j]<b[i])
{
x++;
}
else
break;
}
for(int j=n-1;j>=0;j--)
{
if(c[j]>b[i])
{
y++;
}
else
break;
}
sum=sum+x*y;
}
cout<<sum;
return 0;
}
但是再看一下数据感觉肯定还会被爆,过60%没问题,估计运气好能混个80%,然后继续思考,不报的方法只有一重循环,那么怎么做?
我想到我已经给数组排序了,也就是说
举个例子:总数为n,如果a[i]中比b[j]小,那么有bshang[j]=i+1个数比b[j]小,
反之如果c[i]>b[j],那么有bxia[j]=n-i个数比b[j]大,最后再乘一下,就ok
#include<bits/stdc++.h>
using namespace std;
int a[100002],b[100002],c[100002],n,shang[100002],xia[100002];
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];
sort(a,a+n);
sort(b,b+n);
sort(c,c+n);
long long sum=0,i=n-1,j=n-1;
while(i>=0&&j>=0)
{
if(b[j]>a[i])
{shang[j]=i+1;
j--;
}
else
i--;
}
i=0,j=0;
while(i<n&&j<n)
{
if(c[i]>b[j])
{
sum=sum+(n-i)*shang[j]; //我这里直接边乘边加的结果了
j++;
}
else
i++;
}
cout<<sum;
return 0;
}
总的来说这道题还是很有意思,如果考试的话我认为想出来第二种就可以了,毕竟第三种实在是有点难想,考试没那么多时间,但练习就好好想想,对思维也是一种开阔