AcWing
  • 首页
  • 题库
  • 题解
  • 分享
  • 问答
  • 活动
  • 应用
  • 吐槽
  • 登录/注册

AcWing 1236. 递增三元组    原题链接    中等

作者: 作者的头像   Jocelin ,  2021-02-23 22:24:59 ,  阅读 24


0


暴力

//暴力
#include<iostream>

using namespace std;

int n;
#define N 100010
int a[N];
int b[N];
int c[N];
int res;
int main()
{
    cin >> n;


    for(int j = 0; j <n;j++) scanf("%d",&a[j]);
    for(int j = 0; j <n;j++) scanf("%d",&b[j]);
    for(int j = 0; j <n;j++) scanf("%d",&c[j]);

    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j ++)
        {
            for(int k = 0; k < n;k++)
            {
                if( a[i] < b[j] && b[j] < c[k])
                    res++;
            }
        }

    }

    cout << res << endl;
    return 0;
}

排序+二分,直接用二分找左右的两个模板 求出即可

//枚举B后,A,C的方案数相乘就确定了

#include<iostream>
#include<algorithm>
using namespace std;

int n;
#define N 100010
int a[N];
int b[N];
int c[N];
long long res;

//二分查找法
int left_find(int left,int right,int target,int num[])
{


    while( left < right)
    {
        int mid =  (right + left) / 2;

        if(num[mid] == target)
            right = mid;
        else if( num[mid] > target)
            right = mid;
        else if( num[mid] < target)
            left = mid + 1;
    }
    return left ;
}

int right_find(int left,int right,int target,int num[])
{


    while( left < right)
    {
        int mid =  (right + left) / 2;

        if(num[mid] == target)
            left = mid+1;
        else if( num[mid] > target)
            right = mid;
        else if( num[mid] < target)
            left = mid + 1;
    }
    // return left-1;
    return left; //比target大的位置起始坐标
}

int main()
{
    cin >> n;


    for(int j = 0; j <n;j++) scanf("%d",&a[j]);
    sort(a,a+n);
    // for(int j = 0; j <n;j++) cout << a[j] << " ";
    // cout << endl;
    for(int j = 0; j <n;j++) scanf("%d",&b[j]);
    sort(b,b+n);
    for(int j = 0; j <n;j++) scanf("%d",&c[j]);
    sort(c,c+n);


    // cout << left_find(0,n,3,a) << endl;
    // cout << (right_find(0,n,7,a) ) << endl;
    //遍历b[i],找出a中小于b[i]的个数,找出c中大于b[i]的个数
    for(int i = 0; i < n; i++)
    {
        long long num_a = left_find(0,n,b[i],a);
        long long num_c = n - right_find(0,n,b[i],c);  
        res +=  (num_a*num_c);

    }

    cout << res << endl;
    return 0;
}

前缀和

//暴力
// #include<iostream>

// using namespace std;

// int n;
// #define N 100010
// int a[N];
// int b[N];
// int c[N];
// int res;
// int main()
// {
//     cin >> n;


//     for(int j = 0; j <n;j++) scanf("%d",&a[j]);
//     for(int j = 0; j <n;j++) scanf("%d",&b[j]);
//     for(int j = 0; j <n;j++) scanf("%d",&c[j]);

//     for(int i = 0; i < n; i++)
//     {
//         for(int j = 0; j < n; j ++)
//         {
//             for(int k = 0; k < n;k++)
//             {
//                 if( a[i] < b[j] && b[j] < c[k])
//                     res++;
//             }
//         }

//     }

//     cout << res << endl;
//     return 0;
// }


// //2、二分+排序
// //枚举B后,A,C的方案数相乘就确定了

// #include<iostream>
// #include<algorithm>
// using namespace std;

// int n;
// #define N 100010
// int a[N];
// int b[N];
// int c[N];
// long long res;

// //二分查找法
// int left_find(int left,int right,int target,int num[])
// {


//     while( left < right)
//     {
//         int mid =  (right + left) / 2;

//         if(num[mid] == target)
//             right = mid;
//         else if( num[mid] > target)
//             right = mid;
//         else if( num[mid] < target)
//             left = mid + 1;
//     }
//     return left ;
// }

// int right_find(int left,int right,int target,int num[])
// {


//     while( left < right)
//     {
//         int mid =  (right + left) / 2;

//         if(num[mid] == target)
//             left = mid+1;
//         else if( num[mid] > target)
//             right = mid;
//         else if( num[mid] < target)
//             left = mid + 1;
//     }
//     // return left-1;
//     return left; //比target大的位置起始坐标
// }

// int main()
// {
//     cin >> n;


//     for(int j = 0; j <n;j++) scanf("%d",&a[j]);
//     sort(a,a+n);
//     // for(int j = 0; j <n;j++) cout << a[j] << " ";
//     // cout << endl;
//     for(int j = 0; j <n;j++) scanf("%d",&b[j]);
//     sort(b,b+n);
//     for(int j = 0; j <n;j++) scanf("%d",&c[j]);
//     sort(c,c+n);


//     // cout << left_find(0,n,3,a) << endl;
//     // cout << (right_find(0,n,7,a) ) << endl;
//     //遍历b[i],找出a中小于b[i]的个数,找出c中大于b[i]的个数
//     for(int i = 0; i < n; i++)
//     {
//         int num_a = left_find(0,n,b[i],a);
//         int num_c = n - right_find(0,n,b[i],c);  
//         res += (long long) (num_a*num_c);

//     }

//     cout << res << endl;
//     return 0;
// }


//3、前缀和
//枚举B后,A,C的方案数相乘就确定了

#include<iostream>
#include<algorithm>
using namespace std;

int n;
#define N 100010
int a[N],cnt_a[N],S_a[N]; 
int b[N];
int c[N],cnt_c[N],S_c[N];

long long res;


int main()
{
    cin >> n;

    for(int j = 0; j <n;j++)
    {
        scanf("%d",&a[j]);
        cnt_a[ a[j] ]++; //统计数组出现的次数

    }
    for(int j = 0; j <n;j++) 
        scanf("%d",&b[j]);

    for(int j = 0; j <n;j++) 
    {
        scanf("%d",&c[j]);
        cnt_c[ c[j] ]++;
    }

    S_a[0] = cnt_a[0];
    for(int j = 1; j <N;j++) //这里得从大N遍历,因为是从0-N所有出现的数
    {
        S_a[j] = S_a[j-1] + cnt_a[ j ];
    }

    S_c[0] = cnt_c[0];
    for(int j = 1; j <N;j++)
    {
        S_c[j] = S_c[j-1] + cnt_c[ j ];
    }


    for(int i = 0; i < n; i++)
    {
        long long num_a = S_a[ b[i] - 1];
        long long num_c = n - S_c[ b[i] ];

        res += num_a*num_c;

    }

    cout << res << endl;
    return 0;
}

0 评论

你确定删除吗?

© 2018-2021 AcWing 版权所有  |  京ICP备17053197号-1
联系我们  |  常见问题
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息