题意为 若存在 a中的数小于b中的数,b中的数小于c中的数 则该数算一种方案
思路
暴力模拟优化
两层循环遍历即可
从b到c的过程我们发现 第三层并不需要循环 直接加上 大于b的数量即可
那么第一层和第三层是对称的 我们有没有可能再去掉一层循环
只做一次遍历
可以的
直接以b为媒介
往上a层找小于b的元素个数
往下c层找大于b的元素个数
ans+=两者数量相乘即可
并且在两次查找 的过程中 我们可以使用二分来查找
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int a[N], b[N], c[N];
int main()
{
int n;
scanf("%d", &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);
LL res = 0; //答案可能会很大,会爆int
for (int i = 0; i < n; i++)
{
int l = 0, r = n - 1; //二分查找a数组中最后一个小于b[i]的数的下标
while (l < r)
{
int mid = (l + r + 1) / 2;
if (a[mid] < b[i]) {
l = mid;
}
else {
r = mid - 1;
}
}
if (a[l] >= b[i]) //如果未找到小于b[i]的数,将x标记为-1,后续计算时 x+1==0
{
l = -1;
}
int x = l;
l = 0, r = n - 1;
while (l < r)
{
int mid = (l + r) / 2;
if (c[mid] > b[i]) {
r = mid;
}
else {
l = mid + 1;
}
}
if (c[l] <= b[i]) //如果未找到大于b[i]的数,将y标记为n,后续计算时 n-y==0;
{
r = n;
}
int y = r;
res += (LL)(x + 1)*(n - y);
}
printf("%lld\n", res);
return 0;
}