第九届蓝桥杯C++B组-递增三元组

A=[A1,A2,…AN], 
B=[B1,B2,…BN], 
C=[C1,C2,…CN],

请你统计有多少个三元组 (i,j,k) 满足:

  1. 1≤i,j,k≤N
  2. 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

暴力做法:

#include<iostream> // 输入输出操作
#include<cstdio> // 输入输出函数
#include<algorithm> // 标准排序函数
#include<cstring> // 字符串处理函数
using namespace std;

typedef long long LL; // 将 long long 定义为 LL
const int N=1e5+10; // 将常量 N 定义为 1e5+10

int n; // 元素个数
int a[N], b[N], c[N]; // 元素数组

signed main()
{
    cin>>n; // 输入 n 的值
    for(int i=0;i<n;i++) scanf("%d", &a[i]); // 输入数组 a 的元素
    for(int i=0;i<n;i++) scanf("%d", &b[i]); // 输入数组 b 的元素
    for(int i=0;i<n;i++) scanf("%d", &c[i]); // 输入数组 c 的元素

    LL res=0; // 将结果初始化为 0
    for(int i=0;i<n;i++) {
        int count_a = 0, count_c = 0;
        for(int j=0;j<n;j++) {
            if(a[j] < b[i]) count_a++;
            if(c[j] > b[i]) count_c++;
        }
        res += (LL)count_a * count_c;
    }

    cout<<res<<endl; // 输出结果
}

 前缀和

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n;
int a[N], b[N], c[N];
int s[N], aa[N], cc[N];
int main()
{
    cin>>n;
    //s前缀和数组,是以值为下标,在那一位置加一
    for(int i=0;i<n;i++) scanf("%d", &a[i]), a[i]++;//前缀和下表从1开始
    for(int i=0;i<n;i++) scanf("%d", &b[i]), b[i]++;
    for(int i=0;i<n;i++) scanf("%d", &c[i]), c[i]++;

    for(int i=0;i<n;i++) s[a[i]]++;//s数组存的是a值在这一位置的数
    for(int i=1;i<N;i++) s[i]+=s[i-1];
    for(int i=0;i<n;i++) aa[i]=s[b[i]-1];//aa存储的是当前下标,小于b[i]的数的个数,即为s[b[i]-1]

    memset(s, 0, sizeof s);
    for(int i=0;i<n;i++) s[c[i]]++;
    for(int i=1;i<N;i++) s[i]+=s[i-1];
    for(int i=0;i<n;i++) cc[i]=s[N-1]-s[b[i]];
    LL res=0;
    for(int i=0;i<n;i++) res+=(LL)aa[i]*cc[i];//枚举b
    cout<<res<<endl;
    return 0;
}
这个代码的思路是为了解决一个特定的问题,即在给定的三个数组 `a`, `b`, `c` 中,找到满足条件 `a[i] < b[j] < c[k]` 的元素对 `(i, j, k)` 的数量。这个思路的核心在于使用前缀和来优化查找过程,使得对于每个 `b[j]`,我们能够快速找到所有满足条件的 `a[i]` 和 `c[k]`。

 

代码解释:
1. **前缀和数组的应用**:
   - 代码使用前缀和数组 `s` 来记录每个值在数组 `a` 和 `c` 中出现的次数。前缀和数组 `s` 的索引代表值,而 `s[i]` 代表值小于等于 `i` 的元素个数。
   - 通过前缀和,我们可以快速计算任意区间内元素的个数,这对于统计满足条件的元素对非常有效。
2. **处理数组 `a` 和 `c`**:
   - 首先,代码读取数组 `a` 和 `c` 的元素,并对每个元素加一,这是因为前缀和数组 `s` 的索引从 `1` 开始。
   - 然后,代码更新前缀和数组 `s`,使得 `s[a[i]]` 和 `s[c[i]]` 增加 `1`,表示值 `a[i]` 和 `c[i]` 出现了 `1` 次。
   - 接着,计算 `s` 的累积和,这样 `s[i]` 就存储了值小于等于 `i` 的元素个数。
3. **计算 `aa` 和 `cc` 数组**:
   - 对于数组 `b`,代码计算 `aa[i]`,即小于 `b[i]` 的元素个数,通过 `s[b[i]-1]` 获取。
   - 对于数组 `c`,代码计算 `cc[i]`,即大于 `b[i]` 的元素个数,通过 `s[N-1]-s[b[i]]` 获取。
4. **计算结果**:
   - 最后,代码遍历数组 `b`,对于每个 `b[j]`,计算满足条件的 `a[i]` 和 `c[k]` 的对数,即 `aa[j] * cc[j]`,并将这些对数累加到结果变量 `res` 中。
5. **输出结果**:
   - 代码输出最终的结果 `res`,即满足 `a[i] < b[j] < c[k]` 的元素对 `(i, j, k)` 的总数。


这个思路之所以有效,是因为它利用了前缀和数组来快速计算区间内元素的个数,从而避免了嵌套循环,大大提高了算法的效率。此外,通过清零并重用前缀和数组 `s`,代码还优化了空间复杂度。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值