zoukankan      html  css  js  c++  java
  • [蓝桥杯][2018年第九届真题]递增三元组

    二分做法

    考虑到(A_i < B_j < C_k),如果以(A_i)为基准进行二分,时间复杂度为:(O(n^2log^2n))

    若以(B_j)为基准,则只需在(A)数组中查找最后一个小于(B_j)的位置,以及(C)数组中查找第一个大于(B_j)的位置,时间复杂度为:(O(nlogn))

    const int N=1e5+10;
    int a[N],b[N],c[N];
    int n;
    
    int main()
    {
        cin>>n;
    
        for(int i=0;i<n;i++) cin>>a[i];
        sort(a,a+n);
        for(int i=0;i<n;i++) cin>>b[i];
        sort(b,b+n);
        for(int i=0;i<n;i++) cin>>c[i];
        sort(c,c+n);
    
        LL res=0;
        for(int i=0;i<n;i++)
        {
            int ra=lower_bound(a,a+n,b[i])-a;
            int lc=upper_bound(c,c+n,b[i])-c;
            res+=(LL)ra*(n-lc);
        }
        cout<<res<<endl;
        //system("pause");
        return 0;
    }
    

    双指针做法

    由于存在单调性,可用双指针替代二分。

    const int N=1e5+10;
    int a[N],b[N],c[N];
    int n;
    
    int main()
    {
        cin>>n;
    
        for(int i=0;i<n;i++) cin>>a[i];
        sort(a,a+n);
        for(int i=0;i<n;i++) cin>>b[i];
        sort(b,b+n);
        for(int i=0;i<n;i++) cin>>c[i];
        sort(c,c+n);
    
        LL res=0;
        int ra=0,lc=0;
        for(int i=0;i<n;i++)
        {
            while(ra<n && a[ra] < b[i]) ra++;
            while(lc<n && c[lc] <= b[i]) lc++;
            res+=(LL)ra*(n-lc);
        }
        cout<<res<<endl;
        //system("pause");
        return 0;
    }
    

    前缀和做法

    开两个桶分别记录数组(a)(c)中各数字出现的次数,对桶数组求前缀和,之后枚举(b)数组中的每个数累加答案。

    为方便前缀和处理,将(a)(b)(c)读入的数字均做加一处理。

    const int N=1e5+10;
    int a[N],b[N],c[N];
    int cnta[N],cntc[N];
    int suma[N],sumc[N];
    int n;
    
    int main()
    {
        cin>>n;
    
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            cnta[++a[i]]++;
        }
        for(int i=1;i<N;i++) suma[i]=suma[i-1]+cnta[i];
    
        for(int i=1;i<=n;i++) cin>>b[i],b[i]++;
    
        for(int i=1;i<=n;i++)
        {
            cin>>c[i];
            cntc[++c[i]]++;
        }
        for(int i=1;i<N;i++) sumc[i]=sumc[i-1]+cntc[i];
    
        LL res=0;
        for(int i=1;i<=n;i++)
            res+=(LL)suma[b[i]-1]*(sumc[N-1]-sumc[b[i]]);
        cout<<res<<endl;
    
        //system("pause");
        return 0;
    }
    
  • 相关阅读:
    文字转语音功能
    windows定时计划任务
    写电子合同,爬过的坑,趟过的雷,犯过的错,都是泪
    前端应该如何去认识http
    I/O理解
    观察者模式
    js --代理模式
    js --策略模式
    js --单例模式
    js 单线程 异步
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14572541.html
Copyright © 2011-2022 走看看