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

原题链接:https://www.acwing.com/problem/content/description/1238/

时/空限制:1s / 64MB

给定三个整数数组

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

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

  1. 1≤i,j,k≤N1≤i,j,k≤N
  2. Ai<Bj<CkAi<Bj<Ck

输入格式

第一行包含一个整数 NN。

第二行包含 NN 个整数 A1,A2,…ANA1,A2,…AN。

第三行包含 NN 个整数 B1,B2,…BNB1,B2,…BN。

第四行包含 NN 个整数 C1,C2,…CNC1,C2,…CN。

输出格式

一个整数表示答案。

数据范围

1≤N≤1051≤N≤105,
0≤Ai,Bi,Ci≤1050≤Ai,Bi,Ci≤105

输入样例:

3
1 1 1
2 2 2
3 3 3

输出样例:

27

思路:枚举或者二分。

 二分:

#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int N = 100000 + 10;

int a[N],b[N],c[N];
int n;

int find2(int x, int y[])//大于于x最小处
{
    int l = 1, r = n;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        if(y[mid] > x) r = mid;
        else l = mid + 1;
    }
    if(y[r] <= x) return 0;
    return n - r + 1;
}

int find1(int x, int y[])//小于x最大处
{
    int l = 1, r = n;
    while(l < r)
    {
        int mid = (l + r + 1) >> 1;//+1
        if(y[mid] < x) l = mid;
        else r = mid - 1;
    }
    if(y[l] >= x) return 0;
    return l;
}

int 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);
    long long ans = 0;
    for(int i=1; i<=n; i++)
    {
        int x = find1(b[i], a);
        int y = find2(b[i], c);
        // cout<<x<<' '<<y<<endl;
        ans += 1ll * x * y;//注意乘积爆int
    }
    cout<<ans;
    return 0;
}

枚举:

#include<bits/stdc++.h>

using namespace std;

const int maxn=1e5+10;
typedef long long ll;
int a[maxn];
int b[maxn];
int c[maxn];
int main()
{
    int n;
    ll ans=0;
    cin>>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 cnt1=0,cnt2=0;
    for(int i=0;i<n;i++){
        while(cnt1<n&&a[cnt1]<b[i]) cnt1++;
		while(cnt2<n&&c[cnt2]<=b[i]) cnt2++;
        ans+=cnt1*(n-cnt2);
    }
    
    cout<<ans<<endl;
}

令人疑惑的是枚举竟然比二分快

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值