堆箱子 - 二分+前缀和

题目

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值