蓝桥杯 递增三元组

给定三个整数数组

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。

输出格式
一个整数表示答案。

数据范围
1≤N≤105,
0≤Ai,Bi,Ci≤105
输入样例:
3
1 1 1
2 2 2
3 3 3
输出样例:
27
思路 就枚举b[i] 看看a[i]中有多少个数小于b[i],在看看c[i]中有多少个数大于b[i],让他俩相乘即可,这里用到乘法原理

//前缀和算法
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],b[N],c[N];
int s[N],cnt[N];
long long res;
int ac[N],cc[N];//ac[i]表示a数组中用多少个数小于b[i],cc[i]表示c数组中有多少个数大于b[i];
int n;
int main(){
    cin >> n;
    for(int i=0;i<n;i++) cin >> a[i],a[i]++;//+1防止下面出现负的下标
    for(int i=0;i<n;i++) cin >> b[i],b[i]++;
    for(int i=0;i<n;i++) cin >> c[i],c[i]++;
    for(int i=0;i<n;i++) cnt[a[i]]++; //比如cnt[6]=2,它就表示a数组中有2个数为6;
    for(int i=1;i<N;i++) s[i]=s[i-1]+cnt[i];//s[8]=3,就表示CNT数组的前缀和,前8个数的和为3,
        //也就是说a数组中小于等于8的数有3个,
    for(int i=0;i<n;i++) ac[i]=s[b[i]-1];  //比如b[i]=8,b[i]-1=7,s[7]就表示a数组中小于等于7的数有几个
    memset(s,0,sizeof s);
    memset(cnt,0,sizeof cnt);
    for(int i=0;i<n;i++) cnt[c[i]]++;
    for(int i=1;i<N;i++) s[i]=s[i-1]+cnt[i];
    for(int i=0;i<n;i++) cc[i]=s[N-1]-s[b[i]];
    for(int i=0;i<n;i++) res+=(long long)ac[i]*cc[i];
    cout << res;
    return 0;
}
二分也能做,挺简单的


#include<bits/stdc++.h>
using namespace std;
#define int long long
//先排序,然后预处理一下看b中的第bi个元素在a中有多少个比它小的,
//同理,预处理一下c中第ci个元素在b中有多少个比它小的然后相乘再累加即可
const int N=1e5+10;
int n;
int a[N],b[N],c[N];
int cntb[N],cntc[N];//cntb[i]=j 表示 a中有j个元素比b中的第i个元素小
//                    cntc[i]=j 表示 c中有j个元素比b中的第i个元素大 
//我们要找的是在b中第i个元素有多少个c中的元素比它大,即找到大于它的最小值
signed main(){
    cin >> n;
    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];
    }
    sort(a+1,a+n+1);
    sort(b+1,b+n+1);
    sort(c+1,c+n+1);
    for(int i=1;i<=n;i++){
        int l=1,r=n;
        while(l<r){
            int mid=(l+r+1)>>1;
            if(b[i]>a[mid]){
                l=mid;
            }
            else {
                r=mid-1;
            }
        }
        if(a[l]>=b[i]){
            cntb[i]=0;
        }
        else cntb[i]=l;
     //   cout << cntb[i] << " ";
    }
   // cout << endl;
    for(int i=1;i<=n;i++){
        int l=1,r=n;
        while(l<r){
            int mid=l+r>>1;
            if(b[i]<c[mid]){
                r=mid;
            }
            else {
                l=mid+1;
            }
        }
        if(b[i]>=c[l]) cntc[i]=0;
        else cntc[i]=n-l+1;
      //  cout << cntc[i] << " ";
    }
 //   cout << endl;
    int res=0;
    for(int i=1;i<=n;i++){
        res+=cntb[i]*cntc[i];
    }
    cout << res;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值