堆箱子 - 二分+前缀和

题目

Snuke Festival的季节今年又来了。首先,林戈将举行仪式来召唤斯库克。对于仪式,他需要一个祭坛​​,由三部分组成,三个部分分别为一个:上部,中部和下部。
他对这三个类别中的每一个都有N个部分。第i个上部的尺寸是Ai,第i个中部的尺寸是Bi,第i个下部的尺寸是Ci。
要建造一个祭坛,中间部分的大小必须严格大于上部的大小,下部的大小必须严格大于中间部分的大小。另一方面,满足这些条件的任何三个部分可以组合形成祭坛。
Ringo可以建造多少个不同的祭坛?这里,当使用的三个部分中的至少一个不同时,认为两个祭坛是不同的。

约束
1≤N≤10 5
1≤Ai≤10 9(1≤i≤N)
1≤Bi≤10 9(1≤i≤N)
1≤Ci≤10 9(1≤i≤N)
的所有输入值是整数。

输入

输入由标准输入以下列格式给出:

A1 ... AN 
B1 ... BN 
C1 ... CN

输出

打印Ringo可以构建的不同祭坛的数量。

样例输入


1 5
2 4
3 6

样例输出

3

提示

可以建造以下三个祭坛:
上部:第一部分,中部:第一部分,下部:第一部分
上部:第一部分,中部:第一部分,下部:第二部分
上部:第1部分,中部:第2部分,下部:第2部分


题解

也就是说我们考虑这样的一个问题

建造的祭坛是严格递增的。

我们考虑中部 和 下部 的方案数。对其进行一个前缀和的操作。

那么我们可以对上部箱子/中部箱子进行同样的操作,对满足条件的中部箱子累加前缀和即可。


代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
ll arr[3][maxn];
ll val[maxn];
int n;
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<3;i++) {
            for(int j=0;j<n;j++) scanf("%lld",&arr[i][j]);
            sort(arr[i],arr[i]+n);
        }
        ll res = 0;
        for(int i=0;i<n;i++) {
            val[i] = (ll)n - (upper_bound(arr[2],arr[2]+n,arr[1][i])-arr[2]);
            //printf("%lld\n",val[i]);
            if(i > 0) val[i] += val[i-1];
        }
        for(int i=0;i<n;i++) {
            int pos = upper_bound(arr[1],arr[1]+n,arr[0][i])-arr[1];
            res += val[n-1] - (pos > 0 ? val[pos-1] : 0);
        }
        printf("%lld\n",res);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38013346/article/details/81395064