枚举算法

枚举算法

  • 一、枚举
    • 例题
      • 1、连号区间数
        • 题目信息
        • 思路
        • 题解
      • 2、递增三元组
        • 题目信息
        • 思路
          • 暴力做法
          • 优化
            • 方法一:前缀和
            • 方法二:排序+二分
        • 题解
          • 暴力做法
          • 优化
            • 方法一:前缀和
            • 方法二:排序+二分

一、枚举

例题

1、连号区间数

题目信息

枚举算法_第1张图片

思路

[a,b]连号区间的性质:区间中的最大值-最小值=b-a;
注:这里的a,b值下标数,因为是连续的,所以每两个数之间的值相差为1,在区间[a,b]中一共有b-a+1个数,若为连号,相差的值为b-a。

题解
#include 
#define int long long
#define endl '\n'
#define maxsize 10010
using namespace std;

int n;
int a[maxsize];

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    int count=0;
    int max,min;
    for(int i=0;i<n;i++)   //枚举区间左端点
    {
        max=min=a[i];
        for(int j=i;j<n;j++)   //枚举区间右端点
        {
            if(a[j]>max) max=a[j];
            if(a[j]<min) min=a[j];
            if(max-min==j-i) count++; 
        }
    }
    cout<<count<<endl;
    return 0;
}

2、递增三元组

题目信息

枚举算法_第2张图片

思路
暴力做法

用三个for循环来进行比较,符合条件,count++
但是会超时

优化

枚举B数组,对于Bj,判断:
(1)在A中有多少个小于Bj
(2)在C中有多少个大于Bj

方法一:前缀和

枚举算法_第3张图片

方法二:排序+二分

对A、C进行二分,Bj作为分界值
要考虑边界问题,如果二分后l和r都等于0或都等于n-1,还要进行分类讨论(以都等于0为例):
(1)a[n-1]左边的所有数都小于b[j],a[n-1]大于b[j]
(2)a[n-1]左边的所有数都小于b[j],a[n-1]也小于b[j]

题解
暴力做法
#include 
#define endl '\n'
#define int long long 
#define maxsize 100010
using namespace std;

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

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int count=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];
    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]) count++;
            }
        }
    }
    cout<<count<<endl;
    return 0;
}
优化
方法一:前缀和
#include 
#define endl '\n'
#define int long long 
#define maxsize 100010
using namespace std;

int n;
int a[maxsize],b[maxsize],c[maxsize];
int acnt[maxsize];  //记录a数组中每个数出现的次数
int ccnt[maxsize];  //记录c数组中每个数出现的次数
int s[maxsize];     //记录每个数出现的次数
int as[maxsize];   //as[i]表示在a数组中小于b[i]的数的个数
int cs[maxsize];   //cs[i]表示在c数组中大于b[i]的数的个数

//前缀和
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        a[i]++;
    }
    for(int i=0;i<n;i++) 
    {
        cin>>b[i];
        b[i]++;
    }
    for(int i=0;i<n;i++)
    {
        cin>>c[i];
        c[i]++;
    }

    //求as[i]
    for(int i=0;i<n;i++) acnt[a[i]]++;
    for(int i=1;i<maxsize;i++) s[i]=s[i-1]+acnt[i];
    for(int i=0;i<n;i++) as[i]=s[b[i]-1];

    //求cs[i]
    for(int i=0;i<n;i++) ccnt[c[i]]++;
    for(int i=1;i<maxsize;i++) s[i]=s[i-1]+ccnt[i];
    for(int i=0;i<n;i++) cs[i]=s[maxsize-1]-s[b[i]];

    int count=0;
    for(int i=0;i<n;i++) count +=as[i]*cs[i];
    cout<<count<<endl;
    return 0;
}
方法二:排序+二分
#include 
#define endl '\n'
#define int long long 
#define maxsize 100010
using namespace std;

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

//排序二分
int bsearch_l(int u)
{
    int l=0,r=n-1;
    while(l<r)
    {
        int mid=(l+r)/2;
        if(a[mid]>=u) r=mid;
        else l=mid+1;
    }
    return r;
}

int bsearch_r(int u)
{
    int l=0,r=n-1;
    while(l<r)
    {
        int mid=(l+r+1)/2;
        if(c[mid]<=u) l=mid;
        else r=mid-1;
    }
    return l;
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    int count=0;
    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(c,c+n);
    int num1,num2;
    for(int i=0;i<n;i++)
    {
        if(a[n-1]<b[i]){
            num1=n;
        }else{
           num1=bsearch_l(b[i]);
        }
        if(c[0]>b[i])
        {
            num2=n;
        }else{
            num2=bsearch_r(b[i]);
            num2=n-1-num2;   
        }
        count +=num1*num2;
    }
    cout<<count<<endl;
    return 0;
}

上述代码中sort的用法可以参考以下文章:
C++ sort()排序详解

你可能感兴趣的:(算法,算法,c++)